diff -u --recursive --new-file v2.1.53/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.53/linux/Documentation/Configure.help	Wed Sep  3 20:52:41 1997
+++ linux/Documentation/Configure.help	Sat Sep  6 10:43:49 1997
@@ -680,21 +680,38 @@
   VGA driver is used.  Note that, at this time, there is no X server
   for these systems. If unsure, try N.
 
-PCI bios support
+PCI support
 CONFIG_PCI
   Find out whether you have a PCI motherboard. PCI is the name of a
   bus system, i.e. the way the CPU talks to the other stuff inside
   your box. Other bus systems are ISA, EISA, Microchannel (MCA) or
-  VESA. If you have PCI, say Y, otherwise N. Note: some old PCI
-  motherboards have BIOS bugs and may crash if "PCI bios support" is
-  enabled (but they run fine without this option). The PCI-HOWTO,
-  available via ftp (user: anonymous) in
-  sunsite.unc.edu:/pub/Linux/docs/HOWTO, contains valuable information
-  about which PCI hardware does work under Linux and which doesn't.
+  VESA. If you have PCI, say Y, otherwise N. The PCI-HOWTO, available
+  via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO,
+  contains valuable information about which PCI hardware does work
+  under Linux and which doesn't.
   If some of your PCI devices don't work and you get a warning during
   boot time ("man dmesg"), please follow the instructions at the top
   of include/linux/pci.h.
 
+PCI BIOS support
+CONFIG_PCI_BIOS
+  If you have enabled PCI bus support above, you probably want to allow
+  Linux to use your PCI BIOS to detect the PCI devices and determine
+  their configuration. Note: some old PCI motherboards have BIOS bugs
+  and may crash if this switch is enabled -- for such motherboards,
+  you should disable PCI BIOS support and use direct PCI access instead.
+  Except for some special cases (embedded systems with no BIOS), you
+  probably should say Y here.
+
+PCI direct access support
+CONFIG_PCI_DIRECT
+  If you don't want to use the PCI BIOS (e.g., because you run some
+  embedded system with no BIOS at all) or Linux says it cannot use
+  your PCI BIOS, you can enable direct PCI hardware here. It might fail
+  if your machine is based on some unusual chipset, but it usually
+  works. If both PCI BIOS and direct PCI access are enabled, the use
+  of BIOS is preferred. If unsure, say Y.
+
 PCI bridge optimization (experimental)
 CONFIG_PCI_OPTIMIZE
   This can improve access times for some hardware devices under
@@ -2653,6 +2670,26 @@
   can only use one protocol at a time, depending on what the other end
   can understand).
 
+Shortwave radio modem driver
+CONFIG_HFMODEM
+  This experimental driver is used by a package (to be released)
+  that implements the shortwave radio protocols RTTY, Sitor (Amtor),
+  Pactor 1 and GTOR using a standard PC soundcard. If unsure,
+  say N.
+
+Shortwave radio modem driver support for SoundBlaster and compatible cards
+CONFIG_HFMODEM_SBC
+  This option enables the hfmodem driver to use SoundBlaster and
+  compatible cards. It requires a 16bit capable card, i.e.
+  SB16 or better, or ESS1688 or newer.
+
+Shortwave radio modem driver support for WSS and Crystal cards
+CONFIG_HFMODEM_WSS
+  This option enables the hfmodem driver to use WindowsSoundSystem
+  compatible cards. These cards feature a codec chip from either
+  Analog Devices (such as AD1848, AD1845, AD1812) or Crystal
+  Semiconductors (such as CS4248, CS423x).
+
 Serial port KISS driver for AX.25
 CONFIG_MKISS
   KISS is the protocol used to send IP traffic over AX.25 radio
@@ -3056,10 +3093,14 @@
   linux, read the Multiple-Ethernet-mini-HOWTO, available from
   sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
 
-ARCnet support
+Generic ARCnet support
 CONFIG_ARCNET
   If you have a network card of this type, say Y and check out the
   (arguably) beautiful poetry in Documentation/networking/arcnet.txt.
+  You need both this driver, and the driver for the particular ARCnet
+  chipset of your card. If you don't know, then it's probably a 
+  COM90xx type card, so say Y (or M) to ARCnet COM90xx chipset support
+  below.
   You might also want to have a look at the Ethernet-HOWTO, available
   via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO
   (even though ARCnet is not really ethernet). This driver is also
@@ -3097,6 +3138,31 @@
   documentation in Documentation/networking/arcnet.txt for more
   information about using arc0e and arc0s.
 
+ARCnet COM90xx chipset support
+CONFIG_ARCNET_COM90xx
+  This is the chipset driver for the standard COM90xx cards. If you always
+  used the old arcnet driver without knowing what type of card you had, 
+  this is probably the one for you.
+
+ARCnet COM90xx IO mapped mode chipset support
+CONFIG_ARCNET_COM90xxIO
+  This is the chipset driver for the COM90xx cards, using them in IO-mapped
+  mode instead of memory-mapped mode. This is slower than the normal driver.
+  Only use it if your card doesn't support shared memory.
+
+ARCnet RIM I chipset support
+CONFIG_ARCNET_RIM_I
+  This is yet another chipset driver for the COM90xx cards, but this time
+  only using memory-mapped mode, and no IO ports at all. This driver is
+  completely untested, so if you have one of these cards, please mail 
+  dwmw2@cam.ac.uk, especially if it works!
+
+ARCnet COM20020 chipset support
+CONFIG_ARCNET_COM20020
+  This is the driver for the new COM20020 chipset. It supports such things
+  as promiscuous mode, so packet sniffing is possible, and extra diagnostic
+  information.
+
 Cabletron E21xx support
 CONFIG_E2100
   If you have a network (ethernet) card of this type, say Y and read
@@ -3222,6 +3288,16 @@
   linux, read the Multiple-Ethernet-mini-HOWTO, available from
   sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
 
+NI5010 support
+CONFIG_NI5010
+  If you have a network (ethernet) card of this type, say Y and read
+  the Ethernet-HOWTO, available via ftp (user: anonymous) in
+  sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you plan to use more than
+  one network card under linux, read the Multiple-Ethernet-mini-HOWTO,
+  available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
+  Note that this is still experimental code. If you use this driver,
+  please contact the authors to join the development team.
+
 NI5210 support
 CONFIG_NI52
   If you have a network (ethernet) card of this type, say Y and read
@@ -4445,6 +4521,12 @@
   other console device, in which case you probably want to say Y to
   "Console on serial port", below. If unsure, say N.
 
+Software generated cursor
+CONFIG_SOFTCURSOR
+  If you enable this option, you'll be able to do lots of nice things
+  with your cursor -- for example to turn it into a non-blinking one.
+  See Documentation/VGA-softcursor.txt for more information.
+
 Standard/generic serial support
 CONFIG_SERIAL
   This selects whether you want to include the driver for the standard
@@ -4938,6 +5020,18 @@
   module is called pcwd.o. If you want to compile it as a module, say
   M here and read Documentation/modules.txt.  Most people will say N.
 
+Acquire SBC Watchdog Timer
+CONFIG_ACQUIRE_WDT
+  This is the driver for the hardware watchdog on the PSC-6x86 Single
+  Board Computer produced by Acquire Inc (and others). This watchdog
+  simply watches your kernel to make sure it doesn't freeze, and if
+  it does, it resets your computer after a certain amount of time.
+  This driver is like the WDT501 driver but for different hardware.
+  This driver is also available as a module ( = code which can be 
+  inserted in and removed from the running kernel whenever you want).
+  The module is called pscwdt.o. If you want to compile it as a module,
+  say M here and read Documentation/modules.txt.  Most people will say N.
+  
 Enhanced Real Time Clock Support
 CONFIG_RTC
   If you say Y here and create a character special file /dev/rtc with
@@ -5853,6 +5947,76 @@
   sharing a hard disk between i386 and m68k Linux boxes, for example.
   Say Y if you need this feature; users who are only using their
   system-native partitioning scheme can say N here.
+
+Build PowerMac Kernel (not PReP)
+CONFIG_PMAC
+  There are currently two different kinds of PowerPC-based machines
+  available: Apple Power Macintoshes and clones (such as the Motorola
+  Starmax series, and PReP (PowerPC Reference Platform) machines such
+  as the Motorola PowerStack range.  Currently, a single kernel binary
+  only supports one type or the other.  Say Y here to compile a kernel
+  which will run on Power Macintoshes and clones.
+
+Build PReP Kernel (not PowerMac)
+CONFIG_PREP
+  Say Y here to compile a kernel which will run on PReP (PowerPC
+  Reference Platform) machines such as the Motorola PowerStack range.
+  For Power Macintosh clones, including the Motorola Starmaxes, you
+  should say N (and Y to the previous question).
+
+Processor type
+CONFIG_MCOMMON
+  If you are compiling a kernel to run on a specific machine, you can
+  indicate which type of PowerPC processor it has.  Currently this
+  option does very little.
+
+Support for Open Firmware device tree in /proc
+CONFIG_PROC_DEVICETREE
+  This option adds a device-tree directory under /proc which contains
+  an image of the device tree that the kernel copies from Open
+  Firmware.  If unsure, say Y here.
+
+Support for ATI Mach64 display cards
+CONFIG_ATY_VIDEO
+  Several of the newer Power Macintoshes and clones have a video
+  display interface based on the ATI Mach64 chipset.  Say N here if
+  you are sure you don't need this functionality, otherwise Y.
+
+Support for IMS Twin Turbo display card
+CONFIG_IMSTT_VIDEO
+  Some Power Macintosh clones have an IMS Twin Turbo video display
+  interface.  Say Y to include support for this.
+
+MESH (Power Mac internal SCSI) support
+CONFIG_SCSI_MESH
+  Many Power Macintoshes and clones have a MESH (Macintosh Enhanced
+  SCSI Hardware) SCSI bus adaptor (the 7200 doesn't, but all of the
+  other Power Macintoshes do).  Say Y to include support for this SCSI
+  adaptor.
+
+Maximum synchronous transfer rate
+CONFIG_SCSI_MESH_SYNC_RATE
+  On Power Macintoshes (and clones) where the MESH SCSI bus adaptor
+  drives a bus which is entirely internal to the machine (such as the
+  7500, 7600, 8500, etc.), the MESH is capable of synchronous
+  operation at up to 10MB/s.  On machines where the SCSI bus
+  controlled by the MESH can have external devices connected, it is
+  usually rated at 5MB/s.  5 is a safe value here unless you know the
+  MESH SCSI bus is internal only; in that case you can say 10.  Say 0
+  to disable synchronous operation.
+
+53C94 (Power Mac external SCSI) support
+CONFIG_SCSI_MAC53C94
+  On Power Macintoshes (and clones) with two SCSI buses, the external
+  SCSI bus is usually controlled by a 53C94 SCSI bus adaptor.  Older
+  machines which only have one SCSI bus, such as the 7200, also use
+  the 53C94.  Say Y to include support for the 53C94.
+
+MACE (Power Mac ethernet) support
+CONFIG_MACE
+  Power Macintoshes and clones with ethernet built-in on the
+  motherboard will usually use a MACE (Medium Access Control for
+  Ethernet) interface.  Say Y to include support for the MACE chip.
 
 # need an empty line after last entry, for sed script in Configure.
 
diff -u --recursive --new-file v2.1.53/linux/Documentation/devices.tex linux/Documentation/devices.tex
--- v2.1.53/linux/Documentation/devices.tex	Thu Aug 14 20:49:16 1997
+++ linux/Documentation/devices.tex	Sat Sep  6 10:28:27 1997
@@ -47,7 +47,7 @@
 %
 \title{{\bf Linux Allocated Devices}}
 \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$}
-\date{Last revised: July 28, 1997}
+\date{Last revised: September 5, 1997}
 \maketitle
 %
 \noindent
@@ -216,7 +216,9 @@
 \major{85}{}{char }{Linux/SGI shared memory input queue}
 \major{86}{}{char }{SCSI media changer}
 \major{87}{}{char }{Sony Control-A1 stereo control bus}
-\major{88}{--119}{}{Unallocated}
+\major{88}{}{char }{COMX synchronous serial card}
+\major{89}{}{char }{I$^2$C bus interface}
+\major{90}{--119}{}{Unallocated}
 \major{120}{--127}{}{Local/experimental use}
 \major{128}{--239}{}{Unallocated}
 \major{240}{--254}{}{Local/experimental use}
@@ -525,6 +527,7 @@
 	\minor{148}{/dev/gfx}{Linux/SGI graphics effects device}
 	\minor{149}{/dev/input/mouse}{Linux/SGI Irix emulation mouse}
 	\minor{150}{/dev/input/keyboard}{Linux/SGI Irix emulation keyboard}
+	\minor{151}{/dev/led}{Front panel LEDs}
 \end{devicelist}
 
 \begin{devicelist}
@@ -1417,8 +1420,8 @@
 
 \begin{devicelist}
 \major{82}{}{char }{WiNRADiO communications receiver card}
-	\major{0}{/dev/winradio0}{First WiNRADiO card}
-	\major{1}{/dev/winradio1}{Second WiNRADiO card}
+	\minor{0}{/dev/winradio0}{First WiNRADiO card}
+	\minor{1}{/dev/winradio1}{Second WiNRADiO card}
 	\minordots
 \end{devicelist}
 
@@ -1465,7 +1468,21 @@
 \end{devicelist}
 
 \begin{devicelist}
-\major{88}{--119}{}{Unallocated}
+\major{88}{}{char }{COMX synchronous serial card}
+	\minor{0}{/dev/comx0}{Channel 0}
+	\minor{1}{/dev/comx1}{Channel 1}
+	\minordots
+\end{devicelist}
+
+\begin{devicelist}
+\major{89}{}{char }{I$^2$C bus interface}
+	\minor{0}{/dev/i2c0}{First I$^2$C adapter}
+	\minor{1}{/dev/i2c1}{Second I$^2$C adapter}
+	\minordots
+\end{devicelist}
+
+\begin{devicelist}
+\major{90}{--119}{}{Unallocated}
 \end{devicelist}
 
 \begin{devicelist}
diff -u --recursive --new-file v2.1.53/linux/Documentation/devices.txt linux/Documentation/devices.txt
--- v2.1.53/linux/Documentation/devices.txt	Thu Aug 14 20:49:16 1997
+++ linux/Documentation/devices.txt	Sat Sep  6 10:28:27 1997
@@ -1,7 +1,7 @@
 		       LINUX ALLOCATED DEVICES
 	     Maintained by H. Peter Anvin <hpa@zytor.com>
 
-		     Last revised: July 28, 1997
+		   Last revised: September 5, 1997
 
 This list is the successor to Rick Miller's Linux Device List, which
 he stopped maintaining when he got busy with other things in 1993.  It
@@ -301,6 +301,7 @@
 		148 = /dev/gfx		Linux/SGI graphics effects device
 		149 = /dev/input/mouse	Linux/SGI Irix emulation mouse
 		150 = /dev/input/keyboard Linux/SGI Irix emulation keyboard
+		151 = /dev/led		Front panel LEDs
 
  11 char	Raw keyboard device
 		  0 = /dev/kbd		Raw keyboard device
@@ -1031,7 +1032,17 @@
 		  1 = /dev/controla1	Second device on chain
 		    ...
 
- 88-119		UNALLOCATED
+ 88 char	COMX synchronous serial card
+		  0 = /dev/comx0	COMX channel 0
+		  1 = /dev/comx1	COMX channel 1
+		    ...
+
+ 89 char	I2C bus interface
+		  0 = /dev/i2c0		First I2C adapter
+		  1 = /dev/i2c1		Second I2C adapter
+		    ...
+
+ 90-119		UNALLOCATED
 
 120-127		LOCAL/EXPERIMENTAL USE
 
diff -u --recursive --new-file v2.1.53/linux/Makefile linux/Makefile
--- v2.1.53/linux/Makefile	Thu Sep  4 17:07:29 1997
+++ linux/Makefile	Thu Sep  4 17:07:54 1997
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 53
+SUBLEVEL = 54
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
diff -u --recursive --new-file v2.1.53/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
--- v2.1.53/linux/arch/alpha/kernel/bios32.c	Sun Feb  2 05:00:34 1997
+++ linux/arch/alpha/kernel/bios32.c	Sat Sep  6 10:43:49 1997
@@ -186,6 +186,7 @@
 		pcibios_read_config_dword(bus->number, dev->devfn, reg, &base);
 		if (!base) {
 			/* this base-address register is unused */
+			dev->base_address[(reg - PCI_BASE_ADDRESS_0)>>2] = 0;
 			continue;
 		}
 
diff -u --recursive --new-file v2.1.53/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.1.53/linux/arch/i386/config.in	Wed Sep  3 20:52:41 1997
+++ linux/arch/i386/config.in	Sat Sep  6 10:43:49 1997
@@ -23,8 +23,10 @@
 
 bool 'Kernel math emulation' CONFIG_MATH_EMULATION
 bool 'Networking support' CONFIG_NET
-bool 'PCI bios support' CONFIG_PCI
+bool 'PCI support' CONFIG_PCI
 if [ "$CONFIG_PCI" = "y" ]; then
+  bool '   PCI BIOS support' CONFIG_PCI_BIOS
+  bool '   PCI direct access support' CONFIG_PCI_DIRECT
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
     bool '   PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
   fi
diff -u --recursive --new-file v2.1.53/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.1.53/linux/arch/i386/defconfig	Mon Aug 18 18:19:42 1997
+++ linux/arch/i386/defconfig	Sat Sep  6 10:49:53 1997
@@ -20,6 +20,8 @@
 # CONFIG_MATH_EMULATION is not set
 CONFIG_NET=y
 CONFIG_PCI=y
+CONFIG_PCI_BIOS=y
+# CONFIG_PCI_DIRECT is not set
 # CONFIG_MCA is not set
 CONFIG_SYSVIPC=y
 CONFIG_SYSCTL=y
@@ -139,7 +141,6 @@
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_PPA is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
@@ -162,6 +163,7 @@
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_NET_ISA is not set
 CONFIG_NET_EISA=y
 # CONFIG_PCNET32 is not set
@@ -174,7 +176,6 @@
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
 # CONFIG_DLCI is not set
-# CONFIG_PLIP is not set
 # CONFIG_PPP is not set
 # CONFIG_NET_RADIO is not set
 # CONFIG_SLIP is not set
@@ -239,6 +240,7 @@
 # CONFIG_APM is not set
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
+# CONFIG_H8 is not set
 # CONFIG_NVRAM is not set
 # CONFIG_JOYSTICK is not set
 
diff -u --recursive --new-file v2.1.53/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- v2.1.53/linux/arch/i386/kernel/bios32.c	Thu Jul 17 10:06:03 1997
+++ linux/arch/i386/kernel/bios32.c	Sat Sep  6 10:43:49 1997
@@ -1,7 +1,7 @@
 /*
  * bios32.c - BIOS32, PCI BIOS functions.
  *
- * $Id: bios32.c,v 1.12 1997/06/26 13:33:46 mj Exp $
+ * $Id: bios32.c,v 1.14 1997/08/02 22:20:57 mj Exp $
  *
  * Sponsored by
  *	iX Multiuser Multitasking Magazine
@@ -61,6 +61,9 @@
  * 
  * Jun 20, 1997 : Corrected problems in "conf1" type accesses.
  *      (paubert@iram.es)
+ *
+ * Aug 2,  1997 : Split to PCI BIOS handling and direct PCI access parts
+ *	and cleaned it up...     Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  */
 
 #include <linux/config.h>
@@ -75,69 +78,12 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#define PCIBIOS_PCI_FUNCTION_ID 	0xb1XX
-#define PCIBIOS_PCI_BIOS_PRESENT 	0xb101
-#define PCIBIOS_FIND_PCI_DEVICE		0xb102
-#define PCIBIOS_FIND_PCI_CLASS_CODE	0xb103
-#define PCIBIOS_GENERATE_SPECIAL_CYCLE	0xb106
-#define PCIBIOS_READ_CONFIG_BYTE	0xb108
-#define PCIBIOS_READ_CONFIG_WORD	0xb109
-#define PCIBIOS_READ_CONFIG_DWORD	0xb10a
-#define PCIBIOS_WRITE_CONFIG_BYTE	0xb10b
-#define PCIBIOS_WRITE_CONFIG_WORD	0xb10c
-#define PCIBIOS_WRITE_CONFIG_DWORD	0xb10d
-
-
-/* BIOS32 signature: "_32_" */
-#define BIOS32_SIGNATURE	(('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
-
-/* PCI signature: "PCI " */
-#define PCI_SIGNATURE		(('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
-
-/* PCI service signature: "$PCI" */
-#define PCI_SERVICE		(('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
-
 /*
- * This is the standard structure used to identify the entry point
- * to the BIOS32 Service Directory, as documented in
- * 	Standard BIOS 32-bit Service Directory Proposal
- * 	Revision 0.4 May 24, 1993
- * 	Phoenix Technologies Ltd.
- *	Norwood, MA
- * and the PCI BIOS specification.
+ * Generic PCI access -- indirect calls according to detected HW.
  */
 
-union bios32 {
-	struct {
-		unsigned long signature;	/* _32_ */
-		unsigned long entry;		/* 32 bit physical address */
-		unsigned char revision;		/* Revision level, 0 */
-		unsigned char length;		/* Length in paragraphs should be 01 */
-		unsigned char checksum;		/* All bytes must add up to zero */
-		unsigned char reserved[5]; 	/* Must be zero */
-	} fields;
-	char chars[16];
-};
-
-#ifdef CONFIG_PCI
-/*
- * Physical address of the service directory.  I don't know if we're
- * allowed to have more than one of these or not, so just in case
- * we'll make pcibios_present() take a memory start parameter and store
- * the array there.
- */
-
-static unsigned long bios32_entry = 0;
-static struct {
-	unsigned long address;
-	unsigned short segment;
-} bios32_indirect = { 0, KERNEL_CS };
-
-
-/*
- * function table for accessing PCI configuration space
- */
 struct pci_access {
+    int pci_present;
     int (*find_device)(unsigned short, unsigned short, unsigned short, unsigned char *, unsigned char *);
     int (*find_class)(unsigned int, unsigned short, unsigned char *, unsigned char *);
     int (*read_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char *);
@@ -148,363 +94,137 @@
     int (*write_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int);
 };
 
-/*
- * pointer to selected PCI access function table
- */
-static struct pci_access *access_pci = NULL;
-
-
-
-/*
- * Returns the entry point for the given service, NULL on error
- */
-
-static unsigned long bios32_service(unsigned long service)
+static int pci_stub(void)
 {
-	unsigned char return_code;	/* %al */
-	unsigned long address;		/* %ebx */
-	unsigned long length;		/* %ecx */
-	unsigned long entry;		/* %edx */
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	__asm__("lcall (%%edi)"
-		: "=a" (return_code),
-		  "=b" (address),
-		  "=c" (length),
-		  "=d" (entry)
-		: "0" (service),
-		  "1" (0),
-		  "D" (&bios32_indirect));
-	restore_flags(flags);
-
-	switch (return_code) {
-		case 0:
-			return address + entry;
-		case 0x80:	/* Not present */
-			printk("bios32_service(0x%lx) : not present\n", service);
-			return 0;
-		default: /* Shouldn't happen */
-			printk("bios32_service(0x%lx) : returned 0x%x, mail drew@colorado.edu\n",
-				service, return_code);
-			return 0;
-	}
+	return PCIBIOS_FUNC_NOT_SUPPORTED;
 }
 
-static long pcibios_entry = 0;
-static struct {
-	unsigned long address;
-	unsigned short segment;
-} pci_indirect = { 0, KERNEL_CS };
+static struct pci_access pci_access_none = {
+	0,		   		/* No PCI present */
+	(void *) pci_stub,	        /* No functions implemented */
+	(void *) pci_stub,
+	(void *) pci_stub,
+	(void *) pci_stub,
+	(void *) pci_stub,
+	(void *) pci_stub,
+	(void *) pci_stub,
+	(void *) pci_stub
+};
 
+static struct pci_access *access_pci = &pci_access_none;
 
-__initfunc(static int check_pcibios(void))
+int pcibios_present(void)
 {
-	unsigned long signature;
-	unsigned char present_status;
-	unsigned char major_revision;
-	unsigned char minor_revision;
-	unsigned long flags;
-	int pack;
-
-	if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
-		pci_indirect.address = pcibios_entry | PAGE_OFFSET;
-
-		save_flags(flags); cli();
-		__asm__("lcall (%%edi)\n\t"
-			"jc 1f\n\t"
-			"xor %%ah, %%ah\n"
-			"1:\tshl $8, %%eax\n\t"
-			"movw %%bx, %%ax"
-			: "=d" (signature),
-			  "=a" (pack)
-			: "1" (PCIBIOS_PCI_BIOS_PRESENT),
-			  "D" (&pci_indirect)
-			: "bx", "cx");
-		restore_flags(flags);
-
-		present_status = (pack >> 16) & 0xff;
-		major_revision = (pack >> 8) & 0xff;
-		minor_revision = pack & 0xff;
-		if (present_status || (signature != PCI_SIGNATURE)) {
-			printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n"
-				"	but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
-				"	and signature of 0x%08lx (%c%c%c%c).  mail drew@Colorado.EDU\n",
-				(signature == PCI_SIGNATURE) ?  "WARNING" : "ERROR",
-				present_status, signature,
-				(char) (signature >>  0), (char) (signature >>  8),
-				(char) (signature >> 16), (char) (signature >> 24));
-
-			if (signature != PCI_SIGNATURE)
-				pcibios_entry = 0;
-		}
-		if (pcibios_entry) {
-			printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n",
-				major_revision, minor_revision, pcibios_entry);
-			return 1;
-		}
-	}
-	return 0;
+	return access_pci->pci_present;
 }
 
-
-static int pci_bios_find_class (unsigned int class_code, unsigned short index,
+int pcibios_find_class (unsigned int class_code, unsigned short index,
 	unsigned char *bus, unsigned char *device_fn)
 {
-	unsigned long bx;
-	unsigned long ret;
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	__asm__ ("lcall (%%edi)\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=b" (bx),
-		  "=a" (ret)
-		: "1" (PCIBIOS_FIND_PCI_CLASS_CODE),
-		  "c" (class_code),
-		  "S" ((int) index),
-		  "D" (&pci_indirect));
-	restore_flags(flags);
-	*bus = (bx >> 8) & 0xff;
-	*device_fn = bx & 0xff;
-	return (int) (ret & 0xff00) >> 8;
+	return access_pci->find_class(class_code, index, bus, device_fn);
 }
 
-
-static int pci_bios_find_device (unsigned short vendor, unsigned short device_id,
+int pcibios_find_device (unsigned short vendor, unsigned short device_id,
 	unsigned short index, unsigned char *bus, unsigned char *device_fn)
 {
-	unsigned short bx;
-	unsigned short ret;
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	__asm__("lcall (%%edi)\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=b" (bx),
-		  "=a" (ret)
-		: "1" (PCIBIOS_FIND_PCI_DEVICE),
-		  "c" (device_id),
-		  "d" (vendor),
-		  "S" ((int) index),
-		  "D" (&pci_indirect));
-	restore_flags(flags);
-	*bus = (bx >> 8) & 0xff;
-	*device_fn = bx & 0xff;
-	return (int) (ret & 0xff00) >> 8;
+	return access_pci->find_device(vendor, device_id, index, bus, device_fn);
 }
 
-static int pci_bios_read_config_byte(unsigned char bus,
+int pcibios_read_config_byte (unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned char *value)
 {
-	unsigned long ret;
-	unsigned long bx = (bus << 8) | device_fn;
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	__asm__("lcall (%%esi)\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=c" (*value),
-		  "=a" (ret)
-		: "1" (PCIBIOS_READ_CONFIG_BYTE),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	restore_flags(flags);
-	return (int) (ret & 0xff00) >> 8;
+	return access_pci->read_config_byte(bus, device_fn, where, value);
 }
 
-static int pci_bios_read_config_word (unsigned char bus,
+int pcibios_read_config_word (unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned short *value)
 {
-	unsigned long ret;
-	unsigned long bx = (bus << 8) | device_fn;
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	__asm__("lcall (%%esi)\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=c" (*value),
-		  "=a" (ret)
-		: "1" (PCIBIOS_READ_CONFIG_WORD),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	restore_flags(flags);
-	return (int) (ret & 0xff00) >> 8;
+	return access_pci->read_config_word(bus, device_fn, where, value);
 }
 
-static int pci_bios_read_config_dword (unsigned char bus,
+int pcibios_read_config_dword (unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned int *value)
 {
-	unsigned long ret;
-	unsigned long bx = (bus << 8) | device_fn;
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	__asm__("lcall (%%esi)\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=c" (*value),
-		  "=a" (ret)
-		: "1" (PCIBIOS_READ_CONFIG_DWORD),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	restore_flags(flags);
-	return (int) (ret & 0xff00) >> 8;
+	return access_pci->read_config_dword(bus, device_fn, where, value);
 }
 
-static int pci_bios_write_config_byte (unsigned char bus,
+int pcibios_write_config_byte (unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned char value)
 {
-	unsigned long ret;
-	unsigned long bx = (bus << 8) | device_fn;
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	__asm__("lcall (%%esi)\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=a" (ret)
-		: "0" (PCIBIOS_WRITE_CONFIG_BYTE),
-		  "c" (value),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	restore_flags(flags);
-	return (int) (ret & 0xff00) >> 8;
+	return access_pci->write_config_byte(bus, device_fn, where, value);
 }
 
-static int pci_bios_write_config_word (unsigned char bus,
+int pcibios_write_config_word (unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned short value)
 {
-	unsigned long ret;
-	unsigned long bx = (bus << 8) | device_fn;
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	__asm__("lcall (%%esi)\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=a" (ret)
-		: "0" (PCIBIOS_WRITE_CONFIG_WORD),
-		  "c" (value),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	restore_flags(flags);
-	return (int) (ret & 0xff00) >> 8;
+	return access_pci->write_config_word(bus, device_fn, where, value);
 }
 
-static int pci_bios_write_config_dword (unsigned char bus,
+int pcibios_write_config_dword (unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned int value)
 {
-	unsigned long ret;
-	unsigned long bx = (bus << 8) | device_fn;
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	__asm__("lcall (%%esi)\n\t"
-		"jc 1f\n\t"
-		"xor %%ah, %%ah\n"
-		"1:"
-		: "=a" (ret)
-		: "0" (PCIBIOS_WRITE_CONFIG_DWORD),
-		  "c" (value),
-		  "b" (bx),
-		  "D" ((long) where),
-		  "S" (&pci_indirect));
-	restore_flags(flags);
-	return (int) (ret & 0xff00) >> 8;
+	return access_pci->write_config_dword(bus, device_fn, where, value);
 }
 
 /*
- * function table for BIOS32 access
+ * Direct access to PCI hardware...
  */
-static struct pci_access pci_bios_access = {
-      pci_bios_find_device,
-      pci_bios_find_class,
-      pci_bios_read_config_byte,
-      pci_bios_read_config_word,
-      pci_bios_read_config_dword,
-      pci_bios_write_config_byte,
-      pci_bios_write_config_word,
-      pci_bios_write_config_dword
-};
-
-
 
 /*
  * Given the vendor and device ids, find the n'th instance of that device
  * in the system.  
  */
+
+#ifdef CONFIG_PCI_DIRECT
+
 static int pci_direct_find_device (unsigned short vendor, unsigned short device_id,
 			   unsigned short index, unsigned char *bus,
 			   unsigned char *devfn)
 {
     unsigned int curr = 0;
     struct pci_dev *dev;
-    unsigned long flags;
 
-    save_flags(flags);
     for (dev = pci_devices; dev; dev = dev->next) {
 	if (dev->vendor == vendor && dev->device == device_id) {
 	    if (curr == index) {
 		*devfn = dev->devfn;
 		*bus = dev->bus->number;
-		restore_flags(flags);
 		return PCIBIOS_SUCCESSFUL;
 	    }
 	    ++curr;
 	}
     }
-    restore_flags(flags);
     return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
-
 /*
  * Given the class, find the n'th instance of that device
  * in the system.
  */
+
 static int pci_direct_find_class (unsigned int class_code, unsigned short index,
 			  unsigned char *bus, unsigned char *devfn)
 {
     unsigned int curr = 0;
     struct pci_dev *dev;
-    unsigned long flags;
 
-    save_flags(flags); cli();
     for (dev = pci_devices; dev; dev = dev->next) {
 	if (dev->class == class_code) {
 	    if (curr == index) {
 		*devfn = dev->devfn;
 		*bus = dev->bus->number;
-		restore_flags(flags);
 		return PCIBIOS_SUCCESSFUL;
 	    }
 	    ++curr;
 	}
     }
-    restore_flags(flags);
     return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
 /*
  * Functions for accessing PCI configuration space with type 1 accesses
  */
+
 #define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
 
 static int pci_conf1_read_config_byte(unsigned char bus, unsigned char device_fn,
@@ -585,10 +305,8 @@
 
 #undef CONFIG_CMD
 
-/*
- * functiontable for type 1
- */
 static struct pci_access pci_direct_conf1 = {
+      1,
       pci_direct_find_device,
       pci_direct_find_class,
       pci_conf1_read_config_byte,
@@ -602,6 +320,7 @@
 /*
  * Functions for accessing PCI configuration space with type 2 accesses
  */
+
 #define IOADDR(devfn, where)   ((0xC000 | ((devfn & 0x78) << 5)) + where)
 #define FUNC(devfn)            (((devfn & 7) << 1) | 0xf0)
 
@@ -698,10 +417,8 @@
 #undef IOADDR
 #undef FUNC
 
-/*
- * functiontable for type 2
- */
 static struct pci_access pci_direct_conf2 = {
+      1,
       pci_direct_find_device,
       pci_direct_find_class,
       pci_conf2_read_config_byte,
@@ -712,8 +429,7 @@
       pci_conf2_write_config_dword
 };
 
-
-__initfunc(static struct pci_access *check_direct_pci(void))
+__initfunc(static struct pci_access *pci_check_direct(void))
 {
     unsigned int tmp;
     unsigned long flags;
@@ -721,7 +437,7 @@
     save_flags(flags); cli();
 
     /*
-     * check if configuration type 1 works
+     * Check if configuration type 1 works.
      */
     outb (0x01, 0xCFB);
     tmp = inl (0xCF8);
@@ -729,153 +445,385 @@
     if (inl (0xCF8) == 0x80000000) {
 	outl (tmp, 0xCF8);
 	restore_flags(flags);
-	printk("pcibios_init: Using configuration type 1\n");
+	printk("PCI: Using configuration type 1\n");
 	return &pci_direct_conf1;
     }
     outl (tmp, 0xCF8);
 
     /*
-     * check if configuration type 2 works
+     * Check if configuration type 2 works.
      */
     outb (0x00, 0xCFB);
     outb (0x00, 0xCF8);
     outb (0x00, 0xCFA);
     if (inb (0xCF8) == 0x00 && inb (0xCFB) == 0x00) {
 	restore_flags(flags);
-	printk("pcibios_init: Using configuration type 2\n");
+	printk("PCI: Using configuration type 2\n");
 	return &pci_direct_conf2;
     }
     restore_flags(flags);
-    printk("pcibios_init: Not supported chipset for direct PCI access !\n");
+    printk("PCI: PCI hardware not found (i.e., not present or not supported).\n");
     return NULL;
 }
 
+#endif
+
+/*
+ * BIOS32 and PCI BIOS handling.
+ */
+
+#ifdef CONFIG_PCI_BIOS
+
+#define PCIBIOS_PCI_FUNCTION_ID 	0xb1XX
+#define PCIBIOS_PCI_BIOS_PRESENT 	0xb101
+#define PCIBIOS_FIND_PCI_DEVICE		0xb102
+#define PCIBIOS_FIND_PCI_CLASS_CODE	0xb103
+#define PCIBIOS_GENERATE_SPECIAL_CYCLE	0xb106
+#define PCIBIOS_READ_CONFIG_BYTE	0xb108
+#define PCIBIOS_READ_CONFIG_WORD	0xb109
+#define PCIBIOS_READ_CONFIG_DWORD	0xb10a
+#define PCIBIOS_WRITE_CONFIG_BYTE	0xb10b
+#define PCIBIOS_WRITE_CONFIG_WORD	0xb10c
+#define PCIBIOS_WRITE_CONFIG_DWORD	0xb10d
+
+/* BIOS32 signature: "_32_" */
+#define BIOS32_SIGNATURE	(('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
+
+/* PCI signature: "PCI " */
+#define PCI_SIGNATURE		(('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
+
+/* PCI service signature: "$PCI" */
+#define PCI_SERVICE		(('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
+
+/*
+ * This is the standard structure used to identify the entry point
+ * to the BIOS32 Service Directory, as documented in
+ * 	Standard BIOS 32-bit Service Directory Proposal
+ * 	Revision 0.4 May 24, 1993
+ * 	Phoenix Technologies Ltd.
+ *	Norwood, MA
+ * and the PCI BIOS specification.
+ */
+
+union bios32 {
+	struct {
+		unsigned long signature;	/* _32_ */
+		unsigned long entry;		/* 32 bit physical address */
+		unsigned char revision;		/* Revision level, 0 */
+		unsigned char length;		/* Length in paragraphs should be 01 */
+		unsigned char checksum;		/* All bytes must add up to zero */
+		unsigned char reserved[5]; 	/* Must be zero */
+	} fields;
+	char chars[16];
+};
+
+/*
+ * Physical address of the service directory.  I don't know if we're
+ * allowed to have more than one of these or not, so just in case
+ * we'll make pcibios_present() take a memory start parameter and store
+ * the array there.
+ */
+
+static unsigned long bios32_entry = 0;
+static struct {
+	unsigned long address;
+	unsigned short segment;
+} bios32_indirect = { 0, KERNEL_CS };
+
+/*
+ * Returns the entry point for the given service, NULL on error
+ */
+
+static unsigned long bios32_service(unsigned long service)
+{
+	unsigned char return_code;	/* %al */
+	unsigned long address;		/* %ebx */
+	unsigned long length;		/* %ecx */
+	unsigned long entry;		/* %edx */
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	__asm__("lcall (%%edi)"
+		: "=a" (return_code),
+		  "=b" (address),
+		  "=c" (length),
+		  "=d" (entry)
+		: "0" (service),
+		  "1" (0),
+		  "D" (&bios32_indirect));
+	restore_flags(flags);
+
+	switch (return_code) {
+		case 0:
+			return address + entry;
+		case 0x80:	/* Not present */
+			printk("bios32_service(0x%lx): not present\n", service);
+			return 0;
+		default: /* Shouldn't happen */
+			printk("bios32_service(0x%lx): returned 0x%x, mail drew@colorado.edu\n",
+				service, return_code);
+			return 0;
+	}
+}
+
+static long pcibios_entry = 0;
+static struct {
+	unsigned long address;
+	unsigned short segment;
+} pci_indirect = { 0, KERNEL_CS };
+
+__initfunc(static int check_pcibios(void))
+{
+	unsigned long signature;
+	unsigned char present_status;
+	unsigned char major_revision;
+	unsigned char minor_revision;
+	unsigned long flags;
+	int pack;
 
-/*
- * access defined pcibios functions via
- * the function table
- */
+	if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
+		pci_indirect.address = pcibios_entry | PAGE_OFFSET;
 
-int pcibios_present(void)
-{
-	return access_pci ? 1 : 0;
+		save_flags(flags); cli();
+		__asm__("lcall (%%edi)\n\t"
+			"jc 1f\n\t"
+			"xor %%ah, %%ah\n"
+			"1:\tshl $8, %%eax\n\t"
+			"movw %%bx, %%ax"
+			: "=d" (signature),
+			  "=a" (pack)
+			: "1" (PCIBIOS_PCI_BIOS_PRESENT),
+			  "D" (&pci_indirect)
+			: "bx", "cx");
+		restore_flags(flags);
+
+		present_status = (pack >> 16) & 0xff;
+		major_revision = (pack >> 8) & 0xff;
+		minor_revision = pack & 0xff;
+		if (present_status || (signature != PCI_SIGNATURE)) {
+			printk ("PCI: %s: BIOS32 Service Directory says PCI BIOS is present,\n"
+				"	but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
+				"	and signature of 0x%08lx (%c%c%c%c).  Mail drew@Colorado.EDU\n",
+				(signature == PCI_SIGNATURE) ?  "WARNING" : "ERROR",
+				present_status, signature,
+				(char) (signature >>  0), (char) (signature >>  8),
+				(char) (signature >> 16), (char) (signature >> 24));
+
+			if (signature != PCI_SIGNATURE)
+				pcibios_entry = 0;
+		}
+		if (pcibios_entry) {
+			printk ("PCI: PCI BIOS revision %x.%02x entry at 0x%lx\n",
+				major_revision, minor_revision, pcibios_entry);
+			return 1;
+		}
+	}
+	return 0;
 }
 
-int pcibios_find_class (unsigned int class_code, unsigned short index,
+static int pci_bios_find_class (unsigned int class_code, unsigned short index,
 	unsigned char *bus, unsigned char *device_fn)
 {
-   if (access_pci && access_pci->find_class)
-      return access_pci->find_class(class_code, index, bus, device_fn);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+	unsigned long bx;
+	unsigned long ret;
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	__asm__ ("lcall (%%edi)\n\t"
+		"jc 1f\n\t"
+		"xor %%ah, %%ah\n"
+		"1:"
+		: "=b" (bx),
+		  "=a" (ret)
+		: "1" (PCIBIOS_FIND_PCI_CLASS_CODE),
+		  "c" (class_code),
+		  "S" ((int) index),
+		  "D" (&pci_indirect));
+	restore_flags(flags);
+	*bus = (bx >> 8) & 0xff;
+	*device_fn = bx & 0xff;
+	return (int) (ret & 0xff00) >> 8;
 }
 
-int pcibios_find_device (unsigned short vendor, unsigned short device_id,
+static int pci_bios_find_device (unsigned short vendor, unsigned short device_id,
 	unsigned short index, unsigned char *bus, unsigned char *device_fn)
 {
-    if (access_pci && access_pci->find_device)
-      return access_pci->find_device(vendor, device_id, index, bus, device_fn);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+	unsigned short bx;
+	unsigned short ret;
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	__asm__("lcall (%%edi)\n\t"
+		"jc 1f\n\t"
+		"xor %%ah, %%ah\n"
+		"1:"
+		: "=b" (bx),
+		  "=a" (ret)
+		: "1" (PCIBIOS_FIND_PCI_DEVICE),
+		  "c" (device_id),
+		  "d" (vendor),
+		  "S" ((int) index),
+		  "D" (&pci_indirect));
+	restore_flags(flags);
+	*bus = (bx >> 8) & 0xff;
+	*device_fn = bx & 0xff;
+	return (int) (ret & 0xff00) >> 8;
 }
 
-int pcibios_read_config_byte (unsigned char bus,
+static int pci_bios_read_config_byte(unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned char *value)
 {
-    if (access_pci && access_pci->read_config_byte)
-      return access_pci->read_config_byte(bus, device_fn, where, value);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+	unsigned long ret;
+	unsigned long bx = (bus << 8) | device_fn;
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	__asm__("lcall (%%esi)\n\t"
+		"jc 1f\n\t"
+		"xor %%ah, %%ah\n"
+		"1:"
+		: "=c" (*value),
+		  "=a" (ret)
+		: "1" (PCIBIOS_READ_CONFIG_BYTE),
+		  "b" (bx),
+		  "D" ((long) where),
+		  "S" (&pci_indirect));
+	restore_flags(flags);
+	return (int) (ret & 0xff00) >> 8;
 }
 
-int pcibios_read_config_word (unsigned char bus,
+static int pci_bios_read_config_word (unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned short *value)
 {
-    if (access_pci && access_pci->read_config_word)
-      return access_pci->read_config_word(bus, device_fn, where, value);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+	unsigned long ret;
+	unsigned long bx = (bus << 8) | device_fn;
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	__asm__("lcall (%%esi)\n\t"
+		"jc 1f\n\t"
+		"xor %%ah, %%ah\n"
+		"1:"
+		: "=c" (*value),
+		  "=a" (ret)
+		: "1" (PCIBIOS_READ_CONFIG_WORD),
+		  "b" (bx),
+		  "D" ((long) where),
+		  "S" (&pci_indirect));
+	restore_flags(flags);
+	return (int) (ret & 0xff00) >> 8;
 }
 
-int pcibios_read_config_dword (unsigned char bus,
+static int pci_bios_read_config_dword (unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned int *value)
 {
-    if (access_pci && access_pci->read_config_dword)
-      return access_pci->read_config_dword(bus, device_fn, where, value);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+	unsigned long ret;
+	unsigned long bx = (bus << 8) | device_fn;
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	__asm__("lcall (%%esi)\n\t"
+		"jc 1f\n\t"
+		"xor %%ah, %%ah\n"
+		"1:"
+		: "=c" (*value),
+		  "=a" (ret)
+		: "1" (PCIBIOS_READ_CONFIG_DWORD),
+		  "b" (bx),
+		  "D" ((long) where),
+		  "S" (&pci_indirect));
+	restore_flags(flags);
+	return (int) (ret & 0xff00) >> 8;
 }
 
-int pcibios_write_config_byte (unsigned char bus,
+static int pci_bios_write_config_byte (unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned char value)
 {
-    if (access_pci && access_pci->write_config_byte)
-      return access_pci->write_config_byte(bus, device_fn, where, value);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+	unsigned long ret;
+	unsigned long bx = (bus << 8) | device_fn;
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	__asm__("lcall (%%esi)\n\t"
+		"jc 1f\n\t"
+		"xor %%ah, %%ah\n"
+		"1:"
+		: "=a" (ret)
+		: "0" (PCIBIOS_WRITE_CONFIG_BYTE),
+		  "c" (value),
+		  "b" (bx),
+		  "D" ((long) where),
+		  "S" (&pci_indirect));
+	restore_flags(flags);
+	return (int) (ret & 0xff00) >> 8;
 }
 
-int pcibios_write_config_word (unsigned char bus,
+static int pci_bios_write_config_word (unsigned char bus,
 	unsigned char device_fn, unsigned char where, unsigned short value)
 {
-    if (access_pci && access_pci->write_config_word)
-      return access_pci->write_config_word(bus, device_fn, where, value);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;    
-}
+	unsigned long ret;
+	unsigned long bx = (bus << 8) | device_fn;
+	unsigned long flags;
 
-int pcibios_write_config_dword (unsigned char bus,
-	unsigned char device_fn, unsigned char where, unsigned int value)
-{
-    if (access_pci && access_pci->write_config_dword)
-      return access_pci->write_config_dword(bus, device_fn, where, value);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+	save_flags(flags); cli();
+	__asm__("lcall (%%esi)\n\t"
+		"jc 1f\n\t"
+		"xor %%ah, %%ah\n"
+		"1:"
+		: "=a" (ret)
+		: "0" (PCIBIOS_WRITE_CONFIG_WORD),
+		  "c" (value),
+		  "b" (bx),
+		  "D" ((long) where),
+		  "S" (&pci_indirect));
+	restore_flags(flags);
+	return (int) (ret & 0xff00) >> 8;
 }
 
-const char *pcibios_strerror (int error)
+static int pci_bios_write_config_dword (unsigned char bus,
+	unsigned char device_fn, unsigned char where, unsigned int value)
 {
-	static char buf[80];
-
-	switch (error) {
-		case PCIBIOS_SUCCESSFUL:
-			return "SUCCESSFUL";
-
-		case PCIBIOS_FUNC_NOT_SUPPORTED:
-			return "FUNC_NOT_SUPPORTED";
-
-		case PCIBIOS_BAD_VENDOR_ID:
-			return "SUCCESSFUL";
-
-		case PCIBIOS_DEVICE_NOT_FOUND:
-			return "DEVICE_NOT_FOUND";
-
-		case PCIBIOS_BAD_REGISTER_NUMBER:
-			return "BAD_REGISTER_NUMBER";
-
-                case PCIBIOS_SET_FAILED:          
-			return "SET_FAILED";
-
-                case PCIBIOS_BUFFER_TOO_SMALL:    
-			return "BUFFER_TOO_SMALL";
+	unsigned long ret;
+	unsigned long bx = (bus << 8) | device_fn;
+	unsigned long flags;
 
-		default:
-			sprintf (buf, "UNKNOWN RETURN 0x%x", error);
-			return buf;
-	}
+	save_flags(flags); cli();
+	__asm__("lcall (%%esi)\n\t"
+		"jc 1f\n\t"
+		"xor %%ah, %%ah\n"
+		"1:"
+		: "=a" (ret)
+		: "0" (PCIBIOS_WRITE_CONFIG_DWORD),
+		  "c" (value),
+		  "b" (bx),
+		  "D" ((long) where),
+		  "S" (&pci_indirect));
+	restore_flags(flags);
+	return (int) (ret & 0xff00) >> 8;
 }
 
+/*
+ * Function table for BIOS32 access
+ */
 
-__initfunc(unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end))
-{
-    return mem_start;
-}
+static struct pci_access pci_bios_access = {
+      1,
+      pci_bios_find_device,
+      pci_bios_find_class,
+      pci_bios_read_config_byte,
+      pci_bios_read_config_word,
+      pci_bios_read_config_dword,
+      pci_bios_write_config_byte,
+      pci_bios_write_config_word,
+      pci_bios_write_config_dword
+};
 
-#endif
+/*
+ * Try to find PCI BIOS.
+ */
 
-__initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end))
+__initfunc(static struct pci_access *pci_find_bios(void))
 {
-#ifdef CONFIG_PCI
 	union bios32 *check;
 	unsigned char sum;
 	int i, length;
@@ -884,7 +832,6 @@
 	 * Follow the standard procedure for locating the BIOS32 Service
 	 * directory by scanning the permissible address range from
 	 * 0xe0000 through 0xfffff for a valid BIOS32 structure.
-	 *
 	 */
 
 	for (check = (union bios32 *) __va(0xe0000);
@@ -901,24 +848,59 @@
 		if (sum != 0)
 			continue;
 		if (check->fields.revision != 0) {
-			printk("pcibios_init : unsupported revision %d at 0x%p, mail drew@colorado.edu\n",
+			printk("PCI: unsupported BIOS32 revision %d at 0x%p, mail drew@colorado.edu\n",
 				check->fields.revision, check);
 			continue;
 		}
-		printk ("pcibios_init : BIOS32 Service Directory structure at 0x%p\n", check);
-		if (!bios32_entry) {
-			if (check->fields.entry >= 0x100000) {
-				printk("pcibios_init: entry in high memory, trying direct PCI access\n");
- 				access_pci = check_direct_pci();
-			} else {
-				bios32_entry = check->fields.entry;
-				printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
-				bios32_indirect.address = bios32_entry + PAGE_OFFSET;
-			}
+		printk ("PCI: BIOS32 Service Directory structure at 0x%p\n", check);
+		if (check->fields.entry >= 0x100000) {
+#ifdef CONFIG_PCI_DIRECT
+			printk("PCI: BIOS32 entry in high memory, trying direct PCI access.\n");
+			return pci_check_direct();
+#else
+			printk("PCI: BIOS32 entry in high memory, cannot use.\n");
+#endif
+		} else {
+			bios32_entry = check->fields.entry;
+			printk ("PCI: BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
+			bios32_indirect.address = bios32_entry + PAGE_OFFSET;
+			if (check_pcibios())
+				return &pci_bios_access;
 		}
+		break;	/* Hopefully more than one BIOS32 cannot happen... */
 	}
-	if (bios32_entry && check_pcibios())
- 		access_pci = &pci_bios_access;
+
+	return NULL;
+}
+
+#endif
+
+/*
+ * No fixup function used.
+ */
+
+__initfunc(unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end))
+{
+    return mem_start;
+}
+
+/*
+ * Initialization. Try all known PCI access methods.
+ */
+
+__initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end))
+{
+	struct pci_access *a = NULL;
+
+#ifdef CONFIG_PCI_BIOS
+	a = pci_find_bios();
+#else
+#ifdef CONFIG_PCI_DIRECT
+	a = pci_check_direct();
 #endif
+#endif
+	if (a)
+		access_pci = a;
+
 	return memory_start;
 }
diff -u --recursive --new-file v2.1.53/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.1.53/linux/arch/i386/kernel/irq.c	Mon Jun 30 15:57:04 1997
+++ linux/arch/i386/kernel/irq.c	Sat Sep  6 10:43:49 1997
@@ -42,8 +42,6 @@
 extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS];
 #endif
 
-#define CR0_NE 32
-
 unsigned int local_irq_count[NR_CPUS];
 #ifdef __SMP__
 atomic_t __intel_bh_counter;
@@ -55,6 +53,8 @@
 static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},};
 #endif
 
+atomic_t nmi_counter;
+
 /*
  * This contains the irq mask for both irq controllers
  */
@@ -199,7 +199,6 @@
  * be shot.
  */
  
-
 static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
 {
 	outb(0,0xF0);
@@ -224,28 +223,26 @@
 
 int get_irq_list(char *buf)
 {
-	int i, len = 0;
+	int i;
 	struct irqaction * action;
+	char *p = buf;
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		action = irq_action[i];
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %10u   %s",
+		p += sprintf(p, "%3d: %10u   %s",
 			i, kstat.interrupts[i], action->name);
 		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ", %s", action->name);
+			p += sprintf(p, ", %s", action->name);
 		}
-		len += sprintf(buf+len, "\n");
+		*p++ = '\n';
 	}
-/*
- *	Linus - should you add NMI counts here ?????
- */
+	p += sprintf(p, "NMI: %10u\n", atomic_read(&nmi_counter));
 #ifdef __SMP_PROF__
-	len+=sprintf(buf+len, "IPI: %8lu received\n",
-		ipi_count);
+	p += sprintf(p, "IPI: %10lu\n", ipi_count);
 #endif		
-	return len;
+	return p - buf;
 }
 
 #ifdef __SMP_PROF__
diff -u --recursive --new-file v2.1.53/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.1.53/linux/arch/i386/kernel/traps.c	Mon Jun 16 16:35:53 1997
+++ linux/arch/i386/kernel/traps.c	Sat Sep  6 10:43:49 1997
@@ -29,6 +29,7 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/spinlock.h>
+#include <asm/atomic.h>
 
 asmlinkage int system_call(void);
 asmlinkage void lcall7(void);
@@ -271,7 +272,9 @@
 asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
 {
 	unsigned char reason = inb(0x61);
+	extern atomic_t nmi_counter;
 
+	atomic_inc(&nmi_counter);
 	if (reason & 0x80)
 		mem_parity_error(reason, regs);
 	if (reason & 0x40)
@@ -348,7 +351,10 @@
 asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
 					  long error_code)
 {
+#if 0
+	/* No need to warn about this any longer. */
 	printk("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
+#endif
 }
 
 /*
diff -u --recursive --new-file v2.1.53/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.1.53/linux/arch/i386/mm/init.c	Mon Aug  4 16:25:35 1997
+++ linux/arch/i386/mm/init.c	Sat Sep  6 10:15:18 1997
@@ -261,6 +261,43 @@
 	return free_area_init(start_mem, end_mem);
 }
 
+/*
+ * Test if the WP bit works in supervisor mode. It isn't supported on 386's
+ * and also on some strange 486's (NexGen etc.). All 586+'s are OK. The jumps
+ * before and after the test are here to work-around some nasty CPU bugs.
+ */
+
+__initfunc(void test_wp_bit(void))
+{
+	unsigned char tmp_reg;
+	unsigned long old = pg0[0];
+
+	printk("Checking if this processor honours the WP bit even in supervisor mode... ");
+	pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY));
+	local_flush_tlb();
+	current->mm->mmap->vm_start += PAGE_SIZE;
+	__asm__ __volatile__(
+		"jmp 1f; 1:\n"
+		"movb %0,%1\n"
+		"movb %1,%0\n"
+		"jmp 1f; 1:\n"
+		:"=m" (*(char *) __va(0)),
+		 "=q" (tmp_reg)
+		:/* no inputs */
+		:"memory");
+	pg0[0] = old;
+	local_flush_tlb();
+	current->mm->mmap->vm_start -= PAGE_SIZE;
+	if (wp_works_ok < 0) {
+		wp_works_ok = 0;
+		printk("No.\n");
+#ifndef CONFIG_M386
+		panic("This kernel doesn't support CPU's with broken WP. Recompile it for a 386!");
+#endif
+	} else
+		printk("Ok.\n");
+}
+
 __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
 {
 	unsigned long start_low_mem = PAGE_SIZE;
@@ -339,30 +376,9 @@
 		reservedpages << (PAGE_SHIFT-10),
 		datapages << (PAGE_SHIFT-10),
 		initpages << (PAGE_SHIFT-10));
-/* test if the WP bit is honoured in supervisor mode */
-	if (wp_works_ok < 0) {
-		unsigned char tmp_reg;
-		unsigned long old = pg0[0];
-		printk("Checking if this processor honours the WP bit even in supervisor mode... ");
-		pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY));
-		local_flush_tlb();
-		current->mm->mmap->vm_start += PAGE_SIZE;
-		__asm__ __volatile__(
-			"movb %0,%1 ; movb %1,%0"
-			:"=m" (*(char *) __va(0)),
-			 "=q" (tmp_reg)
-			:/* no inputs */
-			:"memory");
-		pg0[0] = old;
-		local_flush_tlb();
-		current->mm->mmap->vm_start -= PAGE_SIZE;
-		if (wp_works_ok < 0) {
-			wp_works_ok = 0;
-			printk("No.\n");
-		} else
-			printk("Ok.\n");
-	}
-	return;
+
+	if (wp_works_ok < 0)
+		test_wp_bit();
 }
 
 void free_initmem(void)
diff -u --recursive --new-file v2.1.53/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.1.53/linux/arch/sparc64/defconfig	Thu Sep  4 17:07:30 1997
+++ linux/arch/sparc64/defconfig	Sat Sep  6 10:04:15 1997
@@ -68,7 +68,7 @@
 #
 # Floppy, IDE, and other block devices
 #
-# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_FD=y
 CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=m
 CONFIG_MD_STRIPED=m
diff -u --recursive --new-file v2.1.53/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c
--- v2.1.53/linux/arch/sparc64/kernel/ebus.c	Thu Sep  4 17:07:30 1997
+++ linux/arch/sparc64/kernel/ebus.c	Sat Sep  6 10:04:15 1997
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.7 1997/08/28 02:23:17 ecd Exp $
+/* $Id: ebus.c,v 1.8 1997/09/05 22:59:39 ecd Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -39,16 +39,72 @@
 
 extern unsigned int psycho_irq_build(unsigned int full_ino);
 
-__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev))
+static inline unsigned long
+ebus_alloc(unsigned long *memory_start, size_t size)
+{
+	unsigned long mem;
+
+	*memory_start = (*memory_start + 7) & ~(7);
+	mem = *memory_start;
+	*memory_start += size;
+	return mem;
+}
+
+__initfunc(void fill_ebus_child(int node, struct linux_ebus_child *dev))
+{
+	int regs[PROMREG_MAX];
+	int irqs[PROMREG_MAX];
+	char lbuf[128];
+	int i, len;
+
+	dev->prom_node = node;
+	prom_getstring(node, "name", lbuf, sizeof(lbuf));
+	strcpy(dev->prom_name, lbuf);
+
+	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
+	dev->num_addrs = len / sizeof(regs[0]);
+
+	for (i = 0; i < dev->num_addrs; i++) {
+		if (regs[i] >= dev->parent->num_addrs) {
+			prom_printf("UGH: property for %s was %d, need < %d\n",
+				    dev->prom_name, len, dev->parent->num_addrs);
+			panic(__FUNCTION__);
+		}
+		dev->base_address[i] = dev->parent->base_address[regs[i]];
+	}
+
+	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
+	if ((len == -1) || (len == 0)) {
+		dev->num_irqs = 0;
+	} else {
+		dev->num_irqs = len / sizeof(irqs[0]);
+		for (i = 0; i < dev->num_irqs; i++)
+			dev->irqs[i] = psycho_irq_build(irqs[i]);
+	}
+
+#ifdef DEBUG_FILL_EBUS_DEV
+	printk("child '%s': address%s\n", dev->prom_name,
+	       dev->num_addrs > 1 ? "es" : "");
+	for (i = 0; i < dev->num_addrs; i++)
+		printk("        %016lx\n", dev->base_address[i]);
+	if (dev->num_irqs) {
+		printk("        IRQ%s", dev->num_irqs > 1 ? "s" : "");
+		for (i = 0; i < dev->num_irqs; i++)
+			printk(" %08x", dev->irqs[i]);
+		printk("\n");
+	}
+#endif
+}
+
+__initfunc(unsigned long fill_ebus_device(int node, struct linux_ebus_device *dev,
+					  unsigned long memory_start))
 {
 	struct linux_prom_registers regs[PROMREG_MAX];
+	struct linux_ebus_child *child;
 	int irqs[PROMINTR_MAX];
 	char lbuf[128];
 	int i, n, len;
 
-#ifndef CONFIG_PCI
-	return;
-#endif
 	dev->prom_node = node;
 	prom_getstring(node, "name", lbuf, sizeof(lbuf));
 	strcpy(dev->prom_name, lbuf);
@@ -90,6 +146,27 @@
 		printk("\n");
 	}
 #endif
+	if ((node = prom_getchild(node))) {
+		dev->children = (struct linux_ebus_child *)
+			ebus_alloc(&memory_start, sizeof(struct linux_ebus_child));
+
+		child = dev->children;
+		child->next = 0;
+		child->parent = dev;
+		fill_ebus_child(node, child);
+
+		while ((node = prom_getsibling(node))) {
+			child->next = (struct linux_ebus_child *)
+				ebus_alloc(&memory_start, sizeof(struct linux_ebus_child));
+
+			child = child->next;
+			child->next = 0;
+			child->parent = dev;
+			fill_ebus_child(node, child);
+		}
+	}
+
+	return memory_start;
 }
 
 __initfunc(unsigned long ebus_init(unsigned long memory_start,
@@ -100,31 +177,32 @@
 	struct linux_ebus_device *dev;
 	struct linux_ebus *ebus;
 	struct pci_dev *pdev;
+	struct pcidev_cookie *cookie;
 	char lbuf[128];
 	unsigned long addr, *base;
-	int nd, len, ebusnd, topnd;
+	unsigned short pci_command;
+	int nd, len, ebusnd;
 	int reg, rng, nreg;
-	int devfn;
 	int num_ebus = 0;
 
-#ifndef CONFIG_PCI
-	return memory_start;
-#endif
-
-	memory_start = ((memory_start + 7) & (~7));
-
-	topnd = psycho_root->pbm_B.prom_node;
-	if (!topnd)
+	if (!pcibios_present())
 		return memory_start;
 
-	ebusnd = prom_searchsiblings(prom_getchild(topnd), "ebus");
-	if (ebusnd == 0) {
-		printk("EBUS: No EBUS's found.\n");
+	for (pdev = pci_devices; pdev; pdev = pdev->next) {
+		if ((pdev->vendor == PCI_VENDOR_ID_SUN) &&
+		    (pdev->device == PCI_DEVICE_ID_SUN_EBUS))
+			break;
+	}
+	if (!pdev) {
+		printk("ebus: No EBus's found.\n");
 		return memory_start;
 	}
 
-	ebus_chain = ebus = (struct linux_ebus *)memory_start;
-	memory_start += sizeof(struct linux_ebus);
+	cookie = pdev->sysdata;
+	ebusnd = cookie->prom_node;
+
+	ebus_chain = ebus = (struct linux_ebus *)
+			ebus_alloc(&memory_start, sizeof(struct linux_ebus));
 	ebus->next = 0;
 
 	while (ebusnd) {
@@ -133,7 +211,16 @@
 		prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf));
 		ebus->prom_node = ebusnd;
 		strcpy(ebus->prom_name, lbuf);
-		ebus->parent = pbm = &psycho_root->pbm_B;
+
+		ebus->self = pdev;
+		ebus->parent = pbm = cookie->pbm;
+
+		/* Enable BUS Master. */
+		pcibios_read_config_word(pdev->bus->number, pdev->devfn,
+					 PCI_COMMAND, &pci_command);
+		pci_command |= PCI_COMMAND_MASTER;
+		pcibios_write_config_word(pdev->bus->number, pdev->devfn,
+					  PCI_COMMAND, pci_command);
 
 		len = prom_getproperty(ebusnd, "reg", (void *)regs,
 				       sizeof(regs));
@@ -144,17 +231,6 @@
 		}
 		nreg = len / sizeof(struct linux_prom_pci_registers);
 
-		devfn = (regs[0].phys_hi >> 8) & 0xff;
-		for (pdev = pbm->pci_bus.devices; pdev; pdev = pdev->sibling)
-			if (pdev->devfn == devfn)
-				break;
-		if (!pdev) {
-			prom_printf("%s: can't find PCI device\n",
-				    __FUNCTION__);
-			prom_halt();
-		}
-		ebus->self = pdev;
-
 		base = &ebus->self->base_address[0];
 		for (reg = 0; reg < nreg; reg++) {
 			if (!(regs[reg].phys_hi & 0x03000000))
@@ -181,25 +257,41 @@
 		prom_ebus_ranges_init(ebus);
 
 		nd = prom_getchild(ebusnd);
-		ebus->devices = (struct linux_ebus_device *)memory_start;
-		memory_start += sizeof(struct linux_ebus_device);
+		ebus->devices = (struct linux_ebus_device *)
+			ebus_alloc(&memory_start, sizeof(struct linux_ebus_device));
 
 		dev = ebus->devices;
 		dev->next = 0;
+		dev->children = 0;
 		dev->parent = ebus;
-		fill_ebus_device(nd, dev);
+		memory_start = fill_ebus_device(nd, dev, memory_start);
 
 		while ((nd = prom_getsibling(nd))) {
-			dev->next = (struct linux_ebus_device *)memory_start;
-			memory_start += sizeof(struct linux_ebus_device);
+			dev->next = (struct linux_ebus_device *)
+				ebus_alloc(&memory_start, sizeof(struct linux_ebus_device));
 
 			dev = dev->next;
 			dev->next = 0;
+			dev->children = 0;
 			dev->parent = ebus;
-			fill_ebus_device(nd, dev);
+			memory_start = fill_ebus_device(nd, dev, memory_start);
 		}
 
-		ebusnd = prom_searchsiblings(prom_getsibling(ebusnd), "ebus");
+		for (pdev = pdev->next; pdev; pdev = pdev->next) {
+			if ((pdev->vendor == PCI_VENDOR_ID_SUN) &&
+			    (pdev->device == PCI_DEVICE_ID_SUN_EBUS))
+				break;
+		}
+		if (!pdev)
+			break;
+
+		cookie = pdev->sysdata;
+		ebusnd = cookie->prom_node;
+
+		ebus->next = (struct linux_ebus *)
+			ebus_alloc(&memory_start, sizeof(struct linux_ebus));
+		ebus = ebus->next;
+		ebus->next = 0;
 		++num_ebus;
 	}
 
diff -u --recursive --new-file v2.1.53/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.1.53/linux/arch/sparc64/kernel/ioctl32.c	Thu Sep  4 17:07:30 1997
+++ linux/arch/sparc64/kernel/ioctl32.c	Sat Sep  6 10:04:15 1997
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.17 1997/09/03 11:54:49 ecd Exp $
+/* $Id: ioctl32.c,v 1.18 1997/09/06 02:25:13 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -33,13 +33,6 @@
 #include <asm/rtc.h>
 #include <asm/openpromio.h>
 
-/*
- * XXX: for DaveM:
- * This is the kludge to know what size of buffer to
- * copy back to the user... (ecd)
- */
-int ifr_data_len;
-
 /* As gcc will warn about casting u32 to some ptr, we have to cast it to
  * unsigned long first, and that's what is A() for.
  * You just do (void *)A(x), instead of having to type (void *)((unsigned long)x)
@@ -203,13 +196,17 @@
 		case SIOCGPPPVER:
 		{
 			u32 data;
+			int len;
+
 			__get_user(data, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_data));
-			/*
-			 * XXX: for DaveM:
-			 * Here we use 'ifr_data_len' to know what size of buffer to
-			 * copy back to the user... (ecd)
-			 */
-			if (copy_to_user((char *)A(data), ifr.ifr_data, ifr_data_len))
+			if(cmd == SIOCGPPPVER)
+				len = strlen(PPP_VERSION) + 1;
+			else if(cmd == SIOCGPPPCSTATS)
+				len = sizeof(struct ppp_comp_stats);
+			else
+				len = sizeof(struct ppp_stats);
+
+			if (copy_to_user((char *)A(data), ifr.ifr_data, len))
 				return -EFAULT;
 			break;
 		}
diff -u --recursive --new-file v2.1.53/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.1.53/linux/drivers/block/floppy.c	Mon Aug 18 18:19:45 1997
+++ linux/drivers/block/floppy.c	Sat Sep  6 10:09:56 1997
@@ -161,11 +161,6 @@
 #include <linux/blk.h>
 #include <linux/cdrom.h> /* for the compatibility eject ioctl */
 
-
-#ifndef FLOPPY_MOTOR_MASK
-#define FLOPPY_MOTOR_MASK 0xf0
-#endif
-
 #ifndef fd_get_dma_residue
 #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
 #endif
diff -u --recursive --new-file v2.1.53/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v2.1.53/linux/drivers/block/hd.c	Tue May 13 22:41:04 1997
+++ linux/drivers/block/hd.c	Sat Sep  6 10:08:56 1997
@@ -584,7 +584,7 @@
 	unsigned int cmd, unsigned long arg)
 {
 	struct hd_geometry *loc = (struct hd_geometry *) arg;
-	int dev, err;
+	int dev;
 
 	if ((!inode) || !(inode->i_rdev))
 		return -EINVAL;
@@ -593,19 +593,15 @@
 		return -EINVAL;
 	switch (cmd) {
 		case HDIO_GETGEO:
+		{
+			struct hd_geometry g; 
 			if (!loc)  return -EINVAL;
-			err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
-			if (err)
-				return err;
-			put_user(hd_info[dev].head,
-				(char *) &loc->heads);
-			put_user(hd_info[dev].sect,
-				(char *) &loc->sectors);
-			put_user(hd_info[dev].cyl,
-				(short *) &loc->cylinders);
-			put_user(hd[MINOR(inode->i_rdev)].start_sect,
-				(long *) &loc->start);
-			return 0;
+			g.heads = hd_info[dev].head;
+			g.sectors = hd_info[dev].sect;
+			g.cylinders = hd_info[dev].cyl;
+			g.start = hd[MINOR(inode->i_rdev)].start_sect;
+			return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
+		}
 		case BLKRASET:
 			if(!suser())  return -EACCES;
 			if(arg > 0xff) return -EINVAL;
@@ -613,18 +609,12 @@
 			return 0;
 		case BLKRAGET:
 			if (!arg)  return -EINVAL;
-			err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-			if (err)
-				return err;
-			put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);
-			return 0;
+			return put_user(read_ahead[MAJOR(inode->i_rdev)],
+					(long *) arg); 
          	case BLKGETSIZE:   /* Return device size */
 			if (!arg)  return -EINVAL;
-			err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-			if (err)
-				return err;
-			put_user(hd[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
-			return 0;
+			return put_user(hd[MINOR(inode->i_rdev)].nr_sects, 
+					(long *) arg);
 		case BLKFLSBUF:
 			if(!suser())  return -EACCES;
 			fsync_dev(inode->i_rdev);
@@ -817,7 +807,7 @@
 
 /*
  * This routine is called to flush all partitions and partition tables
- * for a changed scsi disk, and then re-read the new partition table.
+ * for a changed disk, and then re-read the new partition table.
  * If we are revalidating a disk because of a media change, then we
  * enter with usage == 0.  If we are using an ioctl, we automatically have
  * usage == 1 (we need an open channel to use an ioctl :-), so this
@@ -850,8 +840,11 @@
 	for (i=max_p - 1; i >=0 ; i--) {
 		int minor = start + i;
 		kdev_t devi = MKDEV(MAJOR_NR, minor);
+		struct super_block *sb = get_super(devi); 
+
 		sync_dev(devi);
-		invalidate_inodes(devi);
+		if (sb)
+			invalidate_inodes(sb);
 		invalidate_buffers(devi);
 		gdev->part[minor].start_sect = 0;
 		gdev->part[minor].nr_sects = 0;
diff -u --recursive --new-file v2.1.53/linux/drivers/block/raid0.c linux/drivers/block/raid0.c
--- v2.1.53/linux/drivers/block/raid0.c	Sun May 19 21:50:46 1996
+++ linux/drivers/block/raid0.c	Sat Sep  6 10:07:51 1997
@@ -20,13 +20,13 @@
 #include <linux/module.h>
 #include <linux/md.h>
 #include <linux/raid0.h>
-#include <linux/malloc.h>
+#include <linux/vmalloc.h>
 
 #define MAJOR_NR MD_MAJOR
 #define MD_DRIVER
 #define MD_PERSONALITY
 
-static void create_strip_zones (int minor, struct md_dev *mddev)
+static int create_strip_zones (int minor, struct md_dev *mddev)
 {
   int i, j, c=0;
   int current_offset=0;
@@ -50,8 +50,8 @@
     c=0;
   }
 
-  data->strip_zone=kmalloc (sizeof(struct strip_zone)*data->nr_strip_zones,
-			      GFP_KERNEL);
+  if ((data->strip_zone=vmalloc(sizeof(struct strip_zone)*data->nr_strip_zones)) == NULL)
+    return 1;
 
   data->smallest=NULL;
   
@@ -81,6 +81,7 @@
 					   data->strip_zone[i-1].size) : 0;
     current_offset=smallest_by_zone->size;
   }
+  return 0;
 }
 
 static int raid0_run (int minor, struct md_dev *mddev)
@@ -90,17 +91,26 @@
 
   MOD_INC_USE_COUNT;
 
-  mddev->private=kmalloc (sizeof (struct raid0_data), GFP_KERNEL);
+  if ((mddev->private=vmalloc (sizeof (struct raid0_data))) == NULL) return 1;
   data=(struct raid0_data *) mddev->private;
   
-  create_strip_zones (minor, mddev);
+  if (create_strip_zones (minor, mddev)) 
+  {
+  	vfree(data);
+  	return 1;
+  }
 
   nb_zone=data->nr_zones=
     md_size[minor]/data->smallest->size +
     (md_size[minor]%data->smallest->size ? 1 : 0);
-  
-  data->hash_table=kmalloc (sizeof (struct raid0_hash)*nb_zone, GFP_KERNEL);
 
+  printk ("raid0 : Allocating %d bytes for hash.\n",sizeof(struct raid0_hash)*nb_zone);
+  if ((data->hash_table=vmalloc (sizeof (struct raid0_hash)*nb_zone)) == NULL)
+  {
+    vfree(data->strip_zone);
+    vfree(data);
+    return 1;
+  }
   size=data->strip_zone[cur].size;
 
   i=0;
@@ -142,9 +152,9 @@
 {
   struct raid0_data *data=(struct raid0_data *) mddev->private;
 
-  kfree (data->hash_table);
-  kfree (data->strip_zone);
-  kfree (data);
+  vfree (data->hash_table);
+  vfree (data->strip_zone);
+  vfree (data);
 
   MOD_DEC_USE_COUNT;
   return 0;
diff -u --recursive --new-file v2.1.53/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.1.53/linux/drivers/block/rd.c	Thu Jul 17 10:06:04 1997
+++ linux/drivers/block/rd.c	Sat Sep  6 10:23:14 1997
@@ -447,7 +447,7 @@
  	struct inode inode, out_inode;
 	struct file infile, outfile;
 	struct dentry in_dentry, out_dentry;
-	unsigned short fs;
+	unsigned long fs;
 	kdev_t ram_device;
 	int nblocks, i;
 	char *buf;
diff -u --recursive --new-file v2.1.53/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.1.53/linux/drivers/char/Config.in	Thu Aug 14 20:49:16 1997
+++ linux/drivers/char/Config.in	Sat Sep  6 10:16:07 1997
@@ -101,8 +101,10 @@
   fi
   tristate '   Software Watchdog' CONFIG_SOFT_WATCHDOG
   tristate '   Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
+  tristate '   Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
 fi
 bool 'Enhanced Real Time Clock Support' CONFIG_RTC
+bool 'Tadpole ANA H8 Support'  CONFIG_H8
 tristate '/dev/nvram support' CONFIG_NVRAM
 tristate 'PC joystick support' CONFIG_JOYSTICK
 endmenu
diff -u --recursive --new-file v2.1.53/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.1.53/linux/drivers/char/Makefile	Thu Aug 14 20:49:16 1997
+++ linux/drivers/char/Makefile	Sat Sep  6 10:16:07 1997
@@ -204,6 +204,16 @@
   endif
 endif
 
+ifeq ($(CONFIG_ACQUIRE_WDT),y)
+M = y
+L_OBJS += acquirewdt.o
+else
+  ifeq ($(CONFIG_ACQUIRE_WDT),m)
+  M_OBJS += acquirewdt.o
+  MM = m
+  endif
+endif
+
 ifeq ($(CONFIG_AMIGAMOUSE),y)
 M = y
 L_OBJS += amigamouse.o
@@ -290,6 +300,11 @@
 
 ifdef CONFIG_APM
 LX_OBJS += apm_bios.o
+M = y
+endif
+
+ifdef CONFIG_H8
+LX_OBJS += h8.o
 M = y
 endif
 
diff -u --recursive --new-file v2.1.53/linux/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c
--- v2.1.53/linux/drivers/char/acquirewdt.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/acquirewdt.c	Sat Sep  6 10:16:07 1997
@@ -0,0 +1,221 @@
+/*
+ *	Acquire Single Board Computer Watchdog Timer driver for Linux 2.1.x
+ *
+ *      Based on wdt.c. Original copyright messages:
+ *
+ *	(c) Copyright 1996 Alan Cox <alan@cymru.net>, All Rights Reserved.
+ *				http://www.cymru.net
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *	
+ *	Neither Alan Cox nor CymruNet Ltd. admit liability nor provide 
+ *	warranty for any of this software. This material is provided 
+ *	"AS-IS" and at no charge.	
+ *
+ *	(c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/malloc.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+static int acq_is_open=0;
+
+/*
+ *	You must set these - there is no sane way to probe for this board.
+ */
+ 
+#define WDT_STOP 0x43
+#define WDT_START 0x443
+#define WATCHDOG_MINOR 130
+
+#define WD_TIMO (100*60)		/* 1 minute */
+
+
+/*
+ *	Kernel methods.
+ */
+ 
+
+static void acq_ping(void)
+{
+	/* Write a watchdog value */
+	inb_p(WDT_START);
+}
+
+static long acq_write(struct inode *inode, struct file *file, const char *buf, unsigned long count)
+{
+	if(count)
+	{
+		acq_ping();
+		return 1;
+	}
+	return 0;
+}
+
+static long acq_read(struct inode *inode, struct file *file, char *buf, unsigned long count)
+{
+	return -EINVAL;
+}
+
+
+
+static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	static struct watchdog_info ident=
+	{
+		WDIOF_KEEPALIVEPING, 1, "Acquire WDT"
+	};
+	
+	switch(cmd)
+	{
+	case WDIOC_GETSUPPORT:
+	  if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+	    return -EFAULT;
+	  break;
+	  
+	case WDIOC_GETSTATUS:
+	  if (copy_to_user((int *)arg, &acq_is_open,  sizeof(int)))
+	    return -EFAULT;
+	  break;
+
+	case WDIOC_KEEPALIVE:
+	  acq_ping();
+	  break;
+
+	default:
+	  return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static int acq_open(struct inode *inode, struct file *file)
+{
+	switch(MINOR(inode->i_rdev))
+	{
+		case WATCHDOG_MINOR:
+			if(acq_is_open)
+				return -EBUSY;
+			MOD_INC_USE_COUNT;
+			/*
+			 *	Activate 
+			 */
+	 
+			acq_is_open=1;
+			inb_p(WDT_START);      
+			return 0;
+		default:
+			return -ENODEV;
+	}
+}
+
+static int acq_close(struct inode *inode, struct file *file)
+{
+	if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
+	{
+#ifndef CONFIG_WATCHDOG_NOWAYOUT	
+		inb_p(WDT_STOP);
+#endif		
+		acq_is_open=0;
+	}
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/*
+ *	Notifier for system down
+ */
+
+static int acq_notify_sys(struct notifier_block *this, unsigned long code,
+	void *unused)
+{
+	if(code==SYS_DOWN || code==SYS_HALT)
+	{
+		/* Turn the card off */
+		inb_p(WDT_STOP);
+	}
+	return NOTIFY_DONE;
+}
+ 
+/*
+ *	Kernel Interfaces
+ */
+ 
+ 
+static struct file_operations acq_fops = {
+	NULL,
+	acq_read,
+	acq_write,
+	NULL,		/* No Readdir */
+	NULL,		/* No Select */
+	acq_ioctl,
+	NULL,		/* No mmap */
+	acq_open,
+	acq_close
+};
+
+static struct miscdevice acq_miscdev=
+{
+	WATCHDOG_MINOR,
+	"Acquire WDT",
+	&acq_fops
+};
+
+
+/*
+ *	The WDT card needs to learn about soft shutdowns in order to
+ *	turn the timebomb registers off. 
+ */
+ 
+static struct notifier_block acq_notifier=
+{
+	acq_notify_sys,
+	NULL,
+	0
+};
+
+#ifdef MODULE
+
+#define acq_init init_module
+
+void cleanup_module(void)
+{
+	misc_deregister(&acq_miscdev);
+	unregister_reboot_notifier(&acq_notifier);
+	release_region(WDT_STOP,1);
+	release_region(WDT_START,1);
+}
+
+#endif
+
+__initfunc(int acq_init(void))
+{
+	printk("WDT driver for Acquire single board computer initialising.\n");
+
+	misc_register(&acq_miscdev);
+	request_region(WDT_STOP, 1, "Acquire WDT");
+	request_region(WDT_START, 1, "Acquire WDT");
+	unregister_reboot_notifier(&acq_notifier);
+	return 0;
+}
+
diff -u --recursive --new-file v2.1.53/linux/drivers/char/h8.c linux/drivers/char/h8.c
--- v2.1.53/linux/drivers/char/h8.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/h8.c	Sat Sep  6 10:16:07 1997
@@ -0,0 +1,1272 @@
+/*
+ */
+/*
+ * Hitachi H8/337 Microcontroller driver
+ *
+ * The H8 is used to deal with the power and thermal environment
+ * of a system.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/timer.h>
+#include <linux/fcntl.h>
+#include <linux/malloc.h>
+#include <linux/linkage.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+#endif
+#include <linux/miscdevice.h>
+#include <linux/lists.h>
+#include <linux/ioport.h>
+
+#define __KERNEL_SYSCALLS__
+#include <asm/unistd.h>
+
+#include "h8.h"
+
+#define DEBUG_H8
+
+#ifdef DEBUG_H8
+#define Dprintk		printk
+#else
+#define Dprintk
+#endif
+
+#define XDprintk if(h8_debug==-1)printk
+
+/*
+ * The h8 device is one of the misc char devices.
+ */
+#define H8_MINOR_DEV   140
+
+/*
+ * Forward declarations.
+ */
+int          h8_init(void);
+int          h8_display_blank(void);
+int          h8_display_unblank(void);
+
+static int   h8_open(struct inode *, struct file *);
+static void  h8_release(struct inode *, struct file *);
+static long  h8_read(struct inode *, struct file *, char *, u_long);
+static int   h8_select(struct inode *, struct file *, int, select_table *);
+static int   h8_ioctl(struct inode *, struct file *, u_int, u_long);
+
+static void  h8_intr(int irq, void *dev_id, struct pt_regs *regs);
+
+#ifdef CONFIG_PROC_FS
+static int   h8_get_info(char *, char **, off_t, int, int);
+#endif
+
+/*
+ * Support Routines.
+ */
+static void h8_hw_init(void);
+static void h8_start_new_cmd(void);
+static void h8_send_next_cmd_byte(void);
+static void h8_read_event_status(void);
+static void h8_sync(void);
+static void h8_q_cmd(u_char *, int, int);
+static void h8_cmd_done(h8_cmd_q_t *qp);
+static int  h8_alloc_queues(void);
+
+static u_long h8_get_cpu_speed(void);
+static int h8_get_curr_temp(u_char curr_temp[]);
+static void h8_get_max_temp(void);
+static void h8_get_upper_therm_thold(void);
+static void h8_set_upper_therm_thold(int);
+static int h8_get_ext_status(u_char stat_word[]);
+
+static int h8_monitor_thread(void *);
+
+static int h8_manage_therm(void);
+static void h8_set_cpu_speed(int speed_divisor);
+
+static void h8_start_monitor_timer(unsigned long secs);
+static void h8_activate_monitor(unsigned long unused);
+
+/* in arch/alpha/kernel/lca.c */
+extern void lca_clock_print(void);
+extern int  lca_get_clock(void);
+extern void lca_clock_fiddle(int);
+
+static void h8_set_event_mask(int);
+static void h8_clear_event_mask(int);
+
+/*
+ * Driver structures
+ */
+
+static struct timer_list h8_monitor_timer;
+static int h8_monitor_timer_active = 0;
+
+static char  driver_version[] = "X0.0";/* no spaces */
+
+static struct file_operations h8_fops = {
+        NULL,           /* lseek */
+        h8_read,
+        NULL,           /* write */
+        NULL,           /* readdir */
+        h8_select,
+        h8_ioctl,
+        NULL,           /* mmap */
+        h8_open,
+        h8_release,
+        NULL,           /* fsync */
+        NULL            /* fasync */
+};
+
+static struct miscdevice h8_device = {
+        H8_MINOR_DEV,
+        "h8",
+        &h8_fops
+};
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry    h8_proc_entry = {
+        0, 3, "h8", S_IFREG | S_IRUGO, 1, 0, 0, 0, 0, h8_get_info
+};
+#endif
+
+union	intr_buf intrbuf;
+int	intr_buf_ptr;
+union   intr_buf xx;	
+u_char  last_temp;
+
+/*
+ * I/O Macros for register reads and writes.
+ */
+#define H8_READ(a) 	inb((a))
+#define H8_WRITE(d,a)	outb((d),(a))
+
+#define	H8_GET_STATUS	H8_READ((h8_base) + H8_STATUS_REG_OFF)
+#define H8_READ_DATA	H8_READ((h8_base) + H8_DATA_REG_OFF)
+#define WRITE_DATA(d)	H8_WRITE((d), h8_base + H8_DATA_REG_OFF)
+#define WRITE_CMD(d)	H8_WRITE((d), h8_base + H8_CMD_REG_OFF)
+
+unsigned int h8_base = H8_BASE_ADDR;
+unsigned int h8_irq = H8_IRQ;
+unsigned int h8_state = H8_IDLE;
+unsigned int h8_index = -1;
+unsigned int h8_enabled = 0;
+
+queue_head_t h8_actq, h8_cmdq, h8_freeq;
+
+/* 
+ * Globals used in thermal control of Alphabook1.
+ */
+int cpu_speed_divisor = -1;			
+int h8_event_mask = 0;			
+struct wait_queue *h8_monitor_wait = NULL;
+unsigned int h8_command_mask = 0;
+int h8_uthermal_threshold = DEFAULT_UTHERMAL_THRESHOLD;
+int h8_uthermal_window = UTH_HYSTERESIS;		      
+int h8_debug = 0xfffffdfc;
+int h8_ldamp = MHZ_115;
+int h8_udamp = MHZ_57;
+u_char h8_current_temp = 0;
+u_char h8_system_temp = 0;
+int h8_sync_channel = 0;
+struct wait_queue *h8_sync_wait = NULL;
+int h8_init_performed;
+
+/* CPU speeds and clock divisor values */
+int speed_tab[6] = {230, 153, 115, 57, 28, 14};
+  
+/*
+ * H8 interrupt handler
+ */
+static void h8_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u_char	stat_reg, data_reg;
+	h8_cmd_q_t *qp = (h8_cmd_q_t *)QUEUE_FIRST(&h8_actq, link);
+
+	stat_reg = H8_GET_STATUS;
+	data_reg = H8_READ_DATA;
+
+	XDprintk("h8_intr: state %d status 0x%x data 0x%x\n", h8_state, stat_reg, data_reg);
+
+	switch (h8_state) {
+	  /* Response to an asynchronous event. */
+	case H8_IDLE: { /* H8_IDLE */
+	    if (stat_reg & H8_OFULL) {
+	        if (data_reg == H8_INTR) {
+		    h8_state = H8_INTR_MODE;
+		    /* Executing a command to determine what happened. */
+		    WRITE_CMD(H8_RD_EVENT_STATUS);
+		    intr_buf_ptr = 1;
+		    WRITE_CMD(H8_RD_EVENT_STATUS);
+		} else {
+		    Dprintk("h8_intr: idle stat 0x%x data 0x%x\n",
+			    stat_reg, data_reg);
+		}
+	    } else {
+	        Dprintk("h8_intr: bogus interrupt\n");
+	    }
+	    break;
+	}
+	case H8_INTR_MODE: { /* H8_INTR_MODE */
+	    XDprintk("H8 intr/intr_mode\n");
+	    if (data_reg == H8_BYTE_LEVEL_ACK) {
+	        return;
+	    } else if (data_reg == H8_CMD_ACK) {
+	        return;
+	    } else {
+	        intrbuf.byte[intr_buf_ptr] = data_reg;
+		if(!intr_buf_ptr) {
+		    h8_state = H8_IDLE;
+		    h8_read_event_status();
+		}
+		intr_buf_ptr--;
+	    }
+	    break;
+	}
+	/* Placed in this state by h8_start_new_cmd(). */
+	case H8_XMIT: { /* H8_XMIT */
+	    XDprintk("H8 intr/xmit\n");
+	    /* If a byte level acknowledgement has been received */
+	    if (data_reg == H8_BYTE_LEVEL_ACK) {
+	        XDprintk("H8 intr/xmit BYTE ACK\n");
+		qp->nacks++;
+		if (qp->nacks > qp->ncmd)
+		    if(h8_debug & 0x1)
+		        Dprintk("h8intr: bogus # of acks!\n");
+		/* 
+		 * If the number of bytes sent is less than the total 
+		 * number of bytes in the command.
+		 */ 
+		if (qp->cnt < qp->ncmd) {
+		    h8_send_next_cmd_byte();
+		}
+		return;
+		/* If the complete command has produced an acknowledgement. */
+	    } else if (data_reg == H8_CMD_ACK) {
+	        XDprintk("H8 intr/xmit CMD ACK\n");
+		/* If there are response bytes */
+		if (qp->nrsp)
+		    h8_state = H8_RCV;
+		else
+		    h8_state = H8_IDLE;
+		qp->cnt = 0;
+		return;
+		/* Error, need to start over with a clean slate. */
+	    } else if (data_reg == H8_NACK) {
+	        XDprintk("h8_intr: NACK received restarting command\n");
+		qp->nacks = 0;
+		qp->cnt = 0;
+		h8_state = H8_IDLE;
+		WRITE_CMD(H8_SYNC);
+		return;
+	    } else {
+	        Dprintk ("h8intr: xmit unknown data 0x%x \n", data_reg);
+		return;
+	    }
+	    break;
+	}
+	case H8_RESYNC: { /* H8_RESYNC */
+	    XDprintk("H8 intr/resync\n");
+	    if (data_reg == H8_BYTE_LEVEL_ACK) {
+	        return;
+	    } else if (data_reg == H8_SYNC_BYTE) {
+	        h8_state = H8_IDLE;
+		if (!QUEUE_EMPTY(&h8_actq, link))
+		    h8_send_next_cmd_byte();
+	    } else {
+	        Dprintk ("h8_intr: resync unknown data 0x%x \n", data_reg);
+		return;
+	    }
+	    break;
+	} 
+	case H8_RCV: { /* H8_RCV */
+	    XDprintk("H8 intr/rcv\n");
+	    if (qp->cnt < qp->nrsp) {
+	        qp->rcvbuf[qp->cnt] = data_reg;
+		qp->cnt++;
+		/* If command reception finished. */
+		if (qp->cnt == qp->nrsp) {
+		    h8_state = H8_IDLE;
+		    QUEUE_REMOVE(&h8_actq, qp, link);
+		    h8_cmd_done (qp);
+		    /* More commands to send over? */
+		    if (!QUEUE_EMPTY(&h8_cmdq, link))
+		        h8_start_new_cmd();
+		}
+		return;
+	    } else {
+	        Dprintk ("h8intr: rcv overflow cmd 0x%x\n", qp->cmdbuf[0]);
+	    }
+	    break;
+	}
+	default: /* default */
+	    Dprintk("H8 intr/unknown\n");
+	    break;
+	}
+	return;
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+        printk("H8 module at %X(Interrupt %d)\n", h8_base, h8_irq);
+        if(request_irq(h8_irq, h8_intr, SA_INTERRUPT, "h8", NULL))
+        {
+                printk("H8: error: IRQ %d is not free.\n", h8_irq);
+                return -EIO;
+        }
+
+        misc_register(&h8_device);
+        request_region(h8_base, 8, "h8");
+
+#ifdef CONFIG_PROC_FS
+        proc_register_dynamic(&proc_root, &h8_proc_entry);
+#endif
+
+	QUEUE_INIT(&h8_actq, link, h8_cmd_q_t *);
+	QUEUE_INIT(&h8_cmdq, link, h8_cmd_q_t *);
+	QUEUE_INIT(&h8_freeq, link, h8_cmd_q_t *);
+	h8_alloc_queues();
+
+	h8_hw_init();
+
+	kernel_thread(h8_monitor_thread, NULL, 0);
+
+        return 0;
+}
+
+void cleanup_module(void)
+{
+        misc_deregister(&h8_device);
+        release_region(h8_base, 8);
+        free_irq(h8_irq, NULL);
+}
+
+#else /* MODULE */
+
+int h8_init(void)
+{
+        if(request_irq(h8_irq, h8_intr, SA_INTERRUPT, "h8", NULL))
+        {
+                printk("H8: error: IRQ %d is not free\n", h8_irq);
+                return -EIO;
+        }
+        printk("H8 at 0x%x IRQ %d\n", h8_base, h8_irq);
+
+#ifdef CONFIG_PROC_FS
+        proc_register_dynamic(&proc_root, &h8_proc_entry);
+#endif
+
+        misc_register(&h8_device);
+        request_region(h8_base, 8, "h8");
+
+	QUEUE_INIT(&h8_actq, link, h8_cmd_q_t *);
+	QUEUE_INIT(&h8_cmdq, link, h8_cmd_q_t *);
+	QUEUE_INIT(&h8_freeq, link, h8_cmd_q_t *);
+	h8_alloc_queues();
+
+	h8_hw_init();
+
+	kernel_thread(h8_monitor_thread, NULL, 0);
+
+        return 0;
+}
+#endif /* MODULE */
+
+void h8_hw_init(void)
+{
+	u_char	buf[H8_MAX_CMD_SIZE];
+
+	/* set CPU speed to max for booting */
+	h8_set_cpu_speed(MHZ_230);
+
+	/*
+	 * Initialize the H8
+	 */
+	h8_sync();  /* activate interrupts */
+
+	/* To clear conditions left by console */
+	h8_read_event_status(); 
+
+	/* Perform a conditioning read */
+	buf[0] = H8_DEVICE_CONTROL;
+	buf[1] = 0xff;
+	buf[2] = 0x0;
+	h8_q_cmd(buf, 3, 1);
+
+	/* Turn on built-in and external mice, capture power switch */
+	buf[0] = H8_DEVICE_CONTROL;
+	buf[1] = 0x0;
+	buf[2] = H8_ENAB_INT_PTR | H8_ENAB_EXT_PTR |
+	       /*H8_DISAB_PWR_OFF_SW |*/ H8_ENAB_LOW_SPD_IND;
+	h8_q_cmd(buf, 3, 1);
+
+        h8_enabled = 1;
+	return;
+}
+
+#ifdef CONFIG_PROC_FS
+int h8_get_info(char *buf, char **start, off_t fpos, int length, int dummy)
+{
+        char *p;
+
+        if (!h8_enabled)
+                return 0;
+        p = buf;
+
+
+        /*
+           0) Linux driver version (this will change if format changes)
+           1) 
+           2) 
+           3)
+           4)
+	*/
+            
+        p += sprintf(p, "%s \n",
+                     driver_version
+		     );
+
+        return p - buf;
+}
+#endif
+
+static long h8_read(struct inode *inode, struct file *fp, char *buf,
+		    u_long count)
+{
+	printk("h8_read: IMPDEL\n");
+	return 0;
+}
+
+static int h8_select(struct inode *inode, struct file *fp, int sel_type,
+                     select_table * wait)
+{
+	printk("h8_select: IMPDEL\n");
+	return 0;
+}
+
+static int h8_ioctl(struct inode * inode, struct file *filp,
+                    u_int cmd, u_long arg)
+{
+	printk("h8_ioctl: IMPDEL\n");
+	return 0;
+}
+
+static void h8_release(struct inode * inode, struct file * filp)
+{
+	printk("h8_release: IMPDEL\n");
+}
+
+static int h8_open(struct inode * inode, struct file * filp)
+{
+	printk("h8_open: IMPDEL\n");
+	return 0;
+}
+
+/* Called from console driver -- must make sure h8_enabled. */
+int h8_display_blank(void)
+{
+#ifdef CONFIG_H8_DISPLAY_BLANK
+        int     error;
+
+        if (!h8_enabled)
+                return 0;
+        error = h8_set_display_power_state(H8_STATE_STANDBY);
+        if (error == H8_SUCCESS)
+                return 1;
+        h8_error("set display standby", error);
+#endif
+        return 0;
+}
+
+/* Called from console driver -- must make sure h8_enabled. */
+int h8_display_unblank(void)
+{
+#ifdef CONFIG_H8_DISPLAY_BLANK
+        int error;
+
+        if (!h8_enabled)
+                return 0;
+        error = h8_set_display_power_state(H8_STATE_READY);
+        if (error == H8_SUCCESS)
+                return 1;
+        h8_error("set display ready", error);
+#endif
+        return 0;
+}
+
+int
+h8_alloc_queues(void)
+{
+        h8_cmd_q_t *qp;
+	unsigned long flags;
+        int i;
+
+        qp = (h8_cmd_q_t *)kmalloc((sizeof (h8_cmd_q_t) * H8_Q_ALLOC_AMOUNT),
+				   GFP_KERNEL);
+
+        if (!qp) {
+                printk("H8: could not allocate memory for command queue\n");
+                return(0);
+        }
+        /* add to the free queue */
+        save_flags(flags); cli();
+        for (i = 0; i < H8_Q_ALLOC_AMOUNT; i++) {
+                /* place each at front of freeq */
+                QUEUE_ENTER(&h8_freeq, &qp[i], link, h8_cmd_q_t *);
+        }
+        restore_flags(flags);
+        return (1);
+}
+
+/* 
+ * Basic means by which commands are sent to the H8.
+ */
+void
+h8_q_cmd(u_char *cmd, int cmd_size, int resp_size)
+{
+        h8_cmd_q_t      *qp;
+	unsigned long flags;
+        int             i;
+
+        /* get cmd buf */
+	save_flags(flags); cli();
+        while (QUEUE_EMPTY(&h8_freeq, link)) {
+                Dprintk("H8: need to allocate more cmd buffers\n");
+                restore_flags(flags);
+                h8_alloc_queues();
+                save_flags(flags); cli();
+        }
+        /* get first element from queue */
+        qp = (h8_cmd_q_t *)QUEUE_FIRST(&h8_freeq, link);
+        QUEUE_REMOVE(&h8_freeq, qp, link);
+
+        restore_flags(flags);
+
+        /* fill it in */
+        for (i = 0; i < cmd_size; i++)
+            qp->cmdbuf[i] = cmd[i];
+        qp->ncmd = cmd_size;
+        qp->nrsp = resp_size;
+
+        /* queue it at the end of the cmd queue */
+        save_flags(flags); cli();
+
+        QUEUE_ENTER(&h8_cmdq, qp, link, h8_cmd_q_t *);
+
+        restore_flags(flags);
+
+        h8_start_new_cmd();
+}
+
+void
+h8_start_new_cmd(void)
+{
+        unsigned long flags;
+        h8_cmd_q_t *qp;
+
+	save_flags(flags); cli();
+        if (h8_state != H8_IDLE) {
+                if (h8_debug & 0x1)
+                        Dprintk("h8_start_new_cmd: not idle\n");
+                restore_flags(flags);
+                return;
+        }
+
+        if (!QUEUE_EMPTY(&h8_actq, link)) {
+                Dprintk("h8_start_new_cmd: inconsistency: IDLE with non-empty active queue!\n");
+                restore_flags(flags);
+                return;
+        }
+
+        if (QUEUE_EMPTY(&h8_cmdq, link)) {
+                Dprintk("h8_start_new_cmd: no command to dequeue\n");
+                restore_flags(flags);
+                return;
+        }
+        /*
+         * Take first command off of the command queue and put
+         * it on the active queue.
+         */
+        qp = (h8_cmd_q_t *) QUEUE_FIRST(&h8_cmdq, link);
+        QUEUE_REMOVE(&h8_cmdq, qp, link);
+        QUEUE_ENTER(&h8_actq, qp, link, h8_cmd_q_t *);
+        h8_state = H8_XMIT;
+        if (h8_debug & 0x1)
+                Dprintk("h8_start_new_cmd: Starting a command\n");
+
+        qp->cnt = 1;
+        WRITE_CMD(qp->cmdbuf[0]);               /* Kick it off */
+
+        restore_flags(flags);
+        return;
+}
+
+void
+h8_send_next_cmd_byte(void)
+{
+        h8_cmd_q_t      *qp = (h8_cmd_q_t *)QUEUE_FIRST(&h8_actq, link);
+        int cnt;
+
+        cnt = qp->cnt;
+        qp->cnt++;
+
+        if (h8_debug & 0x1)
+                Dprintk("h8 sending next cmd byte 0x%x (0x%x)\n",
+			cnt, qp->cmdbuf[cnt]);
+
+        if (cnt) {
+                WRITE_DATA(qp->cmdbuf[cnt]);
+        } else {
+                WRITE_CMD(qp->cmdbuf[cnt]);
+        }
+        return;
+}
+
+/*
+ * Synchronize H8 communications channel for command transmission.
+ */
+void
+h8_sync(void)
+{
+        u_char  buf[H8_MAX_CMD_SIZE];
+
+        buf[0] = H8_SYNC;
+        buf[1] = H8_SYNC_BYTE;
+        h8_q_cmd(buf, 2, 1);
+}
+
+/*
+ * Responds to external interrupt. Reads event status word and 
+ * decodes type of interrupt. 
+ */
+void
+h8_read_event_status(void)
+{
+
+        if(h8_debug & 0x200)
+                printk("h8_read_event_status: value 0x%x\n", intrbuf.word);
+
+        /*
+         * Power related items
+         */
+        if (intrbuf.word & H8_DC_CHANGE) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: DC_CHANGE\n");
+                /* see if dc added or removed, set batt/dc flag, send event */
+
+                h8_set_event_mask(H8_MANAGE_BATTERY);
+                wake_up(&h8_monitor_wait);
+        }
+
+        if (intrbuf.word & H8_POWER_BUTTON) {
+                printk("Power switch pressed - please wait - preparing to power 
+off\n");
+                h8_set_event_mask(H8_POWER_BUTTON);
+                wake_up(&h8_monitor_wait);
+        }
+
+        /*
+         * Thermal related items
+         */
+        if (intrbuf.word & H8_THERMAL_THRESHOLD) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: THERMAL_THRESHOLD\n");
+                h8_set_event_mask(H8_MANAGE_UTHERM);
+                wake_up(&h8_monitor_wait);
+        }
+
+        /*
+         * nops -for now
+         */
+        if (intrbuf.word & H8_DOCKING_STATION_STATUS) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: DOCKING_STATION_STATUS\n");
+                /* read_ext_status */
+        }
+        if (intrbuf.word & H8_EXT_BATT_STATUS) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: EXT_BATT_STATUS\n");
+
+        }
+        if (intrbuf.word & H8_EXT_BATT_CHARGE_STATE) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: EXT_BATT_CHARGE_STATE\n");
+
+        }
+        if (intrbuf.word & H8_BATT_CHANGE_OVER) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: BATT_CHANGE_OVER\n");
+
+        }
+        if (intrbuf.word & H8_WATCHDOG) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: WATCHDOG\n");
+                /* nop */
+        }
+        if (intrbuf.word & H8_SHUTDOWN) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: SHUTDOWN\n");
+                /* nop */
+        }
+        if (intrbuf.word & H8_KEYBOARD) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: KEYBOARD\n");
+                /* nop */
+        }
+        if (intrbuf.word & H8_EXT_MOUSE_OR_CASE_SWITCH) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: EXT_MOUSE_OR_CASE_SWITCH\n");
+                /* read_ext_status*/
+        }
+        if (intrbuf.word & H8_INT_BATT_LOW) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: INT_BATT_LOW\n");
+                /* post event, warn user */
+        }
+        if (intrbuf.word & H8_INT_BATT_CHARGE_STATE) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: INT_BATT_CHARGE_STATE\n");
+                /* nop - happens often */
+        }
+        if (intrbuf.word & H8_INT_BATT_STATUS) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: INT_BATT_STATUS\n");
+
+        }
+        if (intrbuf.word & H8_INT_BATT_CHARGE_THRESHOLD) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: INT_BATT_CHARGE_THRESHOLD\n");
+                /* nop - happens often */
+        }
+        if (intrbuf.word & H8_EXT_BATT_LOW) {
+		if(h8_debug & 0x4)
+		    printk("h8_read_event_status: EXT_BATT_LOW\n");
+                /*if no internal, post event, warn user */
+                /* else nop */
+        }
+
+        return;
+}
+
+/*
+ * Function called when H8 has performed requested command.
+ */
+void
+h8_cmd_done(h8_cmd_q_t *qp)
+{
+
+        /* what to do */
+        switch (qp->cmdbuf[0]) {
+	case H8_SYNC:
+	    if (h8_debug & 0x40000) 
+	        printk("H8: Sync command done - byte returned was 0x%x\n", 
+		       qp->rcvbuf[0]);
+	    QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+	    break;
+
+	case H8_RD_SN:
+	case H8_RD_ENET_ADDR:
+	    printk("H8: Read ethernet addr - command done - address: %x - %x - %x - %x - %x - %x \n", 
+		   qp->rcvbuf[0], qp->rcvbuf[1], qp->rcvbuf[2],
+		   qp->rcvbuf[3], qp->rcvbuf[4], qp->rcvbuf[5]);
+	    QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+	    break;
+
+	case H8_RD_HW_VER:
+	case H8_RD_MIC_VER:
+	case H8_RD_MAX_TEMP:
+	    printk("H8: Max recorded CPU temp %d, Sys temp %d\n",
+		   qp->rcvbuf[0], qp->rcvbuf[1]);
+	    QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+	    break;
+
+	case H8_RD_MIN_TEMP:
+	    printk("H8: Min recorded CPU temp %d, Sys temp %d\n",
+		   qp->rcvbuf[0], qp->rcvbuf[1]);
+	    QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+	    break;
+
+	case H8_RD_CURR_TEMP:
+	    h8_sync_channel |= H8_RD_CURR_TEMP;
+	    xx.byte[0] = qp->rcvbuf[0];
+	    xx.byte[1] = qp->rcvbuf[1];
+	    wake_up(&h8_sync_wait); 
+	    QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); 
+	    break;
+
+	case H8_RD_SYS_VARIENT:
+	case H8_RD_PWR_ON_CYCLES:
+	    printk(" H8: RD_PWR_ON_CYCLES command done\n");
+	    break;
+
+	case H8_RD_PWR_ON_SECS:
+	    printk("H8: RD_PWR_ON_SECS command done\n");
+	    break;
+
+	case H8_RD_RESET_STATUS:
+	case H8_RD_PWR_DN_STATUS:
+	case H8_RD_EVENT_STATUS:
+	case H8_RD_ROM_CKSM:
+	case H8_RD_EXT_STATUS:
+	    xx.byte[1] = qp->rcvbuf[0];
+	    xx.byte[0] = qp->rcvbuf[1];
+	    h8_sync_channel |= H8_GET_EXT_STATUS;
+	    wake_up(&h8_sync_wait); 
+	    QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); 
+	    break;
+
+	case H8_RD_USER_CFG:
+	case H8_RD_INT_BATT_VOLT:
+	case H8_RD_DC_INPUT_VOLT:
+	case H8_RD_HORIZ_PTR_VOLT:
+	case H8_RD_VERT_PTR_VOLT:
+	case H8_RD_EEPROM_STATUS:
+	case H8_RD_ERR_STATUS:
+	case H8_RD_NEW_BUSY_SPEED:
+	case H8_RD_CONFIG_INTERFACE:
+	case H8_RD_INT_BATT_STATUS:
+	    printk("H8: Read int batt status cmd done - returned was %x %x %x\n",
+		   qp->rcvbuf[0], qp->rcvbuf[1], qp->rcvbuf[2]);
+	    QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+	    break;
+
+	case H8_RD_EXT_BATT_STATUS:
+	case H8_RD_PWR_UP_STATUS:
+	case H8_RD_EVENT_STATUS_MASK:
+	case H8_CTL_EMU_BITPORT:
+	case H8_DEVICE_CONTROL:
+	    if(h8_debug & 0x20000) {
+	        printk("H8: Device control cmd done - byte returned was 0x%x\n",
+		       qp->rcvbuf[0]);
+	    }
+	    QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+	    break;
+
+	case H8_CTL_TFT_BRT_DC:
+	case H8_CTL_WATCHDOG:
+	case H8_CTL_MIC_PROT:
+	case H8_CTL_INT_BATT_CHG:
+	case H8_CTL_EXT_BATT_CHG:
+	case H8_CTL_MARK_SPACE:
+	case H8_CTL_MOUSE_SENSITIVITY:
+	case H8_CTL_DIAG_MODE:
+	case H8_CTL_IDLE_AND_BUSY_SPDS:
+	    printk("H8: Idle and busy speed command done\n");
+	    break;
+
+	case H8_CTL_TFT_BRT_BATT:
+	case H8_CTL_UPPER_TEMP:
+	    if(h8_debug & 0x10) {
+	        XDprintk("H8: ctl upper thermal thresh cmd done - returned was %d\n",
+		       qp->rcvbuf[0]);
+	    }
+	    QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+	    break;
+
+	case H8_CTL_LOWER_TEMP:
+	case H8_CTL_TEMP_CUTOUT:
+	case H8_CTL_WAKEUP:
+	case H8_CTL_CHG_THRESHOLD:
+	case H8_CTL_TURBO_MODE:
+	case H8_SET_DIAG_STATUS:
+	case H8_SOFTWARE_RESET:
+	case H8_RECAL_PTR:
+	case H8_SET_INT_BATT_PERCENT:
+	case H8_WRT_CFG_INTERFACE_REG:
+	case H8_WRT_EVENT_STATUS_MASK:
+	case H8_ENTER_POST_MODE:
+	case H8_EXIT_POST_MODE:
+	case H8_RD_EEPROM:
+	case H8_WRT_EEPROM:
+	case H8_WRT_TO_STATUS_DISP:
+	    printk("H8: Write IO status display command done\n");
+	    break;
+
+	case H8_DEFINE_SPC_CHAR:
+	case H8_DEFINE_TABLE_STRING_ENTRY:
+	case H8_PERFORM_EMU_CMD:
+	case H8_EMU_RD_REG:
+	case H8_EMU_WRT_REG:
+	case H8_EMU_RD_RAM:
+	case H8_EMU_WRT_RAM:
+	case H8_BQ_RD_REG:
+	case H8_BQ_WRT_REG:
+	case H8_PWR_OFF:
+	    printk ("H8: misc command completed\n");
+	    break;
+        }
+        return;
+}
+
+/*
+ * Retrieve the current cpu temperature and case temperature.  Provides
+ * the feedback for the thermal control algorithm.  Synchcronized via 
+ * sleep() for priority so that no other actions in the process will take
+ * place before the data becomes available.
+ */
+int
+h8_get_curr_temp(u_char curr_temp[])
+{
+        u_char  buf[H8_MAX_CMD_SIZE];
+        unsigned long flags;
+
+        memset(buf, 0, H8_MAX_CMD_SIZE); 
+        buf[0] = H8_RD_CURR_TEMP;
+
+        h8_q_cmd(buf, 1, 2);
+
+	save_flags(flags); cli();
+
+        while((h8_sync_channel & H8_RD_CURR_TEMP) == 0)
+                sleep_on(&h8_sync_wait); 
+
+        restore_flags(flags);
+
+        h8_sync_channel &= ~H8_RD_CURR_TEMP;
+        curr_temp[0] = xx.byte[0];
+        curr_temp[1] = xx.byte[1];
+        xx.word = 0;
+
+        if(h8_debug & 0x8) 
+                printk("H8: curr CPU temp %d, Sys temp %d\n",
+		       curr_temp[0], curr_temp[1]);
+        return 0;
+}
+
+static void
+h8_get_max_temp(void)
+{
+        u_char  buf[H8_MAX_CMD_SIZE];
+
+        buf[0] = H8_RD_MAX_TEMP;
+        h8_q_cmd(buf, 1, 2);
+}
+
+/*
+ * Assigns an upper limit to the value of the H8 thermal interrupt.
+ * As an example setting a value of 115 F here will cause the 
+ * interrupt to trigger when the cpu temperature reaches 115 F.
+ */
+static void
+h8_set_upper_therm_thold(int thold)
+{
+        u_char  buf[H8_MAX_CMD_SIZE];
+
+        /* write 0 to reinitialize interrupt */
+        buf[0] = H8_CTL_UPPER_TEMP;
+        buf[1] = 0x0;
+        buf[2] = 0x0;
+        h8_q_cmd(buf, 3, 1); 
+
+        /* Do it for real */
+        buf[0] = H8_CTL_UPPER_TEMP;
+        buf[1] = 0x0;
+        buf[2] = thold;
+        h8_q_cmd(buf, 3, 1); 
+}
+
+static void
+h8_get_upper_therm_thold(void)
+{
+        u_char  buf[H8_MAX_CMD_SIZE];
+
+        buf[0] = H8_CTL_UPPER_TEMP;
+        buf[1] = 0xff;
+        buf[2] = 0;
+        h8_q_cmd(buf, 3, 1); 
+}
+
+/*
+ * The external status word contains information on keyboard controller,
+ * power button, changes in external batt status, change in DC state,
+ * docking station, etc. General purpose querying use.
+ */
+int
+h8_get_ext_status(u_char stat_word[])
+{
+        u_char  buf[H8_MAX_CMD_SIZE];
+	unsigned long flags;
+
+        memset(buf, 0, H8_MAX_CMD_SIZE); 
+        buf[0] = H8_RD_EXT_STATUS;
+
+        h8_q_cmd(buf, 1, 2);
+
+	save_flags(flags); cli();
+
+        while((h8_sync_channel & H8_GET_EXT_STATUS) == 0)
+                sleep_on(&h8_sync_wait); 
+
+        restore_flags(flags);
+
+        h8_sync_channel &= ~H8_GET_EXT_STATUS;
+        stat_word[0] = xx.byte[0];
+        stat_word[1] = xx.byte[1];
+        xx.word = 0;
+
+        if(h8_debug & 0x8) 
+                printk("H8: curr ext status %x,  %x\n",
+		       stat_word[0], stat_word[1]);
+
+        return 0;
+}
+
+/*
+ * Thread attached to task 0 manages thermal/physcial state of Alphabook. 
+ * When a condition is detected by the interrupt service routine, the
+ * isr does a wakeup() on h8_monitor_wait.  The mask value is then
+ * screened for the appropriate action.
+ */
+
+int
+h8_monitor_thread(void * unused)
+{
+        u_char curr_temp[2];
+
+        /*
+         * Need a logic based safety valve here. During boot when this thread is
+         * started and the thermal interrupt is not yet initialized this logic 
+         * checks the temperature and acts accordingly.  When this path is acted
+         * upon system boot is painfully slow, however, the priority associated 
+         * with overheating is high enough to warrant this action.
+         */
+        h8_get_curr_temp(curr_temp);
+
+        printk("H8: Initial CPU temp: %d\n", curr_temp[0]);
+
+        if(curr_temp[0] >= h8_uthermal_threshold) {
+                h8_set_event_mask(H8_MANAGE_UTHERM);
+                h8_manage_therm();
+        } else {
+                /*
+                 * Arm the upper thermal limit of the H8 so that any temp in
+                 * excess will trigger the thermal control mechanism.
+                 */
+                h8_set_upper_therm_thold(h8_uthermal_threshold);
+        }
+
+        for(;;) {
+		sleep_on(&h8_monitor_wait);
+
+                if(h8_debug & 0x2)
+                        printk("h8_monitor_thread awakened, mask:%x\n",
+                                h8_event_mask);
+
+                if (h8_event_mask & (H8_MANAGE_UTHERM|H8_MANAGE_LTHERM)) {
+                        h8_manage_therm();
+                }
+
+#if 0
+                if (h8_event_mask & H8_POWER_BUTTON) {
+                        h8_system_down();
+                }
+
+		/*
+		 * If an external DC supply is removed or added make 
+		 * appropriate cpu speed adjustments.
+		 */
+                if (h8_event_mask & H8_MANAGE_BATTERY) {
+                          h8_run_level_3_manage(H8_RUN); 
+                          h8_clear_event_mask(H8_MANAGE_BATTERY);
+                }
+#endif
+        }
+}
+
+/* 
+ * Function implements the following policy. When the machine is booted
+ * the system is set to run at full clock speed. When the upper thermal
+ * threshold is reached as a result of full clock a damping factor is 
+ * applied to cool off the cpu.  The default value is one quarter clock
+ * (57 Mhz).  When as a result of this cooling a temperature lower by
+ * hmc_uthermal_window is reached, the machine is reset to a higher 
+ * speed, one half clock (115 Mhz).  One half clock is maintained until
+ * the upper thermal threshold is again reached restarting the cycle.
+ */
+
+int
+h8_manage_therm(void)
+{
+        u_char curr_temp[2];
+
+        if(h8_event_mask & H8_MANAGE_UTHERM) {
+		/* Upper thermal interrupt received, need to cool down. */
+		if(h8_debug & 0x10)
+                        printk("H8: Thermal threshold %d F reached\n",
+			       h8_uthermal_threshold);
+		h8_set_cpu_speed(h8_udamp); 
+                h8_clear_event_mask(H8_MANAGE_UTHERM);
+                h8_set_event_mask(H8_MANAGE_LTHERM);
+                /* Check again in 30 seconds for cpu temperature */
+                h8_start_monitor_timer(H8_TIMEOUT_INTERVAL); 
+        } else if (h8_event_mask & H8_MANAGE_LTHERM) {
+		/* See how cool the system has become as a result
+		   of the reduction in speed. */
+                h8_get_curr_temp(curr_temp);
+                last_temp = curr_temp[0];
+                if (curr_temp[0] < (h8_uthermal_threshold - h8_uthermal_window))
+		{
+			/* System cooling has progressed to a point
+			   that the cpu may be speeded up. */
+                        h8_set_upper_therm_thold(h8_uthermal_threshold);
+                        h8_set_cpu_speed(h8_ldamp); /* adjustable */ 
+                        if(h8_debug & 0x10)
+                            printk("H8: CPU cool, applying cpu_divisor: %d \n",
+				   h8_ldamp);
+                        h8_clear_event_mask(H8_MANAGE_LTHERM);
+                }
+		else /* Not cool enough yet, check again in 30 seconds. */
+                        h8_start_monitor_timer(H8_TIMEOUT_INTERVAL);
+        } else {
+                
+        }
+	return 0;
+}
+
+/* 
+ * Function conditions the value of global_rpb_counter before
+ * calling the primitive which causes the actual speed change.
+ */
+void
+h8_set_cpu_speed(int speed_divisor)
+{
+
+#ifdef NOT_YET
+/*
+ * global_rpb_counter is consumed by alpha_delay() in determining just
+ * how much time to delay.  It is necessary that the number of microseconds
+ * in DELAY(n) be kept consistent over a variety of cpu clock speeds.
+ * To that end global_rpb_counter is here adjusted.
+ */ 
+        
+        switch (speed_divisor) {
+                case 0:
+                        global_rpb_counter = rpb->rpb_counter * 2L;
+                        break;
+                case 1:
+                        global_rpb_counter = rpb->rpb_counter * 4L / 3L ;
+                        break;
+                case 3:
+                        global_rpb_counter = rpb->rpb_counter / 2L;
+                        break;
+                case 4:
+                        global_rpb_counter = rpb->rpb_counter / 4L;
+                        break;
+                case 5:
+                        global_rpb_counter = rpb->rpb_counter / 8L;
+                        break;
+                /* 
+                 * This case most commonly needed for cpu_speed_divisor 
+                 * of 2 which is the value assigned by the firmware. 
+                 */
+                default:
+                        global_rpb_counter = rpb->rpb_counter;
+                break;
+        }
+#endif /* NOT_YET */
+
+        if(h8_debug & 0x8)
+                printk("H8: Setting CPU speed to %d MHz\n",
+		       speed_tab[speed_divisor]); 
+
+         /* Make the actual speed change */
+        lca_clock_fiddle(speed_divisor);
+}
+
+/*
+ * Gets value stored in rpb representing cpu clock speed and adjusts this
+ * value based on the current clock speed divisor.
+ */
+u_long
+h8_get_cpu_speed(void)
+{
+        u_long speed = 0;
+        u_long counter;
+
+#ifdef NOT_YET
+        counter = rpb->rpb_counter / 1000000L;
+
+        switch (alphabook_get_clock()) {
+                case 0:
+                        speed = counter * 2L;
+                        break;
+                case 1:
+                        speed = counter * 4L / 3L ;
+                        break;
+                case 2:
+                        speed = counter;
+                        break;
+                case 3:
+                        speed = counter / 2L;
+                        break;
+                case 4:
+                        speed = counter / 4L;
+                        break;
+                case 5:
+                        speed = counter / 8L;
+                        break;
+                default:
+                break;
+        }
+        if(h8_debug & 0x8)
+                printk("H8: CPU speed current setting: %d MHz\n", speed); 
+#endif  /* NOT_YET */
+	return speed;
+}
+
+static void
+h8_activate_monitor(unsigned long unused)
+{
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	h8_monitor_timer_active = 0;
+	restore_flags(flags);
+
+	wake_up(&h8_monitor_wait);
+}
+
+static void
+h8_start_monitor_timer(unsigned long secs)
+{
+	unsigned long flags;
+
+	if (h8_monitor_timer_active)
+	    return;
+
+	save_flags(flags); cli();
+	h8_monitor_timer_active = 1;
+	restore_flags(flags);
+
+        init_timer(&h8_monitor_timer);
+        h8_monitor_timer.function = h8_activate_monitor;
+        h8_monitor_timer.expires = secs * HZ + jiffies;
+        add_timer(&h8_monitor_timer);
+}
+
+static void h8_set_event_mask(int mask)
+{
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	h8_event_mask |= mask;
+	restore_flags(flags);
+}
+
+static void h8_clear_event_mask(int mask)
+{
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	h8_event_mask &= (~mask);
+	restore_flags(flags);
+}
diff -u --recursive --new-file v2.1.53/linux/drivers/char/h8.h linux/drivers/char/h8.h
--- v2.1.53/linux/drivers/char/h8.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/h8.h	Sat Sep  6 10:16:07 1997
@@ -0,0 +1,250 @@
+/*
+ */
+
+#ifndef __H8_H__
+#define __H8_H__
+
+/*
+ * Register address and offsets
+ */
+#define H8_BASE_ADDR                   0x170            /* default */
+#define H8_IRQ			       9                /* default */
+#define H8_STATUS_REG_OFF              0x4              
+#define H8_CMD_REG_OFF                 0x4
+#define H8_DATA_REG_OFF                0x0
+
+
+/* H8 register bit definitions */
+/* status register */
+#define H8_OFULL                       0x1              /* output data register full */
+#define H8_IFULL                       0x2              /* input data register full */
+#define H8_CMD                         0x8              /* command / not data */
+
+#define H8_INTR                        0xfa
+#define H8_NACK                        0xfc
+#define H8_BYTE_LEVEL_ACK              0xfd
+#define H8_CMD_ACK                     0xfe
+#define H8_SYNC_BYTE                   0x99
+
+/*
+ * H8 command definitions
+ */
+/* System info commands */
+#define H8_SYNC                         0x0
+#define H8_RD_SN                        0x1
+#define H8_RD_ENET_ADDR                 0x2
+#define H8_RD_HW_VER                    0x3
+#define H8_RD_MIC_VER                   0x4
+#define H8_RD_MAX_TEMP                  0x5
+#define H8_RD_MIN_TEMP                  0x6
+#define H8_RD_CURR_TEMP                 0x7
+#define H8_RD_SYS_VARIENT               0x8
+#define H8_RD_PWR_ON_CYCLES             0x9
+#define H8_RD_PWR_ON_SECS               0xa
+#define H8_RD_RESET_STATUS              0xb
+#define H8_RD_PWR_DN_STATUS             0xc
+#define H8_RD_EVENT_STATUS              0xd
+#define H8_RD_ROM_CKSM                  0xe
+#define H8_RD_EXT_STATUS                0xf
+#define H8_RD_USER_CFG                  0x10
+#define H8_RD_INT_BATT_VOLT             0x11
+#define H8_RD_DC_INPUT_VOLT             0x12
+#define H8_RD_HORIZ_PTR_VOLT            0x13
+#define H8_RD_VERT_PTR_VOLT             0x14
+#define H8_RD_EEPROM_STATUS             0x15
+#define H8_RD_ERR_STATUS                0x16
+#define H8_RD_NEW_BUSY_SPEED            0x17
+#define H8_RD_CONFIG_INTERFACE          0x18
+#define H8_RD_INT_BATT_STATUS           0x19
+#define H8_RD_EXT_BATT_STATUS           0x1a
+#define H8_RD_PWR_UP_STATUS             0x1b
+#define H8_RD_EVENT_STATUS_MASK         0x56
+
+/* Read/write/modify commands */
+#define H8_CTL_EMU_BITPORT              0x32
+#define H8_DEVICE_CONTROL               0x21
+#define H8_CTL_TFT_BRT_DC               0x22
+#define H8_CTL_WATCHDOG                 0x23
+#define H8_CTL_MIC_PROT                 0x24
+#define H8_CTL_INT_BATT_CHG             0x25
+#define H8_CTL_EXT_BATT_CHG             0x26
+#define H8_CTL_MARK_SPACE               0x27
+#define H8_CTL_MOUSE_SENSITIVITY        0x28
+#define H8_CTL_DIAG_MODE                0x29
+#define H8_CTL_IDLE_AND_BUSY_SPDS       0x2a
+#define H8_CTL_TFT_BRT_BATT             0x2b
+#define H8_CTL_UPPER_TEMP               0x2c
+#define H8_CTL_LOWER_TEMP               0x2d
+#define H8_CTL_TEMP_CUTOUT              0x2e
+#define H8_CTL_WAKEUP                   0x2f
+#define H8_CTL_CHG_THRESHOLD            0x30
+#define H8_CTL_TURBO_MODE               0x31
+#define H8_SET_DIAG_STATUS              0x40
+#define H8_SOFTWARE_RESET               0x41
+#define H8_RECAL_PTR                    0x42
+#define H8_SET_INT_BATT_PERCENT         0x43
+#define H8_WRT_CFG_INTERFACE_REG        0x45
+#define H8_WRT_EVENT_STATUS_MASK        0x57
+#define H8_ENTER_POST_MODE              0x46
+#define H8_EXIT_POST_MODE               0x47
+
+/* Block transfer commands */
+#define H8_RD_EEPROM                    0x50
+#define H8_WRT_EEPROM                   0x51
+#define H8_WRT_TO_STATUS_DISP           0x52
+#define H8_DEFINE_SPC_CHAR              0x53
+ 
+/* Generic commands */
+#define H8_DEFINE_TABLE_STRING_ENTRY    0x60
+
+/* Battery control commands */
+#define H8_PERFORM_EMU_CMD              0x70
+#define H8_EMU_RD_REG                   0x71
+#define H8_EMU_WRT_REG                  0x72
+#define H8_EMU_RD_RAM                   0x73
+#define H8_EMU_WRT_RAM                  0x74
+#define H8_BQ_RD_REG                    0x75
+#define H8_BQ_WRT_REG                   0x76
+
+/* System admin commands */
+#define H8_PWR_OFF                      0x80
+
+/*
+ * H8 command related definitions
+ */
+
+/* device control argument bits */
+#define H8_ENAB_EXTSMI                  0x1
+#define H8_DISAB_IRQ                    0x2
+#define H8_ENAB_FLASH_WRT               0x4
+#define H8_ENAB_THERM                   0x8
+#define H8_ENAB_INT_PTR                 0x10
+#define H8_ENAB_LOW_SPD_IND             0x20
+#define H8_ENAB_EXT_PTR                 0x40
+#define H8_DISAB_PWR_OFF_SW             0x80
+#define H8_POWER_OFF			0x80
+
+/* H8 read event status bits */
+#define H8_DC_CHANGE                    0x1
+#define H8_INT_BATT_LOW                 0x2
+#define H8_INT_BATT_CHARGE_THRESHOLD    0x4
+#define H8_INT_BATT_CHARGE_STATE        0x8
+#define H8_INT_BATT_STATUS              0x10
+#define H8_EXT_BATT_CHARGE_STATE        0x20
+#define H8_EXT_BATT_LOW                 0x40
+#define H8_EXT_BATT_STATUS              0x80
+#define H8_THERMAL_THRESHOLD            0x100
+#define H8_WATCHDOG                     0x200
+#define H8_DOCKING_STATION_STATUS       0x400
+#define H8_EXT_MOUSE_OR_CASE_SWITCH     0x800
+#define H8_KEYBOARD                     0x1000
+#define H8_BATT_CHANGE_OVER             0x2000
+#define H8_POWER_BUTTON                 0x4000
+#define H8_SHUTDOWN                     0x8000
+
+/* H8 control idle and busy speeds */
+#define H8_SPEED_LOW                    0x1
+#define H8_SPEED_MED                    0x2
+#define H8_SPEED_HI                     0x3
+#define H8_SPEED_LOCKED                 0x80
+
+#define H8_MAX_CMD_SIZE                 18      
+#define H8_Q_ALLOC_AMOUNT               10      
+
+/* H8 state field values */
+#define H8_IDLE                         1
+#define H8_XMIT                         2
+#define H8_RCV                          3
+#define H8_RESYNC                       4
+#define H8_INTR_MODE                    5
+
+/* Mask values for control functions */
+#define UTH_HYSTERESIS                  5
+#define DEFAULT_UTHERMAL_THRESHOLD      115
+#define H8_TIMEOUT_INTERVAL		30
+#define H8_RUN                          4
+
+#define H8_GET_MAX_TEMP                 0x1
+#define H8_GET_CURR_TEMP                0x2
+#define H8_GET_UPPR_THRMAL_THOLD        0x4
+#define H8_GET_ETHERNET_ADDR            0x8
+#define H8_SYNC_OP                      0x10 
+#define H8_SET_UPPR_THRMAL_THOLD        0x20
+#define H8_GET_INT_BATT_STAT            0x40
+#define H8_GET_CPU_SPD                  0x80
+#define H8_MANAGE_UTHERM                0x100 
+#define H8_MANAGE_LTHERM                0x200 
+#define H8_HALT                         0x400 
+#define H8_CRASH                        0x800 
+#define H8_GET_EXT_STATUS               0x10000
+#define H8_MANAGE_QUIET                 0x20000
+#define H8_MANAGE_SPEEDUP               0x40000
+#define H8_MANAGE_BATTERY               0x80000
+#define H8_SYSTEM_DELAY_TEST            0x100000
+#define H8_POWER_SWITCH_TEST            0x200000
+
+/* cpu speeds and clock divisor values */
+#define MHZ_14                           5
+#define MHZ_28                           4
+#define MHZ_57                           3
+#define MHZ_115                          2
+#define MHZ_230                          0 
+
+/*
+ * H8 data
+ */
+struct h8_data {
+        u_int           ser_num;
+        u_char          ether_add[6];
+        u_short         hw_ver;
+        u_short         mic_ver;
+        u_short         max_tmp;
+        u_short         min_tmp;
+        u_short         cur_tmp;
+        u_int           sys_var;
+        u_int           pow_on;
+        u_int           pow_on_secs;
+        u_char          reset_status;
+        u_char          pwr_dn_status;
+        u_short         event_status;
+        u_short         rom_cksm;
+        u_short         ext_status;
+        u_short         u_cfg;
+        u_char          ibatt_volt;
+        u_char          dc_volt;
+        u_char          ptr_horiz;
+        u_char          ptr_vert;
+        u_char          eeprom_status;
+        u_char          error_status;
+        u_char          new_busy_speed;
+        u_char          cfg_interface;
+        u_short         int_batt_status;
+        u_short         ext_batt_status;
+        u_char          pow_up_status;
+        u_char          event_status_mask;
+};
+
+
+/*
+ * H8 command buffers
+ */
+typedef struct h8_cmd_q {
+        DLNODE(struct h8_cmd_q) link; /* double linked list */
+        int             ncmd;           /* number of bytes in command */
+        int             nrsp;           /* number of bytes in response */
+        int             cnt;            /* number of bytes sent/received */
+        int             nacks;          /* number of byte level acks */
+        u_char          cmdbuf[H8_MAX_CMD_SIZE]; /* buffer to store command */
+        u_char          rcvbuf[H8_MAX_CMD_SIZE]; /* buffer to store response */
+} h8_cmd_q_t;
+
+typedef struct __queue_head {
+	DLNODE(struct h8_cmd_q) link;
+} queue_head_t;
+
+union   intr_buf {
+        u_char  byte[2];
+        u_int   word;
+};
+
+#endif /* __H8_H_ */
diff -u --recursive --new-file v2.1.53/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.1.53/linux/drivers/char/mem.c	Wed Sep  3 20:52:42 1997
+++ linux/drivers/char/mem.c	Sat Sep  6 10:27:18 1997
@@ -339,13 +339,6 @@
 	return 0;
 }
 
-static long read_full(struct inode * node, struct file * file,
-	char * buf, unsigned long count)
-{
-	file->f_pos += count;
-	return count;
-}
-
 static long write_full(struct inode * inode, struct file * file,
 	const char * buf, unsigned long count)
 {
@@ -390,7 +383,9 @@
 
 #define mmap_kmem	mmap_mem
 #define zero_lseek	null_lseek
+#define full_lseek      null_lseek
 #define write_zero	write_null
+#define read_full       read_zero
 
 static struct file_operations mem_fops = {
 	memory_lseek,
@@ -457,7 +452,7 @@
 };
 
 static struct file_operations full_fops = {
-	memory_lseek,
+	full_lseek,
 	read_full,
 	write_full,
 	NULL,		/* full_readdir */
diff -u --recursive --new-file v2.1.53/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.1.53/linux/drivers/char/misc.c	Mon Aug 11 14:47:04 1997
+++ linux/drivers/char/misc.c	Sat Sep  6 10:16:07 1997
@@ -71,10 +71,12 @@
 extern int sun_mouse_init(void);
 extern void watchdog_init(void);
 extern void wdt_init(void);
+extern void acq_init(void);
 extern void pcwatchdog_init(void);
 extern int rtc_init(void);
 extern int dsp56k_init(void);
 extern int nvram_init(void);
+extern void hfmodem_init(void);
 
 #ifdef CONFIG_PROC_FS
 static int misc_read_proc(char *buf, char **start, off_t offset,
@@ -231,17 +233,26 @@
 #ifdef CONFIG_WDT
 	wdt_init();
 #endif
+#ifdef CONFIG_ACQUIRE_WDT
+	acq_init();
+#endif
 #ifdef CONFIG_SOFT_WATCHDOG
 	watchdog_init();
 #endif
 #ifdef CONFIG_APM
 	apm_bios_init();
 #endif
+#ifdef CONFIG_H8
+	h8_init();
+#endif
 #ifdef CONFIG_RTC
 	rtc_init();
 #endif
 #ifdef CONFIG_ATARI_DSP56K
 	dsp56k_init();
+#endif
+#ifdef CONFIG_HFMODEM
+	hfmodem_init();
 #endif
 #ifdef CONFIG_NVRAM
 	nvram_init();
diff -u --recursive --new-file v2.1.53/linux/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c
--- v2.1.53/linux/drivers/misc/parport_share.c	Wed Sep  3 20:52:42 1997
+++ linux/drivers/misc/parport_share.c	Fri Sep  5 20:42:57 1997
@@ -18,6 +18,8 @@
 #include <linux/kernel.h>
 #include <linux/malloc.h>
 
+#include <linux/config.h>
+
 #ifdef CONFIG_KERNELD
 #include <linux/kerneld.h>
 #endif
diff -u --recursive --new-file v2.1.53/linux/drivers/net/arc-rimi.c linux/drivers/net/arc-rimi.c
--- v2.1.53/linux/drivers/net/arc-rimi.c	Thu Sep  4 17:07:30 1997
+++ linux/drivers/net/arc-rimi.c	Sat Sep  6 10:05:42 1997
@@ -1,4 +1,5 @@
-/* arc-rimi.c:
+/*	$Id: arc-rimi.c,v 1.2 1997/09/05 08:57:51 mj Exp $
+
         Derived from the original arcnet.c,
         Written 1994-1996 by Avery Pennarun,
 	which was in turn derived from skeleton.c by Donald Becker.
@@ -75,41 +76,11 @@
 #undef SLOW_XMIT_COPY
 
 
-
-
-/* External functions from arcnet.c */
-
-
-
-#if ARCNET_DEBUG_MAX & D_SKB
-extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
-			    char *desc);
-#else
-#define arcnet_dump_skb(dev,skb,desc) ;
-#endif
-
-#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
-			       char *desc);
-#else
-#define arcnet_dump_packet(dev,buffer,ext,desc) ;
-#endif
-
-extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
-extern void arcnet_makename(char *device);
-extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-extern void arcnet_setup(struct device *dev);
-extern int arcnet_go_tx(struct device *dev,int enable_irq);
-extern void arcnetA_continue_tx(struct device *dev);
-extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
-extern void arcnet_use_count(int open);
-
-
-
 /* Internal function declarations */
+
 static int arcrimi_probe(struct device *dev);
 static void arcrimi_rx(struct device *dev,int recbuf);
-static int arcrimi_found(struct device *dev,int ioaddr,int airq,u_long shmem); 
+static int arcrimi_found(struct device *dev,int ioaddr,int airq,u_long shmem);
 static void arcrimi_inthandler (struct device *dev);
 static int arcrimi_reset (struct device *dev, int reset_delay);
 static void arcrimi_setmask (struct device *dev, u_char mask);
@@ -122,7 +93,6 @@
 
 /* Module parameters */
 
-
 #ifdef MODULE
 static int shmem=0x0;	/* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
 static int irq=0;	/* or use the insmod io= irq= shmem= options */
@@ -142,7 +112,6 @@
 
 /* Handy defines for ARCnet specific stuff */
 
-
 /* COM 9026 controller chip --> ARCnet register addresses */
 #define _INTMASK (ioaddr+0)	/* writable */
 #define _STATUS  (ioaddr+0)	/* readable */
@@ -155,20 +124,14 @@
 
 #define RDDATAflag      0x00     /* Next access is a read/~write */
 
-
-
-
 #define ARCSTATUS	readb(_STATUS)
 #define ACOMMAND(cmd) writeb((cmd),_COMMAND)
 #define ARCRESET	writeb(TESTvalue,ioaddr-0x800)	/* fake reset */
 #define AINTMASK(msk)	writeb((msk),_INTMASK)
 #define SETCONF	writeb(lp->config,_CONFIG)
 
-
 static const char *version =
-"arc-rimi.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
-
-
+"arc-rimi.c: v2.92 97/09/02 Avery Pennarun <apenwarr@bond.net> et al.\n";
 
 /****************************************************************************
  *                                                                          *
@@ -186,26 +149,25 @@
   BUGLVL(D_NORMAL) printk(version);
   BUGMSG(D_NORMAL,"Given: node %02Xh, shmem %lXh, irq %d\n",
 	 dev->dev_addr[0],dev->mem_start,dev->irq);
-  
+
   if (dev->mem_start<=0 || dev->irq<=0)
     {
       BUGMSG(D_NORMAL,"No autoprobe for RIM I; you "
 	     "must specify the shmem and irq!\n");
       return -ENODEV;
     }
-  
+
   if (dev->dev_addr[0]==0)
     {
       BUGMSG(D_NORMAL,"You need to specify your card's station "
 	     "ID!\n");
       return -ENODEV;
     }
-  
+
   return arcrimi_found(dev,dev->dev_addr[0],dev->irq,dev->mem_start);
 }
 
 
-
 /* Set up the struct device associated with this card.  Called after
  * probing succeeds.
  */
@@ -214,7 +176,7 @@
   struct arcnet_local *lp;
   u_long first_mirror,last_mirror;
   int mirror_size;
-  
+
   /* reserve the irq */
   if (request_irq(airq,&arcnet_interrupt,0,"arcnet (RIM I)",NULL))
     {
@@ -223,15 +185,15 @@
     }
   irq2dev_map[airq]=dev;
   dev->irq=airq;
-  
+
   dev->base_addr=0;
   writeb(TESTvalue,shmem);
   writeb(node,shmem+1);	/* actually the node ID */
-  
+
   /* find the real shared memory start/end points, including mirrors */
 #define BUFFER_SIZE (512)
 #define MIRROR_SIZE (BUFFER_SIZE*4)
-  
+
   /* guess the actual size of one "memory mirror" - the number of
    * bytes between copies of the shared memory.  On most cards, it's
    * 2k (or there are no mirrors at all) but on some, it's 4k.
@@ -241,21 +203,21 @@
       && readb(shmem-mirror_size)!=TESTvalue
       && readb(shmem-2*mirror_size)==TESTvalue)
     mirror_size*=2;
-  
+
   first_mirror=last_mirror=shmem;
   while (readb(first_mirror)==TESTvalue) first_mirror-=mirror_size;
   first_mirror+=mirror_size;
-  
+
   while (readb(last_mirror)==TESTvalue) last_mirror+=mirror_size;
   last_mirror-=mirror_size;
-  
+
   dev->mem_start=first_mirror;
   dev->mem_end=last_mirror+MIRROR_SIZE-1;
   dev->rmem_start=dev->mem_start+BUFFER_SIZE*0;
   dev->rmem_end=dev->mem_start+BUFFER_SIZE*2-1;
-  
+
   /* Initialize the rest of the device structure. */
-  
+
   dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
   if (dev->priv == NULL)
     {
@@ -274,26 +236,26 @@
   lp->openclose_device=arcrimi_openclose;
   lp->prepare_tx=arcrimi_prepare_tx;
   lp->inthandler=arcrimi_inthandler;
-  
+
   /* Fill in the fields of the device structure with generic
    * values.
    */
   arcnet_setup(dev);
-  
+
   /* And now fill particular fields with arcnet values */
   dev->mtu=1500; /* completely arbitrary - agrees with ether, though */
   dev->hard_header_len=sizeof(struct ClientData);
   lp->sequence=1;
   lp->recbuf=0;
-  
+
   BUGMSG(D_DURING,"ClientData header size is %d.\n",
 	 sizeof(struct ClientData));
   BUGMSG(D_DURING,"HardHeader size is %d.\n",
 	 sizeof(struct archdr));
-  
+
   /* get and check the station ID from offset 1 in shmem */
   lp->stationid = readb(first_mirror+1);
-  
+
   if (lp->stationid==0)
     BUGMSG(D_NORMAL,"WARNING!  Station address 00 is reserved "
 	   "for broadcasts!\n");
@@ -301,13 +263,13 @@
     BUGMSG(D_NORMAL,"WARNING!  Station address FF may confuse "
 	   "DOS networking programs!\n");
   dev->dev_addr[0]=lp->stationid;
-  
+
   BUGMSG(D_NORMAL,"ARCnet RIM I: station %02Xh found at IRQ %d, "
 	 "ShMem %lXh (%ld*%d bytes).\n",
 	 lp->stationid,
 	 dev->irq, dev->mem_start,
 	 (dev->mem_end-dev->mem_start+1)/mirror_size,mirror_size);
-  
+
   return 0;
 }
 
@@ -324,46 +286,46 @@
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   short ioaddr=dev->mem_start + 0x800;
   int recbuf=lp->recbuf;
-  
+
   if (reset_delay==3)
     {
       ARCRESET;
       return 0;
     }
-  
+
   /* no IRQ's, please! */
   lp->intmask=0;
   SETMASK;
-  
+
   BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
 	 dev->name,ARCSTATUS);
-  
+
   ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */
   ACOMMAND(CFLAGScmd|CONFIGclear);
-  
+
   /* clear out status variables */
   recbuf=lp->recbuf=0;
   lp->txbuf=2;
-  
+
   /* enable extended (512-byte) packets */
   ACOMMAND(CONFIGcmd|EXTconf);
-  
+
 #ifndef SLOW_XMIT_COPY
   /* clean out all the memory to make debugging make more sense :) */
   BUGLVL(D_DURING)
     memset_io(dev->mem_start,0x42,2048);
 #endif
-  
+
   /* and enable receive of our first packet to the first buffer */
   EnableReceiver();
-  
+
   /* re-enable interrupts */
   lp->intmask|=NORXflag;
 #ifdef DETECT_RECONFIGS
   lp->intmask|=RECONflag;
 #endif
   SETMASK;
-  
+
   /* done!  return success. */
   return 0;
 }
@@ -380,28 +342,25 @@
 static void arcrimi_setmask(struct device *dev, u_char mask)
 {
   int ioaddr=dev->mem_start+0x800;
-  
+
   AINTMASK(mask);
 }
 
 static u_char arcrimi_status(struct device *dev)
 {
   int ioaddr=dev->mem_start+0x800;
-  
+
   return ARCSTATUS;
 }
 
 static void arcrimi_command(struct device *dev, u_char cmd)
 {
   int ioaddr=dev->mem_start+0x800;
-  
+
   ACOMMAND(cmd);
 }
 
 
-
-
-
 /* The actual interrupt handler routine - handle various IRQ's generated
  * by the card.
  */
@@ -410,18 +369,17 @@
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   int ioaddr=dev->mem_start+0x800, status, boguscount = 3, didsomething;
-  
+
   AINTMASK(0);
-  
+
   BUGMSG(D_DURING,"in arcrimi_inthandler (status=%Xh, intmask=%Xh)\n",
 	 ARCSTATUS,lp->intmask);
-  
+
   do
     {
       status = ARCSTATUS;
       didsomething=0;
-      
-      
+
       /* RESET flag was enabled - card is resetting and if RX
        * is disabled, it's NOT because we just got a packet.
        */
@@ -430,44 +388,43 @@
 	  BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
 		 status);
 	  arcrimi_reset(dev,0);
-	  
+
 	  /* all other flag values are just garbage */
 	  break;
 	}
-      
-      
+
       /* RX is inhibited - we must have received something. */
       if (status & lp->intmask & NORXflag)
 	{
 	  int recbuf=lp->recbuf=!lp->recbuf;
-	  
+
 	  BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
 		 status);
-	  
+
 	  /* enable receive of our next packet */
 	  EnableReceiver();
-	  
+
 	  /* Got a packet. */
 	  arcrimi_rx(dev,!recbuf);
-	  
+
 	  didsomething++;
 	}
-      
+
       /* it can only be an xmit-done irq if we're xmitting :) */
       /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
       if (status & lp->intmask & TXFREEflag)
 	{
 	  struct Outgoing *out=&(lp->outgoing);
 	  int was_sending=lp->sending;
-	  
+
 	  lp->intmask &= ~TXFREEflag;
-	  
+
 	  lp->in_txhandler++;
 	  if (was_sending) lp->sending--;
-	  
+
 	  BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
 		 status,out->numsegs,out->segnum,out->skb);
-	  
+
 	  if (was_sending && !(status&TXACKflag))
 	    {
 	      if (lp->lasttrans_dest != 0)
@@ -484,11 +441,11 @@
 			 lp->lasttrans_dest);
 		}
 	    }
-	  
+
 	  /* send packet if there is one */
 	  arcnet_go_tx(dev,0);
 	  didsomething++;
-	  
+
 	  if (lp->intx)
 	    {
 	      BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
@@ -496,24 +453,24 @@
 	      lp->in_txhandler--;
 	      continue;
 	    }
-	  
+
 	  if (!lp->outgoing.skb)
 	    {
 	      BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
-	      
+
 	      /* inform upper layers */
 	      if (!lp->txready) arcnet_tx_done(dev, lp);
 	      lp->in_txhandler--;
 	      continue;
 	    }
-	  
+
 	  /* if more than one segment, and not all segments
 	   * are done, then continue xmit.
 	   */
 	  if (out->segnum<out->numsegs)
 	    arcnetA_continue_tx(dev);
 	  arcnet_go_tx(dev,0);
-	  
+
 	  /* if segnum==numsegs, the transmission is finished;
 	   * free the skb.
 	   */
@@ -527,12 +484,12 @@
 		  dev_kfree_skb(out->skb,FREE_WRITE);
 		}
 	      out->skb=NULL;
-	      
+
 	      /* inform upper layers */
 	      if (!lp->txready) arcnet_tx_done(dev, lp);
 	    }
 	  didsomething++;
-	  
+
 	  lp->in_txhandler--;
 	}
       else if (lp->txready && !lp->sending && !lp->intx)
@@ -542,20 +499,18 @@
 	  arcnet_go_tx(dev,0);
 	  didsomething++;
 	}
-      
+
 #ifdef DETECT_RECONFIGS
       if (status & (lp->intmask) & RECONflag)
 	{
 	  ACOMMAND(CFLAGScmd|CONFIGclear);
 	  lp->stats.tx_carrier_errors++;
-	  
+
 #ifdef SHOW_RECONFIGS
 	  BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n",
 		 status);
-	  
-	  
 #endif /* SHOW_RECONFIGS */
-	  
+
 #ifdef RECON_THRESHOLD
 	  /* is the RECON info empty or old? */
 	  if (!lp->first_recon || !lp->last_recon ||
@@ -565,19 +520,19 @@
 		BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
 	      lp->first_recon=lp->last_recon=jiffies;
 	      lp->num_recons=lp->network_down=0;
-	      
+
 	      BUGMSG(D_DURING,"recon: clearing counters.\n");
 	    }
 	  else /* add to current RECON counter */
 	    {
 	      lp->last_recon=jiffies;
 	      lp->num_recons++;
-	      
+
 	      BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
 		     lp->num_recons,
 		     (lp->last_recon-lp->first_recon)/HZ,
 		     lp->network_down);
-	      
+
 	      /* if network is marked up;
 	       * and first_recon and last_recon are 60+ sec
 	       *   apart;
@@ -609,26 +564,24 @@
 	    BUGMSG(D_NORMAL,"cabling restored?\n");
 	  lp->first_recon=lp->last_recon=0;
 	  lp->num_recons=lp->network_down=0;
-	  
+
 	  BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
 #endif
 	}
 #endif /* DETECT_RECONFIGS */
     } while (--boguscount && didsomething);
-  
+
   BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n",
 	 ARCSTATUS,boguscount);
   BUGMSG(D_DURING,"\n");
-  
+
   SETMASK;	/* put back interrupt mask */
-  
 }
 
 
-
 /* A packet has arrived; grab it from the buffers and pass it to the generic
  * arcnet_rx routing to deal with it.
- */ 
+ */
 
 static void
 arcrimi_rx(struct device *dev,int recbuf)
@@ -640,11 +593,11 @@
   u_char *arcsoft;
   short length,offset;
   u_char daddr,saddr;
-  
+
   lp->stats.rx_packets++;
-  
+
   saddr=arcpacket->hardheader.source;
-  
+
   /* if source is 0, it's a "used" packet! */
   if (saddr==0)
     {
@@ -654,11 +607,11 @@
       return;
     }
   /* Set source address to zero to mark it as old */
-  
+
   arcpacket->hardheader.source=0;
-  
+
   daddr=arcpacket->hardheader.destination;
-  
+
   if (arcpacket->hardheader.offset1) /* Normal Packet */
     {
       offset=arcpacket->hardheader.offset1;
@@ -669,26 +622,22 @@
     {
       offset=arcpacket->hardheader.offset2;
       arcsoft=&arcpacket->raw[offset];
-      
+
       length=512-offset;
     }
-  
-  
+
   arcnet_rx(lp, arcsoft, length, saddr, daddr);
-  
-  
+
   BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx");
-  
+
 #ifndef SLOW_XMIT_COPY
   /* clean out the page to make debugging make more sense :) */
   BUGLVL(D_DURING)
     memset((void *)arcpacket->raw,0x42,512);
 #endif
-  
 }
 
 
-
 /* Given an skb, copy a packet into the ARCnet buffers for later transmission
  * by arcnet_go_tx.
  */
@@ -699,45 +648,45 @@
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   union ArcPacket *arcpacket =
     (union ArcPacket *)phys_to_virt(dev->mem_start+512*(lp->txbuf^1));
-  
+
 #ifdef SLOW_XMIT_COPY
   char *iptr,*iend,*optr;
 #endif
-  
+
   lp->txbuf=lp->txbuf^1;	/* XOR with 1 to alternate between 2 and 3 */
-  
+
   length+=hdrlen;
-  
+
   BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
 	 hdr,length,data);
-  
+
 #ifndef SLOW_XMIT_COPY
   /* clean out the page to make debugging make more sense :) */
   BUGLVL(D_DURING)
     memset_io(dev->mem_start+lp->txbuf*512,0x42,512);
 #endif
-  
+
   arcpacket->hardheader.destination=daddr;
-  
+
   /* load packet into shared memory */
   if (length<=MTU)	/* Normal (256-byte) Packet */
     arcpacket->hardheader.offset1=offset=offset?offset:256-length;
-  
+
   else if (length>=MinTU || offset)	/* Extended (512-byte) Packet */
     {
       arcpacket->hardheader.offset1=0;
-      arcpacket->hardheader.offset2=offset=offset?offset:512-length;   
+      arcpacket->hardheader.offset2=offset=offset?offset:512-length;
     }
   else if (exceptA)		/* RFC1201 Exception Packet */
     {
       arcpacket->hardheader.offset1=0;
       arcpacket->hardheader.offset2=offset=512-length-4;
-      
+
       /* exception-specific stuff - these four bytes
        * make the packet long enough to fit in a 512-byte
        * frame.
        */
-      
+
       arcpacket->raw[offset+0]=hdr[0];
       arcpacket->raw[offset+1]=0xFF; /* FF flag */
       arcpacket->raw[offset+2]=0xFF; /* FF padding */
@@ -748,17 +697,17 @@
     {
       /* RFC1051 - set 4 trailing bytes to 0 */
       memset(&arcpacket->raw[508],0,4);
-      
+
       /* now round up to MinTU */
       arcpacket->hardheader.offset1=0;
       arcpacket->hardheader.offset2=offset=512-MinTU;
     }
-  
-  
+
+
   /* copy the packet into ARCnet shmem
    *  - the first bytes of ClientData header are skipped
    */
-  
+
   memcpy((u_char*)arcpacket+offset, (u_char*)hdr,hdrlen);
 #ifdef SLOW_XMIT_COPY
   for (iptr=data,iend=iptr+length-hdrlen,optr=(char *)arcpacket+offset+hdrlen;
@@ -770,18 +719,17 @@
 #else
   memcpy((u_char*)arcpacket+offset+hdrlen, data,length-hdrlen);
 #endif
-  
+
   BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
 	 daddr,length);
-  
+
   BUGLVL(D_TX) arcnet_dump_packet(dev,arcpacket->raw,length>MTU,"tx");
-  
+
   lp->lastload_dest=daddr;
   lp->txready=lp->txbuf;	/* packet is ready for sending */
 }
 
 
-
 /****************************************************************************
  *                                                                          *
  * Kernel Loadable Module Support                                           *
@@ -806,13 +754,13 @@
   if (device)
     strcpy(dev->name,device);
   else arcnet_makename(dev->name);
-  
+
   if (node && node != 0xff)
     dev->dev_addr[0]=node;
-  
+
   dev->irq=irq;
   if (dev->irq==2) dev->irq=9;
-  
+
   if (shmem)
     {
       dev->mem_start=shmem;
@@ -820,7 +768,7 @@
       dev->rmem_start=thiscard.mem_start+512*0;
       dev->rmem_end=thiscard.mem_start+512*2-1;
     }
-  
+
   if (register_netdev(dev) != 0)
     return -EIO;
   arcnet_use_count(1);
@@ -831,9 +779,9 @@
 {
   struct device *dev=&thiscard;
   int ioaddr=dev->mem_start;
-  
+
   if (dev->start) (*dev->stop)(dev);
-  
+
   /* Flush TX and disable RX */
   if (ioaddr)
     {
@@ -841,13 +789,13 @@
       ACOMMAND(NOTXcmd);	/* stop transmit */
       ACOMMAND(NORXcmd);	/* disable receive */
     }
-  
+
   if (dev->irq)
     {
       irq2dev_map[dev->irq] = NULL;
       free_irq(dev->irq,NULL);
     }
-  
+
   unregister_netdev(dev);
   kfree(dev->priv);
   dev->priv = NULL;
@@ -856,7 +804,6 @@
 
 #else
 
-
 __initfunc(void arcrimi_setup (char *str, int *ints))
 {
   struct device *dev;
@@ -867,9 +814,9 @@
 	     MAX_ARCNET_DEVS);
       return;
     }
-  
+
   dev=&arcnet_devs[arcnet_num_devs];
-  
+
   if (ints[0] < 3)
     {
       printk("ARCnet RIM I: You must give address, IRQ and node ID.\n");
@@ -888,20 +835,17 @@
 
     case 2: /* IRQ */
       dev->irq=ints[2];
-      
+
     case 1: /* Mem address */
       dev->mem_start=ints[1];
     }
 
   dev->name = (char *)&arcnet_dev_names[arcnet_num_devs];
-  
+
   if (str)
     strncpy(dev->name, str, 9);
-  
+
   arcnet_num_devs++;
 }
 
 #endif /* MODULE */
-
-
-
diff -u --recursive --new-file v2.1.53/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
--- v2.1.53/linux/drivers/net/arcnet.c	Thu Sep  4 17:07:30 1997
+++ linux/drivers/net/arcnet.c	Sat Sep  6 10:05:42 1997
@@ -1,8 +1,9 @@
-/* arcnet.c:
+/*	$Id: arcnet.c,v 1.30 1997/09/05 08:57:46 mj Exp $
+
 	Written 1994-1996 by Avery Pennarun,
 	derived from skeleton.c by Donald Becker.
 
-	Contact Avery at: apenwarr@foxnet.net or
+	Contact Avery at: apenwarr@bond.net or
 	RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
 
 	**********************
@@ -17,6 +18,12 @@
 
 	**********************
 
+	v2.92 ALPHA (97/02/09)
+	  - Code cleanup [Martin Mares <mj@atrey.karlin.mff.cuni.cz>]
+	  - Better probing for the COM90xx chipset, although only as
+	    a temporary solution until we implement adding of all found
+	    devices at once. [mj]
+
 	v2.91 ALPHA (97/19/08)
 	  - Add counting of octets in/out.
 
@@ -122,12 +129,13 @@
          - Smarter recovery from RECON-during-transmit conditions. (ie.
            retransmit immediately)
          - Add support for the new 1.3.x IP header cache, and other features.
-         - Debug level should be changed with a system call, not a hack to
-           the "metric" flag.
+         - Replace setting of debug level with the "metric" flag hack by
+	   something better. SIOCDEVPRIVATE is a good candidate, but it would
+	   require an extra user-level utility.
 
          - What about cards with shared memory that can be "turned off?"
            (or that have none at all, like the SMC PC500longboard)
-     Does this work now, with IO_MAPPED_BUFFERS?
+           Does this work now, with IO_MAPPED_BUFFERS?
 
          - Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play
            with temporarily.)  Update: yes, the Pure Data config program
@@ -154,9 +162,7 @@
 */
 
 static const char *version =
- "arcnet.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
-
-
+ "arcnet.c: v2.92 97/09/02 Avery Pennarun <apenwarr@bond.net> et al.\n";
 
 #include <linux/module.h>
 #include <linux/config.h>
@@ -200,16 +206,14 @@
 
 /**************************************************************************/
 
-/* These are now provided by the chipset driver. There's a performance 
+/* These are now provided by the chipset driver. There's a performance
  * overhead in using them.
  */
 
-
 #define AINTMASK(x) ((*lp->asetmask)(dev, x))
 #define ARCSTATUS ((*lp->astatus)(dev))
 #define ACOMMAND(x) ((*lp->acommand)(dev, x))
 
-
 int arcnet_debug=ARCNET_DEBUG;
 
 /* Exported function prototypes */
@@ -235,7 +239,6 @@
 void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
 void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
 
-
 EXPORT_SYMBOL(arcnet_debug);
 EXPORT_SYMBOL(arcnet_tx_done);
 EXPORT_SYMBOL(arcnet_use_count);
@@ -302,10 +305,6 @@
 #endif
 
 
-
-
-
-
 /****************************************************************************
  *                                                                          *
  * Packet dumps for debugging                                               *
@@ -334,6 +333,7 @@
 }
 #endif
 
+
 /* Dump the contents of an ARCnet buffer
  */
 #if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
@@ -357,8 +357,6 @@
 #endif
 
 
-
-
 /* Setup a struct device for ARCnet.  This should really be in net_init.c
  * but since there are three different ARCnet devices ANYWAY... <gargle>
  *
@@ -385,8 +383,7 @@
 	dev->pa_mask		= 0;
 	dev->pa_alen		= 4;
 
-
-	/* Put in this stuff here, so we don't have to export the symbols 
+	/* Put in this stuff here, so we don't have to export the symbols
 	 * to the chipset drivers.
 	 */
 
@@ -405,7 +402,6 @@
  *                                                                          *
  ****************************************************************************/
 
-
 /* Open/initialize the board.  This is called sometime after booting when
  * the 'ifconfig' program is run.
  *
@@ -417,39 +413,33 @@
 arcnet_open(struct device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- 
+
   if (dev->metric>=1000)
     {
       arcnet_debug=dev->metric-1000;
       printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug);
       dev->metric=1;
     }
-  
+
   BUGMSG(D_INIT,"arcnet_open: resetting card.\n");
-  
+
   /* try to put the card in a defined state - if it fails the first
    * time, actually reset it.
    */
   if ((*lp->arcnet_reset)(dev,0) && (*lp->arcnet_reset)(dev,1))
     return -ENODEV;
-#if 0
-  /* reset the card twice in case something goes wrong the first time.
-   */
-  if ((*(lp->arcnet_reset))(dev,1) && (*(lp->arcnet_reset))(dev,1))
-    return -ENODEV;
-#endif
-  
+
   dev->tbusy=0;
   dev->interrupt=0;
   lp->intx=0;
   lp->in_txhandler=0;
-  
+
   /* The RFC1201 driver is the default - just store */
   lp->adev=dev;
 
   /* we're started */
   dev->start=1;
-  
+
 #ifdef CONFIG_ARCNET_ETH
   /* Initialize the ethernet-encap protocol driver */
   lp->edev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
@@ -467,7 +457,7 @@
   lp->edev->init=arcnetE_init;
   register_netdev(lp->edev);
 #endif
-  
+
 #ifdef CONFIG_ARCNET_1051
   /* Initialize the RFC1051-encap protocol driver */
   lp->sdev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
@@ -477,27 +467,27 @@
   lp->sdev->init=arcnetS_init;
   register_netdev(lp->sdev);
 #endif
-    
+
   /* Enable TX if we need to */
   if (lp->en_dis_able_TX)
     (*lp->en_dis_able_TX)(dev, 1);
-  
+
   /* make sure we're ready to receive IRQ's.
    * arcnet_reset sets this for us, but if we receive one before
    * START is set to 1, it could be ignored.  So, we turn IRQ's
    * off, then on again to clean out the IRQ controller.
    */
-  
+
   AINTMASK(0);
   udelay(1);	/* give it time to set the mask before
 		 * we reset it again. (may not even be
 		 * necessary)
 		 */
   SETMASK;
-  
+
   /* Let it increase its use count */
   (*lp->openclose_device)(1);
-  
+
   return 0;
 }
 
@@ -508,7 +498,7 @@
 arcnet_close(struct device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   if (test_and_set_bit(0, (int *)&dev->tbusy))
     BUGMSG(D_NORMAL, "arcnet_close: tbusy already set!\n");
 
@@ -522,36 +512,32 @@
   lp->edev->start=0;
 #endif
 
-  
   /* Shut down the card */
-  
+
   /* Disable TX if we need to */
   if (lp->en_dis_able_TX)
     (*lp->en_dis_able_TX)(dev, 0);
-  
+
   (*lp->arcnet_reset)(dev, 3);	/* reset IRQ won't run if START=0 */
 #if 0
   lp->intmask=0;
-  SETMASK;	/* no IRQ's (except RESET, of course) */
+  SETMASK;		/* no IRQ's (except RESET, of course) */
   ACOMMAND(NOTXcmd);	/* stop transmit */
   ACOMMAND(NORXcmd);	/* disable receive */
 #endif
-  
+
   /* reset more flags */
-	dev->interrupt=0;
+  dev->interrupt=0;
 #ifdef CONFIG_ARCNET_ETH
-	lp->edev->interrupt=0;
+  lp->edev->interrupt=0;
 #endif
 #ifdef CONFIG_ARCNET_1051
-	lp->sdev->interrupt=0;
+  lp->sdev->interrupt=0;
 #endif
 
-
-
-  
   /* do NOT free lp->adev!!  It's static! */
   lp->adev=NULL;
-  
+
 #ifdef CONFIG_ARCNET_ETH
   /* free the ethernet-encap protocol device */
   lp->edev->priv=NULL;
@@ -561,7 +547,7 @@
   kfree(lp->edev);
   lp->edev=NULL;
 #endif
-  
+
 #ifdef CONFIG_ARCNET_1051
   /* free the RFC1051-encap protocol device */
   lp->sdev->priv=NULL;
@@ -571,17 +557,16 @@
   kfree(lp->sdev);
   lp->sdev=NULL;
 #endif
-  
+
   /* Update the statistics here. (not necessary in ARCnet) */
-  
+
   /* Decrease the use count */
   (*lp->openclose_device)(0);
-  
+
   return 0;
 }
 
 
-
 /****************************************************************************
  *                                                                          *
  * Transmitter routines                                                     *
@@ -594,24 +579,24 @@
 arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n",
 	 ARCSTATUS,lp->intx);
-  
+
   if (lp->in_txhandler)
     {
       BUGMSG(D_NORMAL,"send_packet called while in txhandler!\n");
       lp->stats.tx_dropped++;
       return 1;
     }
-  
+
   if (lp->intx>1)
     {
       BUGMSG(D_NORMAL,"send_packet called while intx!\n");
       lp->stats.tx_dropped++;
       return 1;
     }
-  
+
   if (test_bit(0, (int *)&dev->tbusy))
     {
       /* If we get here, some higher level has decided we are broken.
@@ -619,7 +604,7 @@
       int tickssofar = jiffies - dev->trans_start;
 
       int status=ARCSTATUS;
-      
+
       if (tickssofar < TX_TIMEOUT)
 	{
 	  BUGMSG(D_DURING,"premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n",
@@ -628,10 +613,10 @@
 		 lp->outgoing.segnum);
 	  return 1;
 	}
-      
+
       lp->intmask &= ~TXFREEflag;
       SETMASK;
-      
+
       if (status&TXFREEflag)	/* transmit _DID_ finish */
 	{
 	  BUGMSG(D_NORMAL,"tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n",
@@ -644,17 +629,17 @@
 		 status,tickssofar,lp->intmask,lp->lasttrans_dest);
 	  lp->stats.tx_errors++;
 	  lp->stats.tx_aborted_errors++;
-	  
+
 	  ACOMMAND(NOTXcmd);
 	}
-      
+
       if (lp->outgoing.skb)
 	{
 	  dev_kfree_skb(lp->outgoing.skb,FREE_WRITE);
 	  lp->stats.tx_dropped++;
 	}
       lp->outgoing.skb=NULL;
-      
+
 #ifdef CONFIG_ARCNET_ETH
       lp->edev->tbusy=0;
 #endif
@@ -666,10 +651,10 @@
 
       lp->txready=0;
       lp->sending=0;
-      
+
       return 1;
     }
-  
+
   if (lp->txready)	/* transmit already in progress! */
     {
       BUGMSG(D_NORMAL,"trying to start new packet while busy! (status=%Xh)\n",
@@ -681,10 +666,10 @@
       lp->stats.tx_errors++;
       lp->stats.tx_fifo_errors++;
       lp->txready=0;	/* we definitely need this line! */
-      
+
       return 1;
     }
-  
+
   /* Block a timer-based transmit from overlapping.  This could better be
      done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
   if (test_and_set_bit(0, (int *)&lp->adev->tbusy))
@@ -701,7 +686,7 @@
 #ifdef CONFIG_ARCNET_ETH
   lp->edev->tbusy=1;
 #endif
-  
+
   return 0;
 }
 
@@ -714,13 +699,13 @@
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int bad,oldmask=0;
   struct Outgoing *out=&(lp->outgoing);
-  
+
   lp->intx++;
-  
+
   oldmask |= lp->intmask;
   lp->intmask=0;
   SETMASK;
-  
+
   bad=arcnet_send_packet_bad(skb,dev);
   if (bad)
     {
@@ -729,20 +714,20 @@
       SETMASK;
       return bad;
     }
-  
+
   /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
-  
+
   lp->intmask = oldmask & ~TXFREEflag;
   SETMASK;
-  
+
   out->length = 1 < skb->len ? skb->len : 1;
   out->hdr=(struct ClientData*)skb->data;
   out->skb=skb;
-  
+
   BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");
-  
+
   out->hdr->sequence=(lp->sequence++);
-  
+
   /* fits in one packet? */
   if (out->length-EXTRA_CLIENTDATA<=XMTU)
     {
@@ -759,12 +744,12 @@
 			((char *)skb->data)+sizeof(struct ClientData),
 			out->length-sizeof(struct ClientData),
 			out->hdr->daddr,1,0);
-      
+
       /* done right away */
       lp->stats.tx_bytes += out->skb->len;
       dev_kfree_skb(out->skb,FREE_WRITE);
       out->skb=NULL;
-      
+
       if (arcnet_go_tx(dev,1))
 	{
 	  /* inform upper layers */
@@ -774,19 +759,19 @@
   else			/* too big for one - split it */
     {
       int maxsegsize=XMTU-4;
-      
+
       out->data=(u_char *)skb->data
 	+ sizeof(struct ClientData);
       out->dataleft=out->length-sizeof(struct ClientData);
       out->numsegs=(out->dataleft+maxsegsize-1)/maxsegsize;
       out->segnum=0;
-      
+
       BUGMSG(D_TX,"packet (%d bytes) split into %d fragments:\n",
 	     out->length,out->numsegs);
-      
+
       /* if a packet waiting, launch it */
       arcnet_go_tx(dev,1);
-      
+
       if (!lp->txready)
 	{
 	  /* prepare a packet, launch it and prepare
@@ -799,7 +784,7 @@
 	      arcnet_go_tx(dev,1);
 	    }
 	}
-      
+
       /* if segnum==numsegs, the transmission is finished;
        * free the skb right away.
        */
@@ -816,14 +801,14 @@
 	  out->skb=NULL;
 	}
     }
-  
+
   dev->trans_start=jiffies;
   lp->intx--;
- 
+
   /* make sure we didn't ignore a TX IRQ while we were in here */
   lp->intmask |= TXFREEflag;
   SETMASK;
-  
+
   return 0;
 }
 
@@ -837,38 +822,38 @@
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int maxsegsize=XMTU-4;
   struct Outgoing *out=&(lp->outgoing);
-  
+
   BUGMSG(D_DURING,"continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n",
 	 ARCSTATUS,lp->intx,lp->in_txhandler,lp->intmask);
-  
+
   if (lp->txready)
     {
       BUGMSG(D_NORMAL,"continue_tx: called with packet in buffer!\n");
       return;
     }
-  
+
   if (out->segnum>=out->numsegs)
     {
       BUGMSG(D_NORMAL,"continue_tx: building segment %d of %d!\n",
 	     out->segnum+1,out->numsegs);
     }
-  
+
   if (!out->segnum)	/* first packet */
     out->hdr->split_flag=((out->numsegs-2)<<1)+1;
   else
     out->hdr->split_flag=out->segnum<<1;
-  
+
   out->seglen=maxsegsize;
   if (out->seglen>out->dataleft) out->seglen=out->dataleft;
-  
+
   BUGMSG(D_TX,"building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n",
 	 out->segnum+1,out->seglen,out->numsegs,
 	 out->length,out->hdr->split_flag);
-  
+
   (*lp->prepare_tx)(dev,((char *)out->hdr)+EXTRA_CLIENTDATA,
 		    sizeof(struct ClientData)-EXTRA_CLIENTDATA,
 		    out->data,out->seglen,out->hdr->daddr,1,0);
-  
+
   out->dataleft-=out->seglen;
   out->data+=out->seglen;
   out->segnum++;
@@ -936,30 +921,29 @@
 {
 	struct device *dev = (struct device *)(irq2dev_map[irq]);
 	struct arcnet_local *lp;
-	
+
 	if (dev==NULL)
 	  {
 	    BUGLVL(D_DURING)
 	      printk(KERN_DEBUG "arcnet: irq %d for unknown device.\n", irq);
 	    return;
 	  }
-	
+
 	BUGMSG(D_DURING,"in arcnet_interrupt\n");
-	
-	
+
 	lp=(struct arcnet_local *)dev->priv;
-	
+
 	/* RESET flag was enabled - if !dev->start, we must clear it right
 	 * away (but nothing else) since inthandler() is never called.
 	 */
-	
+
 	if (!dev->start)
-	  {	    
+	  {
 	    if (ARCSTATUS & RESETflag)
 	      ACOMMAND(CFLAGScmd|RESETclear);
 	    return;
 	  }
-	
+
 
 	if (test_and_set_bit(0, (int *)&dev->interrupt))
 	  {
@@ -1000,7 +984,7 @@
       if (!test_and_clear_bit(0, (int *)&dev->tbusy))
 	BUGMSG(D_NORMAL, "In arcnet_tx_done: Someone cleared our dev->tbusy"
 	       " flag!\n");
-      
+
       mark_bh(NET_BH);
     }
 }
@@ -1012,7 +996,7 @@
  *                                                                          *
  ****************************************************************************/
 
-/* 
+/*
  * This is a generic packet receiver that calls arcnet??_rx depending on the
  * protocol ID found.
  */
@@ -1020,10 +1004,10 @@
 void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr)
 {
   struct device *dev=lp->adev;
-  
+
   BUGMSG(D_DURING,"received packet from %02Xh to %02Xh (%d bytes)\n",
 	 saddr,daddr,length);
-  
+
   /* call the right receiver for the protocol */
   switch (arcsoft[0])
     {
@@ -1059,13 +1043,13 @@
       lp->stats.rx_crc_errors++;
       break;
     }
-  
+
   /* If any worth-while packets have been received, a mark_bh(NET_BH)
    * has been done by netif_rx and Linux will handle them after we
    * return.
    */
-  
-  
+
+
 }
 
 
@@ -1079,33 +1063,33 @@
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   struct sk_buff *skb;
   struct ClientData *arcsoft,*soft;
-  
+
   BUGMSG(D_DURING,"it's an RFC1201 packet (length=%d)\n",
 	 length);
-  
+
   /* compensate for EXTRA_CLIENTDATA (which isn't actually in the
    * packet)
    */
   arcsoft=(struct ClientData *)(buf-EXTRA_CLIENTDATA);
   length+=EXTRA_CLIENTDATA;
-  
+
   if (arcsoft->split_flag==0xFF)  /* Exception Packet */
     {
       BUGMSG(D_DURING,"compensating for exception packet\n");
-      
+
       /* skip over 4-byte junkola */
       arcsoft=(struct ClientData *)
 	((u_char *)arcsoft + 4);
       length-=4;
     }
-  
+
   if (!arcsoft->split_flag)		/* not split */
     {
       struct Incoming *in=&lp->incoming[saddr];
-      
+
       BUGMSG(D_RX,"incoming is not split (splitflag=%d)\n",
 	     arcsoft->split_flag);
-      
+
       if (in->skb)	/* already assembling one! */
 	{
 	  BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
@@ -1117,9 +1101,9 @@
 	  lp->stats.rx_missed_errors++;
 	  in->skb=NULL;
 	}
-      
+
       in->sequence=arcsoft->sequence;
-      
+
       skb = alloc_skb(length, GFP_ATOMIC);
       if (skb == NULL) {
 	BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
@@ -1127,16 +1111,16 @@
 	return;
       }
       soft=(struct ClientData *)skb->data;
-      
+
       skb_put(skb,length);
       skb->dev = dev;
-      
+
       memcpy((u_char *)soft+EXTRA_CLIENTDATA,
 	     (u_char *)arcsoft+EXTRA_CLIENTDATA,
 	     length-EXTRA_CLIENTDATA);
       soft->daddr=daddr;
       soft->saddr=saddr;
-      
+
       /* ARP packets have problems when sent from DOS.
        * source address is always 0 on some systems!  So we take
        * the hardware source addr (which is impossible to fumble)
@@ -1146,12 +1130,12 @@
 	{
 	  struct arphdr *arp=(struct arphdr *)
 	    ((char *)soft+sizeof(struct ClientData));
-	  
+
 	  /* make sure addresses are the right length */
 	  if (arp->ar_hln==1 && arp->ar_pln==4)
 	    {
 	      char *cptr=(char *)(arp)+sizeof(struct arphdr);
-	      
+
 	      if (!*cptr)	/* is saddr = 00? */
 		{
 		  BUGMSG(D_EXTRA,"ARP source address was 00h, set to %02Xh.\n",
@@ -1173,9 +1157,9 @@
 	      lp->stats.rx_crc_errors++;
 	    }
 	}
-      
+
       BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-      
+
       lp->stats.rx_bytes += skb->len;
       skb->protocol=arcnetA_type_trans(skb,dev);
       netif_rx(skb);
@@ -1198,12 +1182,12 @@
        * ARCnet card possible on the network.  Seems rather like
        * a waste of memory.  Necessary?
        */
-      
+
       struct Incoming *in=&lp->incoming[saddr];
-      
+
       BUGMSG(D_RX,"packet is split (splitflag=%d, seq=%d)\n",
 	     arcsoft->split_flag,in->sequence);
-      
+
       if (in->skb && in->sequence!=arcsoft->sequence)
 	{
 	  BUGMSG(D_EXTRA,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
@@ -1215,7 +1199,7 @@
 	  lp->stats.rx_missed_errors++;
 	  in->lastpacket=in->numpackets=0;
 	}
-      
+
       if (arcsoft->split_flag & 1)	/* first packet in split */
 	{
 	  BUGMSG(D_RX,"brand new splitpacket (splitflag=%d)\n",
@@ -1229,11 +1213,11 @@
 	      lp->stats.rx_missed_errors++;
 	      kfree_skb(in->skb,FREE_WRITE);
 	    }
-	  
+
 	  in->sequence=arcsoft->sequence;
 	  in->numpackets=((unsigned)arcsoft->split_flag>>1)+2;
 	  in->lastpacket=1;
-	  
+
 	  if (in->numpackets>16)
 	    {
 	      BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
@@ -1242,7 +1226,7 @@
 	      lp->stats.rx_length_errors++;
 	      return;
 	    }
-	  
+
 	  in->skb=skb=alloc_skb(508*in->numpackets
 				+ sizeof(struct ClientData),
 				GFP_ATOMIC);
@@ -1251,12 +1235,12 @@
 	    lp->stats.rx_dropped++;
 	    return;
 	  }
-	  
+
 	  soft=(struct ClientData *)skb->data;
-	  
+
 	  skb_put(skb,sizeof(struct ClientData));
 	  skb->dev=dev;
-	  
+
 	  memcpy((u_char *)soft+EXTRA_CLIENTDATA,
 		 (u_char *)arcsoft+EXTRA_CLIENTDATA,
 		 sizeof(struct ClientData)-EXTRA_CLIENTDATA);
@@ -1265,7 +1249,7 @@
       else			/* not first packet */
 	{
 	  int packetnum=((unsigned)arcsoft->split_flag>>1) + 1;
-	  
+
 	  /* if we're not assembling, there's no point
 	   * trying to continue.
 	   */
@@ -1280,7 +1264,7 @@
 		}
 	      return;
 	    }
-	  
+
 	  in->lastpacket++;
 	  if (packetnum!=in->lastpacket) /* not the right flag! */
 	    {
@@ -1293,7 +1277,7 @@
 		  lp->stats.rx_frame_errors++;
 		  return;
 		}
-	      
+
 	      /* "bad" duplicate, kill reassembly */
 	      BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
 		     in->sequence,arcsoft->split_flag,
@@ -1306,20 +1290,20 @@
 	      in->lastpacket=in->numpackets=0;
 	      return;
 	    }
-	  
+
 	  soft=(struct ClientData *)in->skb->data;
 	}
-      
+
       skb=in->skb;
-      
+
       memcpy(skb->data+skb->len,
 	     (u_char *)arcsoft+sizeof(struct ClientData),
 	     length-sizeof(struct ClientData));
       skb_put(skb,length-sizeof(struct ClientData));
-      
+
       soft->daddr=daddr;
       soft->saddr=saddr;
-      
+
       /* are we done? */
       if (in->lastpacket == in->numpackets)
 	{
@@ -1332,9 +1316,9 @@
 	    {
 	      in->skb=NULL;
 	      in->lastpacket=in->numpackets=0;
-	      
+
 	      BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-	      
+
 	      lp->stats.rx_bytes += skb->len;
 	      skb->protocol=arcnetA_type_trans(skb,dev);
 	      netif_rx(skb);
@@ -1344,15 +1328,12 @@
 }
 
 
-
-
 /****************************************************************************
  *                                                                          *
  * Miscellaneous routines                                                   *
  *                                                                          *
  ****************************************************************************/
 
-
 /* Get the current statistics.	This may be called with the card open or
  * closed.
  */
@@ -1360,7 +1341,7 @@
 static struct net_device_stats *arcnet_get_stats(struct device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   return &lp->stats;
 }
 
@@ -1376,12 +1357,12 @@
   struct ClientData *head = (struct ClientData *)
     skb_push(skb,dev->hard_header_len);
   struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-  
+
   BUGMSG(D_DURING,"create header from %d to %d; protocol %d (%Xh); size %u.\n",
 	 saddr ? *(u_char*)saddr : -1,
 	 daddr ? *(u_char*)daddr : -1,
 	 type,type,len);
-  
+
   /* set the protocol ID according to RFC1201 */
   switch(type)
     {
@@ -1409,7 +1390,7 @@
       lp->stats.tx_aborted_errors++;
       return 0;
     }
-  
+
   /*
    * Set the source hardware address.
    *
@@ -1422,10 +1403,10 @@
     head->saddr=((u_char*)saddr)[0];
   else
     head->saddr=((u_char*)(dev->dev_addr))[0];
-  
+
   head->split_flag=0;	/* split packets are done elsewhere */
   head->sequence=0;	/* so are sequence numbers */
-  
+
   /* supposedly if daddr is NULL, we should ignore it... */
   if(daddr)
     {
@@ -1434,12 +1415,11 @@
     }
   else
     head->daddr=0;	/* better fill one in anyway */
-  
+
   return -dev->hard_header_len;
 }
 
 
-
 /* Rebuild the ARCnet ClientData header. This is called after an ARP
  * (or in future other address resolution) has completed on this
  * sk_buff. We now let ARP fill in the other fields.
@@ -1450,13 +1430,13 @@
   struct device *dev=skb->dev;
   struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
   int status;
-  
+
   /*
    * Only ARP and IP are currently supported
    *
    * FIXME: Anyone want to spec IPv6 over ARCnet ?
    */
-  
+
   if(head->protocol_id != ARC_P_IP)
     {
       BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n",
@@ -1467,7 +1447,7 @@
       /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
       return 0;
     }
-  
+
   /*
    * Try to get ARP to resolve the header.
    */
@@ -1492,12 +1472,12 @@
 {
   struct ClientData *head;
   struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
-  
+
   /* Pull off the arcnet header. */
   skb->mac.raw=skb->data;
   skb_pull(skb,dev->hard_header_len);
   head=(struct ClientData *)skb->mac.raw;
-  
+
   if (head->daddr==0)
     skb->pkt_type=PACKET_BROADCAST;
   else if (dev->flags&IFF_PROMISC)
@@ -1506,14 +1486,14 @@
       if (head->daddr != dev->dev_addr[0])
 	skb->pkt_type=PACKET_OTHERHOST;
     }
-  
+
   /* now return the protocol number */
   switch (head->protocol_id)
     {
     case ARC_P_IP:		return htons(ETH_P_IP);
     case ARC_P_ARP:		return htons(ETH_P_ARP);
     case ARC_P_RARP:	return htons(ETH_P_RARP);
-      
+
     case ARC_P_IPX:
     case ARC_P_NOVELL_EC:
       return htons(ETH_P_802_3);
@@ -1522,7 +1502,7 @@
       lp->stats.rx_crc_errors++;
       return 0;
     }
-  
+
   return htons(ETH_P_IP);
 }
 
@@ -1539,7 +1519,7 @@
 static int arcnetE_init(struct device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   ether_setup(dev); /* we're emulating ether here, not ARCnet */
   dev->dev_addr[0]=0;
   dev->dev_addr[5]=lp->stationid;
@@ -1547,7 +1527,7 @@
   dev->open=arcnetE_open_close;
   dev->stop=arcnetE_open_close;
   dev->hard_start_xmit=arcnetE_send_packet;
-  
+
   return 0;
 }
 
@@ -1571,13 +1551,13 @@
   u_char daddr;
   short offset,length=skb->len+1;
   u_char proto=ARC_P_ETHER;
-  
+
   lp->intx++;
-  
+
   oldmask |= lp->intmask;
   lp->intmask=0;
   SETMASK;
-  
+
   bad=arcnet_send_packet_bad(skb,dev);
   if (bad)
     {
@@ -1586,31 +1566,31 @@
       SETMASK;
       return bad;
     }
-  
+
   /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
 
   lp->intmask=oldmask;
   SETMASK;
-  
+
   if (length>XMTU)
     {
       BUGMSG(D_NORMAL,"MTU must be <= 493 for ethernet encap (length=%d).\n",
 	     length);
       BUGMSG(D_NORMAL,"transmit aborted.\n");
-      
+
       dev_kfree_skb(skb,FREE_WRITE);
       lp->intx--;
       return 0;
     }
-  
+
   BUGMSG(D_DURING,"starting tx sequence...\n");
-  
+
   /* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */
   if (((struct ethhdr*)(skb->data))->h_dest[0] == 0xFF)
     daddr=0;
   else
     daddr=((struct ethhdr*)(skb->data))->h_dest[5];
-  
+
   /* load packet into shared memory */
   offset=512-length;
   if (length>MTU)		/* long/exception packet */
@@ -1621,17 +1601,13 @@
     {
       offset-=256;
     }
-  
+
   BUGMSG(D_DURING," length=%Xh, offset=%Xh\n",
 	 length,offset);
-  
 
-
-  (*lp->prepare_tx)(dev, &proto, 1, skb->data, length-1, daddr, 0, 
+  (*lp->prepare_tx)(dev, &proto, 1, skb->data, length-1, daddr, 0,
 			   offset);
-  
-  
-  
+
   dev_kfree_skb(skb,FREE_WRITE);
 
   if (arcnet_go_tx(dev,1))
@@ -1639,7 +1615,7 @@
       /* inform upper layers */
       arcnet_tx_done(lp->adev, lp);
     }
-  
+
 	dev->trans_start=jiffies;
 	lp->intx--;
 
@@ -1697,9 +1673,9 @@
 static int arcnetS_init(struct device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   arcnet_setup(dev);
-  
+
   /* And now fill particular fields with arcnet values */
   dev->dev_addr[0]=lp->stationid;
   dev->hard_header_len=sizeof(struct S_ClientData);
@@ -1710,7 +1686,7 @@
   dev->hard_start_xmit=arcnetS_send_packet;
   dev->hard_header=arcnetS_header;
   dev->rebuild_header=arcnetS_rebuild_header;
-  
+
   return 0;
 }
 
@@ -1732,9 +1708,9 @@
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int bad,length;
   struct S_ClientData *hdr=(struct S_ClientData *)skb->data;
-  
+
   lp->intx++;
-  
+
   bad=arcnet_send_packet_bad(skb,dev);
   if (bad)
     {
@@ -1743,11 +1719,11 @@
     }
 
   /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
-  
+
   length = 1 < skb->len ? skb->len : 1;
-  
+
   BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");
-  
+
   /* fits in one packet? */
   if (length-S_EXTRA_CLIENTDATA<=XMTU)
     {
@@ -1757,10 +1733,10 @@
 			skb->data+sizeof(struct S_ClientData),
 			length-sizeof(struct S_ClientData),
 			hdr->daddr,0,0);
-      
+
       /* done right away */
       dev_kfree_skb(skb,FREE_WRITE);
-      
+
       if (arcnet_go_tx(dev,1))
 	{
 	  /* inform upper layers */
@@ -1775,14 +1751,14 @@
       lp->stats.tx_dropped++;
       arcnet_tx_done(lp->adev, lp);
     }
-  
+
   dev->trans_start=jiffies;
   lp->intx--;
-  
+
   /* make sure we didn't ignore a TX IRQ while we were in here */
   lp->intmask |= TXFREEflag;
   SETMASK;
-  
+
   return 0;
 }
 
@@ -1796,17 +1772,15 @@
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   struct sk_buff *skb;
   struct S_ClientData *arcsoft,*soft;
-  
+
   arcsoft=(struct S_ClientData *)(buf-S_EXTRA_CLIENTDATA);
   length+=S_EXTRA_CLIENTDATA;
-  
+
   BUGMSG(D_DURING,"it's an RFC1051 packet (length=%d)\n",
 	 length);
-  
-  
-  
+
   {    /* was "if not split" in A protocol, S is never split */
-    
+
     skb = alloc_skb(length, GFP_ATOMIC);
     if (skb == NULL) {
       BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
@@ -1823,9 +1797,9 @@
     soft->daddr=daddr;
     soft->saddr=saddr;
     skb->dev = dev;  /* is already lp->sdev */
-    
+
     BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-    
+
     lp->stats.rx_bytes += skb->len;
     skb->protocol=arcnetS_type_trans(skb,dev);
     netif_rx(skb);
@@ -1844,7 +1818,7 @@
   struct S_ClientData *head = (struct S_ClientData *)
     skb_push(skb,dev->hard_header_len);
   struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-  
+
   /* set the protocol ID according to RFC1051 */
   switch(type)
     {
@@ -1863,7 +1837,7 @@
       lp->stats.tx_aborted_errors++;
       return 0;
     }
-  
+
   /*
    * Set the source hardware address.
    *
@@ -1876,7 +1850,7 @@
     head->saddr=((u_char*)saddr)[0];
   else
     head->saddr=((u_char*)(dev->dev_addr))[0];
-  
+
   /* supposedly if daddr is NULL, we should ignore it... */
   if(daddr)
     {
@@ -1885,7 +1859,7 @@
     }
   else
     head->daddr=0;	/* better fill one in anyway */
-  
+
   return -dev->hard_header_len;
 }
 
@@ -1899,11 +1873,11 @@
   struct device *dev=skb->dev;
   struct S_ClientData *head = (struct S_ClientData *)skb->data;
   struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-  
+
   /*
    * Only ARP and IP are currently supported
    */
-  
+
   if(head->protocol_id != ARC_P_IP_RFC1051)
     {
       BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n",
@@ -1914,7 +1888,7 @@
       /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
       return 0;
     }
-  
+
   /*
    * Try to get ARP to resolve the header.
    */
@@ -1934,12 +1908,12 @@
 {
   struct S_ClientData *head;
   struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
-  
+
   /* Pull off the arcnet header. */
   skb->mac.raw=skb->data;
   skb_pull(skb,dev->hard_header_len);
   head=(struct S_ClientData *)skb->mac.raw;
-  
+
   if (head->daddr==0)
     skb->pkt_type=PACKET_BROADCAST;
   else if (dev->flags&IFF_PROMISC)
@@ -1948,7 +1922,7 @@
       if (head->daddr != dev->dev_addr[0])
 	skb->pkt_type=PACKET_OTHERHOST;
     }
-  
+
   /* now return the protocol number */
   switch (head->protocol_id)
     {
@@ -1960,20 +1934,19 @@
       lp->stats.rx_crc_errors++;
       return 0;
     }
-  
+
   return htons(ETH_P_IP);
 }
 
 #endif	/* CONFIG_ARCNET_1051 */
 
+
 /****************************************************************************
  *                                                                          *
  * Kernel Loadable Module Support                                           *
  *                                                                          *
  ****************************************************************************/
 
-
-
 #ifdef MODULE
 
 void cleanup_module(void)
@@ -1982,7 +1955,7 @@
 }
 
 void arcnet_use_count(int open)
-{ 
+{
   if (open)
     MOD_INC_USE_COUNT;
   else
@@ -1999,14 +1972,14 @@
 int arcnet_num_devs=0;
 char arcnet_dev_names[MAX_ARCNET_DEVS][10];
 
-void arcnet_init(void)
+__initfunc(void arcnet_init(void))
 {
   int c;
-  
-  (void) init_module();
+
+  init_module();
 
   /* Don't register_netdev here. The chain hasn't been initialised. */
-  
+
 #ifdef CONFIG_ARCNET_COM90xx
   if ((!com90xx_explicit) && arcnet_num_devs < MAX_ARCNET_DEVS)
     {
@@ -2020,7 +1993,7 @@
   if (!arcnet_num_devs)
     {
       printk("Don't forget to load the chipset driver.\n");
-      return;  
+      return;
     }
 
   /* Link into the device chain */
@@ -2033,20 +2006,24 @@
 
   arcnet_devs[c].next=dev_base;
   dev_base=&arcnet_devs[0];
-  
+
   /* Give names to those without them */
-  
+
   for (c=0; c< arcnet_num_devs; c++)
     if (!arcnet_dev_names[c][0])
       arcnet_makename((char *)&arcnet_dev_names[c]);
-
 }
-static
+
 #endif /* MODULE */
-int init_module()
+
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(static int init_module(void))
+#endif
 {
- 
-#if 1
+#ifdef ALPHA_WARNING
   BUGLVL(D_EXTRA)
     {
       printk("arcnet: ***\n");
@@ -2058,8 +2035,7 @@
     }
 #endif
 
-  printk("%sGeneric arcnet support for Linux kernel.\n"
-	 "Available protocols: ARCnet RFC1201"
+  printk("%sAvailable protocols: ARCnet RFC1201"
 #ifdef CONFIG_ARCNET_ETH
 	 ", Ethernet-Encap"
 #endif
@@ -2074,50 +2050,20 @@
 }
 
 
-
-
-
 void arcnet_makename(char *device)
 {
-  __u32 arcmask=0;
   struct device *dev;
-  char *c;
   int arcnum;
 
-  for (dev = dev_base; dev; dev=dev->next)
-    {
-      arcnum=0;
-
-      if (!strncmp(dev->name, "arc", 3))
-	{
-	  c = &dev->name[3];
-	  while ((*c)>='0' && (*c)<='9')
-	    {
-	      arcnum *= 10;
-	      arcnum += (*(c++)-'0');
-      	    }
-	  
-	  if (arcnum<32)              
-	    arcmask |= ((__u32)1 << arcnum);
-	}
-      
-      
-    }
-  
-  /* arcmask now holds a mask of the first 32 arcnet names available */
-  
-  if ((__u32)~arcmask)
-    {
-      for (arcnum=0; arcmask&1; arcnum++, arcmask >>=1)
-	;
-      
-      sprintf (device, "arc%d",arcnum);
-    } 
-  else
+  arcnum = 0;
+  for (;;)
     {
-      printk (KERN_INFO "arcnet: Can't find name for device\n");
-      sprintf (device, "arc???");
+      sprintf(device, "arc%d", arcnum);
+      for (dev = dev_base; dev; dev=dev->next)
+	if (dev->name != device && !strcmp(dev->name, device))
+	  break;
+      if (!dev)
+	return;
+      arcnum++;
     }
 }
-
-
diff -u --recursive --new-file v2.1.53/linux/drivers/net/com20020.c linux/drivers/net/com20020.c
--- v2.1.53/linux/drivers/net/com20020.c	Thu Sep  4 17:07:30 1997
+++ linux/drivers/net/com20020.c	Sat Sep  6 10:05:42 1997
@@ -1,4 +1,5 @@
-/* com20020.c:
+/*	$Id: com20020.c,v 1.2 1997/09/05 08:57:50 mj Exp $
+
         Written 1997 by David Woodhouse <dwmw2@cam.ac.uk>
 
 	Derived from the original arcnet.c,
@@ -59,36 +60,6 @@
 #include <net/arp.h>
 
 
-
-
-
-/* External functions from arcnet.c */
-
-
-
-#if ARCNET_DEBUG_MAX & D_SKB
-extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
-			    char *desc);
-#else
-#define arcnet_dump_skb(dev,skb,desc) ;
-#endif
-
-#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
-			       char *desc);
-#else
-#define arcnet_dump_packet(dev,buffer,ext,desc) ;
-#endif
-extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
-extern void arcnet_makename(char *device);
-extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-extern void arcnet_setup(struct device *dev);
-extern int arcnet_go_tx(struct device *dev,int enable_irq);
-extern void arcnetA_continue_tx(struct device *dev);
-extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
-extern void arcnet_use_count(int open);
-
-
 /* Internal function declarations */
 
 static int arc20020_probe(struct device *dev);
@@ -136,7 +107,6 @@
 #endif
 
 
-
 /* Handy defines for ARCnet specific stuff */
 
 static char *clockrates[]={"2.5 Mb/s","1.25Mb/s","625 Kb/s","312.5 Kb/s",
@@ -144,7 +114,7 @@
 		    "Reserved"};
 
 
-/* The number of low I/O ports used by the ethercard. */
+/* The number of low I/O ports used by the card. */
 #define ARCNET_TOTAL_SIZE 9
 
 #define _INTMASK (ioaddr+0)	/* writable */
@@ -156,7 +126,6 @@
 #define _ADDR_HI  (ioaddr+2)     /* Control registers for said */
 #define _ADDR_LO  (ioaddr+3)
 
-
 #define RDDATAflag      0x80     /* Next access is a read/~write */
 #define NEWNXTIDflag    0x02     /* ID to which token is passed has changed */
 
@@ -178,7 +147,6 @@
 		    outb(0x18 , _CONFIG);            \
                   }
 
-
 #define ARCSTATUS	inb(_STATUS)
 #define ACOMMAND(cmd) outb((cmd),_COMMAND)
 #define AINTMASK(msk)	outb((msk),_INTMASK)
@@ -247,7 +215,7 @@
 
 
 static const char *version =
- "com20020.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
+ "com20020.c: v2.92 97/09/02 Avery Pennarun <apenwarr@bond.net> et al.\n";
 
 /****************************************************************************
  *                                                                          *
@@ -256,7 +224,6 @@
  ****************************************************************************/
 
 
-
 /* We cannot probe for an IO mapped card either, although we can check that
  * it's where we were told it was, and even autoirq
  */
@@ -300,15 +267,12 @@
       return -ENODEV;
     }
   
-  
   BUGMSG(D_INIT_REASONS,"Status after reset: %X\n",status);
   
-  
   /* Enable TX */
   outb(0x39,_CONFIG);
   outb(inb(ioaddr+8),ioaddr+7);
   
-  
   ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear);
   
   BUGMSG(D_INIT_REASONS,"Status after reset acknowledged: %X\n",status);
@@ -364,7 +328,6 @@
 }
 
 
-
 /* Set up the struct device associated with this card.  Called after
  * probing succeeds.
  */
@@ -385,12 +348,10 @@
   request_region(ioaddr,ARCNET_TOTAL_SIZE,"arcnet (COM20020)");
   dev->base_addr=ioaddr;
   
-  
   dev->mem_start=dev->mem_end=dev->rmem_start=dev->rmem_end=(long)NULL;
-  
-  
+
   /* Initialize the rest of the device structure. */
-  
+
   dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
   if (dev->priv == NULL)
     {
@@ -404,7 +365,7 @@
   lp=(struct arcnet_local *)(dev->priv);
   lp->card_type = ARC_20020;
   lp->card_type_str = "COM 20020";
-  
+
   lp->arcnet_reset=arc20020_reset;
   lp->asetmask=arc20020_setmask;
   lp->astatus=arc20020_status;
@@ -413,31 +374,30 @@
   lp->openclose_device=arc20020_openclose;
   lp->prepare_tx=arc20020_prepare_tx;
   lp->inthandler=arc20020_inthandler;
-  
-  
+
   dev->set_multicast_list = arc20020_set_mc_list;
-  
+
   /* Fill in the fields of the device structure with generic
    * values.
    */
   arcnet_setup(dev);
-  
+
   /* And now fill particular fields with arcnet values */
   dev->mtu=1500; /* completely arbitrary - agrees with ether, though */
   dev->hard_header_len=sizeof(struct ClientData);
   lp->sequence=1;
   lp->recbuf=0;
-  
+
   BUGMSG(D_DURING,"ClientData header size is %d.\n",
 	 sizeof(struct ClientData));
   BUGMSG(D_DURING,"HardHeader size is %d.\n",
 	 sizeof(struct archdr));
-  
+
   /* get and check the station ID from offset 1 in shmem */
   lp->timeout = dev->dev_addr[3] & 3; dev->dev_addr[3]=0;
   lp->backplane =dev->dev_addr[1] & 1; dev->dev_addr[1]=0;
   lp->setup = (dev->dev_addr[2] & 7) << 1; dev->dev_addr[2]=0;
-  
+
   if (dev->dev_addr[0])
     lp->stationid=dev->dev_addr[0];
   else
@@ -447,11 +407,11 @@
   /* Default 0x38 + register: Node ID */
   SETCONF;
   outb(lp->stationid, ioaddr+7);
-  
+
   REGSETUP;
   SETCONF;
   outb(lp->setup, ioaddr+7);
-  
+
   if (!lp->stationid)
     BUGMSG(D_NORMAL,"WARNING!  Station address 00 is reserved "
 	   "for broadcasts!\n");
@@ -459,19 +419,19 @@
     BUGMSG(D_NORMAL,"WARNING!  Station address FF may confuse "
 	   "DOS networking programs!\n");
   dev->dev_addr[0]=lp->stationid;
-  
+
   BUGMSG(D_NORMAL,"ARCnet COM20020: station %02Xh found at %03lXh, IRQ %d.\n",
 	 lp->stationid, dev->base_addr,dev->irq);
-  
+
   if (lp->backplane)
     BUGMSG (D_NORMAL, "Using backplane mode.\n");
-  
+
   if (lp->timeout != 3)
     BUGMSG (D_NORMAL, "Using Extended Timeout value of %d.\n",lp->timeout);
   if (lp->setup)
     {
       BUGMSG (D_NORMAL, "Using CKP %d - Data rate %s.\n",
-	      lp->setup >>1,clockrates[lp->setup >> 1] );	
+	      lp->setup >>1,clockrates[lp->setup >> 1] );
     }
   return 0;
 }
@@ -479,7 +439,7 @@
 
 /****************************************************************************
  *                                                                          *
- * Utility routines for arcnet.c                                            *
+ * Utility routines                                                         *
  *                                                                          *
  ****************************************************************************/
 
@@ -495,59 +455,59 @@
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   short ioaddr=dev->base_addr;
   int delayval,recbuf=lp->recbuf;
-  
+
   if (reset_delay==3)
     {
       ARCRESET;
       return 0;
     }
-  
+
   /* no IRQ's, please! */
   lp->intmask=0;
   SETMASK;
-  
+
   BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
 	 dev->name,ARCSTATUS);
-  
-  lp->config = 0x20 | (lp->timeout<<3) | (lp->backplane<<2); 
+
+  lp->config = 0x20 | (lp->timeout<<3) | (lp->backplane<<2);
   /* power-up defaults */
   SETCONF;
-  
+
   if (reset_delay)
     {
       /* reset the card */
       ARCRESET;
       JIFFER(RESETtime);
     }
-  
+
   ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */
   ACOMMAND(CFLAGScmd|CONFIGclear);
-  
+
   /* verify that the ARCnet signature byte is present */
-  
+
   if (get_buffer_byte(dev,0) != TESTvalue)
     {
       BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n");
       return 1;
     }
-  
+
   /* clear out status variables */
   recbuf=lp->recbuf=0;
   lp->txbuf=2;
-  
+
   /* enable extended (512-byte) packets */
   ACOMMAND(CONFIGcmd|EXTconf);
-  
+
   /* and enable receive of our first packet to the first buffer */
   EnableReceiver();
-  
+
   /* re-enable interrupts */
   lp->intmask|=NORXflag;
 #ifdef DETECT_RECONFIGS
   lp->intmask|=RECONflag;
 #endif
   SETMASK;
-  
+
   /* done!  return success. */
   return 0;
 }
@@ -565,7 +525,7 @@
 {
   struct arcnet_local *lp=dev->priv;
   int ioaddr=dev->base_addr;
-  
+
   if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP))
     {	/* Enable promiscuous mode */
       if (!(lp->setup & PROMISCflag))
@@ -583,7 +543,7 @@
 	SETCONF;
 	lp->setup &= ~PROMISCflag;
 	outb(lp->setup,ioaddr+7);
-      } 
+      }
 }
 
 
@@ -595,11 +555,12 @@
     MOD_DEC_USE_COUNT;
 }
 
+
 static void arc20020_en_dis_able_TX(struct device *dev, int enable)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   int ioaddr=dev->base_addr;
-  
+
   lp->config=enable?(lp->config | TXENflag):(lp->config & ~TXENflag);
   SETCONF;
 }
@@ -608,10 +569,11 @@
 static void arc20020_setmask(struct device *dev, u_char mask)
 {
   short ioaddr=dev->base_addr;
-  
+
   AINTMASK(mask);
 }
 
+
 static u_char arc20020_status(struct device *dev)
 {
   short ioaddr=dev->base_addr;
@@ -619,6 +581,7 @@
   return ARCSTATUS;
 }
 
+
 static void arc20020_command(struct device *dev, u_char cmd)
 {
   short ioaddr=dev->base_addr;
@@ -634,22 +597,20 @@
 arc20020_inthandler(struct device *dev)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
-  int ioaddr=dev->base_addr, status, boguscount = 3, didsomething, 
+  int ioaddr=dev->base_addr, status, boguscount = 3, didsomething,
     dstatus;
-  
-	
-    
+
   AINTMASK(0);
-  
+
   BUGMSG(D_DURING,"in arc20020_inthandler (status=%Xh, intmask=%Xh)\n",
 	 ARCSTATUS,lp->intmask);
-  
+
   do
     {
       status = ARCSTATUS;
       didsomething=0;
-      
-      
+
+
       /* RESET flag was enabled - card is resetting and if RX
        * is disabled, it's NOT because we just got a packet.
        */
@@ -658,56 +619,53 @@
 	  BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
 		 status);
 	  arc20020_reset(dev,0);
-	  
+
 	  /* all other flag values are just garbage */
 	  break;
 	}
-      
-      
+
       /* RX is inhibited - we must have received something. */
       if (status & lp->intmask & NORXflag)
 	{
 	  int recbuf=lp->recbuf=!lp->recbuf;
 	  int oldaddr=0;
-	  
+
 	  BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
 		 status);
-	  
+
 	  /* enable receive of our next packet */
 	  EnableReceiver();
-	  
+
 	  if (lp->intx)
 	    oldaddr=(inb(_ADDR_HI)<<8) | inb(_ADDR_LO);
-	  
-	  
+
 	  /* Got a packet. */
 	  arc20020_rx(dev,!recbuf);
-	  
-	  
+
 	  if (lp->intx)
 	    {
 	      outb( (oldaddr >> 8),  _ADDR_HI);
 	      outb( oldaddr & 0xff, _ADDR_LO);
 	    }
-	  
+
 	  didsomething++;
 	}
-      
+
       /* it can only be an xmit-done irq if we're xmitting :) */
       /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
       if (status & lp->intmask & TXFREEflag)
 	{
 	  struct Outgoing *out=&(lp->outgoing);
 	  int was_sending=lp->sending;
-	  
+
 	  lp->intmask &= ~TXFREEflag;
-	  
+
 	  lp->in_txhandler++;
 	  if (was_sending) lp->sending--;
-	  
+
 	  BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
 		 status,out->numsegs,out->segnum,out->skb);
-	  
+
 	  if (was_sending && !(status&TXACKflag))
 	    {
 	      if (lp->lasttrans_dest != 0)
@@ -724,11 +682,11 @@
 			 lp->lasttrans_dest);
 		}
 	    }
-	  
+
 	  /* send packet if there is one */
 	  arcnet_go_tx(dev,0);
 	  didsomething++;
-	  
+
 	  if (lp->intx)
 	    {
 	      BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
@@ -736,24 +694,24 @@
 	      lp->in_txhandler--;
 	      continue;
 	    }
-	  
+
 	  if (!lp->outgoing.skb)
 	    {
 	      BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
-	      
+
 	      /* inform upper layers */
 	      if (!lp->txready) arcnet_tx_done(dev, lp);
 	      lp->in_txhandler--;
 	      continue;
 	    }
-	  
+
 	  /* if more than one segment, and not all segments
 	   * are done, then continue xmit.
 	   */
 	  if (out->segnum<out->numsegs)
 	    arcnetA_continue_tx(dev);
 	  arcnet_go_tx(dev,0);
-	  
+
 	  /* if segnum==numsegs, the transmission is finished;
 	   * free the skb.
 	   */
@@ -767,12 +725,12 @@
 		  dev_kfree_skb(out->skb,FREE_WRITE);
 		}
 	      out->skb=NULL;
-	      
+
 	      /* inform upper layers */
 	      if (!lp->txready) arcnet_tx_done(dev, lp);
 	    }
 	  didsomething++;
-	  
+
 	  lp->in_txhandler--;
 	}
       else if (lp->txready && !lp->sending && !lp->intx)
@@ -782,27 +740,26 @@
 	  arcnet_go_tx(dev,0);
 	  didsomething++;
 	}
-      
+
       if ((dstatus=inb(_DIAGSTAT)) & NEWNXTIDflag)
 	{
 	  REGNXTID;
 	  SETCONF;
 	  BUGMSG(D_EXTRA,"New NextID detected: %X\n",inb(ioaddr+7));
 	}
-      
-      
+
+
 #ifdef DETECT_RECONFIGS
       if (status & (lp->intmask) & RECONflag)
 	{
 	  ACOMMAND(CFLAGScmd|CONFIGclear);
 	  lp->stats.tx_carrier_errors++;
-	  
+
 #ifdef SHOW_RECONFIGS
-	  
 	  BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh, diag status=%Xh, config=%X)\n",
 		 status,dstatus,lp->config);
 #endif /* SHOW_RECONFIGS */
-	  
+
 #ifdef RECON_THRESHOLD
 	  /* is the RECON info empty or old? */
 	  if (!lp->first_recon || !lp->last_recon ||
@@ -812,19 +769,19 @@
 		BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
 	      lp->first_recon=lp->last_recon=jiffies;
 	      lp->num_recons=lp->network_down=0;
-	      
+
 	      BUGMSG(D_DURING,"recon: clearing counters.\n");
 	    }
 	  else /* add to current RECON counter */
 	    {
 	      lp->last_recon=jiffies;
 	      lp->num_recons++;
-	      
+
 	      BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
 		     lp->num_recons,
 		     (lp->last_recon-lp->first_recon)/HZ,
 		     lp->network_down);
-	      
+
 	      /* if network is marked up;
 	       * and first_recon and last_recon are 60+ sec
 	       *   apart;
@@ -856,26 +813,25 @@
 	    BUGMSG(D_NORMAL,"cabling restored?\n");
 	  lp->first_recon=lp->last_recon=0;
 	  lp->num_recons=lp->network_down=0;
-	  
+
 	  BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
 #endif
 	}
 #endif /* DETECT_RECONFIGS */
     } while (--boguscount && didsomething);
-  
+
   BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n",
 	 ARCSTATUS,boguscount);
   BUGMSG(D_DURING,"\n");
-  
+
   SETMASK;	/* put back interrupt mask */
-  
-}
 
+}
 
 
 /* A packet has arrived; grab it from the buffers and pass it to the generic
  * arcnet_rx routing to deal with it.
- */ 
+ */
 
 static void
 arc20020_rx(struct device *dev,int recbuf)
@@ -887,13 +843,13 @@
   u_char *arcsoft;
   short length,offset;
   u_char daddr,saddr;
-  
+
   lp->stats.rx_packets++;
-  
+
   get_whole_buffer(dev,recbuf*512,4,(char *)arcpacket);
-  
+
   saddr=arcpacket->hardheader.source;
-  
+
   /* if source is 0, it's a "used" packet! */
   if (saddr==0)
     {
@@ -903,13 +859,13 @@
       return;
     }
   /* Set source address to zero to mark it as old */
-  
+
   put_buffer_byte(dev,recbuf*512,0);
-  
+
   arcpacket->hardheader.source=0;
-  
+
   daddr=arcpacket->hardheader.destination;
-  
+
   if (arcpacket->hardheader.offset1) /* Normal Packet */
     {
       offset=arcpacket->hardheader.offset1;
@@ -922,16 +878,15 @@
       arcsoft=&arcpacket->raw[offset];
       length=512-offset;
     }
-  
+
   get_whole_buffer(dev,recbuf*512+offset,length,(char *)arcpacket+offset);
-  
+
   arcnet_rx(lp, arcsoft, length, saddr, daddr);
-  
+
   BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx");
 }
 
 
-
 /* Given an skb, copy a packet into the ARCnet buffers for later transmission
  * by arcnet_go_tx.
  */
@@ -940,20 +895,20 @@
 		    char *data,int length,int daddr,int exceptA, int offset)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   lp->txbuf=lp->txbuf^1;	/* XOR with 1 to alternate between 2 and 3 */
-  
+
   length+=hdrlen;
-  
+
   BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
 	 hdr,length,data);
-  
+
   put_buffer_byte(dev, lp->txbuf*512+1, daddr);
 
   /* load packet into shared memory */
   if (length<=MTU)	/* Normal (256-byte) Packet */
     put_buffer_byte(dev, lp->txbuf*512+2, offset=offset?offset:256-length);
-  
+
   else if (length>=MinTU || offset)	/* Extended (512-byte) Packet */
     {
       put_buffer_byte(dev, lp->txbuf*512+2, 0);
@@ -963,36 +918,36 @@
     {
       put_buffer_byte(dev, lp->txbuf*512+2, 0);
       put_buffer_byte(dev, lp->txbuf*512+3, offset=512-length-4);
-      
+
       /* exception-specific stuff - these four bytes
        * make the packet long enough to fit in a 512-byte
        * frame.
        */
-      
+
       put_whole_buffer(dev, lp->txbuf*512+offset,4,"\0\0xff\0xff\0xff");
       offset+=4;
     }
   else				/* "other" Exception packet */
     {
       /* RFC1051 - set 4 trailing bytes to 0 */
-      
+
       put_whole_buffer(dev,lp->txbuf*512+508,4,"\0\0\0\0");
-      
+
       /* now round up to MinTU */
       put_buffer_byte(dev, lp->txbuf*512+2, 0);
       put_buffer_byte(dev, lp->txbuf*512+3, offset=512-MinTU);
     }
-  
+
   /* copy the packet into ARCnet shmem
    *  - the first bytes of ClientData header are skipped
    */
-  
+
   put_whole_buffer(dev, 512*lp->txbuf+offset, hdrlen,(u_char *)hdr);
   put_whole_buffer(dev, 512*lp->txbuf+offset+hdrlen,length-hdrlen,data);
-  
+
   BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
 	 daddr,length);
-  
+
   lp->lastload_dest=daddr;
   lp->txready=lp->txbuf;	/* packet is ready for sending */
 }
@@ -1014,13 +969,13 @@
 int init_module(void)
 {
   struct device *dev;
-  
+
   cards[0]=dev=(struct device *)kmalloc(sizeof(struct device), GFP_KERNEL);
   if (!dev)
     return -ENOMEM;
-  
+
   memset(dev, 0, sizeof(struct device));
-  
+
   dev->name=(char *)kmalloc(9, GFP_KERNEL);
   if (!dev->name)
     {
@@ -1035,19 +990,19 @@
 
   if (node && node != 0xff)
     dev->dev_addr[0]=node;
-  
+
   if (backplane) dev->dev_addr[1]=backplane?1:0;
   if (clock) dev->dev_addr[2]=clock&7;
   dev->dev_addr[3]=timeout&3;
 
   dev->base_addr=io;
   dev->irq=irq;
-  
+
   if (dev->irq==2) dev->irq=9;
 
   if (register_netdev(dev) != 0)
     return -EIO;
-  
+
   /* Increase use count of arcnet.o */
   arcnet_use_count(1);
 
@@ -1058,9 +1013,9 @@
 {
   struct device *dev=cards[0];
   int ioaddr=dev->base_addr;
-  
+
   if (dev->start) (*dev->stop)(dev);
-  
+
   /* Flush TX and disable RX */
   if (ioaddr)
     {
@@ -1068,21 +1023,22 @@
       ACOMMAND(NOTXcmd);	/* stop transmit */
       ACOMMAND(NORXcmd);	/* disable receive */
     }
-  
+
   if (dev->irq)
     {
       irq2dev_map[dev->irq] = NULL;
       free_irq(dev->irq,NULL);
     }
-  
+
   if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE);
   unregister_netdev(dev);
   kfree(dev->priv);
   dev->priv = NULL;
-  
+
   /* Decrease use count of arcnet.o */
   arcnet_use_count(0);
 }
+
 #else
 
 __initfunc(void com20020_setup (char *str, int *ints))
@@ -1095,9 +1051,9 @@
 	     MAX_ARCNET_DEVS);
       return;
     }
-  
+
   dev=&arcnet_devs[arcnet_num_devs];
-  
+
   if (ints[0] < 1)
     {
       printk("com20020: You must give an IO address.\n");
@@ -1126,19 +1082,16 @@
 
     case 2: /* IRQ */
       dev->irq=ints[2];
-      
+
     case 1: /* IO address */
       dev->base_addr=ints[1];
     }
 
   dev->name = (char *)&arcnet_dev_names[arcnet_num_devs];
-  
+
   if (str)
     strncpy(dev->name, str, 9);
-  
+
   arcnet_num_devs++;
 }
 #endif /* MODULE */
-
-
-
diff -u --recursive --new-file v2.1.53/linux/drivers/net/com90io.c linux/drivers/net/com90io.c
--- v2.1.53/linux/drivers/net/com90io.c	Thu Sep  4 17:07:30 1997
+++ linux/drivers/net/com90io.c	Sat Sep  6 10:05:42 1997
@@ -1,11 +1,12 @@
-/* com90io.c:
+/*	$Id: com90io.c,v 1.2 1997/09/05 08:57:52 mj Exp $
+
         Written 1997 by David Woodhouse <dwmw2@cam.ac.uk>
 
 	Derived from the original arcnet.c,
 	Written 1994-1996 by Avery Pennarun,
 	which was in turn derived from skeleton.c by Donald Becker.
 
-	Contact Avery at: apenwarr@foxnet.net or
+	Contact Avery at: apenwarr@bond.net or
 	RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
 
 	**********************
@@ -59,36 +60,6 @@
 #include <net/arp.h>
 
 
-
-
-
-/* External functions from arcnet.c */
-
-
-
-#if ARCNET_DEBUG_MAX & D_SKB
-extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
-			    char *desc);
-#else
-#define arcnet_dump_skb(dev,skb,desc) ;
-#endif
-
-#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
-			       char *desc);
-#else
-#define arcnet_dump_packet(dev,buffer,ext,desc) ;
-#endif
-extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
-extern void arcnet_makename(char *device);
-extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-extern void arcnet_setup(struct device *dev);
-extern int arcnet_go_tx(struct device *dev,int enable_irq);
-extern void arcnetA_continue_tx(struct device *dev);
-extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
-extern void arcnet_use_count(int open);
-
-
 /* Internal function declarations */
 
 static int arc90io_probe(struct device *dev);
@@ -127,13 +98,12 @@
 #endif
 
 
-
 /* Handy defines for ARCnet specific stuff */
 
-/* The number of low I/O ports used by the ethercard. */
+/* The number of low I/O ports used by the card. */
 #define ARCNET_TOTAL_SIZE 16
 
-	/* COM 9026 controller chip --> ARCnet register addresses */
+/* COM 9026 controller chip --> ARCnet register addresses */
 #define _INTMASK (ioaddr+0)	/* writable */
 #define _STATUS  (ioaddr+0)	/* readable */
 #define _COMMAND (ioaddr+1)	/* writable, returns random vals on read (?) */
@@ -149,7 +119,6 @@
 
 #define ARCRESET	inb(_RESET)
 
-
 #define SETCONF 	outb((lp->config),_CONFIG)
 
 
@@ -163,7 +132,7 @@
 {
   int ioaddr=dev->base_addr;
 
-  outb(offset >> 8,  _ADDR_HI); 
+  outb(offset >> 8,  _ADDR_HI);
   outb(offset & 0xff, _ADDR_LO);
 
   return inb(_MEMDATA);
@@ -173,7 +142,7 @@
 {
   int ioaddr=dev->base_addr;
 
-  outb(offset >> 8,   _ADDR_HI); 
+  outb(offset >> 8,   _ADDR_HI);
   outb(offset & 0xff, _ADDR_LO);
 
   outb(datum, _MEMDATA);
@@ -204,7 +173,7 @@
 
   outb( (offset >> 8) | AUTOINCflag,   _ADDR_HI);
   outb( offset & 0xff,                 _ADDR_LO);
- 
+
   while (length--)
 #ifdef ONE_AT_A_TIME_TX
     put_buffer_byte(dev,offset++,*(dest++));
@@ -217,14 +186,13 @@
 static const char *version =
  "com90io.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
 
+
 /****************************************************************************
  *                                                                          *
  * Probe and initialization                                                 *
  *                                                                          *
  ****************************************************************************/
 
-
-
 /* We cannot probe for an IO mapped card either, although we can check that
  * it's where we were told it was, and even autoirq
  */
@@ -233,104 +201,100 @@
 {
   int ioaddr=dev->base_addr,status,delayval;
   unsigned long airqmask;
-  
+
   BUGLVL(D_NORMAL) printk(version);
-  
+
   if (ioaddr<0x200)
     {
       BUGMSG(D_NORMAL,"No autoprobe for IO mapped cards; you "
 	     "must specify the base address!\n");
       return -ENODEV;
     }
-  
+
   if (check_region(ioaddr, ARCNET_TOTAL_SIZE))
     {
       BUGMSG(D_INIT_REASONS,"IO check_region %x-%x failed.\n",
 	     ioaddr,ioaddr+ARCNET_TOTAL_SIZE-1);
       return -ENXIO;
     }
-  
+
   if (ARCSTATUS == 0xFF)
     {
       BUGMSG(D_INIT_REASONS,"IO address %x empty\n",ioaddr);
       return -ENODEV;
     }
-  
+
   ARCRESET;
   JIFFER(RESETtime);
-  
+
   status=ARCSTATUS;
-  
+
   if ((status & 0x9D)
       !=  (NORXflag|RECONflag|TXFREEflag|RESETflag))
     {
       BUGMSG(D_INIT_REASONS,"Status invalid (%Xh).\n",status);
       return -ENODEV;
     }
-  
-  
+
   BUGMSG(D_INIT_REASONS,"Status after reset: %X\n",status);
-  
-  
+
   ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear);
-  
+
   BUGMSG(D_INIT_REASONS,"Status after reset acknowledged: %X\n",status);
-  
+
   status=ARCSTATUS;
-  
+
   if (status & RESETflag)
     {
       BUGMSG(D_INIT_REASONS,"Eternal reset (status=%Xh)\n",status);
       return -ENODEV;
     }
-  
+
   outb((0x16 | IOMAPflag) &~ENABLE16flag, _CONFIG);
-  
-  
+
   /* Read first loc'n of memory */
-  
+
   outb(AUTOINCflag ,_ADDR_HI);
   outb(0,_ADDR_LO);
-  
+
   if ((status=inb(_MEMDATA)) != 0xd1)
     {
       BUGMSG(D_INIT_REASONS,"Signature byte not found"
 	     " (%Xh instead).\n", status);
       return -ENODEV;
     }
-  
+
   if (!dev->irq)
     {
       /* if we do this, we're sure to get an IRQ since the
        * card has just reset and the NORXflag is on until
        * we tell it to start receiving.
        */
-      
+
       airqmask = probe_irq_on();
       outb(NORXflag,_INTMASK);
       udelay(1);
       outb(0,_INTMASK);
       dev->irq = probe_irq_off(airqmask);
-      
+
       if (dev->irq<=0)
 	{
 	  BUGMSG(D_INIT_REASONS,"Autoprobe IRQ failed\n");
 	  return -ENODEV;
 	}
     }
-  
+
   return arc90io_found(dev,dev->base_addr,dev->irq);
 }
 
 
-
 /* Set up the struct device associated with this card.  Called after
  * probing succeeds.
  */
 __initfunc(int arc90io_found(struct device *dev,int ioaddr,int airq))
 {
   struct arcnet_local *lp;
-  
+
   /* reserve the irq */
   if (request_irq(airq,&arcnet_interrupt,0,"arcnet (COM90xx-IO)",NULL))
     {
@@ -339,17 +303,15 @@
     }
   irq2dev_map[airq]=dev;
   dev->irq=airq;
-  
+
   /* reserve the I/O region - guaranteed to work by check_region */
   request_region(ioaddr,ARCNET_TOTAL_SIZE,"arcnet (COM90xx-IO)");
   dev->base_addr=ioaddr;
-  
-  
+
   dev->mem_start=dev->mem_end=dev->rmem_start=dev->rmem_end=(long)NULL;
-  
-  
+
   /* Initialize the rest of the device structure. */
-  
+
   dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
   if (dev->priv == NULL)
     {
@@ -363,7 +325,7 @@
   lp=(struct arcnet_local *)(dev->priv);
   lp->card_type = ARC_90xx_IO;
   lp->card_type_str = "COM 90xx (IO)";
-  
+
   lp->arcnet_reset=arc90io_reset;
   lp->asetmask=arc90io_setmask;
   lp->astatus=arc90io_status;
@@ -371,33 +333,30 @@
   lp->openclose_device=arc90io_openclose;
   lp->prepare_tx=arc90io_prepare_tx;
   lp->inthandler=arc90io_inthandler;
-  
-  
 
-  
   /* Fill in the fields of the device structure with generic
    * values.
    */
   arcnet_setup(dev);
-  
+
   /* And now fill particular fields with arcnet values */
   dev->mtu=1500; /* completely arbitrary - agrees with ether, though */
   dev->hard_header_len=sizeof(struct ClientData);
   lp->sequence=1;
   lp->recbuf=0;
-  
+
   BUGMSG(D_DURING,"ClientData header size is %d.\n",
 	 sizeof(struct ClientData));
   BUGMSG(D_DURING,"HardHeader size is %d.\n",
 	 sizeof(struct archdr));
-  
+
   lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag;
   SETCONF;
-  
+
   /* get and check the station ID from offset 1 in shmem */
 
   lp->stationid = get_buffer_byte(dev,1);
-  
+
   if (!lp->stationid)
     BUGMSG(D_NORMAL,"WARNING!  Station address 00 is reserved "
 	   "for broadcasts!\n");
@@ -405,19 +364,19 @@
     BUGMSG(D_NORMAL,"WARNING!  Station address FF may confuse "
 	   "DOS networking programs!\n");
   dev->dev_addr[0]=lp->stationid;
-  
+
   BUGMSG(D_NORMAL,"ARCnet COM90xx in IO-mapped mode:  "
 	 "station %02Xh found at %03lXh, IRQ %d.\n",
 	 lp->stationid,
 	 dev->base_addr,dev->irq);
-  
+
   return 0;
 }
 
 
 /****************************************************************************
  *                                                                          *
- * Utility routines for arcnet.c                                            *
+ * Utility routines                                                         *
  *                                                                          *
  ****************************************************************************/
 
@@ -433,59 +392,59 @@
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   short ioaddr=dev->base_addr;
   int delayval,recbuf=lp->recbuf;
-  
+
   if (reset_delay==3)
     {
       ARCRESET;
       return 0;
     }
-  
+
   /* no IRQ's, please! */
   lp->intmask=0;
   SETMASK;
-  
+
   BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
 	 dev->name,ARCSTATUS);
-  
+
   /* Set the thing to IO-mapped, 8-bit  mode */
   lp->config = (0x1C|IOMAPflag) & ~ENABLE16flag;
   SETCONF;
-  
+
   if (reset_delay)
     {
       /* reset the card */
       ARCRESET;
       JIFFER(RESETtime);
     }
-  
+
   ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */
   ACOMMAND(CFLAGScmd|CONFIGclear);
-  
+
   /* verify that the ARCnet signature byte is present */
-  
+
   if (get_buffer_byte(dev,0) != TESTvalue)
     {
       BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n");
       return 1;
     }
-  
+
   /* clear out status variables */
   recbuf=lp->recbuf=0;
   lp->txbuf=2;
-  
+
   /* enable extended (512-byte) packets */
   ACOMMAND(CONFIGcmd|EXTconf);
-  
+
   /* and enable receive of our first packet to the first buffer */
   EnableReceiver();
-  
+
   /* re-enable interrupts */
   lp->intmask|=NORXflag;
 #ifdef DETECT_RECONFIGS
   lp->intmask|=RECONflag;
 #endif
   SETMASK;
-  
+
   /* done!  return success. */
   return 0;
 }
@@ -500,11 +459,10 @@
 }
 
 
-
 static void arc90io_setmask(struct device *dev, u_char mask)
 {
   short ioaddr=dev->base_addr;
-  
+
   AINTMASK(mask);
 }
 
@@ -530,22 +488,18 @@
 arc90io_inthandler(struct device *dev)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
-  int ioaddr=dev->base_addr, status, boguscount = 3, didsomething; 
+  int ioaddr=dev->base_addr, status, boguscount = 3, didsomething;
 
-  
-	
-    
   AINTMASK(0);
-  
+
   BUGMSG(D_DURING,"in arc90io_inthandler (status=%Xh, intmask=%Xh)\n",
 	 ARCSTATUS,lp->intmask);
-  
+
   do
     {
       status = ARCSTATUS;
       didsomething=0;
-      
-      
+
       /* RESET flag was enabled - card is resetting and if RX
        * is disabled, it's NOT because we just got a packet.
        */
@@ -554,56 +508,55 @@
 	  BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
 		 status);
 	  arc90io_reset(dev,0);
-	  
+
 	  /* all other flag values are just garbage */
 	  break;
 	}
-      
-      
+
       /* RX is inhibited - we must have received something. */
       if (status & lp->intmask & NORXflag)
 	{
 	  int recbuf=lp->recbuf=!lp->recbuf;
 	  int oldaddr=0;
-	  
+
 	  BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
 		 status);
-	  
+
 	  /* enable receive of our next packet */
 	  EnableReceiver();
-	  
+
 	  if (lp->intx)
 	    oldaddr=(inb(_ADDR_HI)<<8) | inb(_ADDR_LO);
-	  
-	  
+
+
 	  /* Got a packet. */
 	  arc90io_rx(dev,!recbuf);
-	  
-	  
+
+
 	  if (lp->intx)
 	    {
 	      outb( (oldaddr >> 8),  _ADDR_HI);
 	      outb( oldaddr & 0xff, _ADDR_LO);
 	    }
-	  
+
 	  didsomething++;
 	}
-      
+
       /* it can only be an xmit-done irq if we're xmitting :) */
       /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
       if (status & lp->intmask & TXFREEflag)
 	{
 	  struct Outgoing *out=&(lp->outgoing);
 	  int was_sending=lp->sending;
-	  
+
 	  lp->intmask &= ~TXFREEflag;
-	  
+
 	  lp->in_txhandler++;
 	  if (was_sending) lp->sending--;
-	  
+
 	  BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
 		 status,out->numsegs,out->segnum,out->skb);
-	  
+
 	  if (was_sending && !(status&TXACKflag))
 	    {
 	      if (lp->lasttrans_dest != 0)
@@ -620,11 +573,11 @@
 			 lp->lasttrans_dest);
 		}
 	    }
-	  
+
 	  /* send packet if there is one */
 	  arcnet_go_tx(dev,0);
 	  didsomething++;
-	  
+
 	  if (lp->intx)
 	    {
 	      BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
@@ -632,24 +585,24 @@
 	      lp->in_txhandler--;
 	      continue;
 	    }
-	  
+
 	  if (!lp->outgoing.skb)
 	    {
 	      BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
-	      
+
 	      /* inform upper layers */
 	      if (!lp->txready) arcnet_tx_done(dev, lp);
 	      lp->in_txhandler--;
 	      continue;
 	    }
-	  
+
 	  /* if more than one segment, and not all segments
 	   * are done, then continue xmit.
 	   */
 	  if (out->segnum<out->numsegs)
 	    arcnetA_continue_tx(dev);
 	  arcnet_go_tx(dev,0);
-	  
+
 	  /* if segnum==numsegs, the transmission is finished;
 	   * free the skb.
 	   */
@@ -663,12 +616,12 @@
 		  dev_kfree_skb(out->skb,FREE_WRITE);
 		}
 	      out->skb=NULL;
-	      
+
 	      /* inform upper layers */
 	      if (!lp->txready) arcnet_tx_done(dev, lp);
 	    }
 	  didsomething++;
-	  
+
 	  lp->in_txhandler--;
 	}
       else if (lp->txready && !lp->sending && !lp->intx)
@@ -678,21 +631,19 @@
 	  arcnet_go_tx(dev,0);
 	  didsomething++;
 	}
-      
-      
+
 #ifdef DETECT_RECONFIGS
       if (status & (lp->intmask) & RECONflag)
 	{
 	  ACOMMAND(CFLAGScmd|CONFIGclear);
 	  lp->stats.tx_carrier_errors++;
-	  
+
 #ifdef SHOW_RECONFIGS
-	  
 	  BUGMSG(D_NORMAL,"Network reconfiguration detected"
 		 " (status=%Xh, config=%X)\n",
 		 status,lp->config);
 #endif /* SHOW_RECONFIGS */
-	  
+
 #ifdef RECON_THRESHOLD
 	  /* is the RECON info empty or old? */
 	  if (!lp->first_recon || !lp->last_recon ||
@@ -702,19 +653,19 @@
 		BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
 	      lp->first_recon=lp->last_recon=jiffies;
 	      lp->num_recons=lp->network_down=0;
-	      
+
 	      BUGMSG(D_DURING,"recon: clearing counters.\n");
 	    }
 	  else /* add to current RECON counter */
 	    {
 	      lp->last_recon=jiffies;
 	      lp->num_recons++;
-	      
+
 	      BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
 		     lp->num_recons,
 		     (lp->last_recon-lp->first_recon)/HZ,
 		     lp->network_down);
-	      
+
 	      /* if network is marked up;
 	       * and first_recon and last_recon are 60+ sec
 	       *   apart;
@@ -746,26 +697,24 @@
 	    BUGMSG(D_NORMAL,"cabling restored?\n");
 	  lp->first_recon=lp->last_recon=0;
 	  lp->num_recons=lp->network_down=0;
-	  
+
 	  BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
 #endif
 	}
 #endif /* DETECT_RECONFIGS */
     } while (--boguscount && didsomething);
-  
+
   BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n",
 	 ARCSTATUS,boguscount);
   BUGMSG(D_DURING,"\n");
-  
+
   SETMASK;	/* put back interrupt mask */
-  
 }
 
 
-
 /* A packet has arrived; grab it from the buffers and pass it to the generic
  * arcnet_rx routing to deal with it.
- */ 
+ */
 
 static void
 arc90io_rx(struct device *dev,int recbuf)
@@ -777,13 +726,13 @@
   u_char *arcsoft;
   short length,offset;
   u_char daddr,saddr;
-  
+
   lp->stats.rx_packets++;
-  
+
   get_whole_buffer(dev,recbuf*512,4,(char *)arcpacket);
-  
+
   saddr=arcpacket->hardheader.source;
-  
+
   /* if source is 0, it's a "used" packet! */
   if (saddr==0)
     {
@@ -793,13 +742,13 @@
       return;
     }
   /* Set source address to zero to mark it as old */
-  
+
   put_buffer_byte(dev,recbuf*512,0);
-  
+
   arcpacket->hardheader.source=0;
-  
+
   daddr=arcpacket->hardheader.destination;
-  
+
   if (arcpacket->hardheader.offset1) /* Normal Packet */
     {
       offset=arcpacket->hardheader.offset1;
@@ -812,16 +761,15 @@
       arcsoft=&arcpacket->raw[offset];
       length=512-offset;
     }
-  
+
   get_whole_buffer(dev,recbuf*512+offset,length,(char *)arcpacket+offset);
-  
+
   arcnet_rx(lp, arcsoft, length, saddr, daddr);
-  
+
   BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx");
 }
 
 
-
 /* Given an skb, copy a packet into the ARCnet buffers for later transmission
  * by arcnet_go_tx.
  */
@@ -830,20 +778,20 @@
 		    char *data,int length,int daddr,int exceptA, int offset)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   lp->txbuf=lp->txbuf^1;	/* XOR with 1 to alternate between 2 and 3 */
-  
+
   length+=hdrlen;
-  
+
   BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
 	 hdr,length,data);
-  
+
   put_buffer_byte(dev, lp->txbuf*512+1, daddr);
 
   /* load packet into shared memory */
   if (length<=MTU)	/* Normal (256-byte) Packet */
     put_buffer_byte(dev, lp->txbuf*512+2, offset=offset?offset:256-length);
-  
+
   else if (length>=MinTU || offset)	/* Extended (512-byte) Packet */
     {
       put_buffer_byte(dev, lp->txbuf*512+2, 0);
@@ -853,36 +801,36 @@
     {
       put_buffer_byte(dev, lp->txbuf*512+2, 0);
       put_buffer_byte(dev, lp->txbuf*512+3, offset=512-length-4);
-      
+
       /* exception-specific stuff - these four bytes
        * make the packet long enough to fit in a 512-byte
        * frame.
        */
-      
+
       put_whole_buffer(dev, lp->txbuf*512+offset,4,"\0\0xff\0xff\0xff");
       offset+=4;
     }
   else				/* "other" Exception packet */
     {
       /* RFC1051 - set 4 trailing bytes to 0 */
-      
+
       put_whole_buffer(dev,lp->txbuf*512+508,4,"\0\0\0\0");
-      
+
       /* now round up to MinTU */
       put_buffer_byte(dev, lp->txbuf*512+2, 0);
       put_buffer_byte(dev, lp->txbuf*512+3, offset=512-MinTU);
     }
-  
+
   /* copy the packet into ARCnet shmem
    *  - the first bytes of ClientData header are skipped
    */
-  
+
   put_whole_buffer(dev, 512*lp->txbuf+offset, hdrlen,(u_char *)hdr);
   put_whole_buffer(dev, 512*lp->txbuf+offset+hdrlen,length-hdrlen,data);
-  
+
   BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
 	 daddr,length);
-  
+
   lp->lastload_dest=daddr;
   lp->txready=lp->txbuf;	/* packet is ready for sending */
 }
@@ -904,13 +852,13 @@
 int init_module(void)
 {
   struct device *dev=cards[0];
-  
+
   cards[0]=dev=(struct device *)kmalloc(sizeof(struct device), GFP_KERNEL);
   if (!dev)
     return -ENOMEM;
-  
+
   memset(dev, 0, sizeof(struct device));
-  
+
   dev->name=(char *)kmalloc(9, GFP_KERNEL);
   if (!dev->name)
     {
@@ -918,19 +866,19 @@
       return -ENOMEM;
     }
   dev->init=arc90io_probe;
-  
+
   if (device)
     strcpy(dev->name,device);
   else arcnet_makename(dev->name);
 
   dev->base_addr=io;
   dev->irq=irq;
-  
+
   if (dev->irq==2) dev->irq=9;
-  
+
   if (register_netdev(dev) != 0)
     return -EIO;
-  
+
   /* Increase use count of arcnet.o */
   arcnet_use_count(1);
   return 0;
@@ -940,9 +888,9 @@
 {
   struct device *dev=cards[0];
   int ioaddr=dev->base_addr;
-  
+
   if (dev->start) (*dev->stop)(dev);
-  
+
   /* Flush TX and disable RX */
   if (ioaddr)
     {
@@ -954,23 +902,23 @@
 	         driver is loaded later */
       outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG);
     }
-  
+
   if (dev->irq)
     {
       irq2dev_map[dev->irq] = NULL;
       free_irq(dev->irq,NULL);
     }
-  
+
   if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE);
   unregister_netdev(dev);
   kfree(dev->priv);
   dev->priv = NULL;
-  
+
   /* Decrease use count of arcnet.o */
   arcnet_use_count(0);
 }
-#else
 
+#else
 
 __initfunc(void com90io_setup (char *str, int *ints))
 {
@@ -982,9 +930,9 @@
 	     MAX_ARCNET_DEVS);
       return;
     }
-  
+
   dev=&arcnet_devs[arcnet_num_devs];
-  
+
   if (ints[0] < 1)
     {
       printk("com90xx IO-MAP: You must give an IO address.\n");
@@ -1000,20 +948,17 @@
 
     case 2: /* IRQ */
       dev->irq=ints[2];
-      
+
     case 1: /* IO address */
       dev->base_addr=ints[1];
     }
 
   dev->name = (char *)&arcnet_dev_names[arcnet_num_devs];
-  
+
   if (str)
     strncpy(dev->name, str, 9);
-  
+
   arcnet_num_devs++;
 }
 
 #endif /* MODULE */
-
-
-
diff -u --recursive --new-file v2.1.53/linux/drivers/net/com90xx.c linux/drivers/net/com90xx.c
--- v2.1.53/linux/drivers/net/com90xx.c	Thu Sep  4 17:07:30 1997
+++ linux/drivers/net/com90xx.c	Sat Sep  6 10:05:42 1997
@@ -1,9 +1,10 @@
-/* com90xx.c:
+/*	$Id: com90xx.c,v 1.3 1997/09/05 18:27:23 mj Exp $
+
 	Derived from the original arcnet.c,
 	Written 1994-1996 by Avery Pennarun,
 	which was in turn derived from skeleton.c by Donald Becker.
 
-	Contact Avery at: apenwarr@foxnet.net or
+	Contact Avery at: apenwarr@bond.net or
 	RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
 
 	**********************
@@ -90,47 +91,13 @@
 #undef FAST_PROBE
 
 
-
-
-
-
-/* External functions from arcnet.c */
-
-
-
-#if ARCNET_DEBUG_MAX & D_SKB
-extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
-			    char *desc);
-#else
-#define arcnet_dump_skb(dev,skb,desc) ;
-#endif
-
-#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
-			       char *desc);
-#else
-#define arcnet_dump_packet(dev,buffer,ext,desc) ;
-#endif
-
-
-extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
-extern void arcnet_makename(char *device);
-extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-extern void arcnet_setup(struct device *dev);
-extern int arcnet_go_tx(struct device *dev,int enable_irq);
-extern void arcnetA_continue_tx(struct device *dev);
-extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
-extern void arcnet_use_count(int open);
-
-
-
 /* Internal function declarations */
-#ifdef MODULE 
-static 
+#ifdef MODULE
+static
 #endif
        int arc90xx_probe(struct device *dev);
 static void arc90xx_rx(struct device *dev,int recbuf);
-static int arc90xx_found(struct device *dev,int ioaddr,int airq,u_long shmem); 
+static int arc90xx_found(struct device *dev,int ioaddr,int airq,u_long shmem,int more);
 static void arc90xx_inthandler (struct device *dev);
 static int arc90xx_reset (struct device *dev, int reset_delay);
 static void arc90xx_setmask (struct device *dev, u_char mask);
@@ -160,18 +127,15 @@
 extern struct device arcnet_devs[];
 extern char arcnet_dev_names[][10];
 extern int arcnet_num_devs;
-
 #endif
 
 
-
-
 /* Handy defines for ARCnet specific stuff */
 
-/* The number of low I/O ports used by the ethercard. */
+/* The number of low I/O ports used by the card. */
 #define ARCNET_TOTAL_SIZE	16
 
-	/* COM 9026 controller chip --> ARCnet register addresses */
+/* COM 9026 controller chip --> ARCnet register addresses */
 #define _INTMASK (ioaddr+0)	/* writable */
 #define _STATUS  (ioaddr+0)	/* readable */
 #define _COMMAND (ioaddr+1)	/* writable, returns random vals on read (?) */
@@ -183,14 +147,14 @@
 
 #define RDDATAflag      0x00     /* Next access is a read/~write */
 
-  #define ARCSTATUS	inb(_STATUS)
-  #define ACOMMAND(cmd) outb((cmd),_COMMAND)
-  #define AINTMASK(msk)	outb((msk),_INTMASK)
-  #define SETCONF	outb(lp->config,_CONFIG)
-  #define ARCRESET	inb(_RESET)
+#define ARCSTATUS	inb(_STATUS)
+#define ACOMMAND(cmd) 	outb((cmd),_COMMAND)
+#define AINTMASK(msk)	outb((msk),_INTMASK)
+#define SETCONF		outb(lp->config,_CONFIG)
+#define ARCRESET	inb(_RESET)
 
 static const char *version =
- "com90xx.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
+ "com90xx.c: v2.92 97/09/02 Avery Pennarun <apenwarr@bond.net> et al.\n";
 
 
 /****************************************************************************
@@ -220,32 +184,28 @@
   static int init_once = 0;
   static int numports=sizeof(ports)/sizeof(ports[0]),
     numshmems=sizeof(shmems)/sizeof(shmems[0]);
-  
   int count,status,delayval,ioaddr,numprint,airq,retval=-ENODEV,
     openparen=0;
   unsigned long airqmask;
   int *port;
   u_long *shmem;
-  
+
   if (!init_once)
     {
       for (count=0x200; count<=0x3f0; count+=16)
 	ports[(count-0x200)/16] = count;
       for (count=0xA0000; count<=0xFF800; count+=2048)
 	shmems[(count-0xA0000)/2048] = count;
-      init_once=1;
-    }
-  
-  BUGLVL(D_NORMAL) printk(version);
-  BUGMSG(D_DURING,"space used for probe buffers: %d+%d=%d bytes\n",
+      BUGLVL(D_NORMAL) printk(version);
+      BUGMSG(D_DURING,"space used for probe buffers: %d+%d=%d bytes\n",
 	 sizeof(ports),sizeof(shmems),
 	 sizeof(ports)+sizeof(shmems));
-  
- 
-  
+    }
+  init_once++;
+
   BUGMSG(D_INIT,"given: base %lXh, IRQ %d, shmem %lXh\n",
 	 dev->base_addr,dev->irq,dev->mem_start);
-  
+
   if (dev->base_addr > 0x1ff)	/* Check a single specified port */
     {
       ports[0]=dev->base_addr;
@@ -253,17 +213,16 @@
     }
   else if (dev->base_addr > 0)	/* Don't probe at all. */
     return -ENXIO;
-  
+
   if (dev->mem_start)
     {
       shmems[0]=dev->mem_start;
       numshmems=1;
     }
-  
-  
+
   /* Stage 1: abandon any reserved ports, or ones with status==0xFF
-	 * (empty), and reset any others by reading the reset port.
-	 */
+   * (empty), and reset any others by reading the reset port.
+   */
   BUGMSG(D_INIT,"Stage 1: ");
   numprint=0;
   for (port = &ports[0]; port-ports<numports; port++)
@@ -276,9 +235,9 @@
 	  numprint=1;
 	}
       BUGMSG2(D_INIT,"%Xh ",*port);
-      
+
       ioaddr=*port;
-      
+
       if (check_region(*port, ARCNET_TOTAL_SIZE))
 	{
 	  BUGMSG2(D_INIT_REASONS,"(check_region)\n");
@@ -289,18 +248,18 @@
 	  port--;
 	  continue;
 	}
-      
+
       if (ARCSTATUS == 0xFF)
 	{
-			BUGMSG2(D_INIT_REASONS,"(empty)\n");
-			BUGMSG(D_INIT_REASONS,"Stage 1: ");
-			BUGLVL(D_INIT_REASONS) numprint=0;
-			*port=ports[numports-1];
-			numports--;
-			port--;
-			continue;
+	  BUGMSG2(D_INIT_REASONS,"(empty)\n");
+	  BUGMSG(D_INIT_REASONS,"Stage 1: ");
+	  BUGLVL(D_INIT_REASONS) numprint=0;
+	  *port=ports[numports-1];
+	  numports--;
+	  port--;
+	  continue;
 	}
-      
+
       ARCRESET;	/* begin resetting card */
 
       BUGMSG2(D_INIT_REASONS,"\n");
@@ -308,279 +267,280 @@
       BUGLVL(D_INIT_REASONS) numprint=0;
     }
   BUGMSG2(D_INIT,"\n");
-  
+
   if (!numports)
     {
       BUGMSG(D_NORMAL,"Stage 1: No ARCnet cards found.\n");
       return -ENODEV;
     }
-  
-  
+
   /* Stage 2: we have now reset any possible ARCnet cards, so we can't
    * do anything until they finish.  If D_INIT, print the list of
    * cards that are left.
    */
-	BUGMSG(D_INIT,"Stage 2: ");
-	numprint=0;
-	for (port = &ports[0]; port-ports<numports; port++)
-	  {
-	    numprint++;
-	    if (numprint>8)
-	      {
-		BUGMSG2(D_INIT,"\n");
-		BUGMSG(D_INIT,"Stage 2: ");
-		numprint=1;
-	      }
-	    BUGMSG2(D_INIT,"%Xh ",*port);
-	  }
-	BUGMSG2(D_INIT,"\n");
-	JIFFER(RESETtime);
-	
-	
-	/* Stage 3: abandon any shmem addresses that don't have the signature
-	 * 0xD1 byte in the right place, or are read-only.
-	 */
-	BUGMSG(D_INIT,"Stage 3: ");
-	numprint=0;
-	for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
-	  {
-	    u_long ptr;
-	    
-		numprint++;
-		if (numprint>8)
-		  {
-		    BUGMSG2(D_INIT,"\n");
-		    BUGMSG(D_INIT,"Stage 3: ");
-		    numprint=1;
-		  }
-		BUGMSG2(D_INIT,"%lXh ",*shmem);
-		
-		ptr=(u_long)(*shmem);
-		
-		if (readb(ptr) != TESTvalue)
-		{
-		  BUGMSG2(D_INIT_REASONS,"(mem=%02Xh, not %02Xh)\n",
-			  readb(ptr),TESTvalue);
-		  BUGMSG(D_INIT_REASONS,"Stage 3: ");
-		  BUGLVL(D_INIT_REASONS) numprint=0;
-		  *shmem=shmems[numshmems-1];
-		  numshmems--;
-		  shmem--;
-		  continue;
-		}
-		
-		/* By writing 0x42 to the TESTvalue location, we also make
-		 * sure no "mirror" shmem areas show up - if they occur
-		 * in another pass through this loop, they will be discarded
-		 * because *cptr != TESTvalue.
-		 */
-		writeb(0x42,ptr);
-		if (readb(ptr) != 0x42)
-		  {
-		    BUGMSG2(D_INIT_REASONS,"(read only)\n");
-		    BUGMSG(D_INIT_REASONS,"Stage 3: ");
-		    *shmem=shmems[numshmems-1];
-		    numshmems--;
-		    shmem--;
-		    continue;
-		  }
-		
-		BUGMSG2(D_INIT_REASONS,"\n");
-		BUGMSG(D_INIT_REASONS,"Stage 3: ");
-		BUGLVL(D_INIT_REASONS) numprint=0;
-	  }
-	BUGMSG2(D_INIT,"\n");
-	
-	if (!numshmems)
-	  {
-	    BUGMSG(D_NORMAL,"Stage 3: No ARCnet cards found.\n");
-	    return -ENODEV;
-	  }
-	
-	/* Stage 4: something of a dummy, to report the shmems that are
-	 * still possible after stage 3.
-	 */
-	BUGMSG(D_INIT,"Stage 4: ");
-	numprint=0;
-	for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
-	  {
-	    numprint++;
-	    if (numprint>8)
-	      {
-		BUGMSG2(D_INIT,"\n");
-		BUGMSG(D_INIT,"Stage 4: ");
-		numprint=1;
-	      }
-	    BUGMSG2(D_INIT,"%lXh ",*shmem);
-	  }
-	BUGMSG2(D_INIT,"\n");
-	
-	
-	/* Stage 5: for any ports that have the correct status, can disable
-	 * the RESET flag, and (if no irq is given) generate an autoirq,
-	 * register an ARCnet device.
-	 *
-	 * Currently, we can only register one device per probe, so quit
-	 * after the first one is found.
-	 */
-	BUGMSG(D_INIT,"Stage 5: ");
-	numprint=0;
-	for (port = &ports[0]; port-ports<numports; port++)
-	  {
-	    numprint++;
-	    if (numprint>8)
-	      {
-		BUGMSG2(D_INIT,"\n");
-		BUGMSG(D_INIT,"Stage 5: ");
-		numprint=1;
-	      }
-	    BUGMSG2(D_INIT,"%Xh ",*port);
-	    
-	    ioaddr=*port;
-	    status=ARCSTATUS;
-	    
-	    if ((status & 0x9D)
-		!= (NORXflag|RECONflag|TXFREEflag|RESETflag))
-	      {
-		BUGMSG2(D_INIT_REASONS,"(status=%Xh)\n",status);
-		BUGMSG(D_INIT_REASONS,"Stage 5: ");
-		BUGLVL(D_INIT_REASONS) numprint=0;
-		*port=ports[numports-1];
-		numports--;
-		port--;
-		continue;
-		}
-	    
-	    ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear);
-	    status=ARCSTATUS;
-	    if (status & RESETflag)
-	      {
-		BUGMSG2(D_INIT_REASONS," (eternal reset, status=%Xh)\n",
-			status);
-		BUGMSG(D_INIT_REASONS,"Stage 5: ");
-		BUGLVL(D_INIT_REASONS) numprint=0;
-			*port=ports[numports-1];
-			numports--;
-			port--;
-			continue;
-	      }
-	    
-	    /* skip this completely if an IRQ was given, because maybe
-	     * we're on a machine that locks during autoirq!
-	     */
-		if (!dev->irq)
-		  {
-		    /* if we do this, we're sure to get an IRQ since the
-		     * card has just reset and the NORXflag is on until
-		     * we tell it to start receiving.
-		     */
-		    airqmask = probe_irq_on();
-		    AINTMASK(NORXflag);
-		    udelay(1);
-		    AINTMASK(0);
-		    airq = probe_irq_off(airqmask);
-
-		    if (airq<=0)
-		      {
-			BUGMSG2(D_INIT_REASONS,"(airq=%d)\n",airq);
-			BUGMSG(D_INIT_REASONS,"Stage 5: ");
-			BUGLVL(D_INIT_REASONS) numprint=0;
-			*port=ports[numports-1];
-			numports--;
-			port--;
-				continue;
-		      }
-		  }
-		else
-		{
-		  airq=dev->irq;
-		}
-		
-		BUGMSG2(D_INIT,"(%d,", airq);
-		openparen=1;
-		
-		/* Everything seems okay.  But which shmem, if any, puts
-		 * back its signature byte when the card is reset?
-		 *
-		 * If there are multiple cards installed, there might be
-		 * multiple shmems still in the list.
-		 */
+  BUGMSG(D_INIT,"Stage 2: ");
+  numprint=0;
+  for (port = &ports[0]; port-ports<numports; port++)
+    {
+      numprint++;
+      if (numprint>8)
+	{
+	  BUGMSG2(D_INIT,"\n");
+	  BUGMSG(D_INIT,"Stage 2: ");
+	  numprint=1;
+	}
+      BUGMSG2(D_INIT,"%Xh ",*port);
+    }
+  BUGMSG2(D_INIT,"\n");
+  JIFFER(RESETtime);
+
+  /* Stage 3: abandon any shmem addresses that don't have the signature
+   * 0xD1 byte in the right place, or are read-only.
+   */
+  BUGMSG(D_INIT,"Stage 3: ");
+  numprint=0;
+  for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
+    {
+      u_long ptr;
+
+      numprint++;
+      if (numprint>8)
+	{
+	  BUGMSG2(D_INIT,"\n");
+	  BUGMSG(D_INIT,"Stage 3: ");
+	  numprint=1;
+	}
+      BUGMSG2(D_INIT,"%lXh ",*shmem);
+
+      ptr=(u_long)(*shmem);
+
+      if (readb(ptr) != TESTvalue)
+	{
+	  BUGMSG2(D_INIT_REASONS,"(mem=%02Xh, not %02Xh)\n",
+		  readb(ptr),TESTvalue);
+	  BUGMSG(D_INIT_REASONS,"Stage 3: ");
+	  BUGLVL(D_INIT_REASONS) numprint=0;
+	  *shmem=shmems[numshmems-1];
+	  numshmems--;
+	  shmem--;
+	  continue;
+	}
+
+      /* By writing 0x42 to the TESTvalue location, we also make
+       * sure no "mirror" shmem areas show up - if they occur
+       * in another pass through this loop, they will be discarded
+       * because *cptr != TESTvalue.
+       */
+      writeb(0x42,ptr);
+      if (readb(ptr) != 0x42)
+	{
+	  BUGMSG2(D_INIT_REASONS,"(read only)\n");
+	  BUGMSG(D_INIT_REASONS,"Stage 3: ");
+	  *shmem=shmems[numshmems-1];
+	  numshmems--;
+	  shmem--;
+	  continue;
+	}
+
+      BUGMSG2(D_INIT_REASONS,"\n");
+      BUGMSG(D_INIT_REASONS,"Stage 3: ");
+      BUGLVL(D_INIT_REASONS) numprint=0;
+    }
+  BUGMSG2(D_INIT,"\n");
+
+  if (!numshmems)
+    {
+      BUGMSG(D_NORMAL,"Stage 3: No ARCnet cards found.\n");
+      return -ENODEV;
+    }
+
+  /* Stage 4: something of a dummy, to report the shmems that are
+   * still possible after stage 3.
+   */
+  BUGMSG(D_INIT,"Stage 4: ");
+  numprint=0;
+  for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
+    {
+      numprint++;
+      if (numprint>8)
+	{
+	  BUGMSG2(D_INIT,"\n");
+	  BUGMSG(D_INIT,"Stage 4: ");
+	  numprint=1;
+	}
+      BUGMSG2(D_INIT,"%lXh ",*shmem);
+    }
+  BUGMSG2(D_INIT,"\n");
+
+  /* Stage 5: for any ports that have the correct status, can disable
+   * the RESET flag, and (if no irq is given) generate an autoirq,
+   * register an ARCnet device.
+   *
+   * Currently, we can only register one device per probe, so quit
+   * after the first one is found.
+   */
+  BUGMSG(D_INIT,"Stage 5: ");
+  numprint=0;
+  for (port = &ports[0]; port-ports<numports; port++)
+    {
+      numprint++;
+      if (numprint>8)
+	{
+	  BUGMSG2(D_INIT,"\n");
+	  BUGMSG(D_INIT,"Stage 5: ");
+	  numprint=1;
+	}
+      BUGMSG2(D_INIT,"%Xh ",*port);
+
+      ioaddr=*port;
+      status=ARCSTATUS;
+
+      if ((status & 0x9D)
+	  != (NORXflag|RECONflag|TXFREEflag|RESETflag))
+	{
+	  BUGMSG2(D_INIT_REASONS,"(status=%Xh)\n",status);
+	  BUGMSG(D_INIT_REASONS,"Stage 5: ");
+	  BUGLVL(D_INIT_REASONS) numprint=0;
+	  *port=ports[numports-1];
+	  numports--;
+	  port--;
+	  continue;
+	}
+
+      ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear);
+      status=ARCSTATUS;
+      if (status & RESETflag)
+	{
+	  BUGMSG2(D_INIT_REASONS," (eternal reset, status=%Xh)\n",
+		  status);
+	  BUGMSG(D_INIT_REASONS,"Stage 5: ");
+	  BUGLVL(D_INIT_REASONS) numprint=0;
+	  *port=ports[numports-1];
+	  numports--;
+	  port--;
+	  continue;
+	}
+
+      /* skip this completely if an IRQ was given, because maybe
+       * we're on a machine that locks during autoirq!
+       */
+      if (!dev->irq)
+	{
+	  /* if we do this, we're sure to get an IRQ since the
+	   * card has just reset and the NORXflag is on until
+	   * we tell it to start receiving.
+	   */
+	  airqmask = probe_irq_on();
+	  AINTMASK(NORXflag);
+	  udelay(1);
+	  AINTMASK(0);
+	  airq = probe_irq_off(airqmask);
+
+	  if (airq<=0)
+	    {
+	      BUGMSG2(D_INIT_REASONS,"(airq=%d)\n",airq);
+	      BUGMSG(D_INIT_REASONS,"Stage 5: ");
+	      BUGLVL(D_INIT_REASONS) numprint=0;
+	      *port=ports[numports-1];
+	      numports--;
+	      port--;
+	      continue;
+	    }
+	}
+      else
+	{
+	  airq=dev->irq;
+	}
+
+      BUGMSG2(D_INIT,"(%d,", airq);
+      openparen=1;
+
+      /* Everything seems okay.  But which shmem, if any, puts
+       * back its signature byte when the card is reset?
+       *
+       * If there are multiple cards installed, there might be
+       * multiple shmems still in the list.
+       */
 #ifdef FAST_PROBE
-		if (numports>1 || numshmems>1)
-		  {
-		    ARCRESET;
-		    JIFFER(RESETtime);
-		  }
-		else
-		  {
-		    /* just one shmem and port, assume they match */
-		    writeb(TESTvalue,shmems[0]);
-		  }
+      if (numports>1 || numshmems>1)
+	{
+	  ARCRESET;
+	  JIFFER(RESETtime);
+	}
+      else
+	{
+	  /* just one shmem and port, assume they match */
+	  writeb(TESTvalue,shmems[0]);
+	}
 #else
-		ARCRESET;
-		JIFFER(RESETtime);
+      ARCRESET;
+      JIFFER(RESETtime);
 #endif
-		
-		
-		for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
-		  {
-		    u_long ptr;
-		    ptr=(u_long)(*shmem);
-		    
-		    if (readb(ptr) == TESTvalue)	/* found one */
-		      {
-			BUGMSG2(D_INIT,"%lXh)\n", *shmem);
-			openparen=0;
-			
-			/* register the card */
-			retval=arc90xx_found(dev,*port,airq,*shmem);
-			if (retval) openparen=0;
-			
-			/* remove shmem from the list */
-			*shmem=shmems[numshmems-1];
-			numshmems--;
-			
-			break;
-		      }
-		    else
-		      {
-			BUGMSG2(D_INIT_REASONS,"%Xh-", readb(ptr));
-		      }
-		  }
-		
-		if (openparen)
-		  {
-		    BUGMSG2(D_INIT,"no matching shmem)\n");
-		    BUGMSG(D_INIT_REASONS,"Stage 5: ");
-		    BUGLVL(D_INIT_REASONS) numprint=0;
-		  }
-		
-		*port=ports[numports-1];
-		numports--;
-		port--;
-		
-		if (!retval) break;
-	  }
-	BUGMSG(D_INIT_REASONS,"\n");
-	
-	/* Now put back TESTvalue on all leftover shmems.
-	 */
-	for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
-	  writeb(TESTvalue,*shmem);
-	
-	if (retval) BUGMSG(D_NORMAL,"Stage 5: No ARCnet cards found.\n");
-	return retval;
+
+      for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
+	{
+	  u_long ptr;
+	  ptr=(u_long)(*shmem);
+
+	  if (readb(ptr) == TESTvalue)	/* found one */
+	    {
+	      int probe_more;
+	      BUGMSG2(D_INIT,"%lXh)\n", *shmem);
+	      openparen=0;
+
+	      /* register the card */
+	      if (init_once == 1 && numshmems > 1)
+		probe_more = numshmems - 1;
+	      else
+		probe_more = 0;
+	      retval=arc90xx_found(dev,*port,airq,*shmem,probe_more);
+	      if (retval) openparen=0;
+
+	      /* remove shmem from the list */
+	      *shmem=shmems[numshmems-1];
+	      numshmems--;
+
+	      break;
+	    }
+	  else
+	    {
+	      BUGMSG2(D_INIT_REASONS,"%Xh-", readb(ptr));
+	    }
+	}
+
+      if (openparen)
+	{
+	  BUGMSG2(D_INIT,"no matching shmem)\n");
+	  BUGMSG(D_INIT_REASONS,"Stage 5: ");
+	  BUGLVL(D_INIT_REASONS) numprint=0;
+	}
+
+      *port=ports[numports-1];
+      numports--;
+      port--;
+
+      if (!retval) break;
+    }
+  BUGMSG(D_INIT_REASONS,"\n");
+
+  /* Now put back TESTvalue on all leftover shmems.
+   */
+  for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
+    writeb(TESTvalue,*shmem);
+
+  if (retval) BUGMSG(D_NORMAL,"Stage 5: No ARCnet cards found.\n");
+  return retval;
 }
 
 /* Set up the struct device associated with this card.  Called after
  * probing succeeds.
  */
-__initfunc(int arc90xx_found(struct device *dev,int ioaddr,int airq, u_long shmem))
+__initfunc(static int arc90xx_found(struct device *dev,int ioaddr,int airq, u_long shmem, int more))
 {
   struct arcnet_local *lp;
   u_long first_mirror,last_mirror;
   int mirror_size;
-  
+
   /* reserve the irq */
   if (request_irq(airq,&arcnet_interrupt,0,"arcnet (90xx)",NULL))
     {
@@ -589,40 +549,39 @@
     }
   irq2dev_map[airq]=dev;
   dev->irq=airq;
-  
-  
+
   /* reserve the I/O region - guaranteed to work by check_region */
   request_region(ioaddr,ARCNET_TOTAL_SIZE,"arcnet (90xx)");
   dev->base_addr=ioaddr;
-  
+
   /* find the real shared memory start/end points, including mirrors */
 #define BUFFER_SIZE (512)
 #define MIRROR_SIZE (BUFFER_SIZE*4)
-  
+
   /* guess the actual size of one "memory mirror" - the number of
-	 * bytes between copies of the shared memory.  On most cards, it's
-	 * 2k (or there are no mirrors at all) but on some, it's 4k.
-	 */
+   * bytes between copies of the shared memory.  On most cards, it's
+   * 2k (or there are no mirrors at all) but on some, it's 4k.
+   */
   mirror_size=MIRROR_SIZE;
   if (readb(shmem)==TESTvalue
       && readb(shmem-mirror_size)!=TESTvalue
       && readb(shmem-2*mirror_size)==TESTvalue)
     mirror_size*=2;
-  
+
   first_mirror=last_mirror=shmem;
   while (readb(first_mirror)==TESTvalue) first_mirror-=mirror_size;
   first_mirror+=mirror_size;
-  
+
   while (readb(last_mirror)==TESTvalue) last_mirror+=mirror_size;
   last_mirror-=mirror_size;
-  
+
   dev->mem_start=first_mirror;
   dev->mem_end=last_mirror+MIRROR_SIZE-1;
   dev->rmem_start=dev->mem_start+BUFFER_SIZE*0;
   dev->rmem_end=dev->mem_start+BUFFER_SIZE*2-1;
-  
-	/* Initialize the rest of the device structure. */
-  
+
+  /* Initialize the rest of the device structure. */
+
   dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
   if (dev->priv == NULL)
     {
@@ -642,27 +601,26 @@
   lp->openclose_device=arc90xx_openclose;
   lp->prepare_tx=arc90xx_prepare_tx;
   lp->inthandler=arc90xx_inthandler;
-  
-  
+
   /* Fill in the fields of the device structure with generic
    * values.
    */
   arcnet_setup(dev);
-  
+
   /* And now fill particular fields with arcnet values */
   dev->mtu=1500; /* completely arbitrary - agrees with ether, though */
   dev->hard_header_len=sizeof(struct ClientData);
   lp->sequence=1;
   lp->recbuf=0;
-  
+
   BUGMSG(D_DURING,"ClientData header size is %d.\n",
 	 sizeof(struct ClientData));
   BUGMSG(D_DURING,"HardHeader size is %d.\n",
 	 sizeof(struct archdr));
-  
+
   /* get and check the station ID from offset 1 in shmem */
   lp->stationid = readb(first_mirror+1);
-  
+
   if (lp->stationid==0)
     BUGMSG(D_NORMAL,"WARNING!  Station address 00 is reserved "
 	   "for broadcasts!\n");
@@ -670,53 +628,35 @@
     BUGMSG(D_NORMAL,"WARNING!  Station address FF may confuse "
 	   "DOS networking programs!\n");
   dev->dev_addr[0]=lp->stationid;
-  
+
   BUGMSG(D_NORMAL,"ARCnet COM90xx: station %02Xh found at %03lXh, IRQ %d, "
 	 "ShMem %lXh (%ld*%xh).\n",
 	 lp->stationid,
 	 dev->base_addr, dev->irq, dev->mem_start,
 	 (dev->mem_end-dev->mem_start+1)/mirror_size,mirror_size);
 
-#ifdef CONFIG_ARCNET_COM90xx
-  /* OK. We're finished. Now do we need to probe for other cards? */
+  /* OK. We're finished. If there are probably other cards, add other
+   * COM90xx drivers to the device chain, so they get probed later.
+   */
 
-  if (!com90xx_explicit)
+#ifndef MODULE
+  while (!com90xx_explicit && more--)
     {
-      /* We need to check whether there's another card here.
-       * Just add another COM90xx driver to the device chain.
-       */
-      
       if (arcnet_num_devs < MAX_ARCNET_DEVS)
 	{
 	  arcnet_devs[arcnet_num_devs].next=dev->next;
 	  dev->next=&arcnet_devs[arcnet_num_devs];
-	  dev->next->name=(char *)&arcnet_dev_names[arcnet_num_devs];
+	  dev=dev->next;
+	  dev->name=(char *)&arcnet_dev_names[arcnet_num_devs];
 	  arcnet_num_devs++;
 	}
       else
 	{
-	  while (dev->next) dev=dev->next;
-	  
-	  dev->next=kmalloc(sizeof(struct device), GFP_KERNEL);
-	  if (!dev->next)
-	    {
-	      BUGMSG(D_NORMAL, "No memory for allocating next device - no more "
-		     "will be probed for.\n");
-	      return 0;
-	    }
-	  memset(dev->next,0,sizeof(struct device));
-	  dev->next->name=kmalloc(10, GFP_KERNEL);
-	  if (!dev->next->name)
-	    {
-	      BUGMSG(D_NORMAL, "No memory for allocating next device - no more "
-		     "will be probed for.\n");
-	      kfree(dev->next);
-	      dev->next=NULL;
-	      return 0;
-	    }
+	  BUGMSG(D_NORMAL, "Too many arcnet devices - no more will be probed for.\n");
+	  return 0;
 	}
-      arcnet_makename(dev->next->name);
-      dev->next->init=arc90xx_probe;      
+      arcnet_makename(dev->name);
+      dev->init=arc90xx_probe;
     }
 #endif
 
@@ -724,7 +664,6 @@
 }
 
 
-
 /* Do a hardware reset on the card, and set up necessary registers.
  *
  * This should be called as little as possible, because it disrupts the
@@ -734,67 +673,68 @@
  */
 int arc90xx_reset(struct device *dev,int reset_delay)
 {
-	struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
-	short ioaddr=dev->base_addr;
-	int delayval,recbuf=lp->recbuf;
+  struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
+  short ioaddr=dev->base_addr;
+  int delayval,recbuf=lp->recbuf;
 
   if (reset_delay==3)
     {
       ARCRESET;
       return 0;
     }
-  
-	/* no IRQ's, please! */
-	lp->intmask=0;
-	SETMASK;
 
-	BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
-			dev->name,ARCSTATUS);
+  /* no IRQ's, please! */
+  lp->intmask=0;
+  SETMASK;
 
-	if (reset_delay)
-	{
-		/* reset the card */
-		ARCRESET;
-		JIFFER(RESETtime);
-	}
+  BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
+	 dev->name,ARCSTATUS);
+
+  if (reset_delay)
+    {
+      /* reset the card */
+      ARCRESET;
+      JIFFER(RESETtime);
+    }
 
-	ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */
-	ACOMMAND(CFLAGScmd|CONFIGclear);
+  ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */
+  ACOMMAND(CFLAGScmd|CONFIGclear);
 
-	/* verify that the ARCnet signature byte is present */
-	if (readb(dev->mem_start) != TESTvalue)
-	{
-		BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n");
-		return 1;
-	}
+  /* verify that the ARCnet signature byte is present */
+  if (readb(dev->mem_start) != TESTvalue)
+    {
+      BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n");
+      return 1;
+    }
 
-	/* clear out status variables */
-	recbuf=lp->recbuf=0;
-	lp->txbuf=2;
+  /* clear out status variables */
+  recbuf=lp->recbuf=0;
+  lp->txbuf=2;
 
-	/* enable extended (512-byte) packets */
-	ACOMMAND(CONFIGcmd|EXTconf);
+  /* enable extended (512-byte) packets */
+  ACOMMAND(CONFIGcmd|EXTconf);
 
 #ifndef SLOW_XMIT_COPY
-	/* clean out all the memory to make debugging make more sense :) */
-	BUGLVL(D_DURING)
-		memset_io(dev->mem_start,0x42,2048);
+  /* clean out all the memory to make debugging make more sense :) */
+  BUGLVL(D_DURING)
+    memset_io(dev->mem_start,0x42,2048);
 #endif
 
-	/* and enable receive of our first packet to the first buffer */
-	EnableReceiver();
+  /* and enable receive of our first packet to the first buffer */
+  EnableReceiver();
 
-	/* re-enable interrupts */
-	lp->intmask|=NORXflag;
+  /* re-enable interrupts */
+  lp->intmask|=NORXflag;
 #ifdef DETECT_RECONFIGS
-	lp->intmask|=RECONflag;
+  lp->intmask|=RECONflag;
 #endif
-	SETMASK;
+  SETMASK;
 
-	/* done!  return success. */
-	return 0;
+  /* done!  return success. */
+  return 0;
 }
 
+
 static void arc90xx_openclose(int open)
 {
  if (open)
@@ -811,6 +751,7 @@
   AINTMASK(mask);
 }
 
+
 static u_char arc90xx_status(struct device *dev)
 {
   short ioaddr=dev->base_addr;
@@ -818,6 +759,7 @@
   return ARCSTATUS;
 }
 
+
 static void arc90xx_command(struct device *dev, u_char cmd)
 {
   short ioaddr=dev->base_addr;
@@ -834,226 +776,219 @@
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   int ioaddr=dev->base_addr, status, boguscount = 3, didsomething;
-  
-  
+
   AINTMASK(0);
-  
+
   BUGMSG(D_DURING,"in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
 	 ARCSTATUS,lp->intmask);
-  
+
   do
     {
       status = ARCSTATUS;
-		didsomething=0;
-		
-		
-		/* RESET flag was enabled - card is resetting and if RX
-		 * is disabled, it's NOT because we just got a packet.
-		 */
-		if (status & RESETflag)
-		  {
-		    BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
-			   status);
-		    arc90xx_reset(dev,0);
-		    
-		    /* all other flag values are just garbage */
-		    break;
-		  }
-		
-		
-		/* RX is inhibited - we must have received something. */
-		if (status & lp->intmask & NORXflag)
-		  {
-		    int recbuf=lp->recbuf=!lp->recbuf;
-		    
-		    BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
-			   status);
-		    
-		    /* enable receive of our next packet */
-		    EnableReceiver();
-		    
-		    /* Got a packet. */
-		    arc90xx_rx(dev,!recbuf);
-			
-		    didsomething++;
-		  }
-		
-		/* it can only be an xmit-done irq if we're xmitting :) */
-		/*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
-		if (status & lp->intmask & TXFREEflag)
-		  {
-		    struct Outgoing *out=&(lp->outgoing);
-		    int was_sending=lp->sending;
-		    
-		    lp->intmask &= ~TXFREEflag;
-		    
-			lp->in_txhandler++;
-			if (was_sending) lp->sending--;
-			
-			BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
-			       status,out->numsegs,out->segnum,out->skb);
-			
-			if (was_sending && !(status&TXACKflag))
-			  {
-			    if (lp->lasttrans_dest != 0)
-			      {
-				BUGMSG(D_EXTRA,"transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n",
-				       status,lp->lasttrans_dest);
-				lp->stats.tx_errors++;
-				lp->stats.tx_carrier_errors++;
-			      }
-			    else
-			      {
-				BUGMSG(D_DURING,"broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n",
-				       status,
-				       lp->lasttrans_dest);
-			      }
-			  }
-			
-			/* send packet if there is one */
-			arcnet_go_tx(dev,0);
-			didsomething++;
-			
-			if (lp->intx)
-			  {
-			    BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
-				   ARCSTATUS,lp->intx);
-			    lp->in_txhandler--;
-			    continue;
-			  }
-			
-			if (!lp->outgoing.skb)
-			  {
-			    BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
-			    
-			    /* inform upper layers */
-			    if (!lp->txready) arcnet_tx_done(dev, lp);
-			    lp->in_txhandler--;
-			    continue;
-			  }
-			
-			/* if more than one segment, and not all segments
-			 * are done, then continue xmit.
-			 */
-			if (out->segnum<out->numsegs)
-			  arcnetA_continue_tx(dev);
-			arcnet_go_tx(dev,0);
-			
-			/* if segnum==numsegs, the transmission is finished;
-			 * free the skb.
-			 */
-			if (out->segnum>=out->numsegs)
-			  {
-			    /* transmit completed */
-			    out->segnum++;
-			    if (out->skb)
-			      {
-				lp->stats.tx_bytes += out->skb->len;
-				dev_kfree_skb(out->skb,FREE_WRITE);
-			      }
-			    out->skb=NULL;
-			    
-			    /* inform upper layers */
-			    if (!lp->txready) arcnet_tx_done(dev, lp);
-			  }
-			didsomething++;
-			
-			lp->in_txhandler--;
-		  }
-		else if (lp->txready && !lp->sending && !lp->intx)
-		  {
-		    BUGMSG(D_NORMAL,"recovery from silent TX (status=%Xh)\n",
-			   status);
-		    arcnet_go_tx(dev,0);
-		    didsomething++;
-		  }
+      didsomething=0;
+
+      /* RESET flag was enabled - card is resetting and if RX
+       * is disabled, it's NOT because we just got a packet.
+       */
+      if (status & RESETflag)
+	{
+	  BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
+		 status);
+	  arc90xx_reset(dev,0);
+
+	  /* all other flag values are just garbage */
+	  break;
+	}
+
+      /* RX is inhibited - we must have received something. */
+      if (status & lp->intmask & NORXflag)
+	{
+	  int recbuf=lp->recbuf=!lp->recbuf;
+
+	  BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
+		 status);
+
+	  /* enable receive of our next packet */
+	  EnableReceiver();
+
+	  /* Got a packet. */
+	  arc90xx_rx(dev,!recbuf);
+
+	  didsomething++;
+	}
+
+      /* it can only be an xmit-done irq if we're xmitting :) */
+      /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
+      if (status & lp->intmask & TXFREEflag)
+	{
+	  struct Outgoing *out=&(lp->outgoing);
+	  int was_sending=lp->sending;
+
+	  lp->intmask &= ~TXFREEflag;
+
+	  lp->in_txhandler++;
+	  if (was_sending) lp->sending--;
+
+	  BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
+		 status,out->numsegs,out->segnum,out->skb);
+
+	  if (was_sending && !(status&TXACKflag))
+	    {
+	      if (lp->lasttrans_dest != 0)
+		{
+		  BUGMSG(D_EXTRA,"transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n",
+			 status,lp->lasttrans_dest);
+		  lp->stats.tx_errors++;
+		  lp->stats.tx_carrier_errors++;
+		}
+	      else
+		{
+		  BUGMSG(D_DURING,"broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n",
+			 status,
+			 lp->lasttrans_dest);
+		}
+	    }
+
+	  /* send packet if there is one */
+	  arcnet_go_tx(dev,0);
+	  didsomething++;
+
+	  if (lp->intx)
+	    {
+	      BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
+		     ARCSTATUS,lp->intx);
+	      lp->in_txhandler--;
+	      continue;
+	    }
+
+	  if (!lp->outgoing.skb)
+	    {
+	      BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
+
+	      /* inform upper layers */
+	      if (!lp->txready) arcnet_tx_done(dev, lp);
+	      lp->in_txhandler--;
+	      continue;
+	    }
+
+	  /* if more than one segment, and not all segments
+	   * are done, then continue xmit.
+	   */
+	  if (out->segnum<out->numsegs)
+	    arcnetA_continue_tx(dev);
+	  arcnet_go_tx(dev,0);
+
+	  /* if segnum==numsegs, the transmission is finished;
+	   * free the skb.
+	   */
+	  if (out->segnum>=out->numsegs)
+	    {
+	      /* transmit completed */
+	      out->segnum++;
+	      if (out->skb)
+		{
+		  lp->stats.tx_bytes += out->skb->len;
+		  dev_kfree_skb(out->skb,FREE_WRITE);
+		}
+	      out->skb=NULL;
+
+	      /* inform upper layers */
+	      if (!lp->txready) arcnet_tx_done(dev, lp);
+	    }
+	  didsomething++;
+
+	  lp->in_txhandler--;
+	}
+      else if (lp->txready && !lp->sending && !lp->intx)
+	{
+	  BUGMSG(D_NORMAL,"recovery from silent TX (status=%Xh)\n",
+		 status);
+	  arcnet_go_tx(dev,0);
+	  didsomething++;
+	}
 
 #ifdef DETECT_RECONFIGS
-		if (status & (lp->intmask) & RECONflag)
-		  {
-		    ACOMMAND(CFLAGScmd|CONFIGclear);
-		    lp->stats.tx_carrier_errors++;
-		    
+      if (status & (lp->intmask) & RECONflag)
+	{
+	  ACOMMAND(CFLAGScmd|CONFIGclear);
+	  lp->stats.tx_carrier_errors++;
+
 #ifdef SHOW_RECONFIGS
-		    BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n",
-			   status);
-		    
-		    
+	  BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n",
+		 status);
 #endif /* SHOW_RECONFIGS */
-		    
+
 #ifdef RECON_THRESHOLD
-		    /* is the RECON info empty or old? */
-		    if (!lp->first_recon || !lp->last_recon ||
-			jiffies-lp->last_recon > HZ*10)
-		      {
-			if (lp->network_down)
-			  BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
-			lp->first_recon=lp->last_recon=jiffies;
-			lp->num_recons=lp->network_down=0;
-			
-			BUGMSG(D_DURING,"recon: clearing counters.\n");
-		      }
-		    else /* add to current RECON counter */
-		      {
-			lp->last_recon=jiffies;
-			lp->num_recons++;
-			
-			BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
-			       lp->num_recons,
-			       (lp->last_recon-lp->first_recon)/HZ,
-			       lp->network_down);
-			
-			/* if network is marked up;
-			 * and first_recon and last_recon are 60+ sec
-			 *   apart;
-			 * and the average no. of recons counted is
-			 *   > RECON_THRESHOLD/min;
-			 * then print a warning message.
-			 */
-			if (!lp->network_down
-			    && (lp->last_recon-lp->first_recon)<=HZ*60
-			    && lp->num_recons >= RECON_THRESHOLD)
-			  {
-			    lp->network_down=1;
-			    BUGMSG(D_NORMAL,"many reconfigurations detected: cabling problem?\n");
-			  }
-			else if (!lp->network_down
-				 && lp->last_recon-lp->first_recon > HZ*60)
-			  {
-			    /* reset counters if we've gone for
-			     * over a minute.
-			     */
-			    lp->first_recon=lp->last_recon;
-			    lp->num_recons=1;
-			  }
-		      }
-		  }
-		else if (lp->network_down && jiffies-lp->last_recon > HZ*10)
-		  {
-		    if (lp->network_down)
-		      BUGMSG(D_NORMAL,"cabling restored?\n");
-		    lp->first_recon=lp->last_recon=0;
-		    lp->num_recons=lp->network_down=0;
-		    
-		    BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
+	  /* is the RECON info empty or old? */
+	  if (!lp->first_recon || !lp->last_recon ||
+	      jiffies-lp->last_recon > HZ*10)
+	    {
+	      if (lp->network_down)
+		BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
+	      lp->first_recon=lp->last_recon=jiffies;
+	      lp->num_recons=lp->network_down=0;
+
+	      BUGMSG(D_DURING,"recon: clearing counters.\n");
+	    }
+	  else /* add to current RECON counter */
+	    {
+	      lp->last_recon=jiffies;
+	      lp->num_recons++;
+
+	      BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
+		     lp->num_recons,
+		     (lp->last_recon-lp->first_recon)/HZ,
+		     lp->network_down);
+
+	      /* if network is marked up;
+	       * and first_recon and last_recon are 60+ sec
+	       *   apart;
+	       * and the average no. of recons counted is
+	       *   > RECON_THRESHOLD/min;
+	       * then print a warning message.
+	       */
+	      if (!lp->network_down
+		  && (lp->last_recon-lp->first_recon)<=HZ*60
+		  && lp->num_recons >= RECON_THRESHOLD)
+		{
+		  lp->network_down=1;
+		  BUGMSG(D_NORMAL,"many reconfigurations detected: cabling problem?\n");
+		}
+	      else if (!lp->network_down
+		       && lp->last_recon-lp->first_recon > HZ*60)
+		{
+		  /* reset counters if we've gone for
+		   * over a minute.
+		   */
+		  lp->first_recon=lp->last_recon;
+		  lp->num_recons=1;
+		}
+	    }
+	}
+      else if (lp->network_down && jiffies-lp->last_recon > HZ*10)
+	{
+	  if (lp->network_down)
+	    BUGMSG(D_NORMAL,"cabling restored?\n");
+	  lp->first_recon=lp->last_recon=0;
+	  lp->num_recons=lp->network_down=0;
+
+	  BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
 #endif
-		  }
+	}
 #endif /* DETECT_RECONFIGS */
     } while (--boguscount && didsomething);
-  
+
   BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n",
 	 ARCSTATUS,boguscount);
   BUGMSG(D_DURING,"\n");
-  
+
   SETMASK;	/* put back interrupt mask */
-  
 }
 
 
-
 /* A packet has arrived; grab it from the buffers and pass it to the generic
  * arcnet_rx routing to deal with it.
- */ 
+ */
 
 static void
 arc90xx_rx(struct device *dev,int recbuf)
@@ -1065,11 +1000,11 @@
   u_char *arcsoft;
   short length,offset;
   u_char daddr,saddr;
-  
+
   lp->stats.rx_packets++;
-  
+
   saddr=arcpacket->hardheader.source;
-  
+
   /* if source is 0, it's a "used" packet! */
   if (saddr==0)
     {
@@ -1079,11 +1014,11 @@
       return;
     }
   /* Set source address to zero to mark it as old */
-  
+
   arcpacket->hardheader.source=0;
-  
+
   daddr=arcpacket->hardheader.destination;
-  
+
   if (arcpacket->hardheader.offset1) /* Normal Packet */
     {
       offset=arcpacket->hardheader.offset1;
@@ -1094,28 +1029,22 @@
     {
       offset=arcpacket->hardheader.offset2;
       arcsoft=&arcpacket->raw[offset];
-      
+
       length=512-offset;
     }
-  
-  
-  arcnet_rx(lp, arcsoft, length, saddr, daddr);
 
+  arcnet_rx(lp, arcsoft, length, saddr, daddr);
 
   BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx");
-   
 
 #ifndef SLOW_XMIT_COPY
   /* clean out the page to make debugging make more sense :) */
   BUGLVL(D_DURING)
     memset((void *)arcpacket->raw,0x42,512);
 #endif
-  
 }
 
 
-
-
 /* Given an skb, copy a packet into the ARCnet buffers for later transmission
  * by arcnet_go_tx.
  */
@@ -1126,45 +1055,45 @@
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   union ArcPacket *arcpacket =
     (union ArcPacket *)phys_to_virt(dev->mem_start+512*(lp->txbuf^1));
-  
+
 #ifdef SLOW_XMIT_COPY
   char *iptr,*iend,*optr;
 #endif
-  
+
   lp->txbuf=lp->txbuf^1;	/* XOR with 1 to alternate between 2 and 3 */
-  
+
   length+=hdrlen;
-  
+
   BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
 	 hdr,length,data);
-  
+
 #ifndef SLOW_XMIT_COPY
   /* clean out the page to make debugging make more sense :) */
   BUGLVL(D_DURING)
     memset_io(dev->mem_start+lp->txbuf*512,0x42,512);
 #endif
-  
+
   arcpacket->hardheader.destination=daddr;
-  
+
   /* load packet into shared memory */
   if (length<=MTU)	/* Normal (256-byte) Packet */
     arcpacket->hardheader.offset1=offset=offset?offset:256-length;
-  
+
   else if (length>=MinTU || offset)	/* Extended (512-byte) Packet */
     {
        arcpacket->hardheader.offset1=0;
-       arcpacket->hardheader.offset2=offset=offset?offset:512-length;   
+       arcpacket->hardheader.offset2=offset=offset?offset:512-length;
     }
   else if (exceptA)		/* RFC1201 Exception Packet */
     {
        arcpacket->hardheader.offset1=0;
        arcpacket->hardheader.offset2=offset=512-length-4;
-       
+
        /* exception-specific stuff - these four bytes
 	* make the packet long enough to fit in a 512-byte
 	* frame.
 	*/
-       
+
        arcpacket->raw[offset+0]=hdr[0];
        arcpacket->raw[offset+1]=0xFF; /* FF flag */
        arcpacket->raw[offset+2]=0xFF; /* FF padding */
@@ -1175,13 +1104,12 @@
     {
       /* RFC1051 - set 4 trailing bytes to 0 */
       memset(&arcpacket->raw[508],0,4);
-      
+
       /* now round up to MinTU */
       arcpacket->hardheader.offset1=0;
       arcpacket->hardheader.offset2=offset=512-MinTU;
     }
-  
-  
+
   /* copy the packet into ARCnet shmem
    *  - the first bytes of ClientData header are skipped
    */
@@ -1197,12 +1125,12 @@
 #else
   memcpy((u_char*)arcpacket+offset+hdrlen, data,length-hdrlen);
 #endif
-   
+
   BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
 	 daddr,length);
-  
+
   BUGLVL(D_TX) arcnet_dump_packet(dev,arcpacket->raw,length>MTU,"tx");
-  
+
   lp->lastload_dest=daddr;
   lp->txready=lp->txbuf;	/* packet is ready for sending */
 }
@@ -1232,12 +1160,12 @@
   if (device)
     strcpy(dev->name,device);
   else arcnet_makename(dev->name);
-  
+
   dev->base_addr=io;
-  
+
   dev->irq=irq;
   if (dev->irq==2) dev->irq=9;
-  
+
   if (shmem)
     {
       dev->mem_start=shmem;
@@ -1245,7 +1173,7 @@
       dev->rmem_start=thiscard.mem_start+512*0;
       dev->rmem_end=thiscard.mem_start+512*2-1;
     }
-  
+
   if (register_netdev(dev) != 0)
     return -EIO;
   arcnet_use_count(1);
@@ -1254,37 +1182,38 @@
 
 void cleanup_module(void)
 {
-	struct device *dev=&thiscard;
-	int ioaddr=dev->mem_start;
+  struct device *dev=&thiscard;
+  int ioaddr=dev->mem_start;
 
-	if (dev->start) (*dev->stop)(dev);
+  if (dev->start) (*dev->stop)(dev);
 
-	/* Flush TX and disable RX */
-	if (ioaddr)
-	{
-		AINTMASK(0);		/* disable IRQ's */
-		ACOMMAND(NOTXcmd);	/* stop transmit */
-		ACOMMAND(NORXcmd);	/* disable receive */
+  /* Flush TX and disable RX */
+  if (ioaddr)
+    {
+      AINTMASK(0);		/* disable IRQ's */
+      ACOMMAND(NOTXcmd);	/* stop transmit */
+      ACOMMAND(NORXcmd);	/* disable receive */
 
 #if defined(IO_MAPPED_BUFFERS) && !defined(COM20020)
-		/* Set the thing back to MMAP mode, in case the old
-        		   driver is loaded later */
-		outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG);
+      /* Set the thing back to MMAP mode, in case the old
+	 driver is loaded later */
+      outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG);
 #endif
-	}
+    }
 
-	if (dev->irq)
-	{
-		irq2dev_map[dev->irq] = NULL;
-		free_irq(dev->irq,NULL);
-	}
+  if (dev->irq)
+    {
+      irq2dev_map[dev->irq] = NULL;
+      free_irq(dev->irq,NULL);
+    }
 
-	if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE);
-	unregister_netdev(dev);
-	kfree(dev->priv);
-	dev->priv = NULL;
-	arcnet_use_count(0);
+  if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE);
+  unregister_netdev(dev);
+  kfree(dev->priv);
+  dev->priv = NULL;
+  arcnet_use_count(0);
 }
+
 #else
 
 __initfunc(void com90xx_setup (char *str, int *ints))
@@ -1297,7 +1226,7 @@
 	     MAX_ARCNET_DEVS);
       return;
     }
-  
+
   if (!ints[0] && (!str || !*str))
     {
       printk("com90xx: Disabled.\n");
@@ -1306,7 +1235,7 @@
     }
 
   dev=&arcnet_devs[arcnet_num_devs];
-  
+
   dev->dev_addr[3]=3;
   dev->init=arc90xx_probe;
 
@@ -1320,13 +1249,13 @@
 
     case 2: /* IRQ */
       dev->irq=ints[2];
-      
+
     case 1: /* IO address */
       dev->base_addr=ints[1];
     }
 
   dev->name = (char *)&arcnet_dev_names[arcnet_num_devs];
-  
+
   if (str)
     strncpy(dev->name, str, 9);
 
diff -u --recursive --new-file v2.1.53/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- v2.1.53/linux/drivers/net/eepro100.c	Wed Sep  3 20:52:42 1997
+++ linux/drivers/net/eepro100.c	Fri Sep  5 20:41:41 1997
@@ -462,13 +462,16 @@
 /* 'options' is used to pass a transceiver override or full-duplex flag
    e.g. "options=16" for FD, "options=32" for 100mbps-only. */
 static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+
 #ifdef MODULE
+
 static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int debug = -1;			/* The debug level */
-#endif
 
 /* A list of all installed Speedo devices, for removing the driver module. */
 static struct device *root_speedo_dev = NULL;
+
+#endif
 
 int eepro100_init(struct device *dev)
 {
diff -u --recursive --new-file v2.1.53/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.1.53/linux/drivers/net/ppp.c	Tue May 13 22:41:09 1997
+++ linux/drivers/net/ppp.c	Sat Sep  6 10:05:42 1997
@@ -521,7 +521,7 @@
 extern inline int
 lock_buffer (register struct ppp_buffer *buf)
 {
-	register int state;
+	register long state;
 	int flags;
 /*
  * Save the current state and if free then set it to the "busy" state
@@ -1071,6 +1071,7 @@
  */
 	if (ppp->flags & SC_LOG_RAWIN)
 		ppp_print_buffer ("receive buffer", data, count);
+
 /*
  * Collect the character and error condition for the character. Set the toss
  * flag for the first character error.
@@ -1083,6 +1084,7 @@
 				ppp->toss = *flags;
 			++flags;
 		}
+
 /*
  * Set the flags for 8 data bits and no parity.
  *
@@ -1467,6 +1469,7 @@
 {
 	__u16		proto = PPP_PROTOCOL (data);
 	ppp_proto_type	*proto_ptr;
+
 /*
  * Ignore empty frames
  */
@@ -1507,6 +1510,7 @@
 	int	addr, ctrl, proto;
 	int	new_count;
 	__u8 *new_data;
+
 /*
  * If there is a pending error from the receiver then log it and discard
  * the damaged frame.
diff -u --recursive --new-file v2.1.53/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.1.53/linux/drivers/pci/pci.c	Thu Aug 14 20:49:16 1997
+++ linux/drivers/pci/pci.c	Sat Sep  6 10:43:50 1997
@@ -1,5 +1,5 @@
 /*
- * drivers/pci/pci.c
+ * $Id: pci.c,v 1.44 1997/09/03 05:08:22 richard Exp $
  *
  * PCI services that are built on top of the BIOS32 service.
  *
@@ -20,7 +20,6 @@
 struct pci_bus pci_root;
 struct pci_dev *pci_devices = 0;
 
-
 /*
  * The bridge_id field is an offset of an item into the array
  * BRIDGE_MAPPING_TYPE. 0xff indicates that the device is not a PCI
@@ -68,6 +67,7 @@
 	DEVICE( VLSI,		VLSI_82C597,	"82C597-AFC2"),
 	DEVICE( VLSI,		VLSI_VAS96011,	"VAS96011 PowerPC"),
 	DEVICE( ADL,		ADL_2301,	"2301"),
+	DEVICE( NS,		NS_87415,	"87415"),
 	DEVICE( NS,		NS_87410,	"87410"),
 	DEVICE( TSENG,		TSENG_W32P_2,	"ET4000W32P"),
 	DEVICE( TSENG,		TSENG_W32P_b,	"ET4000W32P rev B"),
@@ -78,8 +78,9 @@
 	DEVICE( WEITEK,		WEITEK_P9100,	"P9100"),
 	BRIDGE( DEC,		DEC_BRD,	"DC21050", 		0x00),
 	DEVICE( DEC,		DEC_TULIP,	"DC21040"),
-	DEVICE( DEC,		DEC_TGA,	"DC21030"),
+	DEVICE( DEC,		DEC_TGA,	"TGA"),
 	DEVICE( DEC,		DEC_TULIP_FAST,	"DC21140"),
+	DEVICE( DEC,		DEC_TGA2,	"TGA2"),
 	DEVICE( DEC,		DEC_FDDI,	"DEFPA"),
 	DEVICE( DEC,		DEC_TULIP_PLUS,	"DC21041"),
 	DEVICE( DEC,		DEC_21142,	"DC21142"),
@@ -181,6 +182,9 @@
 	DEVICE( OLICOM,		OLICOM_OC2183,	"OC-2183/2185"),
 	DEVICE( OLICOM,		OLICOM_OC2326,	"OC-2326"),
 	DEVICE( OLICOM,		OLICOM_OC6151,	"OC-6151/6152"),
+	DEVICE( SUN,		SUN_EBUS,	"EBUS"),
+	DEVICE( SUN,		SUN_HAPPYMEAL,	"Happy Meal"),
+	BRIDGE( SUN,		SUN_PBM,	"PCI Bus Module",	0x02),
 	DEVICE( CMD,		CMD_640,	"640 (buggy)"),
 	DEVICE( CMD,		CMD_643,	"643"),
 	DEVICE( CMD,		CMD_646,	"646"),
@@ -596,6 +600,7 @@
 	      case PCI_VENDOR_ID_CONTAQ:	return "Contaq";
 	      case PCI_VENDOR_ID_FOREX:		return "Forex";
 	      case PCI_VENDOR_ID_OLICOM:	return "Olicom";
+	      case PCI_VENDOR_ID_SUN:		return "Sun Microsystems";
 	      case PCI_VENDOR_ID_CMD:		return "CMD";
 	      case PCI_VENDOR_ID_VISION:	return "Vision";
 	      case PCI_VENDOR_ID_BROOKTREE:	return "Brooktree";
@@ -668,6 +673,36 @@
 }
 
 
+const char *pcibios_strerror(int error)
+{
+	static char buf[32];
+
+	switch (error) {
+		case PCIBIOS_SUCCESSFUL:
+		case PCIBIOS_BAD_VENDOR_ID:
+			return "SUCCESSFUL";
+
+		case PCIBIOS_FUNC_NOT_SUPPORTED:
+			return "FUNC_NOT_SUPPORTED";
+
+		case PCIBIOS_DEVICE_NOT_FOUND:
+			return "DEVICE_NOT_FOUND";
+
+		case PCIBIOS_BAD_REGISTER_NUMBER:
+			return "BAD_REGISTER_NUMBER";
+
+                case PCIBIOS_SET_FAILED:          
+			return "SET_FAILED";
+
+                case PCIBIOS_BUFFER_TOO_SMALL:    
+			return "BUFFER_TOO_SMALL";
+
+		default:
+			sprintf (buf, "PCI ERROR 0x%x", error);
+			return buf;
+	}
+}
+
 
 /*
  * Turn on/off PCI bridge optimization. This should allow benchmarking.
@@ -793,7 +828,7 @@
 		if (len + 40 > size) {
 			return -1;
 		}
-		len += sprintf(buf + len, "IRQ %d.  ", dev->irq);
+		len += sprintf(buf + len, "IRQ %x.  ", dev->irq);
 	}
 
 	if (dev->master) {
@@ -811,20 +846,24 @@
 		  len += sprintf(buf + len, "Max Lat=%d.", max_lat);
 	}
 
-	for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
+	for (reg = 0; reg < 6; reg++) {
 		if (len + 40 > size) {
 			return -1;
 		}
-		pcibios_read_config_dword(bus, devfn, reg, &l);
-		base = l;
-		if (!base) {
+		pcibios_read_config_dword(bus, devfn,
+				PCI_BASE_ADDRESS_0 + (reg << 2), &l);
+		if (l == 0xffffffff)
+			base = 0;
+		else
+			base = l;
+		if (!base)
 			continue;
-		}
 
 		if (base & PCI_BASE_ADDRESS_SPACE_IO) {
 			len += sprintf(buf + len,
-				       "\n      I/O at 0x%lx.",
-				       base & PCI_BASE_ADDRESS_IO_MASK);
+				       "\n      I/O at 0x%lx [0x%lx].",
+				       base & PCI_BASE_ADDRESS_IO_MASK,
+				       dev->base_address[reg]);
 		} else {
 			const char *pref, *type = "unknown";
 
@@ -848,8 +887,9 @@
 			}
 			len += sprintf(buf + len,
 				       "\n      %srefetchable %s memory at "
-				       "0x%lx.", pref, type,
-				       base & PCI_BASE_ADDRESS_MEM_MASK);
+				       "0x%lx [0x%lx].", pref, type,
+				       base & PCI_BASE_ADDRESS_MEM_MASK,
+				       dev->base_address[reg]);
 		}
 	}
 
@@ -892,7 +932,7 @@
 	void *mem;
 
 #ifdef DEBUG
-	printk("...pci_malloc(size=%ld,mem=%p)", size, *mem_startp);
+	printk("...pci_malloc(size=%ld,mem=%p)", size, (void *)*mem_startp);
 #endif
 	mem = (void*) *mem_startp;
 	*mem_startp += (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
@@ -901,16 +941,18 @@
 }
 
 
-__initfunc(static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp))
+unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
 {
 	unsigned int devfn, l, max;
-	unsigned char cmd, tmp, hdr_type = 0;
+	unsigned char cmd, tmp, irq, hdr_type = 0;
 	struct pci_dev_info *info;
 	struct pci_dev *dev;
 	struct pci_bus *child;
+	int reg;
 
 #ifdef DEBUG
-	printk("...scan_bus(busno=%d,mem=%p)\n", bus->number, *mem_startp);
+	printk("...pci_scan_bus(busno=%d,mem=%p)\n", bus->number,
+	       (void *)*mem_startp);
 #endif
 
 	max = bus->secondary;
@@ -952,7 +994,7 @@
 		 */
 		info = pci_lookup_dev(dev->vendor, dev->device);
 		if (!info) {
-			printk("Warning : Unknown PCI device (%x:%x).  Please read include/linux/pci.h \n",
+			printk("PCI: Warning: Unknown PCI device (%x:%x).  Please read include/linux/pci.h\n",
 				dev->vendor, dev->device);
 		} else {
 			/* Some BIOS' are lazy. Let's do their job: */
@@ -975,7 +1017,20 @@
 
 		/* read irq level (may be changed during pcibios_fixup()): */
 		pcibios_read_config_byte(bus->number, devfn,
-					 PCI_INTERRUPT_LINE, &dev->irq);
+					 PCI_INTERRUPT_LINE, &irq);
+		dev->irq = irq;
+
+		/* read base address registers, again pcibios_fixup() can
+		 * tweak these
+		 */
+		for (reg = 0; reg < 6; reg++) {
+			pcibios_read_config_dword(bus->number, devfn,
+					PCI_BASE_ADDRESS_0 + (reg << 2), &l);
+			if (l == 0xffffffff)
+				dev->base_address[reg] = 0;
+			else
+				dev->base_address[reg] = l;
+		}
 
 		/* check to see if this device is a PCI-PCI bridge: */
 		pcibios_read_config_dword(bus->number, devfn,
@@ -1033,7 +1088,7 @@
 			    child->secondary = (buses >> 8) & 0xFF;
 			    child->subordinate = (buses >> 16) & 0xFF;
 			    child->number = child->secondary;
-			    max = scan_bus(child, mem_startp);
+			    max = pci_scan_bus(child, mem_startp);
 			  }
 			else
 			  {
@@ -1050,7 +1105,7 @@
 			    /*
 			     * Now we can scan all subordinate buses:
 			     */
-			    max = scan_bus(child, mem_startp);
+			    max = pci_scan_bus(child, mem_startp);
 			    /*
 			     * Set the subordinate bus number to its real
 			     * value:
@@ -1081,14 +1136,14 @@
 	mem_start = pcibios_init(mem_start, mem_end);
 
 	if (!pcibios_present()) {
-		printk("pci_init: no PCI BIOS detected\n");
+		printk("PCI: No PCI bus detected\n");
 		return mem_start;
 	}
 
 	printk("Probing PCI hardware.\n");
 
 	memset(&pci_root, 0, sizeof(pci_root));
-	pci_root.subordinate = scan_bus(&pci_root, &mem_start);
+	pci_root.subordinate = pci_scan_bus(&pci_root, &mem_start);
 
 	/* give BIOS a chance to apply platform specific fixes: */
 	mem_start = pcibios_fixup(mem_start, mem_end);
diff -u --recursive --new-file v2.1.53/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.1.53/linux/drivers/sbus/char/pcikbd.c	Thu Sep  4 17:07:31 1997
+++ linux/drivers/sbus/char/pcikbd.c	Sat Sep  6 10:04:15 1997
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.3 1997/09/04 05:50:35 ecd Exp $
+/* $Id: pcikbd.c,v 1.4 1997/09/05 22:59:53 ecd Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -404,51 +404,37 @@
 {
 	struct linux_ebus *ebus;
 	struct linux_ebus_device *edev;
-	int node, index, irq;
+	struct linux_ebus_child *child;
 
 	for_all_ebusdev(edev, ebus) {
 		if(!strcmp(edev->prom_name, "8042")) {
-			node = prom_getchild(edev->prom_node);
-			node = prom_searchsiblings(node, "kb_ps2");
-			if (node == kbd_node)
-				goto found;
+			for_each_edevchild(edev, child) {
+				if (!strcmp(child->prom_name, "kb_ps2"))
+					goto found;
+			}
 		}
 	}
-	printk("pcikbd_init: no 8042 found\n");
+	printk("pcikbd_probe: no 8042 found\n");
 	return -ENODEV;
 
 found:
-	if (prom_getproperty(node, "reg", (char *)&index, sizeof(index)) !=
-							sizeof(index)) {
-		printk("8042: can't get property '%s' from '%s'\n",
-		       "reg", "kb_ps2");
-		return -ENODEV;
-	}
-
-	if (prom_getproperty(node, "interrupts", (char *)&irq, sizeof(irq)) !=
-							sizeof(irq)) {
-		printk("8042: can't get property '%s' from '%s'\n",
-		       "interrupts", "kb_ps2");
-		return -ENODEV;
-	}
-
-	pcikbd_iobase = edev->base_address[index];
+	pcikbd_iobase = child->base_address[0];
 	if (check_region(pcikbd_iobase, sizeof(unsigned long))) {
 		printk("8042: can't get region %lx, %d\n",
 		       pcikbd_iobase, (int)sizeof(unsigned long));
 		return -ENODEV;
 	}
-
 	request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller");
-	printk("8042(kbd): iobase[%016lx] irq[%x]\n", pcikbd_iobase, irq);
-	pcikbd_irq = irq;
 
+	pcikbd_irq = child->irqs[0];
 	if (request_irq(pcikbd_irq, &pcikbd_interrupt,
 			SA_SHIRQ, "keyboard", NULL)) {
 		printk("8042: cannot register IRQ %x\n", pcikbd_irq);
 		return -ENODEV;
 	}
 
+	printk("8042(kbd): iobase[%016lx] irq[%x]\n", pcikbd_iobase, pcikbd_irq);
+
 	/* pcikbd_init(); */
 	kbd_read_mask = KBD_STAT_OBF;
 	return 0;
@@ -806,36 +792,21 @@
 {
 	struct linux_ebus *ebus;
 	struct linux_ebus_device *edev;
-	int node, index, irq;
+	struct linux_ebus_child *child;
 
 	for_all_ebusdev(edev, ebus) {
 		if(!strcmp(edev->prom_name, "8042")) {
-			node = prom_getchild(edev->prom_node);
-			node = prom_searchsiblings(node, "kdmouse");
-			if (node == ms_node)
-				goto found;
+			for_each_edevchild(edev, child) {
+				if (!strcmp(child->prom_name, "kdmouse"))
+					goto found;
+			}
 		}
 	}
 	printk("pcimouse_init: no 8042 found\n");
 	return -ENODEV;
 
 found:
-	if (prom_getproperty(node, "reg", (char *)&index, sizeof(index)) !=
-							sizeof(index)) {
-		printk("8042: can't get property '%s' from '%s'\n",
-		       "reg", "kdmouse");
-		return -ENODEV;
-	}
-
-	if (prom_getproperty(node, "interrupts", (char *)&irq, sizeof(irq)) !=
-							sizeof(irq)) {
-		printk("8042: can't get property '%s' from '%s'\n",
-		       "interrupts", "kdmouse");
-		return -ENODEV;
-	}
-
-	pcimouse_iobase = edev->base_address[index];
-
+	pcimouse_iobase = child->base_address[0];
 	/*
 	 * Just in case the iobases for kbd/mouse ever differ...
 	 */
@@ -843,15 +814,16 @@
 		request_region(pcimouse_iobase, sizeof(unsigned long),
 			       "8042 controller");
 
-	printk("8042(mouse): iobase[%016lx] irq[%x]\n", pcimouse_iobase, irq);
-	pcimouse_irq = irq;
-
+	pcimouse_irq = child->irqs[0];
 	if (request_irq(pcimouse_irq, &pcimouse_interrupt,
 		        SA_SHIRQ, "mouse", NULL)) {
 		printk("8042: Cannot register IRQ %x\n", pcimouse_irq);
 		return -ENODEV;
 	}
 
+	printk("8042(mouse): iobase[%016lx] irq[%x]\n",
+	       pcimouse_iobase, pcimouse_irq);
+
 	printk("8042: PS/2 auxiliary pointing device detected.\n");
 	aux_present = 1;
 	kbd_read_mask = AUX_STAT_OBF;
@@ -873,7 +845,7 @@
 	poll_aux_status();
 	outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG);
 	poll_aux_status();
-	outb(AUX_INTS_OFF, KBD_DATA_REG);
+	outb(AUX_INTS_OFF, pcimouse_iobase + KBD_DATA_REG);
 	poll_aux_status();
 	aux_end_atomic();
 
diff -u --recursive --new-file v2.1.53/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c
--- v2.1.53/linux/drivers/scsi/esp.c	Mon Aug  4 16:25:38 1997
+++ linux/drivers/scsi/esp.c	Sat Sep  6 10:04:15 1997
@@ -12,6 +12,7 @@
  * 3) Add tagged queueing.
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
@@ -34,6 +35,7 @@
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/idprom.h>
 
 #define DEBUG_ESP
@@ -642,6 +644,9 @@
  */
 __initfunc(int esp_detect(Scsi_Host_Template *tpnt))
 {
+#ifdef __sparc_v9__
+	struct devid_cookie dcookie;
+#endif
 	struct Sparc_ESP *esp, *elink;
 	struct Scsi_Host *esp_host;
 	struct linux_sbus *sbus;
@@ -655,8 +660,13 @@
 	int esp_node, i;
 
 	espchain = 0;
-	if(!SBus_chain)
+	if(!SBus_chain) {
+#ifdef CONFIG_PCI
+		return 0;
+#else
 		panic("No SBUS in esp_detect()");
+#endif
+	}
 	for_each_sbus(sbus) {
 		for_each_sbusdev(sbdev_iter, sbus) {
 			struct linux_sbus_device *espdma = 0;
@@ -782,6 +792,7 @@
 				esp->edev->reg_addrs[0].reg_size;
 			esp->ehost->irq = esp->irq = esp->edev->irqs[0].pri;
 
+#ifndef __sparc_v9__
 			/* Allocate the irq only if necessary */
 			for_each_esp(elink) {
 				if((elink != esp) && (esp->irq == elink->irq)) {
@@ -793,6 +804,22 @@
 				panic("Cannot acquire ESP irq line");
 esp_irq_acquired:
 			printk("esp%d: IRQ %d ", esp->esp_id, esp->ehost->irq);
+#else
+			/* On Ultra we must always call request_irq for each
+			 * esp, so that imap registers get setup etc.
+			 */
+			dcookie.real_dev_id = esp;
+			dcookie.imap = dcookie.iclr = 0;
+			dcookie.pil = -1;
+			dcookie.bus_cookie = sbus;
+			if(request_irq(esp->ehost->irq, esp_intr,
+				       (SA_SHIRQ | SA_SBUS | SA_DCOOKIE),
+				       "Sparc ESP SCSI", &dcookie))
+				panic("Cannot acquire ESP irq line");
+			esp->ehost->irq = esp->irq = dcookie.ret_ino;
+			printk("esp%d: INO[%x] IRQ %d ",
+			       esp->esp_id, esp->ehost->irq, dcookie.ret_pil);
+#endif
 
 			/* Figure out our scsi ID on the bus */
 			esp->scsi_id = prom_getintdefault(esp->prom_node,
@@ -2323,11 +2350,6 @@
 		/* Please go to msgout phase, please please please... */
 		ESPLOG(("esp%d: !BSERV after data, probably to msgout\n",
 			esp->esp_id));
-#ifdef __SMP__
-		ESPLOG(("esp%d: local_irq_count[%x:%x:%x:%x]\n", esp->esp_id,
-			local_irq_count[0], local_irq_count[1],
-			local_irq_count[2], local_irq_count[3]));
-#endif
 		return esp_do_phase_determine(esp, eregs, dregs);
 	}	
 
@@ -2410,11 +2432,6 @@
 		ESPLOG(("esp%d: use_sg=%d ptr=%p this_residual=%d\n",
 			esp->esp_id,
 			SCptr->use_sg, SCptr->SCp.ptr, SCptr->SCp.this_residual));
-#ifdef __SMP__
-		ESPLOG(("esp%d: local_irq_count[%x:%x:%x:%x]\n", esp->esp_id,
-			local_irq_count[0], local_irq_count[1],
-			local_irq_count[2], local_irq_count[3]));
-#endif
 		bytes_sent = 0;
 	}
 
@@ -4021,6 +4038,8 @@
 	return;
 }
 
+#ifndef __sparc_v9__
+
 #ifndef __SMP__
 static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
@@ -4031,14 +4050,7 @@
 repeat:
 	again = 0;
 	for_each_esp(esp) {
-		/* XXX Ultra: This is gross, what we really need
-		 * XXX is a sbusirq_to_sparc_pil() function, call
-		 * XXX that and stick the result in the esp soft
-		 * XXX state structure. -DaveM
-		 */
-#ifndef __sparc_v9__
 		if((esp->irq & 0xf) == irq) {
-#endif
 			if(DMA_IRQ_P(esp->dregs)) {
 				again = 1;
 
@@ -4050,23 +4062,12 @@
 
 				DMA_INTSON(esp->dregs);
 			}
-#ifndef __sparc_v9__
 		}
-#endif
 	}
 	if(again)
 		goto repeat;
 }
 #else
-
-/* XXX Gross hack for sun4u SMP, fix it right later... -DaveM */
-#ifdef __sparc_v9__
-extern unsigned char ino_to_pil[];
-#define INO_TO_PIL(esp)		(ino_to_pil[(esp)->irq])
-#else
-#define INO_TO_PIL(esp)		((esp)->irq & 0xf)
-#endif
-
 /* For SMP we only service one ESP on the list list at our IRQ level! */
 static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
@@ -4074,7 +4075,7 @@
 
 	/* Handle all ESP interrupts showing at this IRQ level. */
 	for_each_esp(esp) {
-		if(INO_TO_PIL(esp) == irq) {
+		if(((esp)->irq & 0xf) == irq) {
 			if(DMA_IRQ_P(esp->dregs)) {
 				DMA_INTSOFF(esp->dregs);
 
@@ -4089,4 +4090,23 @@
 		}
 	}
 }
+#endif
+
+#else /* __sparc_v9__ */
+
+static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+{
+	struct Sparc_ESP *esp = dev_id;
+
+	if(DMA_IRQ_P(esp->dregs)) {
+		DMA_INTSOFF(esp->dregs);
+
+		ESPIRQ(("I[%d:%d](", smp_processor_id(), esp->esp_id));
+		esp_handle(esp);
+		ESPIRQ((")"));
+
+		DMA_INTSON(esp->dregs);
+	}
+}
+
 #endif
diff -u --recursive --new-file v2.1.53/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c
--- v2.1.53/linux/drivers/scsi/g_NCR5380.c	Mon Jun 16 16:35:56 1997
+++ linux/drivers/scsi/g_NCR5380.c	Sat Sep  6 10:13:06 1997
@@ -736,4 +736,11 @@
 
 #include <linux/module.h>
 #include "scsi_module.c"
+
+MODULE_PARM(ncr_irq, "i");
+MODULE_PARM(ncr_dma, "i");
+MODULE_PARM(ncr_addr, "i");
+MODULE_PARM(ncr_5380, "i");
+MODULE_PARM(ncr_53c400, "i");
+
 #endif
diff -u --recursive --new-file v2.1.53/linux/drivers/scsi/mesh.c linux/drivers/scsi/mesh.c
--- v2.1.53/linux/drivers/scsi/mesh.c	Mon Aug 18 18:19:46 1997
+++ linux/drivers/scsi/mesh.c	Sat Sep  6 10:04:15 1997
@@ -7,9 +7,7 @@
  * Paul Mackerras, August 1996.
  * Copyright (C) 1996 Paul Mackerras.
  */
-
 #include <linux/config.h>
-
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.1.53/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c
--- v2.1.53/linux/drivers/scsi/qlogicpti.c	Thu Jul 17 10:06:05 1997
+++ linux/drivers/scsi/qlogicpti.c	Sat Sep  6 10:04:16 1997
@@ -37,6 +37,7 @@
 #include <asm/oplib.h>
 #include <asm/vaddrs.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 
 #include <linux/module.h>
 
@@ -351,7 +352,7 @@
 	unsigned short csum = 0;
 	unsigned short param[6];
 	unsigned long flags;
-#ifndef MODULE
+#if !defined(MODULE) && !defined(__sparc_v9__)
 	unsigned long dvma_addr;
 #endif
 	int i, timeout;
@@ -419,8 +420,7 @@
 	}		
 
 	/* Load the firmware. */
-#ifndef MODULE
-	/* XXX THIS SHIT DOES NOT WORK ON ULTRA... FIXME -DaveM */
+#if !defined(MODULE) && !defined(__sparc_v9__)
 	dvma_addr = (unsigned long) mmu_lockarea((char *)&risc_code01[0],
 						 (sizeof(u_short) * risc_code_length01));
 	param[0] = MBOX_LOAD_RAM;
@@ -435,9 +435,9 @@
 		restore_flags(flags);
 		return 1;
 	}
-	/* XXX THIS SHIT DOES NOT WORK ON ULTRA... FIXME -DaveM */
 	mmu_unlockarea((char *)dvma_addr, (sizeof(u_short) * risc_code_length01));
 #else
+	/* We need to do it this slow way always on Ultra. */
 	for(i = 0; i < risc_code_length01; i++) {
 		param[0] = MBOX_WRITE_RAM_WORD;
 		param[1] = risc_code_addr01 + i;
@@ -566,6 +566,9 @@
 /* Detect all PTI Qlogic ISP's in the machine. */
 __initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
 {
+#ifdef __sparc_v9__
+	struct devid_cookie dcookie;
+#endif
 	struct qlogicpti *qpti, *qlink;
 	struct Scsi_Host *qpti_host;
 	struct linux_sbus *sbus;
@@ -643,7 +646,7 @@
 				/* Map this one read only. */
 				qpti->sreg = sreg = (volatile unsigned char *)
 					sparc_alloc_io((qpti->qdev->reg_addrs[0].phys_addr +
-						       (16 * PAGE_SIZE)), 0,
+						       (16 * 4096)), 0,
 						       sizeof(unsigned char),
 						       "PTI Qlogic/ISP Status Reg",
 						       qpti->qdev->reg_addrs[0].which_io, 1);
@@ -659,6 +662,7 @@
 
 			qpti_host->irq = qpti->irq = qpti->qdev->irqs[0].pri;
 
+#ifndef __sparc_v9__
 			/* Allocate the irq only if necessary. */
 			for_each_qlogicpti(qlink) {
 				if((qlink != qpti) && (qpti->irq == qlink->irq)) {
@@ -673,6 +677,25 @@
 			}
 qpti_irq_acquired:
 			printk("qpti%d: IRQ %d ", qpti->qpti_id, qpti->qhost->irq);
+#else
+			/* On Ultra we must always call request_irq for each
+			 * qpti, so that imap registers get setup etc.
+			 */
+			dcookie.real_dev_id = qpti;
+			dcookie.imap = dcookie.iclr = 0;
+			dcookie.pil = -1;
+			dcookie.bus_cookie = sbus;
+			if(request_irq(qpti->qhost->irq, qlogicpti_intr_handler,
+				       (SA_SHIRQ | SA_SBUS | SA_DCOOKIE),
+				       "PTI Qlogic/ISP SCSI", &dcookie)) {
+				printk("Cannot acquire PTI Qlogic/ISP irq line\n");
+				/* XXX Unmap regs, unregister scsi host, free things. */
+				continue;
+			}
+			qpti->qhost->irq = qpti->irq = dcookie.ret_ino;
+			printk("qpti%d: INO[%x] IRQ %d ",
+			       qpti->qpti_id, qpti->qhost->irq, dcookie.ret_pil);
+#endif
 
 			/* Figure out our scsi ID on the bus */
 			qpti->scsi_id = prom_getintdefault(qpti->prom_node,
@@ -805,7 +828,11 @@
 	memset(cmd, 0, sizeof(struct Command_Entry));
 	cmd->hdr.entry_cnt = 1;
 	cmd->hdr.entry_type = ENTRY_COMMAND;
-	cmd->handle = (u_int) ((unsigned long)Cmnd);          /* magic mushroom */
+#ifdef __sparc_v9__
+	cmd->handle = (u_int) (((unsigned long)Cmnd) - PAGE_OFFSET); /* magic mushroom */
+#else
+	cmd->handle = (u_int) ((unsigned long)Cmnd);                 /* magic mushroom */
+#endif
 	cmd->target_id = Cmnd->target;
 	cmd->target_lun = Cmnd->lun;
 	cmd->cdb_length = Cmnd->cmd_len;
@@ -1013,6 +1040,8 @@
 	return (sts->scsi_status & STATUS_MASK) | (host_status << 16);
 }
 
+#ifndef __sparc_v9__
+
 static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	static int running = 0;
@@ -1098,6 +1127,76 @@
 		goto repeat;
 	running--;
 }
+
+#else /* __sparc_v9__ */
+
+static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct qlogicpti *qpti = dev_id;
+	Scsi_Cmnd *Cmnd;
+	struct Status_Entry *sts;
+	u_int in_ptr, out_ptr;
+
+	if(qpti->qregs->sbus_stat & SBUS_STAT_RINT) {
+		struct qlogicpti_regs *qregs = qpti->qregs;
+
+		in_ptr = qregs->mbox5;
+		qregs->hcctrl = HCCTRL_CRIRQ;
+		if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) {
+			switch(qregs->mbox0) {
+			case ASYNC_SCSI_BUS_RESET:
+			case EXECUTION_TIMEOUT_RESET:
+				qpti->send_marker = 1;
+				break;
+			case INVALID_COMMAND:
+			case HOST_INTERFACE_ERROR:
+			case COMMAND_ERROR:
+			case COMMAND_PARAM_ERROR:
+				break;
+			}
+			qregs->sbus_semaphore = 0;
+		}
+
+		/* This looks like a network driver! */
+		out_ptr = qpti->res_out_ptr;
+		while(out_ptr != in_ptr) {
+			sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr];
+			out_ptr = NEXT_RES_PTR(out_ptr);
+			Cmnd = (Scsi_Cmnd *) (((unsigned long)sts->handle)+PAGE_OFFSET);
+
+			if(sts->completion_status == CS_RESET_OCCURRED ||
+			   sts->completion_status == CS_ABORTED ||
+			   (sts->status_flags & STF_BUS_RESET))
+				qpti->send_marker = 1;
+
+			if(sts->state_flags & SF_GOT_SENSE)
+				memcpy(Cmnd->sense_buffer, sts->req_sense_data,
+				       sizeof(Cmnd->sense_buffer));
+
+			if(sts->hdr.entry_type == ENTRY_STATUS)
+				Cmnd->result = qlogicpti_return_status(sts);
+			else
+				Cmnd->result = DID_ERROR << 16;
+
+			if(Cmnd->use_sg)
+				mmu_release_scsi_sgl((struct mmu_sglist *)
+						     Cmnd->buffer,
+						     Cmnd->use_sg - 1,
+						     qpti->qdev->my_bus);
+			else
+				mmu_release_scsi_one((__u32)((unsigned long)Cmnd->SCp.ptr),
+						     Cmnd->request_bufflen,
+						     qpti->qdev->my_bus);
+
+			qpti->cmd_count[Cmnd->target]--;
+			qregs->mbox5 = out_ptr;
+			Cmnd->scsi_done(Cmnd);
+		}
+		qpti->res_out_ptr = out_ptr;
+	}
+}
+
+#endif
 
 int qlogicpti_abort(Scsi_Cmnd *Cmnd)
 {
diff -u --recursive --new-file v2.1.53/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v2.1.53/linux/drivers/scsi/scsi.h	Mon Jul  7 16:02:51 1997
+++ linux/drivers/scsi/scsi.h	Sat Sep  6 10:51:02 1997
@@ -37,6 +37,7 @@
 #endif
 
 #define MAX_SCSI_DEVICE_CODE 10
+extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
 
 extern void scsi_make_blocked_list(void);
 extern volatile int in_scan_scsis;
diff -u --recursive --new-file v2.1.53/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- v2.1.53/linux/drivers/scsi/scsi_syms.c	Fri Jan  3 01:33:26 1997
+++ linux/drivers/scsi/scsi_syms.c	Sat Sep  6 10:13:06 1997
@@ -72,5 +72,7 @@
 EXPORT_SYMBOL(scsi_hosts);
 EXPORT_SYMBOL(scsi_devicelist);
 EXPORT_SYMBOL(scsi_devices);
+EXPORT_SYMBOL(scsi_device_types);
+
 
 #endif /* CONFIG_MODULES */
diff -u --recursive --new-file v2.1.53/linux/fs/autofs/autofs_i.h linux/fs/autofs/autofs_i.h
--- v2.1.53/linux/fs/autofs/autofs_i.h	Mon Aug  4 16:25:38 1997
+++ linux/fs/autofs/autofs_i.h	Sat Sep  6 10:51:49 1997
@@ -23,39 +23,7 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/wait.h>
-
-#define kver(a,b,c) (((a) << 16) + ((b) << 8) + (c)) 
-
-#if LINUX_VERSION_CODE < kver(2,1,0)
-
-/* Segmentation stuff for pre-2.1 kernels */
-#include <asm/segment.h>
-
-static inline int copy_to_user(void *dst, void *src, unsigned long len)
-{
-	int rv = verify_area(VERIFY_WRITE, dst, len);
-	if ( rv )
-		return -1;
-	memcpy_tofs(dst,src,len);
-	return 0;
-}
-
-static inline int copy_from_user(void *dst, void *src, unsigned long len)
-{
-	int rv = verify_area(VERIFY_READ, src, len);
-	if ( rv )
-		return -1;
-	memcpy_fromfs(dst,src,len);
-	return 0;
-}
-
-#else
-
-/* Segmentation stuff for post-2.1 kernels */
 #include <asm/uaccess.h>
-#define register_symtab(x)	((void)0)
-
-#endif
 
 #ifdef DEBUG
 #define DPRINTK(D) (printk D)
@@ -65,9 +33,15 @@
 
 #define AUTOFS_SUPER_MAGIC 0x0187
 
-#define AUTOFS_NEGATIVE_TIMEOUT (60*HZ)	/* Time before asking the daemon again */
+/*
+ * If the daemon returns a negative response (AUTOFS_IOC_FAIL) then the
+ * kernel will keep the negative response cached for up to the time given
+ * here, although the time can be shorter if the kernel throws the dcache
+ * entry away.  This probably should be settable from user space.
+ */
+#define AUTOFS_NEGATIVE_TIMEOUT (60*HZ)	/* 1 minute */
 
-/* Structures associated with the root directory hash */
+/* Structures associated with the root directory hash table */
 
 #define AUTOFS_HASH_SIZE 67
 
@@ -135,20 +109,14 @@
 	u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN];
 };
 
-/* autofs_oz_mode(): do we see the man behind the curtain? */
+/* 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".) */
+
 static inline int autofs_oz_mode(struct autofs_sb_info *sbi) {
 	return sbi->catatonic || current->pgrp == sbi->oz_pgrp;
 }
 
-/* Debug the mysteriously disappearing wait list */
-
-#ifdef DEBUG_WAITLIST
-#define CHECK_WAITLIST(S,O) autofs_check_waitlist_integrity(S,O)
-void autofs_check_waitlist_integrity(struct autofs_sb_info *,char *);
-#else
-#define CHECK_WAITLIST(S,O)
-#endif
-
 /* Hash operations */
 
 void autofs_initialize_hash(struct autofs_dirhash *);
@@ -182,5 +150,5 @@
 #ifdef DEBUG
 void autofs_say(const char *name, int len);
 #else
-#define autofs_say(n,l)
+#define autofs_say(n,l) ((void)0)
 #endif
diff -u --recursive --new-file v2.1.53/linux/fs/autofs/init.c linux/fs/autofs/init.c
--- v2.1.53/linux/fs/autofs/init.c	Thu Jun 26 12:33:39 1997
+++ linux/fs/autofs/init.c	Fri Sep  5 20:15:37 1997
@@ -11,17 +11,12 @@
  * ------------------------------------------------------------------------- */
 
 #include <linux/module.h>
-#include "autofs_i.h"
-
-#if LINUX_VERSION_CODE < kver(2,1,36)
-#define __initfunc(X) X
-#else
 #include <linux/init.h>
-#endif
+#include "autofs_i.h"
 
 static struct file_system_type autofs_fs_type = {
 	"autofs",
-	0 /* FS_NO_DCACHE doesn't work correctly */,
+	0,
 	autofs_read_super,
 	NULL
 };
@@ -29,11 +24,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-	int status;
-	
-	if ((status = register_filesystem(&autofs_fs_type)) == 0)
-		register_symtab(0);
-	return status;
+	return register_filesystem(&autofs_fs_type);
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.1.53/linux/fs/autofs/root.c linux/fs/autofs/root.c
--- v2.1.53/linux/fs/autofs/root.c	Thu Aug 14 20:49:17 1997
+++ linux/fs/autofs/root.c	Fri Sep  5 20:15:37 1997
@@ -394,16 +394,9 @@
 	int rv;
 	unsigned long ntimeout;
 
-#if LINUX_VERSION_CODE < kver(2,1,0)
-	if ( (rv = verify_area(VERIFY_WRITE, p, sizeof(unsigned long))) )
-		return rv;
-	ntimeout = get_user(p);
-	put_user(sbi->exp_timeout/HZ, p);
-#else
 	if ( (rv = get_user(ntimeout, p)) ||
 	     (rv = put_user(sbi->exp_timeout/HZ, p)) )
 		return rv;
-#endif
 
 	if ( ntimeout > ULONG_MAX/HZ )
 		sbi->exp_timeout = 0;
@@ -416,15 +409,7 @@
 /* Return protocol version */
 static inline int autofs_get_protover(int *p)
 {
-#if LINUX_VERSION_CODE < kver(2,1,0)
-	int rv;
-	if ( (rv = verify_area(VERIFY_WRITE, p, sizeof(int))) )
-		return rv;
-	put_user(AUTOFS_PROTO_VERSION, p);
-	return 0;
-#else
 	return put_user(AUTOFS_PROTO_VERSION, p);
-#endif
 }
 
 /* Perform an expiry operation */
diff -u --recursive --new-file v2.1.53/linux/fs/autofs/waitq.c linux/fs/autofs/waitq.c
--- v2.1.53/linux/fs/autofs/waitq.c	Thu Jul 17 10:06:06 1997
+++ linux/fs/autofs/waitq.c	Sat Sep  6 10:23:14 1997
@@ -42,7 +42,7 @@
 
 static int autofs_write(struct file *file, const void *addr, int bytes)
 {
-	unsigned short fs;
+	unsigned long fs;
 	unsigned long old_signal;
 	const char *data = (const char *)addr;
 	int written = 0;
diff -u --recursive --new-file v2.1.53/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- v2.1.53/linux/fs/binfmt_aout.c	Mon Aug  4 16:25:38 1997
+++ linux/fs/binfmt_aout.c	Sat Sep  6 10:23:14 1997
@@ -82,7 +82,7 @@
 	struct dentry * dentry = NULL;
 	struct inode * inode = NULL;
 	struct file file;
-	unsigned short fs;
+	unsigned long fs;
 	int has_dumped = 0;
 	char corefile[6+sizeof(current->comm)];
 	unsigned long dump_start, dump_size;
diff -u --recursive --new-file v2.1.53/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.1.53/linux/fs/binfmt_elf.c	Mon Aug 18 18:19:46 1997
+++ linux/fs/binfmt_elf.c	Sat Sep  6 10:23:14 1997
@@ -391,14 +391,14 @@
 	struct elfhdr interp_elf_ex;
 	struct file * file;
   	struct exec interp_ex;
-	struct dentry *interpreter_dentry;
-	unsigned long load_addr;
+	struct dentry *interpreter_dentry = NULL; /* to shut gcc up */
+ 	unsigned long load_addr, load_bias;
 	int load_addr_set = 0;
 	unsigned int interpreter_type = INTERPRETER_NONE;
 	unsigned char ibcs2_interpreter;
 	int i;
-	int old_fs;
-	int error;
+	unsigned long old_fs;
+	unsigned long error;
 	struct elf_phdr * elf_ppnt, *elf_phdata;
 	int elf_exec_fileno;
 	unsigned long elf_bss, k, elf_brk;
@@ -503,7 +503,16 @@
 			if (retval >= 0) {
 				old_fs = get_fs(); /* This could probably be optimized */
 				set_fs(get_ds());
-				interpreter_dentry = open_namei(elf_interpreter, 0, 0);
+#ifdef __sparc__
+				if (ibcs2_interpreter) {
+					unsigned long old_pers = current->personality;
+					
+					current->personality = PER_SVR4;
+					interpreter_dentry = open_namei(elf_interpreter, 0, 0);
+					current->personality = old_pers;
+				} else
+#endif					
+					interpreter_dentry = open_namei(elf_interpreter, 0, 0);
 				set_fs(old_fs);
 				if (IS_ERR(interpreter_dentry))
 					retval = PTR_ERR(interpreter_dentry);
@@ -593,6 +602,12 @@
 	bprm->p = setup_arg_pages(bprm->p, bprm);
 	current->mm->start_stack = bprm->p;
 
+	/* Try and get dynamic programs out of the way of the default mmap
+	   base, as well as whatever program they might try to exec.  This
+	   is because the brk will follow the loader, and is not movable.  */
+
+	load_bias = (elf_ex.e_type == ET_DYN ? ELF_ET_DYN_BASE : 0);
+
 	/* Now we do a little grungy work by mmaping the ELF image into
 	   the correct location in memory.  At this point, we assume that
 	   the image should be loaded at fixed address, not at a variable
@@ -602,39 +617,47 @@
 	set_fs(get_ds());
 	for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
 		if (elf_ppnt->p_type == PT_LOAD) {
-			int elf_prot = 0;
+			int elf_prot = 0, elf_flags;
+			unsigned long vaddr = 0;
+
 			if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
 			if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
 			if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
 
+			elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;
+
+			if (elf_ex.e_type == ET_EXEC || load_addr_set) {
+				vaddr = elf_ppnt->p_vaddr;
+				elf_flags |= MAP_FIXED;
+			}
+
 			error = do_mmap(file,
-					ELF_PAGESTART(elf_ppnt->p_vaddr),
+					ELF_PAGESTART(load_bias + vaddr),
 					(elf_ppnt->p_filesz +
 					 ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
-					elf_prot,
-					(MAP_FIXED | MAP_PRIVATE |
-					 MAP_DENYWRITE | MAP_EXECUTABLE),
+					elf_prot, elf_flags,
 					(elf_ppnt->p_offset -
 					 ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
 
 #ifdef LOW_ELF_STACK
-			if (ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
-				elf_stack = ELF_PAGESTART(elf_ppnt->p_vaddr);
+			if (error < elf_stack)
+				elf_stack = error-1;
 #endif
 
 			if (!load_addr_set) {
-			  load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
-			  load_addr_set = 1;
+				load_addr_set = 1;
+				load_addr = (elf_ppnt->p_vaddr -
+					     elf_ppnt->p_offset);
+				if (elf_ex.e_type == ET_DYN) {
+					load_bias = error;
+					load_addr += error;
+				}
 			}
 			k = elf_ppnt->p_vaddr;
 			if (k < start_code) start_code = k;
 			k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
 			if (k > elf_bss) elf_bss = k;
-#if 1
 			if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
-#else
-			if ( !(elf_ppnt->p_flags & PF_W) && end_code <  k)
-#endif
 				end_code = k;
 			if (end_data < k) end_data = k;
 			k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
@@ -643,6 +666,13 @@
 	}
 	set_fs(old_fs);
 
+	elf_entry += load_bias;
+	elf_bss += load_bias;
+	elf_brk += load_bias;
+	start_code += load_bias;
+	end_code += load_bias;
+	end_data += load_bias;
+
 	if (elf_interpreter) {
 		if (interpreter_type & 1)
 			elf_entry = load_aout_interp(&interp_ex,
@@ -683,7 +713,7 @@
 	current->executable = dget(bprm->dentry);
 #endif
 #ifdef LOW_ELF_STACK
-	current->start_stack = bprm->p = elf_stack - 4;
+	current->start_stack = bprm->p = elf_stack;
 #endif
 	current->suid = current->euid = current->fsuid = bprm->e_uid;
 	current->sgid = current->egid = current->fsgid = bprm->e_gid;
@@ -1011,7 +1041,7 @@
 	struct file file;
 	struct dentry *dentry;
 	struct inode *inode;
-	unsigned short fs;
+	unsigned long fs;
 	char corefile[6+sizeof(current->comm)];
 	int segs;
 	int i;
diff -u --recursive --new-file v2.1.53/linux/fs/dcache.c linux/fs/dcache.c
--- v2.1.53/linux/fs/dcache.c	Thu Sep  4 17:07:31 1997
+++ linux/fs/dcache.c	Fri Sep  5 18:13:07 1997
@@ -360,8 +360,6 @@
  */
 void d_move(struct dentry * dentry, struct dentry * target)
 {
-	struct list_head * oldhead;
-
 	if (!dentry->d_inode)
 		printk("VFS: moving negative dcache entry\n");
 
diff -u --recursive --new-file v2.1.53/linux/fs/inode.c linux/fs/inode.c
--- v2.1.53/linux/fs/inode.c	Wed Sep  3 20:52:43 1997
+++ linux/fs/inode.c	Thu Sep  4 17:07:07 1997
@@ -563,23 +563,6 @@
 	} while (i);
 }
 
-/*
- * Check whether we can mount.
- */
-int fs_may_mount(kdev_t dev)
-{
-	return 1;
-}
-
-/*
- * Check whether we can unmount.
- */
-int fs_may_umount(struct super_block *sb, struct dentry * root)
-{
-	shrink_dcache();
-	return root->d_count == 1;
-}
-
 /* This belongs in file_table.c, not here... */
 int fs_may_remount_ro(struct super_block *sb)
 {
diff -u --recursive --new-file v2.1.53/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.1.53/linux/fs/nfs/inode.c	Wed Sep  3 20:52:43 1997
+++ linux/fs/nfs/inode.c	Fri Sep  5 12:57:24 1997
@@ -81,6 +81,7 @@
 nfs_delete_inode(struct inode * inode)
 {
 	dprintk("NFS: delete_inode(%x/%ld)\n", inode->i_dev, inode->i_ino);
+	clear_inode(inode);
 }
 
 void
diff -u --recursive --new-file v2.1.53/linux/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c
--- v2.1.53/linux/fs/proc/openpromfs.c	Wed Sep  3 20:52:43 1997
+++ linux/fs/proc/openpromfs.c	Sat Sep  6 10:04:16 1997
@@ -1,4 +1,4 @@
-/* $Id: openpromfs.c,v 1.18 1997/07/17 02:24:01 davem Exp $
+/* $Id: openpromfs.c,v 1.21 1997/08/19 02:05:48 davem Exp $
  * openpromfs.c: /proc/openprom handling routines
  *
  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff -u --recursive --new-file v2.1.53/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.1.53/linux/fs/proc/root.c	Mon Aug 18 18:19:46 1997
+++ linux/fs/proc/root.c	Sat Sep  6 10:04:16 1997
@@ -551,8 +551,12 @@
 #ifdef __powerpc__
 static struct proc_dir_entry proc_root_ppc_htab = {
 	PROC_PPC_HTAB, 8, "ppc_htab",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_ppc_htab_inode_operations
+	S_IFREG | S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 1, 0, 0,
+	0, &proc_ppc_htab_inode_operations,
+	NULL, NULL,                		/* get_info, fill_inode */
+	NULL,					/* next */
+	NULL, NULL				/* parent, subdir */
+
 };
 #endif
 
diff -u --recursive --new-file v2.1.53/linux/fs/super.c linux/fs/super.c
--- v2.1.53/linux/fs/super.c	Wed Sep  3 20:52:44 1997
+++ linux/fs/super.c	Thu Sep  4 17:07:07 1997
@@ -727,6 +727,19 @@
 }
 
 /*
+ * Check whether we can mount the specified device.
+ */
+int fs_may_mount(kdev_t dev)
+{
+	struct super_block * sb = get_super(dev);
+	int busy;
+
+	busy = sb && sb->s_root &&
+	       (sb->s_root->d_count != 1 || sb->s_root->d_covers != sb->s_root);
+	return !busy;
+}
+
+/*
  * do_mount() does the actual mounting after sys_mount has done the ugly
  * parameter parsing. When enough time has gone by, and everything uses the
  * new mount() parameters, sys_mount() can then be cleaned up.
@@ -754,43 +767,56 @@
 	struct vfsmount *vfsmnt;
 	int error;
 
+	error = -EACCES;
 	if (!(flags & MS_RDONLY) && dev && is_read_only(dev))
-		return -EACCES;
+		goto out;
 		/*flags |= MS_RDONLY;*/
 
 	dir_d = namei(dir_name);
 	error = PTR_ERR(dir_d);
 	if (IS_ERR(dir_d))
-		return error;
+		goto out;
 
-	if (dir_d->d_covers != dir_d) {
-		dput(dir_d);
-		return -EBUSY;
-	}
-	if (!S_ISDIR(dir_d->d_inode->i_mode)) {
-		dput(dir_d);
-		return -ENOTDIR;
-	}
-	if (!fs_may_mount(dev)) {
-		dput(dir_d);
-		return -EBUSY;
-	}
-	sb = read_super(dev,type,flags,data,0);
-	if (!sb) {
-		dput(dir_d);
-		return -EINVAL;
-	}
-	if (sb->s_root->d_covers != sb->s_root) {
-		dput(dir_d);
-		return -EBUSY;
+	error = -ENOTDIR;
+	if (!S_ISDIR(dir_d->d_inode->i_mode))
+		goto dput_and_out;
+
+	error = -EBUSY;
+	if (dir_d->d_covers != dir_d)
+		goto dput_and_out;
+
+	/*
+	 * Check whether to read the super block
+	 */
+	sb = get_super(dev);
+	if (!sb || !sb->s_root) {
+		error = -EINVAL;
+		sb = read_super(dev,type,flags,data,0);
+		if (!sb)
+			goto dput_and_out;
 	}
+
+	/*
+	 * We may have slept while reading the super block, 
+	 * so we check afterwards whether it's safe to mount.
+	 */
+	error = -EBUSY;
+	if (!fs_may_mount(dev))
+		goto dput_and_out;
+
+	error = -ENOMEM;
 	vfsmnt = add_vfsmnt(dev, dev_name, dir_name);
 	if (vfsmnt) {
 		vfsmnt->mnt_sb = sb;
 		vfsmnt->mnt_flags = flags;
+		d_mount(dir_d, sb->s_root);
+		return 0;		/* we don't dput(dir) - see umount */
 	}
-	d_mount(dir_d, sb->s_root);
-	return 0;		/* we don't dput(dir) - see umount */
+
+dput_and_out:
+	dput(dir_d);
+out:
+	return error;	
 }
 
 
diff -u --recursive --new-file v2.1.53/linux/include/asm-alpha/elf.h linux/include/asm-alpha/elf.h
--- v2.1.53/linux/include/asm-alpha/elf.h	Sun Aug 18 00:37:57 1996
+++ linux/include/asm-alpha/elf.h	Sat Sep  6 10:23:14 1997
@@ -34,6 +34,13 @@
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	8192
 
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE		(2 * TASK_SIZE / 3)
+
 /* $0 is set by ld.so to a pointer to a function which might be 
    registered using atexit.  This provides a mean for the dynamic
    linker to call DT_FINI functions for shared libraries that have
diff -u --recursive --new-file v2.1.53/linux/include/asm-alpha/floppy.h linux/include/asm-alpha/floppy.h
--- v2.1.53/linux/include/asm-alpha/floppy.h	Sat Sep 28 12:05:41 1996
+++ linux/include/asm-alpha/floppy.h	Sat Sep  6 10:09:56 1997
@@ -48,6 +48,8 @@
 #define N_FDC 2
 #define N_DRIVE 8
 
+#define FLOPPY_MOTOR_MASK 0xf0
+
 /*
  * Most Alphas have no problems with floppy DMA crossing 64k borders. Sigh...
  */
diff -u --recursive --new-file v2.1.53/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h
--- v2.1.53/linux/include/asm-alpha/pgtable.h	Mon Jul  7 08:18:55 1997
+++ linux/include/asm-alpha/pgtable.h	Sat Sep  6 10:10:48 1997
@@ -18,6 +18,7 @@
 #define flush_cache_range(mm, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr)		do { } while (0)
 #define flush_page_to_ram(page)			do { } while (0)
+#define flush_icache_range(start, end)		do { } while (0)
 
 /*
  * Force a context reload. This is needed when we
diff -u --recursive --new-file v2.1.53/linux/include/asm-alpha/uaccess.h linux/include/asm-alpha/uaccess.h
--- v2.1.53/linux/include/asm-alpha/uaccess.h	Mon Apr 14 16:28:18 1997
+++ linux/include/asm-alpha/uaccess.h	Sat Sep  6 10:23:14 1997
@@ -10,6 +10,10 @@
  * performed or not.  If get_fs() == USER_DS, checking is performed, with
  * get_fs() == KERNEL_DS, checking is bypassed.
  *
+ * Or at least it did once upon a time.  Nowadays it is a mask that
+ * defines which bits of the address space are off limits.  This is a
+ * wee bit faster than the above.
+ *
  * For historical reasons, these macros are grossly misnamed.
  */
 
@@ -20,8 +24,16 @@
 #define VERIFY_WRITE	1
 
 #define get_fs()  (current->tss.fs)
-#define set_fs(x) (current->tss.fs = (x))
 #define get_ds()  (KERNEL_DS)
+
+/* Our scheme relies on all bits being preserved.  Trap those evil 
+   Intellists in their plot to use unsigned short.  */
+
+extern unsigned long __bad_fs_size(void);
+
+#define set_fs(x) (current->tss.fs =				\
+		   sizeof(x) == sizeof(unsigned long) ? (x) 	\
+		   : __bad_fs_size())
 
 /*
  * Is a address valid? This does a straighforward calculation rather
diff -u --recursive --new-file v2.1.53/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h
--- v2.1.53/linux/include/asm-i386/bugs.h	Mon Jul  7 16:02:01 1997
+++ linux/include/asm-i386/bugs.h	Sat Sep  6 10:50:21 1997
@@ -15,12 +15,12 @@
 
 #define CONFIG_BUGi386
 
-static void no_halt(char *s, int *ints)
+__initfunc(static void no_halt(char *s, int *ints))
 {
 	hlt_works_ok = 0;
 }
 
-static void no_387(char *s, int *ints)
+__initfunc(static void no_387(char *s, int *ints))
 {
 	hard_math = 0;
 	__asm__("movl %%cr0,%%eax\n\t"
@@ -28,9 +28,9 @@
 		"movl %%eax,%%cr0\n\t" : : : "ax");
 }
 
-static char fpu_error = 0;
+static char __initdata fpu_error = 0;
 
-static void copro_timeout(void)
+__initfunc(static void copro_timeout(void))
 {
 	fpu_error = 1;
 	timer_table[COPRO_TIMER].expires = jiffies+100;
@@ -41,7 +41,7 @@
 	outb_p(0,0xf0);
 }
 
-static void check_fpu(void)
+__initfunc(static void check_fpu(void))
 {
 	static double x = 4195835.0;
 	static double y = 3145727.0;
@@ -99,7 +99,7 @@
 	printk("Hmm, FDIV bug i%c86 system\n", '0'+x86);
 }
 
-static void check_hlt(void)
+__initfunc(static void check_hlt(void))
 {
 	printk(KERN_INFO "Checking 'hlt' instruction... ");
 	if (!hlt_works_ok) {
@@ -110,7 +110,7 @@
 	printk("Ok.\n");
 }
 
-static void check_tlb(void)
+__initfunc(static void check_tlb(void))
 {
 #ifndef CONFIG_M386
 	/*
@@ -125,7 +125,7 @@
 #endif
 }
 
-static void check_bugs(void)
+__initfunc(static void check_bugs(void))
 {
 	check_tlb();
 	check_fpu();
diff -u --recursive --new-file v2.1.53/linux/include/asm-i386/elf.h linux/include/asm-i386/elf.h
--- v2.1.53/linux/include/asm-i386/elf.h	Fri Oct 18 09:55:51 1996
+++ linux/include/asm-i386/elf.h	Sat Sep  6 10:23:14 1997
@@ -27,17 +27,23 @@
 #define ELF_DATA	ELFDATA2LSB;
 #define ELF_ARCH	EM_386
 
-	/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
-	   starts %edx contains a pointer to a function which might be
-	   registered using `atexit'.  This provides a mean for the
-	   dynamic linker to call DT_FINI functions for shared libraries
-	   that have been loaded before the code runs.
+/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program starts %edx
+   contains a pointer to a function which might be registered using `atexit'.
+   This provides a mean for the dynamic linker to call DT_FINI functions for
+   shared libraries that have been loaded before the code runs.
 
-	   A value of 0 tells we have no such handler.  */
+   A value of 0 tells we have no such handler.  */
 #define ELF_PLAT_INIT(_r)	_r->edx = 0
 
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE         (2 * TASK_SIZE / 3)
 
 /* Wow, the "main" arch needs arch dependent functions too.. :) */
 
diff -u --recursive --new-file v2.1.53/linux/include/asm-i386/floppy.h linux/include/asm-i386/floppy.h
--- v2.1.53/linux/include/asm-i386/floppy.h	Mon Jul  7 16:02:14 1997
+++ linux/include/asm-i386/floppy.h	Sat Sep  6 10:50:31 1997
@@ -283,6 +283,8 @@
 #define N_FDC 2
 #define N_DRIVE 8
 
+#define FLOPPY_MOTOR_MASK 0xf0
+
 /*
  * The DMA channel used by the floppy controller cannot access data at
  * addresses >= 16MB
diff -u --recursive --new-file v2.1.53/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v2.1.53/linux/include/asm-i386/pgtable.h	Thu Aug 14 20:49:17 1997
+++ linux/include/asm-i386/pgtable.h	Sat Sep  6 10:50:21 1997
@@ -19,6 +19,7 @@
 #define flush_cache_range(mm, start, end)	do { } while (0)
 #define flush_cache_page(vma, vmaddr)		do { } while (0)
 #define flush_page_to_ram(page)			do { } while (0)
+#define flush_icache_range(start, end)		do { } while (0)
 
 /*
  * TLB flushing:
diff -u --recursive --new-file v2.1.53/linux/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h
--- v2.1.53/linux/include/asm-i386/uaccess.h	Mon Jul  7 16:02:14 1997
+++ linux/include/asm-i386/uaccess.h	Sat Sep  6 10:50:21 1997
@@ -18,9 +18,19 @@
  * For historical reasons, these macros are grossly misnamed.
  */
 
+extern unsigned long __bad_fs_size(void);
+
 #define get_fs()	(current->tss.segment)
-#define set_fs(x)	(current->tss.segment = (x))
 #define get_ds()	(KERNEL_DS)
+
+/* Some architectures -- Alpha for one -- use "segment" schemes that 
+   require all bits to be preserved, thus the i386 traditional `ushort'
+   doesn't work.  To head off problems early, force the Intel folks
+   to do it Right as well.  */
+
+#define set_fs(x)	(current->tss.segment =				\
+			 sizeof(x) == sizeof(unsigned long) ? (x) 	\
+			 : __bad_fs_size())
 
 /*
  * Address Ok:
diff -u --recursive --new-file v2.1.53/linux/include/asm-mips/floppy.h linux/include/asm-mips/floppy.h
--- v2.1.53/linux/include/asm-mips/floppy.h	Mon Aug 18 18:19:46 1997
+++ linux/include/asm-mips/floppy.h	Sat Sep  6 10:09:56 1997
@@ -95,6 +95,8 @@
 #define N_FDC 1			/* do you *really* want a second controller? */
 #define N_DRIVE 8
 
+#define FLOPPY_MOTOR_MASK 0xf0
+
 /*
  * The DMA channel used by the floppy controller cannot access data at
  * addresses >= 16MB
diff -u --recursive --new-file v2.1.53/linux/include/asm-mips/namei.h linux/include/asm-mips/namei.h
--- v2.1.53/linux/include/asm-mips/namei.h	Thu Sep  4 17:07:31 1997
+++ linux/include/asm-mips/namei.h	Sat Sep  6 10:04:16 1997
@@ -25,7 +25,16 @@
 			
 	if (IS_ERR (base)) return base;
 	
-	return lookup_dentry (name, base, follow_link);
+	base = lookup_dentry (name, base, follow_link);
+
+	if (IS_ERR (base)) return base;
+
+	if (!base->d_inode) {
+		dput(base);
+		return ERR_PTR(-ENOENT);
+	}
+        
+        return base;
 }
 
 #ifdef CONFIG_BINFMT_IRIX
diff -u --recursive --new-file v2.1.53/linux/include/asm-ppc/floppy.h linux/include/asm-ppc/floppy.h
--- v2.1.53/linux/include/asm-ppc/floppy.h	Wed Dec 18 00:54:09 1996
+++ linux/include/asm-ppc/floppy.h	Sat Sep  6 10:09:56 1997
@@ -46,6 +46,8 @@
 #define N_FDC 2			/* Don't change this! */
 #define N_DRIVE 8
 
+#define FLOPPY_MOTOR_MASK 0xf0
+
 /*
  * The PowerPC has no problems with floppy DMA crossing 64k borders.
  */
diff -u --recursive --new-file v2.1.53/linux/include/asm-sparc/namei.h linux/include/asm-sparc/namei.h
--- v2.1.53/linux/include/asm-sparc/namei.h	Thu Sep  4 17:07:31 1997
+++ linux/include/asm-sparc/namei.h	Sat Sep  6 10:04:16 1997
@@ -1,4 +1,4 @@
-/* $Id: namei.h,v 1.7 1997/08/29 15:52:27 jj Exp $
+/* $Id: namei.h,v 1.8 1997/09/05 12:38:51 jj Exp $
  * linux/include/asm-sparc/namei.h
  *
  * Routines to handle famous /usr/gnemul/s*.
@@ -31,7 +31,16 @@
 			
 	if (IS_ERR (base)) return base;
 	
-	return lookup_dentry (name, base, follow_link);
+	base = lookup_dentry (name, base, follow_link);
+
+	if (IS_ERR (base)) return base;
+
+	if (!base->d_inode) {
+		dput(base);
+		return ERR_PTR(-ENOENT);
+	}
+        
+        return base;
 }
 
 #define __prefix_lookup_dentry(name, follow_link)				\
diff -u --recursive --new-file v2.1.53/linux/include/asm-sparc64/ebus.h linux/include/asm-sparc64/ebus.h
--- v2.1.53/linux/include/asm-sparc64/ebus.h	Thu Sep  4 17:07:31 1997
+++ linux/include/asm-sparc64/ebus.h	Sat Sep  6 10:04:16 1997
@@ -1,4 +1,4 @@
-/* $Id: ebus.h,v 1.2 1997/08/17 22:40:07 ecd Exp $
+/* $Id: ebus.h,v 1.3 1997/09/05 23:00:14 ecd Exp $
  * ebus.h: PCI to Ebus pseudo driver software state.
  *
  * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -9,8 +9,20 @@
 
 #include <asm/oplib.h>
 
+struct linux_ebus_child {
+	struct linux_ebus_child		*next;
+	struct linux_ebus_device	*parent;
+	int				 prom_node;
+	char				 prom_name[64];
+	unsigned long			 base_address[PROMREG_MAX];
+	int				 num_addrs;
+	unsigned int			 irqs[PROMINTR_MAX];
+	int				 num_irqs;
+};
+
 struct linux_ebus_device {
 	struct linux_ebus_device	*next;
+	struct linux_ebus_child		*children;
 	struct linux_ebus		*parent;
 	int				 prom_node;
 	char				 prom_name[64];
@@ -19,7 +31,7 @@
 	unsigned int			 irqs[PROMINTR_MAX];
 	int				 num_irqs;
 };
-	
+
 struct linux_ebus {
 	struct linux_ebus		*next;
 	struct linux_ebus_device	*devices;
@@ -31,6 +43,39 @@
 	int				 num_ebus_ranges;
 };
 
+struct linux_ebus_dma {
+	unsigned int dcsr;
+	unsigned int dacr;
+	unsigned int dbcr;
+};
+
+#define EBUS_DCSR_INT_PEND	0x00000001
+#define EBUS_DCSR_ERR_PEND	0x00000002
+#define EBUS_DCSR_DRAIN		0x00000004
+#define EBUS_DCSR_INT_EN	0x00000010
+#define EBUS_DCSR_RESET		0x00000080
+#define EBUS_DCSR_WRITE		0x00000100
+#define EBUS_DCSR_EN_DMA	0x00000200
+#define EBUS_DCSR_CYC_PEND	0x00000400
+#define EBUS_DCSR_DIAG_RD_DONE	0x00000800
+#define EBUS_DCSR_DIAG_WR_DONE	0x00001000
+#define EBUS_DCSR_EN_CNT	0x00002000
+#define EBUS_DCSR_TC		0x00004000
+#define EBUS_DCSR_DIS_CSR_DRN	0x00010000
+#define EBUS_DCSR_BURST_SZ_MASK	0x000c0000
+#define EBUS_DCSR_BURST_SZ_1	0x00080000
+#define EBUS_DCSR_BURST_SZ_4	0x00000000
+#define EBUS_DCSR_BURST_SZ_8	0x00040000
+#define EBUS_DCSR_BURST_SZ_16	0x000c0000
+#define EBUS_DCSR_DIAG_EN	0x00100000
+#define EBUS_DCSR_DIS_ERR_PEND	0x00400000
+#define EBUS_DCSR_TCI_DIS	0x00800000
+#define EBUS_DCSR_EN_NEXT	0x01000000
+#define EBUS_DCSR_DMA_ON	0x02000000
+#define EBUS_DCSR_A_LOADED	0x04000000
+#define EBUS_DCSR_NA_LOADED	0x08000000
+#define EBUS_DCSR_DEV_ID_MASK	0xf0000000
+
 extern struct linux_ebus		*ebus_chain;
 
 extern unsigned long ebus_init(unsigned long, unsigned long);
@@ -40,6 +85,9 @@
 
 #define for_each_ebusdev(dev, bus)					\
         for((dev) = (bus)->devices; (dev); (dev) = (dev)->next)
+
+#define for_each_edevchild(dev, child)					\
+        for((child) = (dev)->children; (child); (child) = (child)->next)
 
 #define for_all_ebusdev(dev, bus)					\
 	for ((bus) = ebus_chain, ((dev) = (bus) ? (bus)->devices : 0);	\
diff -u --recursive --new-file v2.1.53/linux/include/asm-sparc64/floppy.h linux/include/asm-sparc64/floppy.h
--- v2.1.53/linux/include/asm-sparc64/floppy.h	Thu Jul 17 10:06:08 1997
+++ linux/include/asm-sparc64/floppy.h	Sat Sep  6 10:09:56 1997
@@ -1,13 +1,17 @@
-/* $Id: floppy.h,v 1.3 1997/07/11 03:03:22 davem Exp $
+/* $Id: floppy.h,v 1.4 1997/09/05 23:00:15 ecd Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * Ultra/PCI support added: Sep 1997  Eddie C. Dost  (ecd@skynet.be)
  */
 
 #ifndef __ASM_SPARC64_FLOPPY_H
 #define __ASM_SPARC64_FLOPPY_H
 
+#include <linux/config.h>
+
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -23,19 +27,12 @@
  * 3) Intel 82077 controller manual
  */
 struct sun_flpy_controller {
-	volatile unsigned char status_82072;  /* Main Status reg. */
-#define dcr_82072              status_82072   /* Digital Control reg. */
-#define status1_82077          status_82072   /* Auxiliary Status reg. 1 */
-
-	volatile unsigned char data_82072;    /* Data fifo. */
-#define status2_82077          data_82072     /* Auxiliary Status reg. 2 */
-
+	volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */
+	volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */
 	volatile unsigned char dor_82077;     /* Digital Output reg. */
 	volatile unsigned char tapectl_82077; /* What the? Tape control reg? */
-
 	volatile unsigned char status_82077;  /* Main Status Register. */
 #define drs_82077              status_82077   /* Digital Rate Select reg. */
-
 	volatile unsigned char data_82077;    /* Data fifo. */
 	volatile unsigned char ___unused;
 	volatile unsigned char dir_82077;     /* Digital Input reg. */
@@ -47,40 +44,42 @@
 volatile unsigned char *fdc_status;
 
 struct sun_floppy_ops {
-	unsigned char (*fd_inb)(int port);
-	void (*fd_outb)(unsigned char value, int port);
+	unsigned char	(*fd_inb) (unsigned long port);
+	void		(*fd_outb) (unsigned char value, unsigned long port);
+	void		(*fd_enable_dma) (void);
+	void		(*fd_disable_dma) (void);
+	void		(*fd_set_dma_mode) (int);
+	void		(*fd_set_dma_addr) (char *);
+	void		(*fd_set_dma_count) (int);
+	unsigned int	(*get_dma_residue) (void);
+	void		(*fd_enable_irq) (void);
+	void		(*fd_disable_irq) (void);
+	int		(*fd_request_irq) (void);
+	void		(*fd_free_irq) (void);
+	int		(*fd_eject) (int);
 };
 
 static struct sun_floppy_ops sun_fdops;
 
 #define fd_inb(port)              sun_fdops.fd_inb(port)
 #define fd_outb(value,port)       sun_fdops.fd_outb(value,port)
-#define fd_enable_dma()           sun_fd_enable_dma()
-#define fd_disable_dma()          sun_fd_disable_dma()
+#define fd_enable_dma()           sun_fdops.fd_enable_dma()
+#define fd_disable_dma()          sun_fdops.fd_disable_dma()
 #define fd_request_dma()          (0) /* nothing... */
 #define fd_free_dma()             /* nothing... */
 #define fd_clear_dma_ff()         /* nothing... */
-#define fd_set_dma_mode(mode)     sun_fd_set_dma_mode(mode)
-#define fd_set_dma_addr(addr)     sun_fd_set_dma_addr(addr)
-#define fd_set_dma_count(count)   sun_fd_set_dma_count(count)
-#define fd_enable_irq()           /* nothing... */
-#define fd_disable_irq()          /* nothing... */
+#define fd_set_dma_mode(mode)     sun_fdops.fd_set_dma_mode(mode)
+#define fd_set_dma_addr(addr)     sun_fdops.fd_set_dma_addr(addr)
+#define fd_set_dma_count(count)   sun_fdops.fd_set_dma_count(count)
+#define get_dma_residue(x)        sun_fdops.get_dma_residue()
+#define fd_enable_irq()           sun_fdops.fd_enable_irq()
+#define fd_disable_irq()          sun_fdops.fd_disable_irq()
 #define fd_cacheflush(addr, size) /* nothing... */
-#define fd_request_irq()          sun_fd_request_irq()
-#define fd_free_irq()             /* nothing... */
-#if 0  /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */
-#define fd_dma_mem_alloc(size)    ((unsigned long) vmalloc(size))
-#define fd_dma_mem_free(addr,size) (vfree((void *)(addr)))
-#endif
-
-#define FLOPPY_MOTOR_MASK         0x10
-
-/* It's all the same... */
-#define virt_to_bus(x)            (x)
-#define bus_to_virt(x)            (x)
+#define fd_request_irq()          sun_fdops.fd_request_irq()
+#define fd_free_irq()             sun_fdops.fd_free_irq()
+#define fd_eject(drive)           sun_fdops.fd_eject(drive)
 
-/* XXX This isn't really correct. XXX */
-#define get_dma_residue(x)        (0)
+static int FLOPPY_MOTOR_MASK = 0x10;
 
 #define FLOPPY0_TYPE  4
 #define FLOPPY1_TYPE  0
@@ -94,7 +93,7 @@
  */
 #define FDC1                      sun_floppy_init()
 
-static int FDC2=-1;
+static int FDC2 = -1;
 
 #define N_FDC    1
 #define N_DRIVE  8
@@ -102,63 +101,11 @@
 /* No 64k boundary crossing problems on the Sparc. */
 #define CROSS_64KB(a,s) (0)
 
-/* Routines unique to each controller type on a Sun. */
-static unsigned char sun_82072_fd_inb(int port)
+static unsigned char sun_82077_fd_inb(unsigned long port)
 {
 	switch(port & 7) {
 	default:
-		printk("floppy: Asked to read unknown port %d\n", port);
-		panic("floppy: Port bolixed.");
-	case 4: /* FD_STATUS */
-		return sun_fdc->status_82072 & ~STATUS_DMA;
-	case 5: /* FD_DATA */
-		return sun_fdc->data_82072;
-	case 7: /* FD_DIR */
-		return (*AUXREG & AUXIO_FLPY_DCHG)? 0x80: 0;
-	};
-	panic("sun_82072_fd_inb: How did I get here?");
-}
-
-static void sun_82072_fd_outb(unsigned char value, int port)
-{
-	switch(port & 7) {
-	default:
-		printk("floppy: Asked to write to unknown port %d\n", port);
-		panic("floppy: Port bolixed.");
-	case 2: /* FD_DOR */
-		/* Oh geese, 82072 on the Sun has no DOR register,
-		 * the functionality is implemented via the AUXIO
-		 * I/O register.  So we must emulate the behavior.
-		 *
-		 * ASSUMPTIONS:  There will only ever be one floppy
-		 *               drive attached to a Sun controller
-		 *               and it will be at drive zero.
-		 */
-		{
-			unsigned bits = 0;
-			if (value & 0x10) bits |= AUXIO_FLPY_DSEL;
-			if ((value & 0x80) == 0) bits |= AUXIO_FLPY_EJCT;
-			set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT));
-		}
-		break;
-	case 5: /* FD_DATA */
-		sun_fdc->data_82072 = value;
-		break;
-	case 7: /* FD_DCR */
-		sun_fdc->dcr_82072 = value;
-		break;
-	case 4: /* FD_STATUS */
-		sun_fdc->status_82072 = value;
-		break;
-	};
-	return;
-}
-
-static unsigned char sun_82077_fd_inb(int port)
-{
-	switch(port & 7) {
-	default:
-		printk("floppy: Asked to read unknown port %d\n", port);
+		printk("floppy: Asked to read unknown port %lx\n", port);
 		panic("floppy: Port bolixed.");
 	case 4: /* FD_STATUS */
 		return sun_fdc->status_82077 & ~STATUS_DMA;
@@ -171,11 +118,11 @@
 	panic("sun_82072_fd_inb: How did I get here?");
 }
 
-static void sun_82077_fd_outb(unsigned char value, int port)
+static void sun_82077_fd_outb(unsigned char value, unsigned long port)
 {
 	switch(port & 7) {
 	default:
-		printk("floppy: Asked to write to unknown port %d\n", port);
+		printk("floppy: Asked to write to unknown port %lx\n", port);
 		panic("floppy: Port bolixed.");
 	case 2: /* FD_DOR */
 		/* Happily, the 82077 has a real DOR register. */
@@ -218,7 +165,7 @@
 	/* nothing... */
 }
 
-static __inline__ void sun_fd_disable_dma(void)
+static void sun_fd_disable_dma(void)
 {
 	doing_pdma = 0;
 	if (pdma_base) {
@@ -227,7 +174,7 @@
 	}
 }
 
-static __inline__ void sun_fd_set_dma_mode(int mode)
+static void sun_fd_set_dma_mode(int mode)
 {
 	switch(mode) {
 	case DMA_MODE_READ:
@@ -242,17 +189,17 @@
 	}
 }
 
-static __inline__ void sun_fd_set_dma_addr(char *buffer)
+static void sun_fd_set_dma_addr(char *buffer)
 {
 	pdma_vaddr = buffer;
 }
 
-static __inline__ void sun_fd_set_dma_count(int length)
+static void sun_fd_set_dma_count(int length)
 {
 	pdma_size = length;
 }
 
-static __inline__ void sun_fd_enable_dma(void)
+static void sun_fd_enable_dma(void)
 {
 	pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
 	pdma_base = pdma_vaddr;
@@ -274,23 +221,207 @@
 	} else return 0;
 }
 
+static void sun_fd_enable_irq(void)
+{
+}
+
+static void sun_fd_disable_irq(void)
+{
+}
+
+static void sun_fd_free_irq(void)
+{
+}
+
+static unsigned int sun_get_dma_residue(void)
+{
+	/* XXX This isn't really correct. XXX */
+	return 0;
+}
+
+static int sun_fd_eject(int drive)
+{
+	set_dor(0x00, 0xff, 0x90);
+	udelay(500);
+	set_dor(0x00, 0x6f, 0x00);
+	udelay(500);
+	return 0;
+}
+
+#ifdef CONFIG_PCI
+#include <asm/ebus.h>
+
+static struct linux_ebus_dma *sun_fd_ebus_dma;
+
+extern void floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+static unsigned char sun_pci_fd_inb(unsigned long port)
+{
+	return inb(port);
+}
+
+static void sun_pci_fd_outb(unsigned char val, unsigned long port)
+{
+	outb(val, port);
+}
+
+static void sun_pci_fd_enable_dma(void)
+{
+	unsigned int dcsr;
+
+	dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+	dcsr |= (EBUS_DCSR_EN_DMA | EBUS_DCSR_EN_CNT);
+	writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static void sun_pci_fd_disable_dma(void)
+{
+	unsigned int dcsr;
+
+	dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+	dcsr &= ~(EBUS_DCSR_EN_DMA | EBUS_DCSR_EN_CNT);
+	writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static void sun_pci_fd_set_dma_mode(int mode)
+{
+	unsigned int dcsr;
+
+	dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+	/*
+	 * For EBus WRITE means to system memory, which is
+	 * READ for us.
+	 */
+	if (mode == DMA_MODE_WRITE)
+		dcsr &= ~(EBUS_DCSR_WRITE);
+	else
+		dcsr |= EBUS_DCSR_WRITE;
+	writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static void sun_pci_fd_set_dma_count(int length)
+{
+	writel(length, (unsigned long)&sun_fd_ebus_dma->dbcr);
+}
+
+static void sun_pci_fd_set_dma_addr(char *buffer)
+{
+	unsigned int addr;
+
+	addr = virt_to_bus(buffer);
+	writel(addr, (unsigned long)&sun_fd_ebus_dma->dacr);
+}
+
+static void sun_pci_fd_enable_irq(void)
+{
+	unsigned int dcsr;
+
+	dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+	dcsr |= EBUS_DCSR_INT_EN;
+	writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static void sun_pci_fd_disable_irq(void)
+{
+	unsigned int dcsr;
+
+	dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+	dcsr &= ~(EBUS_DCSR_INT_EN);
+	writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static int sun_pci_fd_request_irq(void)
+{
+	int error;
+
+	error = request_irq(FLOPPY_IRQ, floppy_interrupt, SA_SHIRQ, "floppy", sun_fdc);
+	return ((error == 0) ? 0 : -1);
+}
+
+static void sun_pci_fd_free_irq(void)
+{
+	free_irq(FLOPPY_IRQ, sun_fdc);
+}
+
+static unsigned int sun_pci_get_dma_residue(void)
+{
+	unsigned int res;
+
+	res = readl((unsigned long)&sun_fd_ebus_dma->dbcr);
+	return res;
+}
+
+static int sun_pci_fd_eject(int drive)
+{
+	return -EINVAL;
+}
+#endif
+
 static struct linux_prom_registers fd_regs[2];
 
-static int sun_floppy_init(void)
+static unsigned long sun_floppy_init(void)
 {
 	char state[128];
 	int fd_node, num_regs;
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev;
 
-	use_virtual_dma = 1;
-	
 	FLOPPY_IRQ = 11;
 	for_all_sbusdev (sdev, bus) {
 		if (!strcmp(sdev->prom_name, "SUNW,fdtwo")) 
 			break;
 	}
-	if (!bus) return -1;
+	if (!bus) {
+#ifdef CONFIG_PCI
+		struct linux_ebus *ebus;
+		struct linux_ebus_device *edev;
+
+		for_all_ebusdev(edev, ebus) {
+			if (!strcmp(edev->prom_name, "fdthree"))
+				break;
+		}
+		if (!edev)
+			return -1;
+
+		if (check_region(edev->base_address[1], sizeof(struct linux_ebus_dma))) {
+			printk("sun_floppy_init: can't get region %016lx (%d)\n",
+			       edev->base_address[1], (int)sizeof(struct linux_ebus_dma));
+			return -1;
+		}
+		request_region(edev->base_address[1], sizeof(struct linux_ebus_dma), "floppy DMA");
+
+		sun_fdc = (struct sun_flpy_controller *)edev->base_address[0];
+		FLOPPY_IRQ = edev->irqs[0];
+
+		sun_fd_ebus_dma = (struct linux_ebus_dma *)edev->base_address[1];
+		writel(EBUS_DCSR_BURST_SZ_16, (unsigned long)&sun_fd_ebus_dma->dcsr);
+
+		sun_fdops.fd_inb = sun_pci_fd_inb;
+		sun_fdops.fd_outb = sun_pci_fd_outb;
+
+		use_virtual_dma = 0;
+		sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma;
+		sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma;
+		sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode;
+		sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr;
+		sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count;
+		sun_fdops.get_dma_residue = sun_pci_get_dma_residue;
+
+		sun_fdops.fd_enable_irq = sun_pci_fd_enable_irq;
+		sun_fdops.fd_disable_irq = sun_pci_fd_disable_irq;
+		sun_fdops.fd_request_irq = sun_pci_fd_request_irq;
+		sun_fdops.fd_free_irq = sun_pci_fd_free_irq;
+
+		sun_fdops.fd_eject = sun_pci_fd_eject;
+
+        	fdc_status = &sun_fdc->status_82077;
+		FLOPPY_MOTOR_MASK = 0xf0;
+
+		return (unsigned long)sun_fdc;
+#else
+		return -1;
+#endif
+	}
 	fd_node = sdev->prom_node;
 	prom_getproperty(fd_node, "status", state, sizeof(state));
 	if(!strcmp(state, "disabled")) return -1;
@@ -304,29 +435,34 @@
 								fd_regs[0].which_io,
 								0x0);
 	/* Last minute sanity check... */
-	if(sun_fdc->status_82072 == 0xff) {
+	if(sun_fdc->status1_82077 == 0xff) {
 		sun_fdc = NULL;
 		return -1;
 	}
 
         sun_fdops.fd_inb = sun_82077_fd_inb;
         sun_fdops.fd_outb = sun_82077_fd_outb;
+
+	use_virtual_dma = 1;
+	sun_fdops.fd_enable_dma = sun_fd_enable_dma;
+	sun_fdops.fd_disable_dma = sun_fd_disable_dma;
+	sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
+	sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
+	sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
+	sun_fdops.get_dma_residue = sun_get_dma_residue;
+
+	sun_fdops.fd_enable_irq = sun_fd_enable_irq;
+	sun_fdops.fd_disable_irq = sun_fd_disable_irq;
+	sun_fdops.fd_request_irq = sun_fd_request_irq;
+	sun_fdops.fd_free_irq = sun_fd_free_irq;
+
+	sun_fdops.fd_eject = sun_fd_eject;
+
         fdc_status = &sun_fdc->status_82077;
         /* printk("DOR @0x%p\n", &sun_fdc->dor_82077); */ /* P3 */
 
 	/* Success... */
-	return (int) ((unsigned long)sun_fdc);
+	return (unsigned long)sun_fdc;
 }
-
-static int sparc_eject(void)
-{
-	set_dor(0x00, 0xff, 0x90);
-	udelay(500);
-	set_dor(0x00, 0x6f, 0x00);
-	udelay(500);
-	return 0;
-}
-
-#define fd_eject(drive) sparc_eject()
 
 #endif /* !(__ASM_SPARC64_FLOPPY_H) */
diff -u --recursive --new-file v2.1.53/linux/include/asm-sparc64/namei.h linux/include/asm-sparc64/namei.h
--- v2.1.53/linux/include/asm-sparc64/namei.h	Thu Sep  4 17:07:31 1997
+++ linux/include/asm-sparc64/namei.h	Sat Sep  6 10:04:16 1997
@@ -1,4 +1,4 @@
-/* $Id: namei.h,v 1.7 1997/09/04 15:46:31 jj Exp $
+/* $Id: namei.h,v 1.8 1997/09/06 02:25:27 davem Exp $
  * linux/include/asm-sparc64/namei.h
  *
  * Routines to handle famous /usr/gnemul/s*.
@@ -14,7 +14,6 @@
 static inline struct dentry *
 __sparc64_lookup_dentry(const char *name, int follow_link)
 {
-	int error;
 	struct dentry *base;
 
 	switch (current->personality) {
diff -u --recursive --new-file v2.1.53/linux/include/linux/arcdevice.h linux/include/linux/arcdevice.h
--- v2.1.53/linux/include/linux/arcdevice.h	Thu Sep  4 17:07:31 1997
+++ linux/include/linux/arcdevice.h	Sat Sep  6 10:05:42 1997
@@ -5,7 +5,7 @@
  *
  *		Definitions for the ARCnet handlers.
  *
- * Version:	@(#)arcdevice.h	1.0	31/07/97
+ * Version:	$Id: arcdevice.h,v 1.2 1997/09/05 08:57:56 mj Exp $
  *
  * Authors:	Avery Pennarun <apenwarr@bond.net>
  *              David Woodhouse <dwmw2@cam.ac.uk>
@@ -24,7 +24,6 @@
 
 #ifdef __KERNEL__
 
-
 #define ARC_20020     1
 #define ARC_RIM_I     2
 #define ARC_90xx      3
@@ -50,6 +49,7 @@
 #define DETECT_RECONFIGS
 #undef SHOW_RECONFIGS
 
+
 /* RECON_THRESHOLD is the maximum number of RECON messages to receive within
  * one minute before printing a "cabling problem" warning.  You must have
  * DETECT_RECONFIGS enabled if you want to use this.  The default value
@@ -62,6 +62,7 @@
  */
 #define RECON_THRESHOLD 30
 
+
 /* Define this to the minimum "timeout" value.  If a transmit takes longer
  * than TX_TIMEOUT jiffies, Linux will abort the TX and retry.  On a large
  * network, or one with heavy network traffic, this timeout may need to be
@@ -71,6 +72,11 @@
 #define TX_TIMEOUT 20
 
 
+/* Display warnings about the driver being an ALPHA version.
+ */
+#define ALPHA_WARNING
+
+
 /* New debugging bitflags: each option can be enabled individually.
  *
  * These can be set while the driver is running by typing:
@@ -195,7 +201,6 @@
 };
 
 
-
 	/* the "client data" header - RFC1201 information
 	 * notice that this screws up if it's not an even number of bytes
 	 * <sigh>
@@ -235,7 +240,6 @@
 #define S_EXTRA_CLIENTDATA (sizeof(struct S_ClientData)-1)
 
 
-
 /* "Incoming" is information needed for each address that could be sending
  * to us.  Mostly for partially-received split packets.
  */
@@ -260,7 +264,6 @@
 };
 
 
-
 struct arcnet_local {
   struct net_device_stats stats;
   u_short sequence;	/* sequence number (incs with each packet) */
@@ -268,12 +271,12 @@
   u_char stationid,	/* our 8-bit station address */
     recbuf,		/* receive buffer # (0 or 1) */
     txbuf,		/* transmit buffer # (2 or 3) */
-    txready,	/* buffer where a packet is ready to send */
-    config,         /* current value of CONFIG register */
-    timeout,        /* Extended timeout for COM20020 */
-    backplane,      /* Backplane flag for COM20020 */     
-    setup,          /* Contents of setup register */
-    intmask;	/* current value of INTMASK register */
+    txready,		/* buffer where a packet is ready to send */
+    config,		/* current value of CONFIG register */
+    timeout,		/* Extended timeout for COM20020 */
+    backplane,		/* Backplane flag for COM20020 */     
+    setup,		/* Contents of setup register */
+    intmask;		/* current value of INTMASK register */
   short intx,		/* in TX routine? */
     in_txhandler,	/* in TX_IRQ handler? */
     sending,		/* transmit in progress? */
@@ -282,8 +285,8 @@
   
 #if defined(DETECT_RECONFIGS) && defined(RECON_THRESHOLD)
   time_t first_recon,	/* time of "first" RECON message to count */
-    last_recon;	/* time of most recent RECON */
-  int num_recons,		/* number of RECONs between first and last. */
+    last_recon;		/* time of most recent RECON */
+  int num_recons,	/* number of RECONs between first and last. */
     network_down;	/* do we think the network is down? */
 #endif
   
@@ -302,8 +305,7 @@
   void (*en_dis_able_TX) (struct device *dev, int enable); 
   void (*prepare_tx)(struct device *dev,u_char *hdr,int hdrlen,
 		     char *data,int length,int daddr,int exceptA, int offset);
-  void (*openclose_device)(int open);
-  
+  void (*openclose_device)(int open);  
   
   struct device *adev;	/* RFC1201 protocol device */
   
@@ -318,12 +320,34 @@
 #ifdef CONFIG_ARCNET_1051
   struct device *sdev;	/* RFC1051 protocol device */
 #endif
+};
 
+/* Functions exported by arcnet.c
+ */
 
-};
+#if ARCNET_DEBUG_MAX & D_SKB
+extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
+			    char *desc);
+#else
+#define arcnet_dump_skb(dev,skb,desc) ;
+#endif
 
+#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
+extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
+			       char *desc);
+#else
+#define arcnet_dump_packet(dev,buffer,ext,desc) ;
+#endif
 
-#endif  /* __KERNEL__ */
-#endif	/* _LINUX_ARCDEVICE_H */
+extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
+extern void arcnet_makename(char *device);
+extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
+extern void arcnet_setup(struct device *dev);
+extern int arcnet_go_tx(struct device *dev,int enable_irq);
+extern void arcnetA_continue_tx(struct device *dev);
+extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
+extern void arcnet_use_count(int open);
 
 
+#endif  /* __KERNEL__ */
+#endif	/* _LINUX_ARCDEVICE_H */
diff -u --recursive --new-file v2.1.53/linux/include/linux/fd.h linux/include/linux/fd.h
--- v2.1.53/linux/include/linux/fd.h	Sun Jan 19 05:27:58 1997
+++ linux/include/linux/fd.h	Sat Sep  6 10:09:56 1997
@@ -248,7 +248,7 @@
 	int dtr;
 	unsigned char version;	/* FDC version code */
 	unsigned char dor;
-	int address;		/* io address */
+	unsigned long address;	/* io address */
 	unsigned int rawcmd:2;
 	unsigned int reset:1;
 	unsigned int need_configure:1;
diff -u --recursive --new-file v2.1.53/linux/include/linux/if_arcnet.h linux/include/linux/if_arcnet.h
--- v2.1.53/linux/include/linux/if_arcnet.h	Thu Sep  4 17:07:31 1997
+++ linux/include/linux/if_arcnet.h	Sat Sep  6 10:05:42 1997
@@ -5,7 +5,7 @@
  *
  *		Global definitions for the ARCnet interface.
  *
- * Version:	@(#)if_arcnet.h	1.0	07/08/97
+ * Version:	$Id: if_arcnet.h,v 1.2 1997/09/05 08:57:54 mj Exp $
  *
  * Author:	David Woodhouse <dwmw2@cam.ac.uk>
  *		Avery Pennarun <apenwarr@bond.net>	
@@ -50,7 +50,7 @@
 /*
  *	This is an ARCnet frame header.
  */
- 
+
 struct archdr                       /* was struct HardHeader */
 {
 	u_char	source,		/* source ARCnet - filled in automagically */
@@ -61,4 +61,3 @@
 };
 
 #endif	/* _LINUX_IF_ARCNET_H */
-
diff -u --recursive --new-file v2.1.53/linux/include/linux/kernel.h linux/include/linux/kernel.h
--- v2.1.53/linux/include/linux/kernel.h	Mon Jun 30 15:23:11 1997
+++ linux/include/linux/kernel.h	Fri Sep  5 20:30:43 1997
@@ -68,6 +68,16 @@
  */
 #define fsuser() (current->fsuid == 0)
 
+/*
+ *      Display an IP address in readable format.
+ */
+
+#define NIPQUAD(addr) \
+	(((addr) >> 0)  & 0xff), \
+	(((addr) >> 8)  & 0xff), \
+	(((addr) >> 16) & 0xff), \
+	(((addr) >> 24) & 0xff)
+
 #endif /* __KERNEL__ */
 
 #define SI_LOAD_SHIFT	16
diff -u --recursive --new-file v2.1.53/linux/include/linux/openpic.h linux/include/linux/openpic.h
--- v2.1.53/linux/include/linux/openpic.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/openpic.h	Sat Sep  6 10:04:16 1997
@@ -0,0 +1,364 @@
+/*
+ *  linux/openpic.h -- OpenPIC definitions
+ *
+ *  Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ *
+ *  This file is based on the following documentation:
+ *
+ *	The Open Programmable Interrupt Controller (PIC)
+ *	Register Interface Specification Revision 1.2
+ *
+ *	Issue Date: October 1995
+ *
+ *	Issued jointly by Advanced Micro Devices and Cyrix Corporation
+ *
+ *	AMD is a registered trademark of Advanced Micro Devices, Inc.
+ *	Copyright (C) 1995, Advanced Micro Devices, Inc. and Cyrix, Inc.
+ *	All Rights Reserved.
+ *
+ *  To receive a copy of this documentation, send an email to openpic@amd.com.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#ifndef _LINUX_OPENPIC_H
+#define _LINUX_OPENPIC_H
+
+#if !defined(__powerpc__) && !defined(__i386__)
+#error Unsupported OpenPIC platform
+#endif
+
+
+#ifdef __KERNEL__
+
+    /*
+     *  OpenPIC supports up to 2048 interrupt sources and up to 32 processors
+     */
+
+#define OPENPIC_MAX_SOURCES	2048
+#define OPENPIC_MAX_PROCESSORS	32
+
+#define OPENPIC_NUM_TIMERS	4
+#define OPENPIC_NUM_IPI		4
+#define OPENPIC_NUM_PRI		16
+#define OPENPIC_NUM_VECTORS	256
+
+
+    /*
+     *  OpenPIC Registers are 32 bits and aligned on 128 bit boundaries
+     */
+
+typedef struct _OpenPIC_Reg {
+    u_int Reg;					/* Little endian! */
+    char Pad[0xc];
+} OpenPIC_Reg;
+
+
+    /*
+     *  Per Processor Registers
+     */
+
+typedef struct _OpenPIC_Processor {
+    /*
+     *  Private Shadow Registers (for SLiC backwards compatibility)
+     */
+    u_int IPI0_Dispatch_Shadow;			/* Write Only */
+    char Pad1[0x4];
+    u_int IPI0_Vector_Priority_Shadow;		/* Read/Write */
+    char Pad2[0x34];
+    /*
+     *  Interprocessor Interrupt Command Ports
+     */
+    OpenPIC_Reg _IPI_Dispatch[OPENPIC_NUM_IPI];	/* Write Only */
+    /*
+     *  Current Task Priority Register
+     */
+    OpenPIC_Reg _Current_Task_Priority;		/* Read/Write */
+#ifndef __powerpc__
+    /*
+     *  Who Am I Register
+     */
+    OpenPIC_Reg _Who_Am_I;			/* Read Only */
+#else
+    char Pad3[0x10];
+#endif
+#ifndef __i386__
+    /*
+     *  Interrupt Acknowledge Register
+     */
+    OpenPIC_Reg _Interrupt_Acknowledge;		/* Read Only */
+#else
+    char Pad4[0x10];
+#endif
+    /*
+     *  End of Interrupt (EOI) Register
+     */
+    OpenPIC_Reg _EOI;				/* Read/Write */
+    char Pad5[0xf40];
+} OpenPIC_Processor;
+
+
+    /*
+     *  Timer Registers
+     */
+
+typedef struct _OpenPIC_Timer {
+    OpenPIC_Reg _Current_Count;			/* Read Only */
+    OpenPIC_Reg _Base_Count;			/* Read/Write */
+    OpenPIC_Reg _Vector_Priority;		/* Read/Write */
+    OpenPIC_Reg _Destination;			/* Read/Write */
+} OpenPIC_Timer;
+
+
+    /*
+     *  Global Registers
+     */
+
+typedef struct _OpenPIC_Global {
+    /*
+     *  Feature Reporting Registers
+     */
+    OpenPIC_Reg _Feature_Reporting0;		/* Read Only */
+    OpenPIC_Reg _Feature_Reporting1;		/* Future Expansion */
+    /*
+     *  Global Configuration Registers
+     */
+    OpenPIC_Reg _Global_Configuration0;		/* Read/Write */
+    OpenPIC_Reg _Global_Configuration1;		/* Future Expansion */
+    /*
+     *  Vendor Specific Registers
+     */
+    OpenPIC_Reg _Vendor_Specific[4];
+    /*
+     *  Vendor Identification Register
+     */
+    OpenPIC_Reg _Vendor_Identification;		/* Read Only */
+    /*
+     *  Processor Initialization Register
+     */
+    OpenPIC_Reg _Processor_Initialization;	/* Read/Write */
+    /*
+     *  IPI Vector/Priority Registers
+     */
+    OpenPIC_Reg _IPI_Vector_Priority[OPENPIC_NUM_IPI];	/* Read/Write */
+    /*
+     *  Spurious Vector Register
+     */
+    OpenPIC_Reg _Spurious_Vector;		/* Read/Write */
+    /*
+     *  Global Timer Registers
+     */
+    OpenPIC_Reg _Timer_Frequency;		/* Read/Write */
+    OpenPIC_Timer Timer[OPENPIC_NUM_TIMERS];
+    char Pad1[0xee00];
+} OpenPIC_Global;
+
+
+    /*
+     *  Interrupt Source Registers
+     */
+
+typedef struct _OpenPIC_Source {
+    OpenPIC_Reg _Vector_Priority;		/* Read/Write */
+    OpenPIC_Reg _Destination;			/* Read/Write */
+} OpenPIC_Source;
+
+
+    /*
+     *  OpenPIC Register Map
+     */
+
+struct OpenPIC {
+#ifndef __powerpc__
+    /*
+     *  Per Processor Registers --- Private Access
+     */
+    OpenPIC_Processor Private;
+#else
+    char Pad1[0x1000];
+#endif
+    /*
+     *  Global Registers
+     */
+    OpenPIC_Global Global;
+    /*
+     *  Interrupt Source Configuration Registers
+     */
+    OpenPIC_Source Source[OPENPIC_MAX_SOURCES];
+    /*
+     *  Per Processor Registers
+     */
+    OpenPIC_Processor Processor[OPENPIC_MAX_PROCESSORS];
+};
+
+extern volatile struct OpenPIC *OpenPIC;
+
+
+    /*
+     *  Current Task Priority Register
+     */
+
+#define OPENPIC_CURRENT_TASK_PRIORITY_MASK	0x0000000f
+
+    /*
+     *  Who Am I Register
+     */
+
+#define OPENPIC_WHO_AM_I_ID_MASK		0x0000001f
+
+    /*
+     *  Feature Reporting Register 0
+     */
+
+#define OPENPIC_FEATURE_LAST_SOURCE_MASK	0x07ff0000
+#define OPENPIC_FEATURE_LAST_SOURCE_SHIFT	16
+#define OPENPIC_FEATURE_LAST_PROCESSOR_MASK	0x00001f00
+#define OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT	8
+#define OPENPIC_FEATURE_VERSION_MASK		0x000000ff
+
+    /*
+     *  Global Configuration Register 0
+     */
+
+#define OPENPIC_CONFIG_RESET			0x80000000
+#define OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE	0x20000000
+#define OPENPIC_CONFIG_BASE_MASK		0x000fffff
+
+    /*
+     *  Vendor Identification Register
+     */
+
+#define OPENPIC_VENDOR_ID_STEPPING_MASK		0x00ff0000
+#define OPENPIC_VENDOR_ID_STEPPING_SHIFT	16
+#define OPENPIC_VENDOR_ID_DEVICE_ID_MASK	0x0000ff00
+#define OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT	8
+#define OPENPIC_VENDOR_ID_VENDOR_ID_MASK	0x000000ff
+
+    /*
+     *  Vector/Priority Registers
+     */
+
+#define OPENPIC_MASK				0x80000000
+#define OPENPIC_ACTIVITY			0x40000000	/* Read Only */
+#define OPENPIC_PRIORITY_MASK			0x000f0000
+#define OPENPIC_PRIORITY_SHIFT			16
+#define OPENPIC_VECTOR_MASK			0x000000ff
+
+
+    /*
+     *  Interrupt Source Registers
+     */
+
+#define OPENPIC_SENSE_POLARITY			0x00800000	/* Undoc'd */
+#define OPENPIC_SENSE_LEVEL			0x00400000
+
+
+    /*
+     *  Timer Registers
+     */
+
+#define OPENPIC_COUNT_MASK			0x7fffffff
+#define OPENPIC_TIMER_TOGGLE			0x80000000
+#define OPENPIC_TIMER_COUNT_INHIBIT		0x80000000
+
+
+    /*
+     *  Aliases to make life simpler
+     */
+
+/* Per Processor Registers */
+#define IPI_Dispatch(i)			_IPI_Dispatch[i].Reg
+#define Current_Task_Priority		_Current_Task_Priority.Reg
+#ifndef __powerpc__
+#define Who_Am_I			_Who_Am_I.Reg
+#endif
+#ifndef __i386__
+#define Interrupt_Acknowledge		_Interrupt_Acknowledge.Reg
+#endif
+#define EOI				_EOI.Reg
+
+/* Global Registers */
+#define Feature_Reporting0		_Feature_Reporting0.Reg
+#define Feature_Reporting1		_Feature_Reporting1.Reg
+#define Global_Configuration0		_Global_Configuration0.Reg
+#define Global_Configuration1		_Global_Configuration1.Reg
+#define Vendor_Specific(i)		_Vendor_Specific[i].Reg
+#define Vendor_Identification		_Vendor_Identification.Reg
+#define Processor_Initialization	_Processor_Initialization.Reg
+#define IPI_Vector_Priority(i)		_IPI_Vector_Priority[i].Reg
+#define Spurious_Vector			_Spurious_Vector.Reg
+#define Timer_Frequency			_Timer_Frequency.Reg
+
+/* Timer Registers */
+#define Current_Count			_Current_Count.Reg
+#define Base_Count			_Base_Count.Reg
+#define Vector_Priority			_Vector_Priority.Reg
+#define Destination			_Destination.Reg
+
+/* Interrupt Source Registers */
+#define Vector_Priority			_Vector_Priority.Reg
+#define Destination			_Destination.Reg
+
+
+    /*
+     *  Vendor and Device IDs
+     */
+
+#define OPENPIC_VENDOR_ID_APPLE		0x14
+#define OPENPIC_DEVICE_ID_APPLE_HYDRA	0x46
+
+
+    /*
+     *  OpenPIC Operations
+     */
+
+/* Global Operations */
+extern void openpic_init(void);
+extern void openpic_reset(void);
+extern void openpic_enable_8259_pass_through(void);
+extern void openpic_disable_8259_pass_through(void);
+#ifndef __i386__
+extern u_int openpic_irq(u_int cpu);
+#endif
+#ifndef __powerpc__
+extern void openpic_eoi(void);
+extern u_int openpic_get_priority(void);
+extern void openpic_set_priority(u_int pri);
+#else
+extern void openpic_eoi(u_int cpu);
+extern u_int openpic_get_priority(u_int cpu);
+extern void openpic_set_priority(u_int cpu, u_int pri);
+#endif
+extern u_int openpic_get_spurious(void);
+extern void openpic_set_spurious(u_int vector);
+extern void openpic_init_processor(u_int cpumask);
+
+/* Interprocessor Interrupts */
+extern void openpic_initipi(u_int ipi, u_int pri, u_int vector);
+#ifndef __powerpc__
+extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
+#else
+extern void openpic_cause_IPI(u_int cpu, u_int ipi, u_int cpumask);
+#endif
+
+/* Timer Interrupts */
+extern void openpic_inittimer(u_int timer, u_int pri, u_int vector);
+extern void openpic_maptimer(u_int timer, u_int cpumask);
+
+/* Interrupt Sources */
+extern void openpic_enable_irq(u_int irq);
+extern void openpic_disable_irq(u_int irq);
+extern void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
+			    int is_level);
+extern void openpic_mapirq(u_int irq, u_int cpumask);
+extern void openpic_set_sense(u_int irq, int sense);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_OPENPIC_H */
diff -u --recursive --new-file v2.1.53/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.1.53/linux/include/linux/pci.h	Thu Aug 14 20:49:17 1997
+++ linux/include/linux/pci.h	Sat Sep  6 10:43:50 1997
@@ -256,6 +256,7 @@
 #define PCI_DEVICE_ID_ADL_2301		0x2301
 
 #define PCI_VENDOR_ID_NS		0x100b
+#define PCI_DEVICE_ID_NS_87415		0x0002
 #define PCI_DEVICE_ID_NS_87410		0xd001
 
 #define PCI_VENDOR_ID_TSENG		0x100c
@@ -274,6 +275,7 @@
 #define PCI_DEVICE_ID_DEC_TULIP		0x0002
 #define PCI_DEVICE_ID_DEC_TGA		0x0004
 #define PCI_DEVICE_ID_DEC_TULIP_FAST	0x0009
+#define PCI_DEVICE_ID_DEC_TGA2		0x000D
 #define PCI_DEVICE_ID_DEC_FDDI		0x000F
 #define PCI_DEVICE_ID_DEC_TULIP_PLUS	0x0014
 #define PCI_DEVICE_ID_DEC_21142		0x0019
@@ -441,6 +443,11 @@
 #define PCI_DEVICE_ID_OLICOM_OC2326	0x0014
 #define PCI_DEVICE_ID_OLICOM_OC6151	0x0021
 
+#define PCI_VENDOR_ID_SUN		0x108e
+#define PCI_DEVICE_ID_SUN_EBUS		0x1000
+#define PCI_DEVICE_ID_SUN_HAPPYMEAL	0x1001
+#define PCI_DEVICE_ID_SUN_PBM		0x8000
+
 #define PCI_VENDOR_ID_CMD		0x1095
 #define PCI_DEVICE_ID_CMD_640		0x0640
 #define PCI_DEVICE_ID_CMD_643		0x0643
@@ -775,7 +782,12 @@
 	 * necessary.  The field must not be 0 unless the device
 	 * cannot generate interrupts at all.
 	 */
-	unsigned char	irq;		/* irq generated by this device */
+	unsigned int	irq;		/* irq generated by this device */
+
+	/* Base registers for this device, can be adjusted by
+	 * pcibios_fixup() as necessary.
+	 */
+	unsigned long	base_address[6];
 };
 
 struct pci_bus {
@@ -811,6 +823,8 @@
 
 
 extern unsigned long pci_init (unsigned long mem_start, unsigned long mem_end);
+
+extern unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp);
 
 extern struct pci_dev_info *pci_lookup_dev (unsigned int vendor,
 					    unsigned int dev);
diff -u --recursive --new-file v2.1.53/linux/include/linux/tty.h linux/include/linux/tty.h
--- v2.1.53/linux/include/linux/tty.h	Mon Aug 18 18:19:47 1997
+++ linux/include/linux/tty.h	Sat Sep  6 10:50:21 1997
@@ -73,6 +73,7 @@
 #define VIDEO_TYPE_TGAC		0x40	/* DEC TGA */
 
 #define VIDEO_TYPE_SUN          0x50    /* Sun frame buffer. */
+#define VIDEO_TYPE_SUNPCI       0x51    /* Sun PCI based frame buffer. */
 
 #define VIDEO_TYPE_PMAC		0x60	/* PowerMacintosh frame buffer. */
 
diff -u --recursive --new-file v2.1.53/linux/include/net/inet_common.h linux/include/net/inet_common.h
--- v2.1.53/linux/include/net/inet_common.h	Thu Sep  4 17:07:31 1997
+++ linux/include/net/inet_common.h	Fri Sep  5 20:40:38 1997
@@ -1,8 +1,6 @@
 #ifndef _INET_COMMON_H
 #define _INET_COMMON_H
 
-#include <linux/config.h>
-
 extern struct proto_ops		inet_stream_ops;
 extern struct proto_ops		inet_dgram_ops;
 
diff -u --recursive --new-file v2.1.53/linux/include/net/snmp.h linux/include/net/snmp.h
--- v2.1.53/linux/include/net/snmp.h	Thu Sep  4 17:07:31 1997
+++ linux/include/net/snmp.h	Fri Sep  5 20:40:28 1997
@@ -19,8 +19,6 @@
 #ifndef _SNMP_H
 #define _SNMP_H
  
-#include <linux/config.h>
-
 /*
  *	We use all unsigned longs. Linux will soon be so reliable that even these
  *	will rapidly get too small 8-). Seriously consider the IpInReceives count
diff -u --recursive --new-file v2.1.53/linux/init/main.c linux/init/main.c
--- v2.1.53/linux/init/main.c	Mon Aug  4 16:25:40 1997
+++ linux/init/main.c	Sat Sep  6 10:04:16 1997
@@ -72,6 +72,7 @@
 extern unsigned long pci_init(unsigned long, unsigned long);
 extern long mca_init(long, long);
 extern long sbus_init(long, long);
+extern long powermac_init(unsigned long, unsigned long);
 extern void sysctl_init(void);
 extern void filescache_init(void);
 
@@ -86,6 +87,18 @@
 extern void lp_setup(char *str, int *ints);
 #endif
 extern void eth_setup(char *str, int *ints);
+#ifdef CONFIG_ARCNET_COM20020
+extern void com20020_setup(char *str, int *ints);
+#endif
+#ifdef CONFIG_ARCNET_RIM_I
+extern void arcrimi_setup(char *str, int *ints);
+#endif
+#ifdef CONFIG_ARCNET_COM90xxIO
+extern void com90io_setup(char *str, int *ints);
+#endif
+#ifdef CONFIG_ARCNET_COM90xx
+extern void com90xx_setup(char *str, int *ints);
+#endif
 #ifdef CONFIG_DECNET
 extern void decnet_setup(char *str, int *ints);
 #endif
@@ -212,6 +225,10 @@
 #ifdef CONFIG_SOUNDMODEM
 extern void sm_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_PMAC_CONSOLE
+extern void pmac_cons_setup(char *str, int *ints);
+extern void pmac_vmode_setup(char *str, int *ints);
+#endif
 #ifdef CONFIG_WDT
 extern void wdt_setup(char *str, int *ints);
 #endif
@@ -221,6 +238,9 @@
 #ifdef CONFIG_PLIP
 extern void plip_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_HFMODEM
+extern void hfmodem_setup(char *str, int *ints);
+#endif
 
 #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
 extern void ipc_init(void);
@@ -329,6 +349,18 @@
 #ifdef CONFIG_INET
 	{ "ether=", eth_setup },
 #endif
+#ifdef CONFIG_ARCNET_COM20020
+	{ "com20020=", com20020_setup },
+#endif
+#ifdef CONFIG_ARCNET_RIM_I
+	{ "arcrimi=", arcrimi_setup },
+#endif
+#ifdef CONFIG_ARCNET_COM90xxIO
+	{ "com90io=", com90io_setup },
+#endif
+#ifdef CONFIG_ARCNET_COM90xx
+	{ "com90xx=", com90xx_setup },
+#endif
 #ifdef CONFIG_DECNET
 	{ "decnet=", decnet_setup },
 #endif
@@ -517,6 +549,13 @@
 #ifdef CONFIG_PLIP
 	{ "plip=", plip_setup },
 #endif
+#ifdef CONFIG_SOUNDMODEM
+	{ "hfmodem=", hfmodem_setup },
+#endif
+#ifdef CONFIG_PMAC_CONSOLE
+	{ "console=", pmac_cons_setup },
+	{ "vmode=", pmac_vmode_setup },
+#endif
 	{ 0, 0 }
 };
 
@@ -875,6 +914,9 @@
 	}
 #ifdef CONFIG_SBUS
 	memory_start = sbus_init(memory_start,memory_end);
+#endif
+#ifdef CONFIG_PMAC
+	memory_start = powermac_init(memory_start, memory_end);
 #endif
 	memory_start = console_init(memory_start,memory_end);
 #ifdef CONFIG_PCI
diff -u --recursive --new-file v2.1.53/linux/ipc/shm.c linux/ipc/shm.c
--- v2.1.53/linux/ipc/shm.c	Thu Jul 17 10:06:09 1997
+++ linux/ipc/shm.c	Sat Sep  6 10:12:16 1997
@@ -498,8 +498,14 @@
 		if (shmflg & SHM_REMAP)
 			goto out;
 		err = -ENOMEM;
-		if (!(addr = get_unmapped_area(0, shp->shm_segsz)))
+		addr = 0;
+	again:
+		if (!(addr = get_unmapped_area(addr, shp->shm_segsz)))
 			goto out;
+		if(addr & (SHMLBA - 1)) {
+			addr = (addr + (SHMLBA - 1)) & ~(SHMLBA - 1);
+			goto again;
+		}
 	} else if (addr & (SHMLBA-1)) {
 		if (shmflg & SHM_RND)
 			addr &= ~(SHMLBA-1);       /* round down */
diff -u --recursive --new-file v2.1.53/linux/kernel/exit.c linux/kernel/exit.c
--- v2.1.53/linux/kernel/exit.c	Wed Sep  3 20:52:44 1997
+++ linux/kernel/exit.c	Sat Sep  6 10:11:31 1997
@@ -523,10 +523,8 @@
 
 NORET_TYPE void do_exit(long code)
 {
-	if (in_interrupt()) {
-		local_irq_count[smp_processor_id()] = 0;	/* Not really correct */
+	if (in_interrupt())
 		printk("Aiee, killing interrupt handler\n");
-	}
 fake_volatile:
 	acct_process(code);
 	current->flags |= PF_EXITING;
diff -u --recursive --new-file v2.1.53/linux/kernel/module.c linux/kernel/module.c
--- v2.1.53/linux/kernel/module.c	Mon Jul  7 08:18:56 1997
+++ linux/kernel/module.c	Sat Sep  6 10:10:48 1997
@@ -9,6 +9,7 @@
 #include <linux/vmalloc.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <asm/pgtable.h>
 
 /*
  * Originally by Anonymous (as far as I know...)
@@ -293,6 +294,10 @@
 		error = -EFAULT;
 		goto err3;
 	}
+
+	/* On some machines it is necessary to do something here
+	   to make the I and D caches consistent.  */
+	flush_icache_range((unsigned long)mod, (unsigned long)mod + mod->size);
 
 	/* Update module references.  */
 	mod->next = mod_tmp.next;
diff -u --recursive --new-file v2.1.53/linux/kernel/sys.c linux/kernel/sys.c
--- v2.1.53/linux/kernel/sys.c	Thu Jul 17 10:06:09 1997
+++ linux/kernel/sys.c	Sat Sep  6 10:23:14 1997
@@ -366,7 +366,7 @@
 int acct_process(long exitcode)
 {
    struct acct ac;
-   unsigned short fs;
+   unsigned long fs;
 
    if (acct_active) {
       strncpy(ac.ac_comm, current->comm, ACCT_COMM);
diff -u --recursive --new-file v2.1.53/linux/kernel/time.c linux/kernel/time.c
--- v2.1.53/linux/kernel/time.c	Wed Apr 23 19:01:29 1997
+++ linux/kernel/time.c	Fri Sep  5 08:53:26 1997
@@ -15,7 +15,7 @@
  * 1993-10-08    Torsten Duwe
  *      adjtime interface update and CMOS clock write code
  * 1995-08-13    Torsten Duwe
- *      kernel PLL updated to 1994-12-13 specs (rfc-1489)
+ *      kernel PLL updated to 1994-12-13 specs (rfc-1589)
  */
 
 #include <linux/errno.h>
diff -u --recursive --new-file v2.1.53/linux/lib/vsprintf.c linux/lib/vsprintf.c
--- v2.1.53/linux/lib/vsprintf.c	Mon Aug  4 16:25:40 1997
+++ linux/lib/vsprintf.c	Fri Sep  5 20:31:57 1997
@@ -253,41 +253,6 @@
 			}
 			continue;
 
-		case 'I': /* IPv4 / IPv6 printout */
-			{
-			  __u8 *ip4;
-			  char sbuf[6];
-			  if (qualifier == 'l') {
-			    __u16 *ip6 = va_arg(args, __u16 *);
-			    i = 6;
-			    for ( ; i > 0; --i, ++ip6)
-			      if (*ip6 != 0)
-				break;
-			    if (i < 6)
-			      *str++ = ':';
-			    for ( ; i > 0; --i, ++ip6) {
-			      sprintf(sbuf,":%04x",(int)(*ip6));
-			      s = sbuf;
-			      while (*s)
-				*str++ = *s++;
-			    }
-			    *str++ = ':';
-			    ip4 = (__u8*) ip6;
-			  } else {
-			    ip4 = va_arg(args, __u8 *);
-			  }
-			  for (i = 0; i < 4; ++i, ++ip4) {
-			    if (i == 3)
-			      sprintf(sbuf,"%d", 0xFF & (*ip4));
-			    else
-			      sprintf(sbuf,"%d.", 0xFF & (*ip4));
-			    s = sbuf;
-			    while (*s)
-			      *str++ = *s++;
-			  }
-			}
-			continue;
-
 		/* integer number formats - set up the flags and "break" */
 		case 'o':
 			base = 8;
diff -u --recursive --new-file v2.1.53/linux/mm/filemap.c linux/mm/filemap.c
--- v2.1.53/linux/mm/filemap.c	Wed Sep  3 20:52:44 1997
+++ linux/mm/filemap.c	Sat Sep  6 10:23:14 1997
@@ -892,8 +892,9 @@
 static inline int do_write_page(struct inode * inode, struct file * file,
 	const char * page, unsigned long offset)
 {
-	int old_fs, retval;
+	int retval;
 	unsigned long size;
+	unsigned long old_fs;
 
 	size = offset + PAGE_SIZE;
 	/* refuse to extend file size.. */
diff -u --recursive --new-file v2.1.53/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c
--- v2.1.53/linux/net/ipv4/ip_fragment.c	Thu Sep  4 17:07:32 1997
+++ linux/net/ipv4/ip_fragment.c	Sat Sep  6 10:05:42 1997
@@ -5,7 +5,7 @@
  *
  *		The IP fragmentation functionality.
  *		
- * Version:	$Id: ip_fragment.c,v 1.25 1997/08/17 05:56:07 freitag Exp $
+ * Version:	$Id: ip_fragment.c,v 1.26 1997/09/04 22:35:00 davem Exp $
  *
  * Authors:	Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
  *		Alan Cox <Alan.Cox@linux.org>
@@ -313,8 +313,7 @@
 	len = qp->ihlen + qp->len;
 	
 	if(len>65535) {
-		printk(KERN_INFO "Oversized IP packet from %I.\n", 
-		       &qp->iph->saddr);
+		printk(KERN_INFO "Oversized IP packet from %d.%d.%d.%d.\n", NIPQUAD(qp->iph->saddr));
 		ip_statistics.IpReasmFails++;
 		ip_free(qp);
 		return NULL;
@@ -322,8 +321,7 @@
 	
 	if ((skb = dev_alloc_skb(len)) == NULL) {
 		ip_statistics.IpReasmFails++;
-		NETDEBUG(printk(KERN_ERR "IP: queue_glue: no memory for gluing "
-				"queue %p\n", qp));
+		NETDEBUG(printk(KERN_ERR "IP: queue_glue: no memory for gluing queue %p\n", qp));
 		ip_free(qp);
 		return NULL;
 	}
@@ -436,8 +434,7 @@
 	
 	/* Attempt to construct an oversize packet. */
 	if(ntohs(iph->tot_len)+(int)offset>65535) {
-		printk(KERN_INFO "Oversized packet received from %I\n",
-		       &iph->saddr);
+		printk(KERN_INFO "Oversized packet received from %d.%d.%d.%d\n", NIPQUAD(iph->saddr));
 		frag_kfree_skb(skb, FREE_READ);
 		ip_statistics.IpReasmFails++;
 		return NULL;
diff -u --recursive --new-file v2.1.53/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.1.53/linux/net/ipv4/tcp.c	Thu Sep  4 17:07:32 1997
+++ linux/net/ipv4/tcp.c	Sat Sep  6 09:16:02 1997
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.70 1997/09/01 03:14:28 davem Exp $
+ * Version:	$Id: tcp.c,v 1.71 1997/09/06 05:11:45 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1503,10 +1503,11 @@
  *	Wait for an incoming connection, avoid race
  *	conditions. This must be called with the socket locked.
  */
-static struct open_request * wait_for_connect(struct sock * sk)
+static struct open_request * wait_for_connect(struct sock * sk,
+					      struct open_request **pprev)
 {
 	struct wait_queue wait = { current, NULL };
-	struct open_request *req = NULL, *dummy;
+	struct open_request *req = NULL;
 
 	add_wait_queue(sk->sleep, &wait);
 	for (;;) {
@@ -1514,7 +1515,7 @@
 		release_sock(sk);
 		schedule();
 		lock_sock(sk);
-		req = tcp_find_established(&(sk->tp_pinfo.af_tcp), &dummy);
+		req = tcp_find_established(&(sk->tp_pinfo.af_tcp), pprev);
 		if (req) 
 			break;
 		if (current->signal & ~current->blocked)
@@ -1569,7 +1570,7 @@
 	error = EAGAIN;
 	if (flags & O_NONBLOCK)
 		goto out;
-	req = wait_for_connect(sk);
+	req = wait_for_connect(sk, &prev);
 	if (req)
 		goto got_new_connect;
 	error = ERESTARTSYS;
diff -u --recursive --new-file v2.1.53/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.1.53/linux/net/ipv4/tcp_ipv4.c	Thu Sep  4 17:07:32 1997
+++ linux/net/ipv4/tcp_ipv4.c	Sat Sep  6 10:05:42 1997
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.61 1997/09/02 09:46:55 freitag Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.62 1997/09/04 22:34:59 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -1440,14 +1440,14 @@
 	case CHECKSUM_HW:
 		if (tcp_v4_check(th,len,saddr,daddr,skb->csum)) {
 			struct iphdr * iph = skb->nh.iph;
-			printk(KERN_DEBUG "TCPv4 bad checksum from %I:%04x to %I:%04x, len=%d/%d/%d\n",
-			       &saddr, ntohs(th->source), &daddr,
+			printk(KERN_DEBUG "TCPv4 bad checksum from %d.%d.%d.%d:%04x to %d.%d.%d.%d:%04x, len=%d/%d/%d\n",
+			       NIPQUAD(saddr), ntohs(th->source), NIPQUAD(daddr),
 			       ntohs(th->dest), len, skb->len, ntohs(iph->tot_len));
 					goto discard_it;
 		}
 	default:
 		/* CHECKSUM_UNNECESSARY */
-	};
+	}
 
 	tcp_statistics.TcpInSegs++;
 
diff -u --recursive --new-file v2.1.53/linux/net/netsyms.c linux/net/netsyms.c
--- v2.1.53/linux/net/netsyms.c	Thu Sep  4 17:07:32 1997
+++ linux/net/netsyms.c	Sat Sep  6 10:07:22 1997
@@ -341,6 +341,8 @@
 EXPORT_SYMBOL(ip_rcv);
 EXPORT_SYMBOL(arp_rcv);
 
+EXPORT_SYMBOL(if_port_text);
+
 #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) 
 #include<linux/if_ltalk.h>
 EXPORT_SYMBOL(ltalk_setup);
