diff -u --recursive --new-file v2.2.0-pre5/linux/CREDITS linux/CREDITS
--- v2.2.0-pre5/linux/CREDITS	Thu Jan  7 15:11:35 1999
+++ linux/CREDITS	Thu Jan  7 08:41:54 1999
@@ -1581,8 +1581,8 @@
 S: France
 
 N: Rik van Riel
-E: H.H.vanRiel@phys.uu.nl
-W: http://www.phys.uu.nl/~riel/
+E: H.H.vanRiel@humbolt.geo.uu.nl
+W: http://humbolt.geo.uu.nl/
 D: Maintainer of the mm-patches page (see www.linuxhq.com)
 D: Documentation/sysctl/*, kswapd fixes, random kernel hacker
 S: Vorenkampsweg 1
@@ -1631,6 +1631,14 @@
 E: rubini@ipvvis.unipv.it
 D: the gpm mouse server and kernel support for it
 
+N: Philipp Rumpf
+E: prumpf@jcsbs.lanobis.de
+D: ipi_count for x86
+D: random bugfixes
+S: Rueting 4
+S: 23743 Groemitz
+S: Germany
+
 N: Paul Russell
 E: Paul.Russell@rustcorp.com.au
 W: http://www.rustcorp.com
@@ -1719,6 +1727,16 @@
 D: wd33c93 SCSI driver (linux-m68k)
 S: San Jose, California
 S: USA
+
+N: Jaspreet Singh
+E: jaspreet@sangoma.com
+W: www.sangoma.com
+D: WANPIPE driver for Sangoma S508/FT1 cards 
+S: Sangoma Technologies Inc.,
+S: 1001 Denison Street
+S: Suite 101
+S: Markham, Ontario L3R 2Z6
+S: Canada
 
 N: Rick Sladkey
 E: jrs@world.std.com
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/cdrom/mcdx linux/Documentation/cdrom/mcdx
--- v2.2.0-pre5/linux/Documentation/cdrom/mcdx	Sat May  2 14:19:50 1998
+++ linux/Documentation/cdrom/mcdx	Thu Jan  7 08:41:54 1999
@@ -21,13 +21,13 @@
 
 This driver:
 
-    o   handles XA (and hopefully) multi session CDs as well as
+    o   handles XA and (hopefully) multi session CDs as well as
         ordinary CDs;
     o   supports up to 5 drives (of course, you'll need free 
         IRQs, i/o ports and slots);
     o   uses much less kernel memory than the standard mcd driver
         (no extra driver internal buffers!).
-        o   plays audio (like the `old' driver, I hope)
+    o   plays audio (like the `old' driver, I hope)
 
 This version doesn't support yet:
 
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/digiboard.txt linux/Documentation/digiboard.txt
--- v2.2.0-pre5/linux/Documentation/digiboard.txt	Sat May  2 14:19:51 1998
+++ linux/Documentation/digiboard.txt	Thu Jan  7 08:41:54 1999
@@ -10,7 +10,7 @@
 
 In case you have problems with this version (1.6.1) of this driver, please
 email directly to me as I made the last update. It you have a report about
-runnning it on other architectures than intel, email me, so I can document
+running it on other architectures than intel, email me, so I can document
 it here.
 
 A version of this driver has been taken by Digiboard to make a driver
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/digiepca.txt linux/Documentation/digiepca.txt
--- v2.2.0-pre5/linux/Documentation/digiepca.txt	Tue May 13 22:40:59 1997
+++ linux/Documentation/digiepca.txt	Thu Jan  7 08:41:54 1999
@@ -27,7 +27,7 @@
 drivers started device names with 1.
 
 PCI boards are auto-detected and configured by the driver.  PCI boards will
-be allocated device numbers (internally) begining with the lowest PCI slot
+be allocated device numbers (internally) beginning with the lowest PCI slot
 first.  In other words a PCI card in slot 3 will always have higher device
 nodes than a PCI card in slot 1. 
 
@@ -46,7 +46,7 @@
    Base of memory window (in HEX if using string identifiers), 
 
 NOTE : PCI boards are auto-detected and configured.  Do not attempt to 
-configure PCI boards with the LILO append comand.  If you wish to override
+configure PCI boards with the LILO append command.  If you wish to override
 previous configuration data (As set by digiConfig), but you do not wish to
 configure any specific card (Example if there are PCI cards in the system) 
 the following override command will accomplish this:
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/fb/matroxfb.txt linux/Documentation/fb/matroxfb.txt
--- v2.2.0-pre5/linux/Documentation/fb/matroxfb.txt	Tue Dec 22 14:16:53 1998
+++ linux/Documentation/fb/matroxfb.txt	Thu Jan  7 12:18:09 1999
@@ -118,8 +118,17 @@
 noinit   - tells driver, that devices were already initialized. You should use it
            if you have G100 and/or if driver cannot detect memory, you see strange
 	   pattern on screen and so on. Devices not enabled by BIOS are still
-	   initialized.
-init     - driver initializes every device it knows about. It is default.
+	   initialized. It is default.
+init     - driver initializes every device it knows about.
+nomtrr   - disables write combining on frame buffer. This slows down driver but
+           there is reported minor incompatibility between GUS DMA and XFree under
+	   high loads if write combining is enabled (sound dropouts).
+mtrr     - enables write combining on frame buffer. It speeds up video accesses
+           much. It is default. You must have MTRR support enabled in kernel and
+	   your CPU must have MTRR (f.e. Pentium II have them).
+sgram    - tells to driver that you have G200 with SGRAM memory. It has no effect 
+           without `init'.
+sdram    - tells to driver that you have G200 with SDRAM memory. It is a default.
 inv24    - change timings parameters for 24bpp modes on Millenium and Millenium II.
            Specify this if you see strange color shadows around characters.
 noinv24  - use standard timmings. It is default.
@@ -200,6 +209,7 @@
  + 24bpp does not support correctly XF-FBDev on big-endian architectures.
  + interlaced text mode is not supported; it looks like hardware limitiation,
    but I'm not sure.
+ + G200 SGRAM/SDRAM is not autodetected.
  + maybe more...
 And following misfeatures:
  + SVGALib does not restore screen on exit.
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/isdn/README.act2000 linux/Documentation/isdn/README.act2000
--- v2.2.0-pre5/linux/Documentation/isdn/README.act2000	Sat May  2 14:19:51 1998
+++ linux/Documentation/isdn/README.act2000	Thu Jan  7 08:41:54 1999
@@ -7,7 +7,7 @@
 Version. Currently, only the ISA-Bus version of the card is supported.
 However MCA and PCMCIA will follow soon.
 
-The ISA-Bus Version uses 8 IO-ports. The base port adress has to be set
+The ISA-Bus Version uses 8 IO-ports. The base port address has to be set
 manually using the DIP switches.
 
 Setting up the DIP switches for the IBM Active 2000 ISDN card:
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/isdn/README.concap linux/Documentation/isdn/README.concap
--- v2.2.0-pre5/linux/Documentation/isdn/README.concap	Sat May  2 14:19:51 1998
+++ linux/Documentation/isdn/README.concap	Thu Jan  7 08:41:54 1999
@@ -229,7 +229,7 @@
 then the interface of the service function could be changed
 by passing a pointer of type (struct device*) instead of
 type (struct concap_proto*). Doing so would make many of the service
-functions compatible to network device support fuctions.
+functions compatible to network device support functions.
 
 e.g. instead of the concap protocol's service function
 
@@ -241,7 +241,7 @@
 
 As this is compatible to the dev->hard_start_xmit() method, the device
 driver could directly register the concap protocol's encap_and_xmit()
-fuction as its hard_start_xmit() method. This would eliminate one
+function as its hard_start_xmit() method. This would eliminate one
 procedure call layer.
 
 
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/isdn/README.x25 linux/Documentation/isdn/README.x25
--- v2.2.0-pre5/linux/Documentation/isdn/README.x25	Sat May  2 14:19:51 1998
+++ linux/Documentation/isdn/README.x25	Thu Jan  7 08:41:54 1999
@@ -210,7 +210,7 @@
 isdnloop driver. It seems that it is not caused by the isdn code.
 Somehow, the inode of a socket is freed while a process still refers
 the socket's wait queue. This causes problems when the process tries to
-remove itself from the wait queue (refered by the dangling
+remove itself from the wait queue (referred by the dangling
 sock->sleep pointer) before returning from a select() system call.
 
 - Henner
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/locks.txt linux/Documentation/locks.txt
--- v2.2.0-pre5/linux/Documentation/locks.txt	Sat May  2 14:19:51 1998
+++ linux/Documentation/locks.txt	Thu Jan  7 08:41:54 1999
@@ -45,7 +45,7 @@
 I wanted the two lock styles to be cooperative, but there were so many
 race and deadlock conditions that the current solution was the only
 practical one. It puts us in the same position as, for example, SunOS
-4.1.x and serveral other commercial Unices. The only OS's that support
+4.1.x and several other commercial Unices. The only OS's that support
 cooperative flock()/fcntl() are those that emulate flock() using
 fcntl(), with all the problems that implies.
 
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/m68k/kernel-options.txt linux/Documentation/m68k/kernel-options.txt
--- v2.2.0-pre5/linux/Documentation/m68k/kernel-options.txt	Sat May  2 14:19:51 1998
+++ linux/Documentation/m68k/kernel-options.txt	Thu Jan  7 08:41:54 1999
@@ -617,7 +617,7 @@
     Legal values are between 0 and 255. Default: 255/0. Note: This
     value is forced to 0 on a Falcon, since scatter-gather isn't
     possible with the ST-DMA. Not using scatter-gather hurts
-    perfomance significantly.
+    performance significantly.
 
   <host-id>:
     The SCSI ID to be used by the initiator (your Atari). This is
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/networking/6pack.txt linux/Documentation/networking/6pack.txt
--- v2.2.0-pre5/linux/Documentation/networking/6pack.txt	Sat May  2 14:19:51 1998
+++ linux/Documentation/networking/6pack.txt	Thu Jan  7 08:41:54 1999
@@ -16,7 +16,7 @@
 - The PC is given full control over the radio
   channel. Special control data is exchanged between the PC and the TNC so
   that the PC knows at any time if the TNC is receiving data, if a TNC
-  buffer underrun or overrun has occured, if the PTT is
+  buffer underrun or overrun has occurred, if the PTT is
   set and so on. This control data is processed at a higher priority than
   normal data, so a data stream can be interrupted at any time to issue an
   important event. This helps to improve the channel access and timing 
@@ -167,7 +167,7 @@
 some cleaning and optimizing. This will be done in a later release.
 
 If you encounter a bug or if you have a question or suggestion concerning the
-driver, feel free to mail me, using the adresses given at the beginning of
+driver, feel free to mail me, using the addresses given at the beginning of
 this file.
 
 Have fun!
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/networking/arcnet-hardware.txt linux/Documentation/networking/arcnet-hardware.txt
--- v2.2.0-pre5/linux/Documentation/networking/arcnet-hardware.txt	Thu Sep 17 17:53:34 1998
+++ linux/Documentation/networking/arcnet-hardware.txt	Thu Jan  7 08:41:55 1999
@@ -2560,7 +2560,7 @@
 --------------------
 
 The two jumpers labeled ET1 and ET2 are used to determine the timeout
-parameters (respons and reconfiguration time). Every node in a network
+parameters (response and reconfiguration time). Every node in a network
 must be set to the same timeout values.
 
    ET1 ET2 | Response Time (us) | Reconfiguration Time (ms)
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/networking/cops.txt linux/Documentation/networking/cops.txt
--- v2.2.0-pre5/linux/Documentation/networking/cops.txt	Sat May  2 14:19:51 1998
+++ linux/Documentation/networking/cops.txt	Thu Jan  7 08:41:55 1999
@@ -17,7 +17,7 @@
 DAYNA driver mode:
 	Dayna DL2000/DaynaTalk PC (Half Length), COPS LT-95,
 	Farallon PhoneNET PC III, Farallon PhoneNET PC II
-Other cards possibly supported mode unkown though:
+Other cards possibly supported mode unknown though:
 	Dayna DL2000 (Full length)
 
 The COPS driver defaults to using Dayna mode. To change the driver's 
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/networking/de4x5.txt linux/Documentation/networking/de4x5.txt
--- v2.2.0-pre5/linux/Documentation/networking/de4x5.txt	Sun Jun  7 11:16:26 1998
+++ linux/Documentation/networking/de4x5.txt	Thu Jan  7 08:41:55 1999
@@ -151,7 +151,7 @@
     autonegotiation feature in  the SROM autoconf  code, this detection will
     occur automatically for that case.
 
-    Command line arguements are  now allowed, similar to  passing arguements
+    Command line  arguments are  now allowed, similar to  passing  arguments
     through LILO. This will allow a per adapter board set  up of full duplex
     and media. The only lexical constraints are:  the board name (dev->name)
     appears in  the list before its parameters.  The list of parameters ends
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/sound/AudioExcelDSP16 linux/Documentation/sound/AudioExcelDSP16
--- v2.2.0-pre5/linux/Documentation/sound/AudioExcelDSP16	Sat Sep  5 16:46:40 1998
+++ linux/Documentation/sound/AudioExcelDSP16	Thu Jan  7 08:41:55 1999
@@ -51,7 +51,7 @@
 ad1848 are the corresponding options for the MSS and OPL3 modules.
 
 Loading MSS and OPL3 needs to pre load the aedsp16 module to set up correctly
-the sound card. Installation dependancies must be written in the conf.modules
+the sound card. Installation dependencies must be written in the conf.modules
 file:
 
 pre-install ad1848 modprobe aedsp16
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/sound/OPL3-SA2 linux/Documentation/sound/OPL3-SA2
--- v2.2.0-pre5/linux/Documentation/sound/OPL3-SA2	Thu Jan  7 15:11:35 1999
+++ linux/Documentation/sound/OPL3-SA2	Thu Jan  7 08:41:55 1999
@@ -2,7 +2,7 @@
 ---------------------------------------------------------------
 
 Scott Murray, scottm@interlog.com
-December, 1998
+January 5, 1998
 
 NOTE: All trade-marked terms mentioned below are properties of their
       respective owners.
@@ -97,25 +97,12 @@
 
 If you still cannot get the module to load, look at the contents of
 your system log file, usually /var/log/messages.  If you see the
-message "No Yamaha audio controller found", then you have a different
-chipset than I've encountered so far.  Look for a line in the log file
-that says "opl3sa2.c: chipset version = <some number>".  If you want
-me to add support for your card, send me the number from this line and
-any information you have on the make and chipset of your sound card,
-and I should be able to work up a permanent fix.
-
-A temporary solution is to force the driver to act as either a SA2 or
-SA3.  If you use the modular driver, this can be done with the "force"
-option.  Using "force=2" makes the driver treat your card as a SA2,
-and "force=3" makes it treat your card as a SA3.  Note that the driver
-does not really differentiate internally between the SA3 and SAx, so
-"force=3" is actually suitable for an SAx card.
-
-If you build the driver into the kernel, a similar option is
-available, "Chipset".  Setting it to 2 or 3 will yield the same result
-as the "force" option does for the module.  I recommend trying
-auto-probing first ("Chipset" equal to the default of -1) before
-forcing compatibility with a specific chipset.
+message "Unknown Yamaha audio controller version", then you have a
+different chipset than I've encountered so far.  Look for a line in
+the log file that says "opl3sa2.c: chipset version = <some number>".
+If you want me to add support for your card, send me the number from
+this line and any information you have on the make and chipset of your
+sound card, and I should be able to work up a permanent fix.
 
 If you do not see the chipset version message, and none of the other
 messages present in the system log are helpful, email me some details
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/sound/VIA-chipset linux/Documentation/sound/VIA-chipset
--- v2.2.0-pre5/linux/Documentation/sound/VIA-chipset	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/VIA-chipset	Thu Jan  7 08:41:55 1999
@@ -0,0 +1,43 @@
+Running sound cards on VIA chipsets
+
+o	There are problems with VIA chipsets and sound cards that appear to
+	lock the hardware solidly. Test programs under DOS have verified the
+	problem exists on at least some (but apparently not all) VIA boards
+
+o	VIA have so far failed to bother to answer support mail on the subject
+	so if you are a VIA engineer feeling aggrieved as you read this 
+	document go chase your own people. If there is a workaround please
+	let us know so we can implement it.
+
+
+Certain patterns of ISA DMA access used for most PC sound cards cause the
+VIA chipsets to lock up. From the collected reports this appears to cover a
+wide range of boards. Some also lock up with sound cards under Win* as well.
+
+Linux implements a workaround providing your chipset is PCI and you compiled
+with PCI Quirks enabled. If so you will see a message
+	"Activating ISA DMA bug workarounds"
+
+during booting. If you have a VIA PCI chipset that hangs when you use the
+sound and is not generating this message even with PCI quirks enabled
+please report the information to the linux-kernel list (see REPORTING-BUGS).
+
+If you are one of the tiny number of unfortunates with a 486 ISA/VLB VIA
+chipset board you need to do the following to build a special kernel for
+your board
+
+	edit linux/include/asm-i386/dma.h
+
+change
+
+#define isa_dma_bridge_buggy 	(0)
+
+to
+
+#define isa_dma_bridge_buggy 	(1)
+
+and rebuild a kernel without PCI quirk support.
+
+
+Other than this paticular glitch the VIA [M]VP* chipsets appear to work
+perfectly with Linux.
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/sysctl/README linux/Documentation/sysctl/README
--- v2.2.0-pre5/linux/Documentation/sysctl/README	Thu Nov 19 09:56:27 1998
+++ linux/Documentation/sysctl/README	Thu Jan  7 08:41:55 1999
@@ -13,7 +13,7 @@
 be actually used, not just for the fun of programming it :-)
 
 If you prefer HTML, feel free to visit the Linux-MM homepage
-<http://www.phys.uu.nl/~riel/mm-patch/>...
+<http://humbolt.geo.uu.nl/Linux-MM/>...
 
 ==============================================================
 
diff -u --recursive --new-file v2.2.0-pre5/linux/Documentation/video4linux/API.html linux/Documentation/video4linux/API.html
--- v2.2.0-pre5/linux/Documentation/video4linux/API.html	Wed Aug 26 11:37:33 1998
+++ linux/Documentation/video4linux/API.html	Thu Jan  7 08:41:55 1999
@@ -314,7 +314,7 @@
 To use the mmap interface a user first sets the desired image size and depth
 properties. Next the VIDIOCGMBUF ioctl is issued. This reports the size
 of buffer to mmap and the offset within the buffer for each frame. The
-number of frames supported is device dependant and may only be one. 
+number of frames supported is device dependent and may only be one. 
 <P>
 The video_mbuf structure contains the following fields
 <P>
diff -u --recursive --new-file v2.2.0-pre5/linux/Makefile linux/Makefile
--- v2.2.0-pre5/linux/Makefile	Thu Jan  7 15:11:35 1999
+++ linux/Makefile	Wed Jan  6 15:01:15 1999
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 0
-EXTRAVERSION =-pre5
+EXTRAVERSION =-pre6
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
diff -u --recursive --new-file v2.2.0-pre5/linux/README linux/README
--- v2.2.0-pre5/linux/README	Mon Jan  4 15:08:16 1999
+++ linux/README	Thu Jan  7 08:41:55 1999
@@ -48,12 +48,12 @@
  - If you install the full sources, do a
 
 		cd /usr/src
-		gzip -cd linux-2.1.XX.tar.gz | tar xfv -
+		gzip -cd linux-2.2.XX.tar.gz | tar xfv -
 
    to get it all put in place. Replace "XX" with the version number of the
    latest kernel.
 
- - You can also upgrade between 2.1.xx releases by patching.  Patches are
+ - You can also upgrade between 2.2.xx releases by patching.  Patches are
    distributed in the traditional gzip and the new bzip2 format.  To
    install by patching, get all the newer patch files and do
 
@@ -91,7 +91,7 @@
 
 SOFTWARE REQUIREMENTS
 
-   Compiling and running the 2.1.x kernels requires up-to-date
+   Compiling and running the 2.2.x kernels requires up-to-date
    versions of various software packages.  Consult
    ./Documentation/Changes for the minimum version numbers required
    and how to get updates for these packages.  Beware that using
@@ -145,7 +145,7 @@
 
 COMPILING the kernel:
 
- - Make sure you have gcc-2.7.0 or newer available.  It seems older gcc
+ - Make sure you have gcc-2.7.2 or newer available.  It seems older gcc
    versions can have problems compiling newer versions of Linux.  This
    is mainly because the older compilers can only generate "a.out"-format
    executables.  As of Linux 2.1.0, the kernel must be compiled as an
diff -u --recursive --new-file v2.2.0-pre5/linux/REPORTING-BUGS linux/REPORTING-BUGS
--- v2.2.0-pre5/linux/REPORTING-BUGS	Wed Dec 31 16:00:00 1969
+++ linux/REPORTING-BUGS	Thu Jan  7 08:41:55 1999
@@ -0,0 +1,56 @@
+[Some of this is taken from Frohwalt Egerer's original linux-kernel FAQ]
+
+     What follows is a suggested proceedure for reporting Linux bugs. You
+aren't obliged to use the bug reporting format, it is provided as a guide
+to the kind of information that can be useful to developers - no more.
+
+     If the failure includes an "OOPS:" type message in your log or on
+screen please read "Documentation/oops-tracing.txt" before posting your
+bug report. This explains what you should do with the "Oops" information
+to make it useful to the recipient.
+
+      Send the output the maintainer of the kernel area that seems to
+be involved with the problem. Don't worry too much about getting the
+wrong person. If you are unsure send it to the person responsible for the
+code relevant to what you were doing. If it occurs repeatably try and
+describe how to recreate it. That is worth even more than the oops itself.
+The list of maintainers is in the MAINTAINERS file in this directory.
+
+      If you are totally stumped as to whom to send the report, send it to
+linux-kernel@vger.rutgers.edu. (For more information on the linux-kernel
+mailing list see http://www.tux.org/lkml/).
+
+This is a suggested format for a bug report sent to the Linux kernel mailing 
+list. Having a standardized bug report form makes it easier  for you not to 
+overlook things, and easier for the developers to find the pieces of 
+information they're really interested in.
+
+   First run the ver_linux script included as scripts/ver_linux or
+at <URL:ftp://ftp.sai.msu.su//sai2/ftp/pub/Linux/ver_linux> It checks out
+the version of some important subsystems. Run it with the commnd
+"sh scripts/ver_linux"
+
+Use that information to fill in all fields of the bug report form, and
+post it to the mailing list with a subject of "ISSUE: <one line
+summary from [1.]>" for easy identification by the developers    
+
+[1.] One line summary of the problem:    
+[2.] Full description of the problem/report:
+[3.] Keywords (i.e., modules, networking, kernel):
+[4.] Kernel version (from /proc/version):
+[5.] Output of Oops.. message (if applicable) with symbolic information 
+     resolved (see Documentation/oops-tracing.txt)
+[6.] A small shell script or example program which triggers the
+     problem (if possible)
+[7.] Environment
+[7.1.] Software (add the output of the ver_linux script here)
+[7.2.] Processor information (from /proc/cpuinfo):
+[7.3.] Module information (from /proc/modules):
+[7.4.] SCSI information (from /proc/scsi/scsi)
+[7.5.] Other information that might be relevant to the problem
+       (please look in /proc and include all information that you
+       think to be relevant):
+[X.] Other notes, patches, fixes, workarounds:
+
+
+Thank you
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.2.0-pre5/linux/arch/alpha/kernel/process.c	Wed Dec 16 10:32:54 1998
+++ linux/arch/alpha/kernel/process.c	Thu Jan  7 08:41:55 1999
@@ -55,7 +55,6 @@
 unsigned long init_user_stack[1024] = { STACK_MAGIC, };
 static struct vm_area_struct init_mmap = INIT_MMAP;
 static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
 struct mm_struct init_mm = INIT_MM;
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.2.0-pre5/linux/arch/i386/config.in	Thu Jan  7 15:11:35 1999
+++ linux/arch/i386/config.in	Thu Jan  7 08:41:55 1999
@@ -97,6 +97,8 @@
   bool '   Power off on shutdown' CONFIG_APM_POWER_OFF
   bool '   Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
   bool '   Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+  bool '   RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT
+  bool '   Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS
 fi
 
 endmenu
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.2.0-pre5/linux/arch/i386/kernel/apm.c	Wed Dec 16 10:32:54 1998
+++ linux/arch/i386/kernel/apm.c	Thu Jan  7 08:41:55 1999
@@ -31,6 +31,7 @@
  * Aug 1998, Version 1.5
  * Sep 1998, Version 1.6
  * Nov 1998, Version 1.7
+ * Jan 1999, Version 1.8
  *
  * History:
  *    0.6b: first version in official kernel, Linux 1.3.46
@@ -72,6 +73,11 @@
  *         Make boot messages far less verbose by default
  *         Make asm safer
  *         Stephen Rothwell
+ *    1.8: Add CONFIG_APM_RTC_IS_GMT
+ *         Richard Gooch <rgooch@atnf.csiro.au>
+ *         change APM_NOINTS to CONFIG_APM_ALLOW_INTS
+ *         remove dependency on CONFIG_PROC_FS
+ *         Stephen Rothwell
  *
  * APM 1.1 Reference:
  *
@@ -105,10 +111,8 @@
 #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/apm_bios.h>
 #include <linux/init.h>
@@ -202,13 +206,6 @@
 #define ALWAYS_CALL_BUSY
 
 /*
- * Define to disable interrupts in APM BIOS calls (the CPU Idle BIOS call
- * should turn interrupts on before it does a 'hlt').
- * This reportedly needs undefining for the ThinkPad 600.
- */
-#define APM_NOINTS
-
-/*
  * Define to make the APM BIOS calls zero all data segment registers (so
  * that an incorrect BIOS implementation will cause a kernel panic if it
  * tries to write to arbitrary memory).
@@ -266,9 +263,7 @@
 static unsigned int do_poll(struct file *, poll_table *);
 static int	do_ioctl(struct inode *, struct file *, u_int, u_long);
 
-#ifdef CONFIG_PROC_FS
 static int	apm_get_info(char *, char **, off_t, int, int);
-#endif
 
 extern int	apm_register_callback(int (*)(apm_event_t));
 extern void	apm_unregister_callback(int (*)(apm_event_t));
@@ -290,8 +285,13 @@
 static int			waiting_for_resume = 0;
 #endif
 
+#ifdef CONFIG_APM_RTC_IS_GMT
+#	define	clock_cmos_diff	0
+#	define	got_clock_diff	1
+#else
 static long			clock_cmos_diff;
 static int			got_clock_diff = 0;
+#endif
 static int			debug = 0;
 static int			apm_disabled = 0;
 
@@ -300,7 +300,7 @@
 
 static struct timer_list	apm_timer;
 
-static char			driver_version[] = "1.7";	/* no spaces */
+static char			driver_version[] = "1.8";	/* no spaces */
 
 #ifdef APM_DEBUG
 static char *	apm_event_name[] = {
@@ -375,22 +375,22 @@
 #define ERROR_COUNT	(sizeof(error_table)/sizeof(lookup_t))
 
 /*
- * These are the actual BIOS calls.  Depending on APM_ZERO_SEGS
- * and APM_NOINTS, we are being really paranoid here!  Not only are
- * interrupts disabled, but all the segment registers (except SS) are
- * saved and zeroed this means that if the BIOS tries to reference any
- * data without explicitly loading the segment registers, the kernel will
- * fault immediately rather than have some unforeseen circumstances for
- * the rest of the kernel.  And it will be very obvious!  :-) Doing this
- * depends on CS referring to the same physical memory as DS so that DS
- * can be zeroed before the call. Unfortunately, we can't do anything
+ * These are the actual BIOS calls.  Depending on APM_ZERO_SEGS and
+ * CONFIG_APM_ALLOW_INTS, we are being really paranoid here!  Not only
+ * are interrupts disabled, but all the segment registers (except SS)
+ * are saved and zeroed this means that if the BIOS tries to reference
+ * any data without explicitly loading the segment registers, the kernel
+ * will fault immediately rather than have some unforeseen circumstances
+ * for the rest of the kernel.  And it will be very obvious!  :-) Doing
+ * this depends on CS referring to the same physical memory as DS so that
+ * DS can be zeroed before the call. Unfortunately, we can't do anything
  * about the stack segment/pointer.  Also, we tell the compiler that
  * everything could change.
  *
  * Also, we KNOW that for the non error case of apm_bios_call, there
  * is no useful data returned in the low order 8 bits of eax.
  */
-#ifdef APM_NOINTS
+#ifndef CONFIG_APM_ALLOW_INTS
 #	define APM_DO_CLI	__cli()
 #else
 #	define APM_DO_CLI
@@ -747,14 +747,17 @@
 	unsigned long	flags;
 	int		err;
 
-				/* Estimate time zone so that set_time can
-                                   update the clock */
+#ifndef CONFIG_APM_RTC_IS_GMT
+	/*
+	 * Estimate time zone so that set_time can update the clock
+	 */
 	save_flags(flags);
 	clock_cmos_diff = -get_cmos_time();
 	cli();
 	clock_cmos_diff += CURRENT_TIME;
 	got_clock_diff = 1;
 	restore_flags(flags);
+#endif
 
 	err = apm_set_power_state(APM_STATE_SUSPEND);
 	if (err)
@@ -826,7 +829,7 @@
 	apm_event_t		event;
 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
 	static unsigned long	last_resume = 0;
-	static int		did_resume = 0;
+	static int		ignore_bounce = 0;
 #endif
 
 	while ((event = get_event()) != 0) {
@@ -838,6 +841,10 @@
 			printk(KERN_DEBUG "apm: received unknown "
 			       "event 0x%02x\n", event);
 #endif
+#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+		if (ignore_bounce && ((jiffies - last_resume) > HZ))
+			ignore_bounce = 0;
+#endif
 		switch (event) {
 		case APM_SYS_STANDBY:
 		case APM_USER_STANDBY:
@@ -859,7 +866,7 @@
 #endif
 		case APM_SYS_SUSPEND:
 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
-			if (did_resume && ((jiffies - last_resume) < HZ))
+			if (ignore_bounce)
 				break;
 #endif
 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
@@ -880,7 +887,7 @@
 #endif
 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
 			last_resume = jiffies;
-			did_resume = 1;
+			ignore_bounce = 1;
 #endif
 			set_time();
 			send_event(event, 0, NULL);
@@ -1139,7 +1146,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_PROC_FS
 int apm_get_info(char *buf, char **start, off_t fpos, int length, int dummy)
 {
 	char *		p;
@@ -1228,7 +1234,6 @@
 
 	return p - buf;
 }
-#endif
 
 void __init apm_setup(char *str, int *dummy)
 {
@@ -1422,10 +1427,9 @@
 	apm_timer.expires = APM_CHECK_TIMEOUT + jiffies;
 	add_timer(&apm_timer);
 
-#ifdef CONFIG_PROC_FS
 	ent = create_proc_entry("apm", 0, 0);
-	ent->get_info = apm_get_info;
-#endif
+	if (ent != NULL)
+		ent->get_info = apm_get_info;
 
 	misc_register(&apm_device);
 
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.2.0-pre5/linux/arch/i386/kernel/entry.S	Mon Dec 28 15:00:52 1998
+++ linux/arch/i386/kernel/entry.S	Fri Jan  8 14:01:36 1999
@@ -559,13 +559,14 @@
 	.long SYMBOL_NAME(sys_sendfile)
 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams1 */
 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams2 */
+	.long SYMBOL_NAME(sys_vfork)            /* 190 */
 
 	/*
-	 * NOTE!! This doesn' thave to be exact - we just have
+	 * NOTE!! This doesn't have to be exact - we just have
 	 * to make sure we have _enough_ of the "sys_ni_syscall"
 	 * entries. Don't panic if you notice that this hasn't
 	 * been shrunk every time we add a new system call.
 	 */
-	.rept NR_syscalls-189
+	.rept NR_syscalls-190
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.2.0-pre5/linux/arch/i386/kernel/process.c	Mon Dec 28 15:00:52 1998
+++ linux/arch/i386/kernel/process.c	Fri Jan  8 15:05:41 1999
@@ -781,6 +781,18 @@
 	return do_fork(clone_flags, newsp, &regs);
 }
 
+asmlinkage int sys_vfork(struct pt_regs regs)
+{
+	int     child;
+
+	child = do_fork(CLONE_VM | SIGCHLD, regs.esp, &regs);
+
+	if (child > 0)
+		sleep_on(&current->vfork_sleep);
+
+	return child;
+}
+
 /*
  * sys_execve() executes a new program.
  */
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v2.2.0-pre5/linux/arch/i386/kernel/ptrace.c	Thu Jan  7 15:11:35 1999
+++ linux/arch/i386/kernel/ptrace.c	Fri Jan  8 10:21:10 1999
@@ -70,7 +70,7 @@
 extern int _stext, _etext;
 static void print_child_state(struct task_struct *task)
 {
-	unsigned int * stack = (unsigned int *) task->tss.esp0;
+	unsigned int * stack = (unsigned int *) task->tss.esp;
 	int count = 40;
 
 	printk("Process: %s (stack=%p, task=%p)\n", task->comm, stack, task);
@@ -78,7 +78,7 @@
 		unsigned int data;
 		if ((unsigned int) stack < (unsigned int) task)
 			break;
-		if ((unsigned int) stack >= PAGE_SIZE + (unsigned int) task)
+		if ((unsigned int) stack >= 2*PAGE_SIZE + (unsigned int) task)
 			break;
 		data = *stack;
 		stack++;
@@ -394,15 +394,16 @@
 		ret = 0;
 		goto out;
 	}
-	if (pid == 1)		/* you may not mess with init */
-		goto out;
 	ret = -ESRCH;
 	read_lock(&tasklist_lock);
 	child = find_task_by_pid(pid);
 	read_unlock(&tasklist_lock);	/* FIXME!!! */
 	if (!child)
 		goto out;
+print_child_state(child);
 	ret = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
+		goto out;
 	if (request == PTRACE_ATTACH) {
 		if (child == current)
 			goto out;
@@ -435,8 +436,6 @@
 	if (!(child->flags & PF_PTRACED))
 		goto out;
 	if (child->state != TASK_STOPPED) {
-print_child_state(child);
-goto out;
 		if (request != PTRACE_KILL)
 			goto out;
 	}
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.2.0-pre5/linux/arch/i386/kernel/setup.c	Mon Jan  4 15:08:16 1999
+++ linux/arch/i386/kernel/setup.c	Thu Jan  7 08:41:55 1999
@@ -619,7 +619,7 @@
 	else
 		printk("%s", c->x86_model_id);
 
-	if (c->x86_mask) 
+	if (c->x86_mask || c->cpuid_level>=0) 
 		printk(" stepping %02x", c->x86_mask);
 
 	if(c->x86_vendor == X86_VENDOR_CENTAUR)
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/m68k/amiga/amiints.c linux/arch/m68k/amiga/amiints.c
--- v2.2.0-pre5/linux/arch/m68k/amiga/amiints.c	Fri Oct  9 13:27:05 1998
+++ linux/arch/m68k/amiga/amiints.c	Thu Jan  7 08:41:55 1999
@@ -15,7 +15,7 @@
  *           - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
  *                           they're executed irq level is set to the previous
  *                           one, but handlers don't need to be reentrant, if
- *                           reentrance occured, slow handlers will be just
+ *                           reentrance occurred, slow handlers will be just
  *                           called again.
  *           The whole interrupt handling for CIAs is moved to cia.c
  *           /Roman Zippel
@@ -367,7 +367,7 @@
 	for (;;) {
 		for (; node; node = node->next)
 			node->handler(irq, node->dev_id, fp);
-		/* if reentrance occured, serve slow handlers again */
+		/* if reentrance occurred, serve slow handlers again */
 		custom.intena = ami_intena_vals[irq];
 		if (!server->reentrance) {
 			server->count--;
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/m68k/apollo/dn_ints.c linux/arch/m68k/apollo/dn_ints.c
--- v2.2.0-pre5/linux/arch/m68k/apollo/dn_ints.c	Tue Feb 17 13:12:44 1998
+++ linux/arch/m68k/apollo/dn_ints.c	Thu Jan  7 08:41:55 1999
@@ -30,7 +30,7 @@
     dn_irqs[irq-160].handler(irq,dn_irqs[irq-160].dev_id,fp);
   }
   else {
-    printk("spurious irq %d occured\n",irq);
+    printk("spurious irq %d occurred\n",irq);
   }
 
 #if 0  
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c
--- v2.2.0-pre5/linux/arch/m68k/kernel/signal.c	Sat Sep  5 16:46:40 1998
+++ linux/arch/m68k/kernel/signal.c	Thu Jan  7 08:41:55 1999
@@ -361,7 +361,7 @@
 			 : "a0");
 #undef frame_offset
 		/*
-		 * If we ever get here an exception occured while
+		 * If we ever get here an exception occurred while
 		 * building the above stack-frame.
 		 */
 		goto badframe;
@@ -460,7 +460,7 @@
 			 : "a0");
 #undef frame_offset
 		/*
-		 * If we ever get here an exception occured while
+		 * If we ever get here an exception occurred while
 		 * building the above stack-frame.
 		 */
 		goto badframe;
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/ppc/amiga/amiints.c linux/arch/ppc/amiga/amiints.c
--- v2.2.0-pre5/linux/arch/ppc/amiga/amiints.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/amiga/amiints.c	Thu Jan  7 08:46:58 1999
@@ -19,7 +19,7 @@
  *           - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
  *                           they're executed irq level is set to the previous
  *                           one, but handlers don't need to be reentrant, if
- *                           reentrance occured, slow handlers will be just
+ *                           reentrance occurred, slow handlers will be just
  *                           called again.
  *           The whole interrupt handling for CIAs is moved to cia.c
  *           /Roman Zippel
@@ -396,7 +396,7 @@
 	for (;;) {
 		for (; node; node = node->next)
 			node->handler(irq, node->dev_id, fp);
-		/* if reentrance occured, serve slow handlers again */
+		/* if reentrance occurred, serve slow handlers again */
 		custom.intena = ami_intena_vals[irq];
 		if (!server->reentrance) {
 			server->count--;
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/ppc/boot/ns16550.c linux/arch/ppc/boot/ns16550.c
--- v2.2.0-pre5/linux/arch/ppc/boot/ns16550.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/ns16550.c	Thu Jan  7 12:06:57 1999
@@ -0,0 +1,56 @@
+/*
+ * COM1 NS16550 support
+ */
+
+#include "ns16550.h"
+typedef struct NS16550 *NS16550_t;
+
+const NS16550_t COM_PORTS[] = { (NS16550_t) COM1,
+    (NS16550_t) COM2,
+    (NS16550_t) COM3,
+    (NS16550_t) COM4 };
+
+volatile struct NS16550 *
+NS16550_init(int chan)
+{
+ volatile struct NS16550 *com_port;
+ volatile unsigned char xx;
+ com_port = (struct NS16550 *) COM_PORTS[chan];
+ /* See if port is present */
+ com_port->lcr = 0x00;
+ com_port->ier = 0xFF;
+#if 0
+ if (com_port->ier != 0x0F) return ((struct NS16550 *)0);
+#endif
+ com_port->ier = 0x00;
+ com_port->lcr = 0x80;  /* Access baud rate */
+ com_port->dll = 0xc;  /* 9600 baud */
+ com_port->dlm = 0xc >> 8;
+ com_port->lcr = 0x03;  /* 8 data, 1 stop, no parity */
+ com_port->mcr = 0x03;  /* RTS/DTR */
+ com_port->fcr = 0x07;  /* Clear & enable FIFOs */
+ return (com_port);
+}
+
+
+NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
+{
+ volatile int i;
+ while ((com_port->lsr & LSR_THRE) == 0) ;
+ com_port->thr = c;
+}
+
+unsigned char
+NS16550_getc(volatile struct NS16550 *com_port)
+{
+ while ((com_port->lsr & LSR_DR) == 0) ;
+ return (com_port->rbr);
+}
+
+NS16550_tstc(volatile struct NS16550 *com_port)
+{
+ return ((com_port->lsr & LSR_DR) != 0);
+}
+
+
+
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/ppc/boot/ns16550.h linux/arch/ppc/boot/ns16550.h
--- v2.2.0-pre5/linux/arch/ppc/boot/ns16550.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/ns16550.h	Thu Jan  7 12:06:57 1999
@@ -0,0 +1,34 @@
+/*
+ * NS16550 Serial Port
+ */
+
+struct NS16550
+ {
+  unsigned char rbr;  /* 0 */
+  unsigned char ier;  /* 1 */
+  unsigned char fcr;  /* 2 */
+  unsigned char lcr;  /* 3 */
+  unsigned char mcr;  /* 4 */
+  unsigned char lsr;  /* 5 */
+  unsigned char msr;  /* 6 */
+  unsigned char scr;  /* 7 */
+ };
+
+#define thr rbr
+#define iir fcr
+#define dll rbr
+#define dlm ier
+
+#define LSR_DR   0x01  /* Data ready */
+#define LSR_OE   0x02  /* Overrun */
+#define LSR_PE   0x04  /* Parity error */
+#define LSR_FE   0x08  /* Framing error */
+#define LSR_BI   0x10  /* Break */
+#define LSR_THRE 0x20  /* Xmit holding register empty */
+#define LSR_TEMT 0x40  /* Xmitter empty */
+#define LSR_ERR  0x80  /* Error */
+
+#define COM1 0x800003F8
+#define COM2 0x800002F8
+#define COM3 0x800003F8
+#define COM4 0x80000388
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/ppc/common_defconfig linux/arch/ppc/common_defconfig
--- v2.2.0-pre5/linux/arch/ppc/common_defconfig	Thu Jan  7 15:11:36 1999
+++ linux/arch/ppc/common_defconfig	Thu Jan  7 12:06:57 1999
@@ -253,16 +253,17 @@
 CONFIG_FB_CONTROL=y
 CONFIG_FB_PLATINUM=y
 CONFIG_FB_VALKYRIE=y
-# CONFIG_FB_ATY is not set
+CONFIG_FB_ATY=y
 CONFIG_FB_IMSTT=y
 CONFIG_FB_CT65550=y
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_MATROX is not set
-# CONFIG_FB_ATY is not set
+CONFIG_FB_ATY=y
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_CFB8=y
 CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
 CONFIG_FBCON_CFB32=y
 # CONFIG_FBCON_FONTWIDTH8_ONLY is not set
 CONFIG_FBCON_FONTS=y
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/ppc/kernel/mbx_setup.c linux/arch/ppc/kernel/mbx_setup.c
--- v2.2.0-pre5/linux/arch/ppc/kernel/mbx_setup.c	Tue Dec 22 14:16:54 1998
+++ linux/arch/ppc/kernel/mbx_setup.c	Thu Jan  7 12:06:57 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: mbx_setup.c,v 1.4 1998/11/15 19:58:55 cort Exp $
+ * $Id: mbx_setup.c,v 1.5 1998/12/29 18:55:07 cort Exp $
  *
  *  linux/arch/ppc/kernel/setup.c
  *
@@ -59,18 +59,21 @@
 void __init powermac_init(void)
 {
 }
+
 void __init adbdev_init(void)
 {
 }
 
 void __init mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
 {
+	ide_ioreg_t port = base;
+	int i = 8;
 
-	*p = 0;
-	*irq = 0;
-
-	if (base != 0)		/* Only map the first ATA flash drive */
-		return;
+	while (i--)
+		*p++ = port++;
+	*p++ = base + 0x206;
+	if (irq != NULL)
+		*irq = 0;
 #ifdef ATA_FLASH
 	base = (unsigned long) ioremap(PCMCIA_MEM_ADDR, 0x200);
 	for (i = 0; i < 8; ++i)
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v2.2.0-pre5/linux/arch/ppc/kernel/pci.c	Tue Dec 22 14:16:54 1998
+++ linux/arch/ppc/kernel/pci.c	Thu Jan  7 12:06:57 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: pci.c,v 1.42 1998/12/04 14:31:37 cort Exp $
+ * $Id: pci.c,v 1.43 1998/12/29 18:55:11 cort Exp $
  * Common pmac/prep/chrp pci routines. -- Cort
  */
 
@@ -123,8 +123,8 @@
 __initfunc(void
 	   setup_pci_ptrs(void))
 {
-	PPC_DEVICE *hostbridge;
 #ifndef CONFIG_MBX  
+	PPC_DEVICE *hostbridge;
 	switch (_machine) {
 	case _MACH_prep:
 	  	hostbridge=residual_find_device(PROCESSORDEVICE, NULL,
@@ -188,6 +188,7 @@
 	extern struct bridge_data **bridges;
 	extern unsigned char *Motherboard_map;
 	extern unsigned char *Motherboard_routes;
+	unsigned char i;
 #ifndef CONFIG_MBX
 	switch (_machine )
 	{
@@ -200,7 +201,7 @@
 			 * irq this device uses.  This is necessary on things
 			 * without residual data. -- Cort
 			 */
-			unsigned char d = PCI_SLOT(dev->devfn), i;
+			unsigned char d = PCI_SLOT(dev->devfn);
 			dev->irq = Motherboard_routes[Motherboard_map[d]];
 			for ( i = 0 ; i <= 5 ; i++ )
 			{
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.2.0-pre5/linux/arch/ppc/kernel/ppc_ksyms.c	Thu Dec 31 10:28:59 1998
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Thu Jan  7 12:06:57 1999
@@ -194,6 +194,7 @@
 EXPORT_SYMBOL(find_path_device);
 EXPORT_SYMBOL(find_phandle);
 EXPORT_SYMBOL(get_property);
+EXPORT_SYMBOL(device_is_compatible);
 EXPORT_SYMBOL(pci_io_base);
 EXPORT_SYMBOL(pci_device_loc);
 EXPORT_SYMBOL(feature_set);
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.2.0-pre5/linux/arch/ppc/kernel/process.c	Thu Jan  7 15:11:36 1999
+++ linux/arch/ppc/kernel/process.c	Thu Jan  7 12:06:57 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: process.c,v 1.69 1998/12/28 10:28:49 paulus Exp $
+ * $Id: process.c,v 1.70 1999/01/07 16:28:59 cort Exp $
  *
  *  linux/arch/ppc/kernel/process.c
  *
@@ -191,19 +191,6 @@
 	_enable_interrupts(s);
 }
 
-void instruction_dump (unsigned long *pc)
-{
-	int i;
-
-	if((((unsigned long) pc) & 3))
-                return;
-
-	printk("Instruction DUMP:");
-	for(i = -3; i < 6; i++)
-		printk("%c%08lx%c",i?' ':'<',pc[i],i?' ':'>');
-	printk("\n");
-}
-
 void show_regs(struct pt_regs * regs)
 {
 	int i;
@@ -242,6 +229,19 @@
 		}
 	}
 out:
+}
+
+void instruction_dump (unsigned long *pc)
+{
+	int i;
+
+	if((((unsigned long) pc) & 3))
+                return;
+
+	printk("Instruction DUMP:");
+	for(i = -3; i < 6; i++)
+		printk("%c%08lx%c",i?' ':'<',pc[i],i?' ':'>');
+	printk("\n");
 }
 
 void exit_thread(void)
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.2.0-pre5/linux/arch/ppc/kernel/setup.c	Tue Dec 22 14:16:54 1998
+++ linux/arch/ppc/kernel/setup.c	Thu Jan  7 12:06:57 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: setup.c,v 1.120 1998/12/10 00:24:28 cort Exp $
+ * $Id: setup.c,v 1.122 1998/12/31 20:51:19 cort Exp $
  * Common prep/pmac/chrp boot and setup code.
  */
 
@@ -259,6 +259,9 @@
 		break;
 	}
 #endif
+#if defined(CONFIG_MBX)
+	mbx_ide_init_hwif_ports(p,base,irq);
+#endif	
 }
 EXPORT_SYMBOL(ide_init_hwif_ports);
 #endif
@@ -464,9 +467,9 @@
  * Find out what kind of machine we're on and save any data we need
  * from the early boot process (devtree is copied on pmac by prom_init() )
  */
-__initfunc(unsigned long
+unsigned long __init
 identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
-		 unsigned long r6, unsigned long r7))
+		 unsigned long r6, unsigned long r7)
 {
 	extern void setup_pci_ptrs(void);
 	
@@ -491,6 +494,9 @@
 		char *model;
 
 		have_of = 1;
+		
+		/* prom_init has already been called from __start */
+		finish_device_tree();
 		/* ask the OF info if we're a chrp or pmac */
 		model = get_property(find_path_device("/"), "device_type", NULL);
 		if ( model && !strncmp("chrp",model,4) )
@@ -510,8 +516,10 @@
 
 	if ( have_of )
 	{
+#ifdef CONFIG_MACH_SPECIFIC
 		/* prom_init has already been called from __start */
 		finish_device_tree();
+#endif /* CONFIG_MACH_SPECIFIC	*/
 		/*
 		 * If we were booted via quik, r3 points to the physical
 		 * address of the command-line parameters.
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.2.0-pre5/linux/arch/ppc/mm/init.c	Tue Dec 22 14:16:54 1998
+++ linux/arch/ppc/mm/init.c	Thu Jan  7 12:06:57 1999
@@ -1,5 +1,5 @@
 /*
- *  $Id: init.c,v 1.138 1998/12/15 17:34:43 cort Exp $
+ *  $Id: init.c,v 1.139 1998/12/29 19:53:49 cort Exp $
  *
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -1027,6 +1027,8 @@
         ioremap(MBX_CSR_ADDR, MBX_CSR_SIZE);
         ioremap(IMAP_ADDR, IMAP_SIZE);
         ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
+	/* ide needs to be able to get at PCI space -- Cort */
+        ioremap(0x80000000, 0x4000);
 #endif /* CONFIG_8xx */
 }
 
@@ -1297,7 +1299,7 @@
 /*
  * This finds the amount of physical ram and does necessary
  * setup for prep.  This is pretty architecture specific so
- * this will likely stay seperate from the pmac.
+ * this will likely stay separate from the pmac.
  * -- Cort
  */
 __initfunc(unsigned long *prep_find_end_of_memory(void))
diff -u --recursive --new-file v2.2.0-pre5/linux/arch/sparc/lib/checksum.S linux/arch/sparc/lib/checksum.S
--- v2.2.0-pre5/linux/arch/sparc/lib/checksum.S	Wed Apr 23 19:01:16 1997
+++ linux/arch/sparc/lib/checksum.S	Thu Jan  7 08:46:58 1999
@@ -535,7 +535,7 @@
 /* %o1 is dst
  * %o3 is # bytes to zero out
  * %o4 is faulting address
- * %o5 is %pc where fault occured */
+ * %o5 is %pc where fault occurred */
 	clr	%o2
 31:
 /* %o0 is src
@@ -543,7 +543,7 @@
  * %o2 is # of bytes to copy from src to dst
  * %o3 is # bytes to zero out
  * %o4 is faulting address
- * %o5 is %pc where fault occured */
+ * %o5 is %pc where fault occurred */
 	save	%sp, -104, %sp
         mov     %i5, %o0
         mov     %i7, %o1
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/acorn/block/fd1772.c linux/drivers/acorn/block/fd1772.c
--- v2.2.0-pre5/linux/drivers/acorn/block/fd1772.c	Mon Dec 28 15:00:52 1998
+++ linux/drivers/acorn/block/fd1772.c	Thu Jan  7 08:46:58 1999
@@ -1039,7 +1039,7 @@
 static void fd_times_out(unsigned long dummy)
 {
 	SET_IRQ_HANDLER(NULL);
-	/* If the timeout occured while the readtrack_check timer was
+	/* If the timeout occurred while the readtrack_check timer was
 	 * active, we need to cancel it, else bad things will happen */
 	del_timer( &readtrack_timer ); 
 	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c
--- v2.2.0-pre5/linux/drivers/block/ide-dma.c	Thu Dec 31 10:28:59 1998
+++ linux/drivers/block/ide-dma.c	Thu Jan  7 08:46:58 1999
@@ -100,11 +100,18 @@
  * bad_dma_drives() lists the model names (from "hdparm -i")
  * of drives which supposedly support (U)DMA but which are
  * known to corrupt data with this interface under Linux.
+ *
+ * This is an empirical list. Its generated from bug reports. That means
+ * while it reflects actual problem distributions it doesn't answer whether
+ * the drive or the controller, or cabling, or software, or some combination
+ * thereof is the fault. If you don't happen to agree with the kernel's 
+ * opinion of your drive - use hdparm to turn DMA on.
  */
 const char *bad_dma_drives[] = {"WDC AC11000H",
 				"WDC AC22100H",
 				"WDC AC32500H",
 				"WDC AC33100H",
+				"WDC AC31600H",
  				NULL};
 
 /*
@@ -246,7 +253,7 @@
 		list = bad_dma_drives;
 		while (*list) {
 			if (!strcmp(*list++,id->model)) {
-				printk("%s: (U)DMA capability is broken for %s\n",
+				printk("%s: Disabling (U)DMA for %s\n",
 					drive->name, id->model);
 				return 1;
 			}
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
--- v2.2.0-pre5/linux/drivers/block/ide-tape.c	Thu Jan  7 15:11:36 1999
+++ linux/drivers/block/ide-tape.c	Fri Jan  8 10:04:58 1999
@@ -483,7 +483,7 @@
 /*
  *	Some tape drives require a long irq timeout
  */
-#define IDETAPE_WAIT_CMD		60
+#define IDETAPE_WAIT_CMD		(60*HZ)
 
 /*
  *	DSC timings.
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.2.0-pre5/linux/drivers/block/xd.c	Thu Nov 12 16:21:18 1998
+++ linux/drivers/block/xd.c	Thu Jan  7 08:46:58 1999
@@ -894,7 +894,7 @@
 				xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
 					((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);
 		}
-	/* 1002 based RLL controler requests converted adressing, but reports physical 
+	/* 1002 based RLL controler requests converted addressing, but reports physical 
 	   (physical 26 sec., logical 17 sec.) 
 	   1004 based ???? */
 		if (rll & wd_1002) {
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.2.0-pre5/linux/drivers/cdrom/cdrom.c	Thu Jan  7 15:11:36 1999
+++ linux/drivers/cdrom/cdrom.c	Thu Jan  7 08:46:59 1999
@@ -417,7 +417,7 @@
 			cdo->lock_door(cdi, 1);
 			cdinfo(CD_OPEN, "door locked.\n");
 	}	
-	cdinfo(CD_OPEN, "device opened sucessfully.\n"); 
+	cdinfo(CD_OPEN, "device opened successfully.\n"); 
 	return ret;
 
 	/* Something failed.  Try to unlock the drive, because some drivers
@@ -699,7 +699,7 @@
 		sanitize_format(&ms_info.addr, &ms_info.addr_format,
 				requested_format);
 		IOCTL_OUT(arg, struct cdrom_multisession, ms_info);
-		cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION sucessful\n"); 
+		cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n"); 
 		return 0;
 		}
 
@@ -789,7 +789,7 @@
 		if ((ret=cdo->get_mcn(cdi, &mcn)))
 			return ret;
 		IOCTL_OUT(arg, struct cdrom_mcn, mcn);
-		cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN sucessful\n"); 
+		cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n"); 
 		return 0;
 		}
 
@@ -895,7 +895,7 @@
 			sanitize_format(&q.cdsc_absaddr, &back, requested);
 			sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
 			IOCTL_OUT(arg, struct cdrom_subchnl, q);
-			/* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL sucessful\n"); */ 
+			/* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ 
 			return 0;
 			}
 		case CDROMREADTOCHDR: {
@@ -908,7 +908,7 @@
 			if ((ret=cdo->audio_ioctl(cdi, cmd, &header)))
 				return ret;
 			IOCTL_OUT(arg, struct cdrom_tochdr, header);
-			/* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR sucessful\n"); */ 
+			/* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */ 
 			return 0;
 			}
 		case CDROMREADTOCENTRY: {
@@ -930,7 +930,7 @@
 			sanitize_format(&entry.cdte_addr,
 			&entry.cdte_format, requested_format);
 			IOCTL_OUT(arg, struct cdrom_tocentry, entry);
-			/* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY sucessful\n"); */ 
+			/* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */ 
 			return 0;
 			}
 		case CDROMPLAYMSF: {
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- v2.2.0-pre5/linux/drivers/cdrom/sonycd535.c	Sun Nov  8 14:02:53 1998
+++ linux/drivers/cdrom/sonycd535.c	Thu Jan  7 08:46:59 1999
@@ -151,6 +151,8 @@
 # define CDU535_MESSAGE_NAME	"Sony CDU-535"
 #endif
 
+#define CDU535_BLOCK_SIZE	2048 
+ 
 #ifndef MAX_SPINUP_RETRY
 # define MAX_SPINUP_RETRY		3	/* 1 is sufficient for most drives... */
 #endif
@@ -591,7 +593,6 @@
 seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
 					   Byte **buff, int buf_size)
 {
-	const int block_size = 2048;
 	Byte cmd_buff[7];
 	int  i;
 	int  read_status;
@@ -599,7 +600,7 @@
 	Byte *data_buff;
 	int  sector_count = 0;
 
-	if (buf_size < ((long)block_size) * n_blocks)
+	if (buf_size < CDU535_BLOCK_SIZE * n_blocks)
 		return NO_ROOM;
 
 	set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
@@ -625,7 +626,7 @@
 			if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
 				/* data is ready, read it */
 				data_buff = buff[sector_count++];
-				for (i = 0; i < block_size; i++)
+				for (i = 0; i < CDU535_BLOCK_SIZE; i++)
 					*data_buff++ = inb(data_reg);	/* unrolling this loop does not seem to help */
 				data_valid = 1;
 				break;			/* exit the timeout loop */
@@ -639,7 +640,7 @@
 	/* read all the data, now read the status */
 	if ((i = read_exec_status(status)) != 0)
 		return i;
-	return block_size * sector_count;
+	return CDU535_BLOCK_SIZE * sector_count;
 }	/* seek_and_read_N_blocks() */
 
 /****************************************************************************
@@ -776,7 +777,7 @@
  * The OS calls this to perform a read or write operation to the drive.
  * Write obviously fail.  Reads to a read ahead of sony_buffer_size
  * bytes to help speed operations.  This especially helps since the OS
- * uses 1024 byte blocks and the drive uses 2048 byte blocks.  Since most
+ * may use 1024 byte blocks and the drive uses 2048 byte blocks.  Since most
  * data access on a CD is done sequentially, this saves a lot of operations.
  */
 static void
@@ -873,7 +874,7 @@
 						 * seek_and_read_N_blocks for the various cases.
 						 */
 						int readStatus = seek_and_read_N_blocks(params, read_size,
-									status, sony_buffer, (read_size * 2048));
+									status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
 						if (0 <= readStatus)	/* Good data; common case, placed first */
 							break;
 						if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
@@ -1480,6 +1481,8 @@
 	NULL						/* revalidate */
 };
 
+static int sonycd535_block_size = CDU535_BLOCK_SIZE;
+
 /*
  * Initialize the driver.
  */
@@ -1580,7 +1583,7 @@
 			if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) == 0) {
 				/* set the drive mode successful, we are set! */
 				sony_buffer_size = SONY535_BUFFER_SIZE;
-				sony_buffer_sectors = sony_buffer_size / 2048;
+				sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
 
 				printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
 					   drive_config.vendor_id,
@@ -1597,6 +1600,7 @@
 					return -EIO;
 				}
 				blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+				blksize_size[MAJOR_NR] = &sonycd535_block_size;
 				read_ahead[MAJOR_NR] = 8;	/* 8 sector (4kB) read-ahead */
 
 				sony_toc = (struct s535_sony_toc *)
@@ -1617,7 +1621,8 @@
 					return -ENOMEM;
 				}
 				for (i = 0; i < sony_buffer_sectors; i++) {
-					sony_buffer[i] = (Byte *)kmalloc(2048, GFP_KERNEL);
+					sony_buffer[i] =
+								(Byte *)kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
 					if (sony_buffer[i] == NULL) {
 						while (--i>=0)
 							kfree(sony_buffer[i]);
@@ -1680,7 +1685,7 @@
 
 	release_region(sony535_cd_base_io, 4);
 	for (i = 0; i < sony_buffer_sectors; i++)
-		kfree_s(sony_buffer[i], 2048);
+		kfree_s(sony_buffer[i], CDU535_BLOCK_SIZE);
 	kfree_s(sony_buffer, 4 * sony_buffer_sectors);
 	kfree_s(last_sony_subcode, sizeof *last_sony_subcode);
 	kfree_s(sony_toc, sizeof *sony_toc);
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/char/README.epca linux/drivers/char/README.epca
--- v2.2.0-pre5/linux/drivers/char/README.epca	Sun Jun  7 11:16:29 1998
+++ linux/drivers/char/README.epca	Thu Jan  7 08:46:59 1999
@@ -155,7 +155,7 @@
    current digiConfig application does not provide this function for PCI cards
    (Though it does build device nodes for non-PCI cards).  To use this program
    execute the following:first install the driver, and execute digiDload (See above).  After digiDload
-   has sucessfully loaded, execute the following:
+   has successfully loaded, execute the following:
 
         buildPCI <arg1> <arg2>
 
@@ -295,7 +295,7 @@
                             Linux kernels support higher baud rates by using
                             0x1000 bit.  When the returned value (ored with
                             0x1000) was used to reference our fbaud table a 
-                            serious memory problem occured.  This has been fixed.
+                            serious memory problem occurred.  This has been fixed.
 
                         4.  Added a request_region call to post_fep_init.  This
                             should cause the i/o ports being used to be 
@@ -401,8 +401,8 @@
                            found in epcaconfig.h; if so it DOESN'T load
                            epcaconfig data depending on epca_setup to handle 
                            board configuration.  pc_open has been modified 
-                           such that it checks to insure that no errors
-                           occured during the LILO boot process.  If a 
+                           such that it checks to ensure that no errors
+                           occurred during the LILO boot process.  If a 
                            user attempts to boot the driver (via. LILO)
                            with incorrect data, the open will fail. 
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.2.0-pre5/linux/drivers/char/console.c	Thu Dec 31 10:28:59 1998
+++ linux/drivers/char/console.c	Fri Jan  8 11:11:45 1999
@@ -2231,6 +2231,12 @@
 	return 0;
 }
 
+static void con_close(struct tty_struct *tty, struct file * filp)
+{
+	if (tty->count == 1)
+		tty->driver_data = 0;
+}
+
 static void vc_init(unsigned int currcons, unsigned int rows, unsigned int cols, int do_clear)
 {
 	int j, k ;
@@ -2292,6 +2298,7 @@
 	console_driver.termios_locked = console_termios_locked;
 
 	console_driver.open = con_open;
+	console_driver.close = con_close;
 	console_driver.write = con_write;
 	console_driver.write_room = con_write_room;
 	console_driver.put_char = con_put_char;
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v2.2.0-pre5/linux/drivers/char/keyboard.c	Wed Dec 16 10:32:55 1998
+++ linux/drivers/char/keyboard.c	Fri Jan  8 11:11:45 1999
@@ -202,8 +202,13 @@
 
 	tty = ttytab? ttytab[fg_console]: NULL;
 	if (tty && (!tty->driver_data)) {
-		/* This is to workaround ugly bug in tty_io.c, which
-                   does not do locking when it should */
+		/*
+		 * We touch the tty structure via the the ttytab array
+		 * without knowing whether or not tty is open, which
+		 * is inherently dangerous.  We currently rely on that
+		 * fact that console_open sets tty->driver_data when
+		 * it opens it, and clears it when it closes it.
+		 */
 		tty = NULL;
 	}
 	kbd = kbd_table + fg_console;
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- v2.2.0-pre5/linux/drivers/char/n_tty.c	Sun Nov  8 14:02:55 1998
+++ linux/drivers/char/n_tty.c	Fri Jan  8 11:11:45 1999
@@ -73,7 +73,8 @@
  */
 static void check_unthrottle(struct tty_struct * tty)
 {
-	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && 
+	if (tty->count &&
+	    test_and_clear_bit(TTY_THROTTLED, &tty->flags) && 
 	    tty->driver.unthrottle)
 		tty->driver.unthrottle(tty);
 }
@@ -923,15 +924,19 @@
 
 	add_wait_queue(&tty->read_wait, &wait);
 
-	disable_bh(TQUEUE_BH);
+	if (down_interruptible(&tty->atomic_read))
+		return -ERESTARTSYS;
+	set_bit(TTY_DONT_FLIP, &tty->flags);
 	while (nr) {
 		/* First test for status change. */
 		if (tty->packet && tty->link->ctrl_status) {
+			unsigned char cs;
 			if (b != buf)
 				break;
-			put_user(tty->link->ctrl_status, b++);
-			nr--;
+			cs = tty->link->ctrl_status;
 			tty->link->ctrl_status = 0;
+			put_user(cs, b++);
+			nr--;
 			break;
 		}
 		/* This statement must be first before checking for input
@@ -960,9 +965,9 @@
 				retval = -ERESTARTSYS;
 				break;
 			}
-			enable_bh(TQUEUE_BH);
+			clear_bit(TTY_DONT_FLIP, &tty->flags);
 			timeout = schedule_timeout(timeout);
-			disable_bh(TQUEUE_BH);
+			set_bit(TTY_DONT_FLIP, &tty->flags);
 			continue;
 		}
 		current->state = TASK_RUNNING;
@@ -1024,7 +1029,8 @@
 		if (time)
 			timeout = time;
 	}
-	enable_bh(TQUEUE_BH);
+	clear_bit(TTY_DONT_FLIP, &tty->flags);
+	up(&tty->atomic_read);
 	remove_wait_queue(&tty->read_wait, &wait);
 
 	if (!waitqueue_active(&tty->read_wait))
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/char/radio-zoltrix.c linux/drivers/char/radio-zoltrix.c
--- v2.2.0-pre5/linux/drivers/char/radio-zoltrix.c	Wed Aug 26 11:37:37 1998
+++ linux/drivers/char/radio-zoltrix.c	Thu Jan  7 08:46:59 1999
@@ -12,6 +12,15 @@
  *  to get fine volume control over the low volume range.
  *
  *  Some code derived from code by Frans Brinkman
+ *
+ * 1999-01-05 - (C. van Schaik)
+ *	      - Changed tuning to 1/160Mhz accuracy
+ *	      - Added stereo support
+ *		(card defaults to stereo)
+ *		(can explicitly force mono on the card)
+ *		(can detect if station is in stereo)
+ *	      - Added unmute function
+ *	      - Reworked ioctl functions
  */
 
 #include <linux/module.h>	/* Modules                        */
@@ -35,6 +44,7 @@
 	int curvol;
 	unsigned long curfreq;
 	int muted;
+	unsigned int stereo;
 };
 
 
@@ -54,61 +64,63 @@
 	}
 }
 
+static int zol_setvol(struct zol_device *dev, int vol)
+{
+	dev->curvol = vol;
+	if (dev->muted)
+		return 0;
+
+	if (vol == 0) {
+		outb(0, io);
+		outb(0, io);
+		inb(io + 3);    /* Zoltrix needs to be read to confirm */
+		return 0;
+	}
+
+	outb(dev->curvol-1, io);
+	sleep_delay(10000);
+	inb(io + 2);
+
+	return 0;
+}
+
 static void zol_mute(struct zol_device *dev)
 {
 	dev->muted = 1;
 	outb(0, io);
 	outb(0, io);
-	inb(io + 3);		/* Zoltrix needs to be read to confirm */
+	inb(io + 3);            /* Zoltrix needs to be read to confirm */
 }
 
-static void zol_on(int vol)
+static void zol_unmute(struct zol_device *dev)
 {
-        int l;
-        outb(vol, io);
-        sleep_delay(10000);
-        l = inb(io + 2);
-}
-
-static int zol_setvol(struct zol_device *dev, int vol)
-{
-	if (vol == dev->curvol) {	/* requested volume = current */
-		if (dev->muted) {	/* user is unmuting the card  */
-			dev->muted = 0;
-                        zol_on(vol);
-		}
-		return 0;
-	}
-	if (vol == 0) {		/* volume = 0 means mute the card */
-                zol_mute(dev);
-		return 0;
-	}
 	dev->muted = 0;
-	dev->curvol = vol;
-
-	zol_on(vol);
-
-	return 0;
+	zol_setvol(dev, dev->curvol);
 }
 
 static int zol_setfreq(struct zol_device *dev, unsigned long freq)
 {
 	/* tunes the radio to the desired frequency */
 	unsigned long long bitmask, f, m;
+	unsigned int stereo = dev->stereo;
 	int i;
 
-	m = (freq * 25 / 4 - 8800) * 2;
+	if (freq == 0)
+		return 1;
+	m = (freq / 160 - 8800) * 2;
 	f = (unsigned long long) m + 0x4d1c;
 
 	bitmask = 0xc480402c10080000ull;
 	i = 45;
 
-	zol_mute(dev);
+	outb(0, io);
+	outb(0, io);
+	inb(io + 3);            /* Zoltrix needs to be read to confirm */
 
 	outb(0x40, io);
 	outb(0xc0, io);
 
-	bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ ( /*stereo */ 0 << 31));
+	bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ ( stereo << 31));
 	while (i--) {
 		if ((bitmask & 0x8000000000000000ull) != 0) {
 			outb(0x80, io);
@@ -131,7 +143,18 @@
 	outb(0x80, io);
 	outb(0xc0, io);
 	outb(0x40, io);
-        zol_on(dev->curvol);
+	sleep_delay(1000);
+	inb(io+2);
+
+        sleep_delay(1000);
+	if (dev->muted)
+	{
+		outb(0, io);
+		outb(0, io);
+		inb(io + 3);
+		sleep_delay(1000);
+	} else
+        zol_setvol(dev, dev->curvol);
 	return 0;
 }
 
@@ -149,27 +172,42 @@
 	sleep_delay(1000);
 	b = inb(io);
 
-        if ((a == b) && (a == 0xdf))  /* I found this out by playing */
-                                      /* with a binary scanner on the card io */
-		return (1);
-	else
+	if (a != b)
 		return (0);
 
-	if (inb(io) & 2)	/* bit set = no signal present    */
-		return 0;
-	return 1;		/* signal present               */
+        if ((a == 0xcf) || (a == 0xdf)  /* I found this out by playing */
+		|| (a == 0xef))       /* with a binary scanner on the card io */
+		return (1);
+ 	return (0);
+}
+
+int zol_is_stereo (struct zol_device *dev)
+{
+	int x1, x2;
+
+	outb(0x00, io);
+	outb(dev->curvol, io);
+	sleep_delay(20000);
+
+	x1 = inb(io);
+	sleep_delay(1000);
+	x2 = inb(io);
+
+	if ((x1 == x2) && (x1 == 0xcf))
+		return 1;
+	return 0;
 }
 
 static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
 {
-	struct zol_device *rt = dev->priv;
+	struct zol_device *zol = dev->priv;
 
 	switch (cmd) {
 	case VIDIOCGCAP:
 		{
 			struct video_capability v;
 			v.type = VID_TYPE_TUNER;
-			v.channels = 1;
+			v.channels = 1 + zol->stereo;
 			v.audios = 1;
 			/* No we don't do pictures */
 			v.maxwidth = 0;
@@ -184,15 +222,21 @@
 	case VIDIOCGTUNER:
 		{
 			struct video_tuner v;
-			if (copy_from_user(&v, arg, sizeof(v)) != 0)
+/*
+			if (copy_from_user(&v, arg, sizeof(v)))
 				return -EFAULT;
-			if (v.tuner)	/* Only 1 tuner */
+			if (v.tuner)	
 				return -EINVAL;
-			v.rangelow = (int) (88.0 * 16);
-			v.rangehigh = (int) (108.0 * 16);
-			v.flags = 0;
+*/
+			v.tuner = 0;
+			strcpy(v.name, "Zoltrix Radio");
+			v.rangelow = (int) (88.0 * 16000);
+			v.rangehigh = (int) (108.0 * 16000);
+			v.flags = zol_is_stereo(zol)
+					? VIDEO_TUNER_STEREO_ON : 0;
+			v.flags |= VIDEO_TUNER_LOW;
 			v.mode = VIDEO_MODE_AUTO;
-			v.signal = 0xFFFF * zol_getsigstr(rt);
+			v.signal = 0xFFFF * zol_getsigstr(zol);
 			if (copy_to_user(arg, &v, sizeof(v)))
 				return -EFAULT;
 			return 0;
@@ -208,22 +252,24 @@
 			return 0;
 		}
 	case VIDIOCGFREQ:
-		if (copy_to_user(arg, &rt->curfreq, sizeof(rt->curfreq)))
+		if (copy_to_user(arg, &zol->curfreq, sizeof(zol->curfreq)))
 			return -EFAULT;
 		return 0;
 	case VIDIOCSFREQ:
-		if (copy_from_user(&rt->curfreq, arg, sizeof(rt->curfreq)))
+		if (copy_from_user(&zol->curfreq, arg, sizeof(zol->curfreq)))
 			return -EFAULT;
-		zol_setfreq(rt, rt->curfreq);
+		zol_setfreq(zol, zol->curfreq);
 		return 0;
 	case VIDIOCGAUDIO:
 		{
 			struct video_audio v;
 			memset(&v, 0, sizeof(v));
 			v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
-			v.volume = rt->curvol * 4096;
+			v.mode != zol_is_stereo(zol)
+				? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
+			v.volume = zol->curvol * 4096;
 			v.step = 4096;
-			strcpy(v.name, "Radio");
+			strcpy(v.name, "Zoltrix Radio");
 			if (copy_to_user(arg, &v, sizeof(v)))
 				return -EFAULT;
 			return 0;
@@ -237,9 +283,23 @@
 				return -EINVAL;
 
 			if (v.flags & VIDEO_AUDIO_MUTE)
-				zol_mute(rt);
+				zol_mute(zol);
 			else
-				zol_setvol(rt, v.volume / 4096);
+				zol_unmute(zol);
+
+			if (v.flags & VIDEO_AUDIO_VOLUME)
+				zol_setvol(zol, v.volume / 4096);
+
+			if (v.mode & VIDEO_SOUND_STEREO)
+			{
+				zol->stereo = 1;
+				zol_setfreq(zol, zol->curfreq);
+			}
+			if (v.mode & VIDEO_SOUND_MONO)
+			{
+				zol->stereo = 0;
+				zol_setfreq(zol, zol->curfreq);
+			}
 
 			return 0;
 		}
@@ -286,6 +346,10 @@
 		printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io);
 		return -EBUSY;
 	}
+	if ((io != 0x20c) && (io != 0x30c)) {
+		printk(KERN_ERR "zoltrix: invalid port, try 0x20c or 0x30c\n");
+		return -ENXIO;
+	}
 	zoltrix_radio.priv = &zoltrix_unit;
 
 	if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO) == -1)
@@ -304,6 +368,7 @@
 	inb(io + 3);
 
 	zoltrix_unit.curvol = 0;
+	zoltrix_unit.stereo = 1;
 
 	return 0;
 }
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.2.0-pre5/linux/drivers/char/tty_io.c	Mon Jan  4 15:08:17 1999
+++ linux/drivers/char/tty_io.c	Fri Jan  8 11:11:45 1999
@@ -866,12 +866,7 @@
 	 * Failures after this point use release_mem to clean up, so 
 	 * there's no need to null out the local pointers.
 	 */
-	driver->table[idx] = tty;	/* FIXME: this is broken and
-	probably causes ^D bug. tty->private_date does not (yet) point
-	to a console, if keypress comes now, await armagedon. 
-
-	also, driver->table is accessed from interrupt for vt case,
-	and this does not look like atomic access at all. */
+	driver->table[idx] = tty;
 	
 	if (!*tp_loc)
 		*tp_loc = tp;
@@ -1846,6 +1841,10 @@
 	int		count;
 	unsigned long flags;
 
+	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
+		queue_task(&tty->flip.tqueue, &tq_timer);
+		return;
+	}
 	if (tty->flip.buf_num) {
 		cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
 		fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
@@ -1872,14 +1871,22 @@
 
 /*
  * Routine which returns the baud rate of the tty
- */
-
-/*
- * This is used to figure out the divisor speeds and the timeouts
+ *
+ * Note that the baud_table needs to be kept in sync with the
+ * include/asm/termbits.h file.
  */
 static int baud_table[] = {
 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
+	9600, 19200, 38400, 57600, 115200, 230400, 460800,
+#ifdef __sparc__
+	76800, 153600, 307200, 614400, 921600
+#else
+	500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
+	2500000, 3000000, 3500000, 4000000
+#endif
+};
+
+static int n_baud_table = sizeof(baud_table)/sizeof(int);
 
 int tty_get_baud_rate(struct tty_struct *tty)
 {
@@ -1890,7 +1897,7 @@
 	i = cflag & CBAUD;
 	if (i & CBAUDEX) {
 		i &= ~CBAUDEX;
-		if (i < 1 || i > 4) 
+		if (i < 1 || i+15 >= n_baud_table) 
 			tty->termios->c_cflag &= ~CBAUDEX;
 		else
 			i += 15;
@@ -1930,6 +1937,7 @@
 	tty->flip.pty_sem = MUTEX;
 	tty->tq_hangup.routine = do_tty_hangup;
 	tty->tq_hangup.data = tty;
+	sema_init(&tty->atomic_read, 1);
 }
 
 /*
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/isdn/icn/icn.h linux/drivers/isdn/icn/icn.h
--- v2.2.0-pre5/linux/drivers/isdn/icn/icn.h	Wed Apr  1 20:11:51 1998
+++ linux/drivers/isdn/icn/icn.h	Thu Jan  7 08:46:59 1999
@@ -318,9 +318,9 @@
 #ifdef MODULE
 MODULE_AUTHOR("Fritz Elfert");
 MODULE_PARM(portbase, "i");
-MODULE_PARM_DESC(portbase, "Port adress of first card");
+MODULE_PARM_DESC(portbase, "Port address of first card");
 MODULE_PARM(membase, "i");
-MODULE_PARM_DESC(membase, "Shared memory adress of all cards");
+MODULE_PARM_DESC(membase, "Shared memory address of all cards");
 MODULE_PARM(icn_id, "s");
 MODULE_PARM_DESC(icn_id, "ID-String of first card");
 MODULE_PARM(icn_id2, "s");
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/isdn/isdn_x25iface.c linux/drivers/isdn/isdn_x25iface.c
--- v2.2.0-pre5/linux/drivers/isdn/isdn_x25iface.c	Sun Jun  7 11:16:30 1998
+++ linux/drivers/isdn/isdn_x25iface.c	Thu Jan  7 08:46:59 1999
@@ -65,7 +65,7 @@
 	&isdn_x25iface_disconn_ind
 };
 
-/* error message helper fuction */
+/* error message helper function */
 static void illegal_state_warn( unsigned state, unsigned char firstbyte) 
 {
 	printk( KERN_WARNING "isdn_x25iface: firstbyte %x illegal in"
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/misc/Makefile linux/drivers/misc/Makefile
--- v2.2.0-pre5/linux/drivers/misc/Makefile	Fri Jan 30 11:28:07 1998
+++ linux/drivers/misc/Makefile	Thu Jan  7 08:46:59 1999
@@ -19,10 +19,7 @@
 MIX_OBJS :=
 
 ifeq ($(CONFIG_PARPORT),y)
-  L_OBJS += parport_share.o parport_ieee1284.o
-  ifeq ($(CONFIG_PROC_FS),y)
-    L_OBJS += parport_procfs.o
-  endif
+  L_OBJS += parport_share.o parport_ieee1284.o parport_procfs.o
   ifeq ($(CONFIG_PARPORT_PC),y)
     LX_OBJS += parport_pc.o
   else
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/misc/parport_arc.c linux/drivers/misc/parport_arc.c
--- v2.2.0-pre5/linux/drivers/misc/parport_arc.c	Mon Jan  4 15:08:17 1999
+++ linux/drivers/misc/parport_arc.c	Thu Jan  7 09:28:47 1999
@@ -14,7 +14,6 @@
  * a subset of the standard printer control lines connected.
  */
 
-#include <linux/config.h>
 #include <linux/tasks.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/misc/parport_ax.c linux/drivers/misc/parport_ax.c
--- v2.2.0-pre5/linux/drivers/misc/parport_ax.c	Mon Jan  4 15:08:17 1999
+++ linux/drivers/misc/parport_ax.c	Thu Jan  7 09:28:47 1999
@@ -11,7 +11,6 @@
  *          Grant Guenther <grant@torque.net>
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/misc/parport_procfs.c linux/drivers/misc/parport_procfs.c
--- v2.2.0-pre5/linux/drivers/misc/parport_procfs.c	Mon Jan  4 15:08:17 1999
+++ linux/drivers/misc/parport_procfs.c	Thu Jan  7 09:28:47 1999
@@ -12,6 +12,7 @@
  * Cleaned up include files - Russell King <linux@arm.uk.linux.org>
  */
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/3c515.c linux/drivers/net/3c515.c
--- v2.2.0-pre5/linux/drivers/net/3c515.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/3c515.c	Thu Jan  7 08:46:59 1999
@@ -747,7 +747,7 @@
 			vp->tx_skbuff[i] = 0;
 		outl(0, ioaddr + DownListPtr);
 	}
-	/* Set reciever mode: presumably accept b-case and phys addr only. */
+	/* Set receiver mode: presumably accept b-case and phys addr only. */
 	set_rx_mode(dev);
 	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/3c523.c linux/drivers/net/3c523.c
--- v2.2.0-pre5/linux/drivers/net/3c523.c	Mon Dec 28 15:00:52 1998
+++ linux/drivers/net/3c523.c	Thu Jan  7 08:46:59 1999
@@ -521,7 +521,7 @@
 	/* The 3c523 has a 24K chunk of memory.  The first 16K is the
 	   shared memory, while the last 8K is for the EtherStart BIOS ROM.
 	   Which we don't care much about here.  We'll just tell Linux that
-	   we're using 16K.  MCA won't permit adress space conflicts caused
+	   we're using 16K.  MCA won't permit address space conflicts caused
 	   by not mapping the other 8K. */
 	dev->mem_start = shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3];
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.2.0-pre5/linux/drivers/net/3c59x.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/net/3c59x.c	Thu Jan  7 08:46:59 1999
@@ -15,18 +15,19 @@
 */
 
 static char *version =
-"3c59x.c:v0.99E 5/12/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
+"3c59x.c:v0.99H 11/17/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
 
 /* "Knobs" that adjust features and parameters. */
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1512 effectively disables this feature. */
-static const rx_copybreak = 200;
+static const int rx_copybreak = 200;
 /* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
-static const mtu = 1500;
+static const int mtu = 1500;
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static int max_interrupt_work = 20;
 
 /* Put out somewhat more debugging messages. (0: no msg, 1 minimal .. 6). */
+#define vortex_debug debug
 #ifdef VORTEX_DEBUG
 static int vortex_debug = VORTEX_DEBUG;
 #else
@@ -37,15 +38,6 @@
    debugging. */
 static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
 
-/* Enable the automatic media selection code -- usually set. */
-#define AUTOMEDIA 1
-
-/* Allow the use of fragment bus master transfers instead of only
-   programmed-I/O for Vortex cards.  Full-bus-master transfers are always
-   enabled by default on Boomerang cards.  If VORTEX_BUS_MASTER is defined,
-   the feature may be turned on using 'options'. */
-#define VORTEX_BUS_MASTER
-
 /* A few values that may be tweaked. */
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  ((400*HZ)/1000)
@@ -56,12 +48,12 @@
 #define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
 
 #include <linux/config.h>
+#include <linux/version.h>
 #ifdef MODULE
 #ifdef MODVERSIONS
 #include <linux/modversions.h>
 #endif
 #include <linux/module.h>
-#include <linux/version.h>
 #else
 #define MOD_INC_USE_COUNT
 #define MOD_DEC_USE_COUNT
@@ -70,69 +62,61 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/ptrace.h>
+#include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/in.h>
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/timer.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h>			/* For NR_IRQS only. */
-#include <asm/bitops.h>
-#include <asm/io.h>
-
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#if LINUX_VERSION_CODE < 0x20155  ||  defined(CARDBUS)
+#include <linux/bios32.h>
+#endif
+#include <asm/irq.h>			/* For NR_IRQS only. */
+#include <asm/bitops.h>
+#include <asm/io.h>
 
-/* Kernel compatibility defines, common to David Hind's PCMCIA package.
+/* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
    This is only in the support-all-kernels source code. */
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>		/* Redundant above, here for easy clean-up. */
-#endif
-#if LINUX_VERSION_CODE < 0x10300
-#define RUN_AT(x) (x)			/* What to put in timer->expires.  */
-#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC)
-#if defined(__alpha)
-#error "The Alpha architecture is only support with kernel version 2.0."
-#endif
-#define virt_to_bus(addr)  ((unsigned long)addr)
-#define bus_to_virt(addr) ((void*)addr)
-#define NR_IRQS 16
-#else  /* 1.3.0 and later */
-#define RUN_AT(x) (jiffies + (x))
-#define DEV_ALLOC_SKB(len) dev_alloc_skb(len)
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define DEV_FREE_SKB(skb) dev_kfree_skb (skb, FREE_WRITE);
-#else  /* Grrr, unneeded incompatible change. */
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
-#endif
 
-#ifdef SA_SHIRQ
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
-#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
-#else
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n)
-#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
-#endif
+#define RUN_AT(x) (jiffies + (x))
 
-#if (LINUX_VERSION_CODE >= 0x10344)
-#define NEW_MULTICAST
 #include <linux/delay.h>
+
+#if (LINUX_VERSION_CODE >= 0x20100)
+char kernel_version[] = UTS_RELEASE;
 #else
-#define udelay(microsec)	do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
+#ifndef __alpha__
+#define ioremap(a,b) \
+	(((a)<0x100000) ? (void *)((u_long)(a)) : vremap(a,b))
+#define iounmap(v) \
+	do { if ((u_long)(v) > 0x100000) vfree(v); } while (0)
+#endif
+#endif
+#if LINUX_VERSION_CODE <= 0x20139
+#define	net_device_stats enet_statistics
+#define NETSTATS_VER2
 #endif
-
 #if LINUX_VERSION_CODE < 0x20138
 #define test_and_set_bit(val, addr) set_bit(val, addr)
+#define le32_to_cpu(val) (val)
+#define cpu_to_le32(val) (val)
+#endif
+#if LINUX_VERSION_CODE < 0x20155
+#define PCI_SUPPORT_VER1
+#else
+#define PCI_SUPPORT_VER2
+#endif
+#if LINUX_VERSION_CODE < 0x20159
+#define DEV_FREE_SKB(skb) dev_kfree_skb (skb, FREE_WRITE);
+#else  /* Grrr, unneeded incompatible change. */
+#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
 #endif
-#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115)
+
+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
 MODULE_PARM(debug, "i");
@@ -142,7 +126,7 @@
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(compaq_ioaddr, "i");
 MODULE_PARM(compaq_irq, "i");
-MODULE_PARM(compaq_prod_id, "i");
+MODULE_PARM(compaq_device_id, "i");
 #endif
 
 /* Operational parameter that usually are not changed. */
@@ -154,35 +138,11 @@
 #define VORTEX_TOTAL_SIZE 0x20
 #define BOOMERANG_TOTAL_SIZE 0x40
 
-#ifdef HAVE_DEVLIST
-struct netdev_entry tc59x_drv =
-{"Vortex", vortex_pci_probe, VORTEX_TOTAL_SIZE, NULL};
-#endif
-
 /* Set iff a MII transceiver on any interface requires mdio preamble.
    This only set with the original DP83840 on older 3c905 boards, so the extra
    code size of a per-interface flag is not worthwhile. */
 static char mii_preamble_required = 0;
 
-/* Caution!  These entries must be consistent. */
-static const int product_ids[] = {
-	0x5900, 0x5920, 0x5970, 0x5950, 0x5951, 0x5952, 0x9000, 0x9001,
-	0x9050, 0x9051, 0x9055,	0x5057, 0 };
-static const char *product_names[] = {
-	"3c590 Vortex 10Mbps",
-	"3c592 EISA 10mbps Demon/Vortex",
-	"3c597 EISA Fast Demon/Vortex",
-	"3c595 Vortex 100baseTX",
-	"3c595 Vortex 100baseT4",
-	"3c595 Vortex 100base-MII",
-	"3c900 Boomerang 10baseT",
-	"3c900 Boomerang 10Mbps/Combo",
-	"3c905 Boomerang 100baseTx",
-	"3c905 Boomerang 100baseT4",
-	"3c905B Cyclone 100baseTx",
-	"3c575",						/* Cardbus Boomerang */
-};
-
 /*
 				Theory of Operation
 
@@ -193,17 +153,19 @@
 versions of the FastEtherLink cards.  The supported product IDs are
   3c590, 3c592, 3c595, 3c597, 3c900, 3c905
 
-The ISA 3c515 is supported with a seperate driver, 3c515.c, included with
-the kernel source or available from
+The related ISA 3c515 is supported with a separate driver, 3c515.c, included
+with the kernel source or available from
     cesdis.gsfc.nasa.gov:/pub/linux/drivers/3c515.html
 
 II. Board-specific settings
 
 PCI bus devices are configured by the system at boot time, so no jumpers
 need to be set on the board.  The system BIOS should be set to assign the
-PCI INTA signal to an otherwise unused system IRQ line.  While it's
-physically possible to shared PCI interrupt lines, the 1.2.0 kernel doesn't
-support it.
+PCI INTA signal to an otherwise unused system IRQ line.
+
+The EEPROM settings for media type and forced-full-duplex are observed.
+The EEPROM media type should be left at the default "autoselect" unless using
+10base2 or AUI connections which cannot be reliably detected.
 
 III. Driver operation
 
@@ -211,10 +173,10 @@
 series.  The primary interface is two programmed-I/O FIFOs, with an
 alternate single-contiguous-region bus-master transfer (see next).
 
-The 3c900 "Boomerang" series uses a full-bus-master interface with seperate
+The 3c900 "Boomerang" series uses a full-bus-master interface with separate
 lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet,
 DEC Tulip and Intel Speedo3.  The first chip version retains a compatible
-programmed-I/O interface that will be removed in the 'B' and subsequent
+programmed-I/O interface that has been removed in 'B' and subsequent board
 revisions.
 
 One extension that is advertised in a very large font is that the adapters
@@ -232,7 +194,7 @@
 single frame.
 
 With full-bus-master support, this driver uses a "RX_COPYBREAK" scheme.
-Tather than a fixed intermediate receive buffer, this scheme allocates
+Rather than a fixed intermediate receive buffer, this scheme allocates
 full-sized skbuffs as receive buffers.  The value RX_COPYBREAK is used as
 the copying breakpoint: it is chosen to trade-off the memory wasted by
 passing the full-sized skbuff to the queue layer for all frames vs. the
@@ -258,7 +220,66 @@
 limit of 4K.
 */
 
-#define TCOM_VENDOR_ID	0x10B7		/* 3Com's manufacturer's ID. */
+/* This table drives the PCI probe routines.  It's mostly boilerplate in all
+   of the drivers, and will likely be provided by some future kernel.
+*/
+enum pci_flags_bit {
+	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
+struct pci_id_info {
+	const char *name;
+	u16	vendor_id, device_id, device_id_mask, flags;
+	int drv_flags, io_size;
+	struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
+};
+
+enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
+	   HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
+static struct device *vortex_probe1(int pci_bus, int pci_devfn,
+									struct device *dev, long ioaddr,
+									int irq, int dev_id, int card_idx);
+static struct pci_id_info pci_tbl[] = {
+	{"3c590 Vortex 10Mbps",			0x10B7, 0x5900, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+	{"3c595 Vortex 100baseTx",		0x10B7, 0x5950, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+	{"3c595 Vortex 100baseT4",		0x10B7, 0x5951, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+	{"3c595 Vortex 100base-MII",	0x10B7, 0x5952, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+	{"3Com Vortex",					0x10B7, 0x5900, 0xff00,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+	{"3c900 Boomerang 10baseT",		0x10B7, 0x9000, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+	{"3c900 Boomerang 10Mbps Combo", 0x10B7, 0x9001, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+	{"3c900 Cyclone 10Mbps Combo", 0x10B7, 0x9005, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+	{"3c900B-FL Cyclone 10base-FL",	0x10B7, 0x900A, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+	{"3c905 Boomerang 100baseTx",	0x10B7, 0x9050, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+	{"3c905 Boomerang 100baseT4",	0x10B7, 0x9051, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+	{"3c905B Cyclone 100baseTx",	0x10B7, 0x9055, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, vortex_probe1},
+	{"3c905B-FX Cyclone 100baseFx",	0x10B7, 0x905A, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+	{"3c980 Cyclone",	0x10B7, 0x9800, 0xfff0,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+	{"3c575 Boomerang CardBus",		0x10B7, 0x5057, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+	{"3CCFE575 Cyclone CardBus",	0x10B7, 0x5157, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
+	 128, vortex_probe1},
+	{"3c575 series CardBus (unknown version)", 0x10B7, 0x5057, 0xf0ff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+	{"3Com Boomerang (unknown version)",	0x10B7, 0x9000, 0xff00,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+	{0,},						/* 0 terminated list. */
+};
 
 /* Operational definitions.
    These are not used by other compilation units and thus are not
@@ -287,7 +308,7 @@
 	SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
 	SetTxThreshold = 18<<11, SetTxStart = 19<<11,
 	StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11,
-	StatsDisable = 22<<11, StopCoax = 23<<11,};
+	StatsDisable = 22<<11, StopCoax = 23<<11, SetFilterBit = 25<<11,};
 
 /* The SetRxFilter command accepts the following classes: */
 enum RxFilter {
@@ -327,26 +348,19 @@
 	NodeAddr01=10, NodeAddr23=11, NodeAddr45=12,
 	DriverTune=13, Checksum=15};
 
+enum Window2 {			/* Window 2. */
+	Wn2_ResetOptions=12,
+};
 enum Window3 {			/* Window 3: MAC/config bits. */
 	Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
 };
 union wn3_config {
 	int i;
 	struct w3_config_fields {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
 		unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
 		int pad8:8;
 		unsigned int ram_split:2, pad18:2, xcvr:4, autoselect:1;
 		int pad24:7;
-#elif defined(__BIG_ENDIAN_BITFIELD)
-		unsigned int rom_size:2, ram_speed:2, ram_width:1, ram_size:3;
-		int pad8:8;
-		unsigned int xcvr:4, pad18:2, ram_split:2;
-		int pad24:7;
-		unsigned int autoselect:1;
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
 	} u;
 };
 
@@ -404,37 +418,37 @@
 enum ChipCaps { CapBusMaster=0x20 };
 
 struct vortex_private {
-	char devname[8];			/* "ethN" string, also for kernel debug. */
-	const char *product_name;
-	struct device *next_module;
-	/* The Rx and Tx rings are here to keep them quad-word-aligned. */
+	/* The Rx and Tx rings should be quad-word-aligned. */
 	struct boom_rx_desc rx_ring[RX_RING_SIZE];
 	struct boom_tx_desc tx_ring[TX_RING_SIZE];
 	/* The addresses of transmit- and receive-in-place skbuffs. */
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
+	struct device *next_module;
+	void *priv_addr;
 	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
 	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
-	struct enet_statistics stats;
+	struct net_device_stats stats;
 	struct sk_buff *tx_skb;		/* Packet being eaten by bus master ctrl.  */
 
 	/* PCI configuration space information. */
-	u8 pci_bus, pci_dev_fn;		/* PCI bus location, for power management. */
-	u16 pci_device_id;
+	u8 pci_bus, pci_devfn;		/* PCI bus location, for power management. */
+	char *cb_fn_base;			/* CardBus function status addr space. */
+	int chip_id;
 
 	/* The remainder are related to chip state, mostly media selection. */
-	int in_interrupt;
+	unsigned long in_interrupt;
 	struct timer_list timer;	/* Media selection timer. */
 	int options;				/* User-settable misc. driver options. */
-	unsigned int
-	  media_override:3, 			/* Passed-in media type. */
-	  default_media:3,				/* Read from the EEPROM/Wn3_Config. */
-	  full_duplex:1, autoselect:1,
-	  bus_master:1,				/* Vortex can only do a fragment bus-m. */
-	  full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang  */
-	  hw_csums:1,				/* Has hardware checksums. */
-      tx_full:1;
+	unsigned int media_override:3, 			/* Passed-in media type. */
+		default_media:4,				/* Read from the EEPROM/Wn3_Config. */
+		full_duplex:1, force_fd:1, autoselect:1,
+		bus_master:1,				/* Vortex can only do a fragment bus-m. */
+		full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang  */
+		hw_csums:1,				/* Has hardware checksums. */
+		tx_full:1;
 	u16 status_enable;
+	u16 intr_enable;
 	u16 available_media;				/* From Wn3_Options. */
 	u16 capabilities, info1, info2;		/* Various, from EEPROM. */
 	u16 advertising;					/* NWay media advertisement */
@@ -469,61 +483,39 @@
   { "Default",	 0,			0xFF, XCVR_10baseT, 10000},
 };
 
-static int vortex_scan(struct device *dev);
-static struct device *vortex_found_device(struct device *dev, int ioaddr,
-										  int irq, int device_id,
-										  int options, int card_idx);
-static int vortex_probe1(struct device *dev);
-static int vortex_open(struct device *dev);
-static void mdio_sync(int ioaddr, int bits);
-static int mdio_read(int ioaddr, int phy_id, int location);
-#ifdef HAVE_PRIVATE_IOCTL
-static void mdio_write(int ioaddr, int phy_id, int location, int value);
+#ifndef CARDBUS
+static int vortex_scan(struct device *dev, struct pci_id_info pci_tbl[]);
 #endif
+static int vortex_open(struct device *dev);
+static void mdio_sync(long ioaddr, int bits);
+static int mdio_read(long ioaddr, int phy_id, int location);
+static void mdio_write(long ioaddr, int phy_id, int location, int value);
 static void vortex_timer(unsigned long arg);
 static int vortex_start_xmit(struct sk_buff *skb, struct device *dev);
 static int boomerang_start_xmit(struct sk_buff *skb, struct device *dev);
 static int vortex_rx(struct device *dev);
 static int boomerang_rx(struct device *dev);
-static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs);
+static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int vortex_close(struct device *dev);
-static void update_stats(int addr, struct device *dev);
-static struct enet_statistics *vortex_get_stats(struct device *dev);
+static void update_stats(long ioaddr, struct device *dev);
+static struct net_device_stats *vortex_get_stats(struct device *dev);
 static void set_rx_mode(struct device *dev);
-#ifdef HAVE_PRIVATE_IOCTL
 static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd);
-#endif
-#ifndef NEW_MULTICAST
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
-#endif
 
 
-/* Unlike the other PCI cards the 59x cards don't need a large contiguous
-   memory region, so making the driver a loadable module is feasible.
-
-   Unfortunately maximizing the shared code between the integrated and
-   module version of the driver results in a complicated set of initialization
-   procedures.
-   init_module() -- modules /  tc59x_init()  -- built-in
-		The wrappers for vortex_scan()
-   vortex_scan()  		 The common routine that scans for PCI and EISA cards
-   vortex_found_device() Allocate a device structure when we find a card.
-					Different versions exist for modules and built-in.
-   vortex_probe1()		Fill in the device structure -- this is separated
-					so that the modules code can put it in dev->init.
-*/
 /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
-/* Note: this is the only limit on the number of cards supported!! */
-static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1,};
-static int full_duplex[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
+/* Option count limit only -- unlimited interfaces are supported. */
+#define MAX_UNITS 8
+static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1,};
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 /* A list of all installed Vortex devices, for removing the driver module. */
 static struct device *root_vortex_dev = NULL;
 
 #ifdef MODULE
+#ifndef CARDBUS
 /* Variables to work-around the Compaq PCI BIOS32 problem. */
 static int compaq_ioaddr = 0, compaq_irq = 0, compaq_device_id = 0x5900;
-
-static int debug = -1;
+#endif
 
 #ifdef CARDBUS
 
@@ -531,19 +523,38 @@
 
 static dev_node_t *vortex_attach(dev_locator_t *loc)
 {
-	u16 dev_id;
+	u16 dev_id, vendor_id;
 	u32 io;
 	u8 bus, devfn, irq;
 	struct device *dev;
+	int chip_idx;
 
 	if (loc->bus != LOC_PCI) return NULL;
 	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
-	printk(KERN_INFO "vortex_attach(bus %d, function %d)\n", bus, devfn);
 	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
 	pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
+	pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);
 	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+	printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n",
+		   bus, devfn, dev_id);
 	io &= ~3;
-	dev = vortex_found_device(NULL, io, irq, dev_id, 0, -1);
+	if (io == 0 || irq == 0) {
+		printk(KERN_ERR "The 3Com CardBus Ethernet interface was not "
+			   "assigned an %s.\n" KERN_ERR "  It will not be activated.\n",
+			   io == 0 ? "I/O address" : "IRQ");
+		return NULL;
+	}
+	for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
+		if (vendor_id == pci_tbl[chip_idx].vendor_id
+			&& (dev_id & pci_tbl[chip_idx].device_id_mask) ==
+			pci_tbl[chip_idx].device_id)
+			break;
+	if (pci_tbl[chip_idx].vendor_id == 0) { 		/* Compiled out! */
+		printk(KERN_INFO "Unable to match chip type %4.4x %4.4x in "
+			   "vortex_attach().\n", vendor_id, dev_id);
+		return NULL;
+	}
+	dev = vortex_probe1(bus, devfn, NULL, io, irq, chip_idx, MAX_UNITS+1);
 	if (dev) {
 		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
 		strcpy(node->dev_name, dev->name);
@@ -565,61 +576,52 @@
 	}
 	if (*devp) {
 		struct device *dev = *devp;
+		struct vortex_private *vp = dev->priv;
 		if (dev->flags & IFF_UP)
 			vortex_close(dev);
 		dev->flags &= ~(IFF_UP|IFF_RUNNING);
 		unregister_netdev(dev);
+		if (vp->cb_fn_base) iounmap(vp->cb_fn_base);
 		kfree(dev);
 		*devp = *next;
+		kfree(vp);
 		kfree(node);
 		MOD_DEC_USE_COUNT;
 	}
 }
 
 struct driver_operations vortex_ops = {
-	"3c59x_cb", vortex_attach, NULL, NULL, vortex_detach
+	"3c575_cb", vortex_attach, NULL, NULL, vortex_detach
 };
 
 #endif  /* Cardbus support */
 
 
-int
-init_module(void)
+int init_module(void)
 {
-	if (debug >= 0)
-		vortex_debug = debug;
 	if (vortex_debug)
-		printk(version);
-
-	root_vortex_dev = NULL;
+		printk(KERN_INFO "%s", version);
 #ifdef CARDBUS
 	register_driver(&vortex_ops);
 	return 0;
 #else
-	{
-		int cards_found = vortex_scan(0);
-		if (cards_found == 0)
-			printk("No 3Com Vortex/Boomerang cards found.\n");
-		return cards_found ? 0 : -ENODEV;
-	}
+	return vortex_scan(0, pci_tbl);
 #endif
 }
 
 #else
 int tc59x_probe(struct device *dev)
 {
-	int cards_found = 0;
-
-	cards_found = vortex_scan(dev);
-
-	if (vortex_debug > 0  &&  cards_found)
-		printk(version);
-
-	return cards_found ? 0 : -ENODEV;
+	static int scanned=0;
+	if(scanned++)
+		return -ENODEV;
+	printk(KERN_INFO "%s", version);
+	return vortex_scan(dev, pci_tbl);
 }
 #endif  /* not MODULE */
 
-static int vortex_scan(struct device *dev)
+#ifndef CARDBUS
+static int vortex_scan(struct device *dev, struct pci_id_info pci_tbl[])
 {
 	int cards_found = 0;
 
@@ -634,25 +636,30 @@
 		unsigned char pci_bus, pci_device_fn;
 
 		for (;pci_index < 0xff; pci_index++) {
-			u8 pci_latency;
-			u16 pci_command, new_command, vendor, device;
-			int irq;
+			u16 vendor, device, pci_command, new_command, pwr_cmd;
+			int chip_idx, irq;
 			long ioaddr;
 
-			if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
-									pci_index, &pci_bus, &pci_device_fn)
+			if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
+									&pci_bus, &pci_device_fn)
 				!= PCIBIOS_SUCCESSFUL)
 				break;
 			pcibios_read_config_word(pci_bus, pci_device_fn,
 									 PCI_VENDOR_ID, &vendor);
 			pcibios_read_config_word(pci_bus, pci_device_fn,
 									 PCI_DEVICE_ID, &device);
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-									 PCI_COMMAND, &pci_command);
+			for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
+				if (vendor == pci_tbl[chip_idx].vendor_id
+					&& (device & pci_tbl[chip_idx].device_id_mask) ==
+					pci_tbl[chip_idx].device_id)
+					break;
+			if (pci_tbl[chip_idx].vendor_id == 0) 		/* Compiled out! */
+				continue;
+
 			{
 #if LINUX_VERSION_CODE >= 0x20155
 				struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
-				ioaddr = pdev->base_address[0];
+				ioaddr = pdev->base_address[0] & ~3;
 				irq = pdev->irq;
 #else
 				u32 pci_ioaddr;
@@ -661,15 +668,28 @@
 										 PCI_INTERRUPT_LINE, &pci_irq_line);
 				pcibios_read_config_dword(pci_bus, pci_device_fn,
 										  PCI_BASE_ADDRESS_0, &pci_ioaddr);
-				ioaddr = pci_ioaddr;
+				ioaddr = pci_ioaddr & ~3;;
 				irq = pci_irq_line;
 #endif
 			}
-			/* Remove I/O space marker in bit 0. */
-			ioaddr &= ~3;
 
-			if (vendor != TCOM_VENDOR_ID)
-				continue;
+			/* Power-up the card. */
+			pcibios_read_config_word(pci_bus, pci_device_fn,
+										 0xe0, &pwr_cmd);
+			if (pwr_cmd & 0x3) {
+				/* Save the ioaddr and IRQ info! */
+				printk(KERN_INFO "  A 3Com network adapter is powered down!"
+					   "  Setting the power state %4.4x->%4.4x.\n",
+					   pwr_cmd, pwr_cmd & ~3);
+				pcibios_write_config_word(pci_bus, pci_device_fn,
+										  0xe0, pwr_cmd & ~3);
+				printk(KERN_INFO "  Setting the IRQ to %d, IOADDR to %#lx.\n",
+					   irq, ioaddr);
+				pcibios_write_config_byte(pci_bus, pci_device_fn,
+										 PCI_INTERRUPT_LINE, irq);
+				pcibios_write_config_dword(pci_bus, pci_device_fn,
+										  PCI_BASE_ADDRESS_0, ioaddr);
+			}
 
 			if (ioaddr == 0) {
 				printk(KERN_WARNING "  A 3Com network adapter has been found, "
@@ -679,34 +699,31 @@
 				continue;
 			}
 
-			if (check_region(ioaddr, VORTEX_TOTAL_SIZE))
+			if (check_region(ioaddr, pci_tbl[chip_idx].io_size))
 				continue;
 
 			/* Activate the card. */
+			pcibios_read_config_word(pci_bus, pci_device_fn,
+									 PCI_COMMAND, &pci_command);
 			new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
 			if (pci_command != new_command) {
-				printk(KERN_INFO "  The PCI BIOS has not enabled this"
-					   " device!  Updating PCI command %4.4x->%4.4x.\n",
-					   pci_command, new_command);
+				printk(KERN_INFO "  The PCI BIOS has not enabled the device "
+					   "at %d/%d. Updating PCI command %4.4x->%4.4x.\n",
+					   pci_bus, pci_device_fn, pci_command, new_command);
 				pcibios_write_config_word(pci_bus, pci_device_fn,
 										  PCI_COMMAND, new_command);
 			}
 
-			dev = vortex_found_device(dev, ioaddr, irq,
-									  device, dev && dev->mem_start
-									  ? dev->mem_start : options[cards_found],
-									  cards_found);
+			dev = vortex_probe1(pci_bus, pci_device_fn, dev, ioaddr, irq,
+								chip_idx, cards_found);
 
 			if (dev) {
-				struct vortex_private *vp = (struct vortex_private *)dev->priv;
 				/* Get and check the latency values.  On the 3c590 series
 				   the latency timer must be set to the maximum value to avoid
 				   data corruption that occurs when the timer expires during
 				   a transfer -- a bug in the Vortex chip only. */
-				u8 new_latency = (device&0xff00) == 0x5900 ? 248 : 32;
-				vp->pci_bus = pci_bus;
-				vp->pci_dev_fn = pci_device_fn;
-				vp->pci_device_id = device;
+				u8 pci_latency;
+				u8 new_latency = (device & 0xff00) == 0x5900 ? 248 : 32;
 				
 				pcibios_read_config_byte(pci_bus, pci_device_fn,
 										 PCI_LATENCY_TIMER, &pci_latency);
@@ -726,7 +743,7 @@
 
 	/* Now check all slots of the EISA bus. */
 	if (EISA_bus) {
-		static int ioaddr = 0x1000;
+		static long ioaddr = 0x1000;
 		for ( ; ioaddr < 0x9000; ioaddr += 0x1000) {
 			int device_id;
 			if (check_region(ioaddr, VORTEX_TOTAL_SIZE))
@@ -738,10 +755,8 @@
 			device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83);
 			if ((device_id & 0xFF00) != 0x5900)
 				continue;
-			vortex_found_device(dev, ioaddr, inw(ioaddr + 0xC88) >> 12,
-								device_id,  dev && dev->mem_start
-								? dev->mem_start : options[cards_found],
-								cards_found);
+			vortex_probe1(0, 0, dev, ioaddr, inw(ioaddr + 0xC88) >> 12,
+						  4, cards_found);
 			dev = 0;
 			cards_found++;
 		}
@@ -750,97 +765,58 @@
 #ifdef MODULE
 	/* Special code to work-around the Compaq PCI BIOS32 problem. */
 	if (compaq_ioaddr) {
-		vortex_found_device(dev, compaq_ioaddr, compaq_irq, compaq_device_id,
-							dev && dev->mem_start ? dev->mem_start
-							: options[cards_found], cards_found);
-		cards_found++;
+		vortex_probe1(0, 0, dev, compaq_ioaddr, compaq_irq,
+					  compaq_device_id, cards_found++);
 		dev = 0;
 	}
 #endif
 
-	/* 3c515 cards are now supported by the 3c515.c driver. */
-
-	return cards_found;
+	return cards_found ? 0 : -ENODEV;
 }
+#endif  /* ! Cardbus */
 
-static struct device *
-vortex_found_device(struct device *dev, int ioaddr, int irq,
-					int device_id, int option, int card_idx)
+static struct device *vortex_probe1(int pci_bus, int pci_devfn,
+									struct device *dev, long ioaddr,
+									int irq, int chip_idx, int card_idx)
 {
 	struct vortex_private *vp;
-	const char *product_name;
-	int board_index = 0;
+	int option;
+	unsigned int eeprom[0x40], checksum = 0;		/* EEPROM contents */
+	int i;
 
-	for (board_index = 0; product_ids[board_index]; board_index++) {
-		if (device_id == product_ids[board_index])
-			break;
-	}
-	/* Handle products we don't recognize, but might still work with. */
-	if (product_ids[board_index])
-		product_name = product_names[board_index];
-	else if ((device_id & 0xff00) == 0x5900)
-		product_name = "3c590 Vortex";
-	else if ((device_id & 0xfff0) == 0x9000)
-		product_name = "3c900";
-	else if ((device_id & 0xfff0) == 0x9050)
-		product_name = "3c905";
-	else {
-		printk(KERN_WARNING "Unknown 3Com PCI ethernet adapter type %4.4x detected:"
-			   " not configured.\n", device_id);
-		return 0;
-	}
+	dev = init_etherdev(dev, 0);
 
-#ifdef MODULE
-	/* Allocate and fill new device structure. */
-	{
-		int dev_size = sizeof(struct device) +
-			sizeof(struct vortex_private) + 15;		/* Pad for alignment */
+	printk(KERN_INFO "%s: 3Com %s at 0x%lx, ",
+		   dev->name, pci_tbl[chip_idx].name, ioaddr);
 
-		dev = (struct device *) kmalloc(dev_size, GFP_KERNEL);
-		memset(dev, 0, dev_size);
-	}
-	/* Align the Rx and Tx ring entries.  */
-	dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15);
-	vp = (struct vortex_private *)dev->priv;
-	dev->name = vp->devname; /* An empty string. */
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
-	dev->init = vortex_probe1;
-	vp->product_name = product_name;
-	vp->options = option;
-	if (card_idx >= 0) {
-		if (full_duplex[card_idx] >= 0)
-			vp->full_duplex = full_duplex[card_idx];
-	} else
-		vp->full_duplex = (option > 0 && (option & 0x10) ? 1 : 0);
+	dev->mtu = mtu;
 
-	if (option > 0) {
-		vp->media_override = ((option & 7) == XCVR_10baseTOnly) ?
-			XCVR_10baseT  :  option & 7;
-		vp->bus_master = (option & 16) ? 1 : 0;
-	} else {
-		vp->media_override = 7;
-		vp->bus_master = 0;
+	/* Make certain the descriptor lists are aligned. */
+	{
+		void *mem = kmalloc(sizeof(*vp) + 15, GFP_KERNEL);
+		vp =  (void *)(((long)mem + 15) & ~15);
+		vp->priv_addr = mem;
 	}
-	ether_setup(dev);
+	memset(vp, 0, sizeof(*vp));
+	dev->priv = vp;
+
 	vp->next_module = root_vortex_dev;
 	root_vortex_dev = dev;
-	if (register_netdev(dev) != 0)
-		return 0;
-#else  /* not a MODULE */
-	if (dev) {
-		/* Caution: quad-word alignment required for rings! */
-		dev->priv = kmalloc(sizeof (struct vortex_private), GFP_KERNEL);
-		memset(dev->priv, 0, sizeof (struct vortex_private));
-	}
-	dev = init_etherdev(dev, sizeof(struct vortex_private));
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	dev->mtu = mtu;
 
-	vp  = (struct vortex_private *)dev->priv;
-	vp->product_name = product_name;
-	vp->options = option;
+	vp->chip_id = chip_idx;
+	vp->pci_bus = pci_bus;
+	vp->pci_devfn = pci_devfn;
+
+	/* The lower four bits are the media type. */
+	if (dev->mem_start)
+		option = dev->mem_start;
+	else if (card_idx < MAX_UNITS)
+		option = options[card_idx];
+	else
+		option = -1;
+
 	if (option >= 0) {
 		vp->media_override = ((option & 7) == 2)  ?  0  :  option & 7;
 		vp->full_duplex = (option & 8) ? 1 : 0;
@@ -850,22 +826,11 @@
 		vp->full_duplex = 0;
 		vp->bus_master = 0;
 	}
+	if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)
+		vp->full_duplex = 1;
 
-	vortex_probe1(dev);
-#endif /* MODULE */
-	return dev;
-}
-
-static int vortex_probe1(struct device *dev)
-{
-	int ioaddr = dev->base_addr;
-	struct vortex_private *vp = (struct vortex_private *)dev->priv;
-	u16 *ether_addr = (u16 *)dev->dev_addr;
-	unsigned int eeprom[0x40], checksum = 0;		/* EEPROM contents */
-	int i;
-
-	printk(KERN_INFO "%s: 3Com %s at %#3x,",
-		   dev->name, vp->product_name, ioaddr);
+	vp->force_fd = vp->full_duplex;
+	vp->options = option;
 
 	/* Read the station address from the EEPROM. */
 	EL3WINDOW(0);
@@ -896,14 +861,30 @@
 		printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
 
 	for (i = 0; i < 3; i++)
-		ether_addr[i] = htons(eeprom[i + 10]);
+		((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
 	for (i = 0; i < 6; i++)
 		printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
+#ifdef __sparc__
+	printk(", IRQ %s\n", __irq_itoa(dev->irq));
+#else
 	printk(", IRQ %d\n", dev->irq);
 	/* Tell them about an invalid IRQ. */
 	if (vortex_debug && (dev->irq <= 0 || dev->irq >= NR_IRQS))
 		printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",
 			   dev->irq);
+#endif
+
+	if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
+		u32 fn_st_addr;			/* Cardbus function status space */
+		pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2,
+								  &fn_st_addr);
+		if (fn_st_addr)
+			vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128);
+		printk("%s: CardBus functions mapped %8.8x->%p (PCMCIA committee"
+			   " brain-damage).\n", dev->name, fn_st_addr, vp->cb_fn_base);
+		EL3WINDOW(2);
+		outw(0x10 | inw(ioaddr + Wn2_ResetOptions), ioaddr + Wn2_ResetOptions);
+	}
 
 	/* Extract our information from the EEPROM data. */
 	vp->info1 = eeprom[13];
@@ -929,7 +910,7 @@
 			   config.u.ram_width ? "word" : "byte",
 			   ram_split[config.u.ram_split],
 			   config.u.autoselect ? "autoselect/" : "",
-			   config.u.xcvr ? "NWay Autonegotiation" :
+			   config.u.xcvr > XCVR_ExtMII ? "<invalid transceiver>" :
 			   media_tbl[config.u.xcvr].name);
 		vp->default_media = config.u.xcvr;
 		vp->autoselect = config.u.autoselect;
@@ -942,22 +923,24 @@
 	} else
 		dev->if_port = vp->default_media;
 
-	if (dev->if_port == XCVR_MII) {
+	if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
 		int phy, phy_idx = 0;
 		EL3WINDOW(4);
-		for (phy = 0; phy < 32 && phy_idx < sizeof(vp->phys); phy++) {
-			int mii_status;
-			mdio_sync(ioaddr, 32);
-			mii_status = mdio_read(ioaddr, phy, 1);
+		mii_preamble_required++;
+		mii_preamble_required++;
+		mdio_read(ioaddr, 24, 1);
+		for (phy = 1; phy <= 32 && phy_idx < sizeof(vp->phys); phy++) {
+			int mii_status, phyx = phy & 0x1f;
+			mii_status = mdio_read(ioaddr, phyx, 1);
 			if (mii_status  &&  mii_status != 0xffff) {
-				vp->phys[phy_idx++] = phy;
-				printk(KERN_INFO "  MII transceiver found at address %d, status %4x.\n",
-					   phy, mii_status);
-				mdio_sync(ioaddr, 32);
-				if ((mdio_read(ioaddr, phy, 1) & 0x0040) == 0)
-					mii_preamble_required = 1;
+				vp->phys[phy_idx++] = phyx;
+				printk(KERN_INFO "  MII transceiver found at address %d,"
+					   " status %4x.\n", phyx, mii_status);
+				if ((mii_status & 0x0040) == 0)
+					mii_preamble_required++;
 			}
 		}
+		mii_preamble_required--;
 		if (phy_idx == 0) {
 			printk(KERN_WARNING"  ***WARNING*** No MII transceivers found!\n");
 			vp->phys[0] = 24;
@@ -965,7 +948,7 @@
 			vp->advertising = mdio_read(ioaddr, vp->phys[0], 4);
 			if (vp->full_duplex) {
 				/* Only advertise the FD media types. */
-				vp->advertising &= 0x015F;
+				vp->advertising &= ~0x02A0;
 				mdio_write(ioaddr, vp->phys[0], 4, vp->advertising);
 			}
 		}
@@ -979,30 +962,24 @@
 	}
 
 	/* We do a request_region() to register /proc/ioports info. */
-	request_region(ioaddr, VORTEX_TOTAL_SIZE, vp->product_name);
+	request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);
 
 	/* The 3c59x-specific entries in the device structure. */
 	dev->open = &vortex_open;
 	dev->hard_start_xmit = &vortex_start_xmit;
 	dev->stop = &vortex_close;
 	dev->get_stats = &vortex_get_stats;
-#ifdef HAVE_PRIVATE_IOCTL
 	dev->do_ioctl = &vortex_ioctl;
-#endif
-#ifdef NEW_MULTICAST
 	dev->set_multicast_list = &set_rx_mode;
-#else
-	dev->set_multicast_list = &set_multicast_list;
-#endif
 
-	return 0;
+	return dev;
 }
 
 
 static int
 vortex_open(struct device *dev)
 {
-	int ioaddr = dev->base_addr;
+	long ioaddr = dev->base_addr;
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	union wn3_config config;
 	int i;
@@ -1017,28 +994,31 @@
 				   dev->name, vp->media_override,
 				   media_tbl[vp->media_override].name);
 		dev->if_port = vp->media_override;
+	} else if (vp->autoselect && pci_tbl[vp->chip_id].drv_flags & HAS_NWAY) {
+			dev->if_port = XCVR_NWAY;
 	} else if (vp->autoselect) {
 		/* Find first available media type, starting with 100baseTx. */
 		dev->if_port = XCVR_100baseTx;
 		while (! (vp->available_media & media_tbl[dev->if_port].mask))
 			dev->if_port = media_tbl[dev->if_port].next;
-
-		if (vortex_debug > 1)
-			printk(KERN_DEBUG "%s: Initial media type %s.\n",
-				   dev->name, media_tbl[dev->if_port].name);
-
-		init_timer(&vp->timer);
-		vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
-		vp->timer.data = (unsigned long)dev;
-		vp->timer.function = &vortex_timer;    /* timer handler */
-		add_timer(&vp->timer);
 	} else
 		dev->if_port = vp->default_media;
 
+	init_timer(&vp->timer);
+	vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
+	vp->timer.data = (unsigned long)dev;
+	vp->timer.function = &vortex_timer;		/* timer handler */
+	add_timer(&vp->timer);
+
+	if (vortex_debug > 1)
+		printk(KERN_DEBUG "%s: Initial media type %s.\n",
+			   dev->name, media_tbl[dev->if_port].name);
+
+	vp->full_duplex = vp->force_fd;
 	config.u.xcvr = dev->if_port;
 	outl(config.i, ioaddr + Wn3_Config);
 
-	if (dev->if_port == XCVR_MII) {
+	if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
 		int mii_reg1, mii_reg5;
 		EL3WINDOW(4);
 		/* Read BMSR (reg1) only to clear old status. */
@@ -1078,20 +1058,10 @@
 
 	outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
 
-#ifdef SA_SHIRQ
 	/* Use the now-standard shared IRQ implementation. */
 	if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, dev->name, dev)) {
 		return -EAGAIN;
 	}
-#else
-	if (dev->irq == 0  ||  irq2dev_map[dev->irq] != NULL)
-		return -EAGAIN;
-	irq2dev_map[dev->irq] = dev;
-	if (request_irq(dev->irq, &vortex_interrupt, 0, vp->product_name)) {
-		irq2dev_map[dev->irq] = NULL;
-		return -EAGAIN;
-	}
-#endif
 
 	if (vortex_debug > 1) {
 		EL3WINDOW(4);
@@ -1109,9 +1079,11 @@
 	if (dev->if_port == XCVR_10base2)
 		/* Start the thinnet transceiver. We should really wait 50ms...*/
 		outw(StartCoax, ioaddr + EL3_CMD);
-	EL3WINDOW(4);
-	outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
-		 media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+	if (dev->if_port != XCVR_NWAY) {
+		EL3WINDOW(4);
+		outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
+			 media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+	}
 
 	/* Switch to the stats window, and clear all stats by reading. */
 	outw(StatsDisable, ioaddr + EL3_CMD);
@@ -1138,22 +1110,23 @@
 			printk(KERN_DEBUG "%s:  Filling in the Rx ring.\n", dev->name);
 		for (i = 0; i < RX_RING_SIZE; i++) {
 			struct sk_buff *skb;
-			vp->rx_ring[i].next = virt_to_bus(&vp->rx_ring[i+1]);
+			vp->rx_ring[i].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[i+1]));
 			vp->rx_ring[i].status = 0;	/* Clear complete bit. */
-			vp->rx_ring[i].length = PKT_BUF_SZ | LAST_FRAG;
-			skb = DEV_ALLOC_SKB(PKT_BUF_SZ);
+			vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG);
+			skb = dev_alloc_skb(PKT_BUF_SZ);
 			vp->rx_skbuff[i] = skb;
 			if (skb == NULL)
 				break;			/* Bad news!  */
 			skb->dev = dev;			/* Mark as being used by this device. */
 #if LINUX_VERSION_CODE >= 0x10300
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[i].addr = virt_to_bus(skb->tail);
+			vp->rx_ring[i].addr = cpu_to_le32(virt_to_bus(skb->tail));
 #else
 			vp->rx_ring[i].addr = virt_to_bus(skb->data);
 #endif
 		}
-		vp->rx_ring[i-1].next = virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */
+		/* Wrap the ring. */
+		vp->rx_ring[i-1].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[0]));
 		outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
 	}
 	if (vp->full_bus_master_tx) { 		/* Boomerang bus master Tx. */
@@ -1181,14 +1154,16 @@
 		(vp->full_bus_master_tx ? DownComplete : TxAvailable) |
 		(vp->full_bus_master_rx ? UpComplete : RxComplete) |
 		(vp->bus_master ? DMADone : 0);
+	vp->intr_enable = SetIntrEnb | IntLatch | TxAvailable | RxComplete |
+		StatsFull | HostError | TxComplete | IntReq
+		| (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete;
 	outw(vp->status_enable, ioaddr + EL3_CMD);
 	/* Ack all pending events, and set active indicator mask. */
 	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
 		 ioaddr + EL3_CMD);
-	outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
-		 | HostError | TxComplete
-		 | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
-			ioaddr + EL3_CMD);
+	outw(vp->intr_enable, ioaddr + EL3_CMD);
+	if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */
+		writel(0x8000, vp->cb_fn_base + 4);
 
 	MOD_INC_USE_COUNT;
 
@@ -1197,24 +1172,23 @@
 
 static void vortex_timer(unsigned long data)
 {
-#ifdef AUTOMEDIA
 	struct device *dev = (struct device *)data;
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
-	int ioaddr = dev->base_addr;
-	unsigned long flags;
+	long ioaddr = dev->base_addr;
+	int next_tick = 0;
 	int ok = 0;
+	int media_status, mii_status, old_window;
 
 	if (vortex_debug > 1)
 		printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n",
 			   dev->name, media_tbl[dev->if_port].name);
 
-	save_flags(flags);	cli(); {
-	  int old_window = inw(ioaddr + EL3_CMD) >> 13;
-	  int media_status;
-	  EL3WINDOW(4);
-	  media_status = inw(ioaddr + Wn4_Media);
-	  switch (dev->if_port) {
-	  case XCVR_10baseT:  case XCVR_100baseTx:  case XCVR_100baseFx:
+	disable_irq(dev->irq);
+	old_window = inw(ioaddr + EL3_CMD) >> 13;
+	EL3WINDOW(4);
+	media_status = inw(ioaddr + Wn4_Media);
+	switch (dev->if_port) {
+	case XCVR_10baseT:  case XCVR_100baseTx:  case XCVR_100baseFx:
 		if (media_status & Media_LnkBeat) {
 		  ok = 1;
 		  if (vortex_debug > 1)
@@ -1223,27 +1197,40 @@
 		} else if (vortex_debug > 1)
 		  printk(KERN_DEBUG "%s: Media %s is has no link beat, %x.\n",
 				   dev->name, media_tbl[dev->if_port].name, media_status);
-
 		break;
-	  case XCVR_MII:
-		  {
-			  int mii_reg1 = mdio_read(ioaddr, vp->phys[0], 1);
+	  case XCVR_MII: case XCVR_NWAY:
+		  mii_status = mdio_read(ioaddr, vp->phys[0], 1);
+		  ok = 1;
+		  if (debug > 1)
+			  printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
+					 dev->name, mii_status);
+		  if (mii_status & 0x0004) {
 			  int mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);
-			  if (vortex_debug > 1)
-				  printk(KERN_DEBUG "%s: MII #%d status register is %4.4x, "
-						 "link partner capability %4.4x.\n",
-						 dev->name, vp->phys[0], mii_reg1, mii_reg5);
-			  if (mii_reg1 & 0x0004)
-				  ok = 1;
-			  break;
+			  if (! vp->force_fd  &&  mii_reg5 != 0xffff) {
+				  int duplex = (mii_reg5&0x0100) ||
+					  (mii_reg5 & 0x01C0) == 0x0040;
+				  if (vp->full_duplex != duplex) {
+					  vp->full_duplex = duplex;
+					  printk(KERN_INFO "%s: Setting %s-duplex based on MII "
+							 "#%d link partner capability of %4.4x.\n",
+							 dev->name, vp->full_duplex ? "full" : "half",
+							 vp->phys[0], mii_reg5);
+					  /* Set the full-duplex bit. */
+					  outb((vp->full_duplex ? 0x20 : 0) |
+						   (dev->mtu > 1500 ? 0x40 : 0),
+						   ioaddr + Wn3_MAC_Ctrl);
+				  }
+				  next_tick = 60*HZ;
+			  }
 		  }
+		  break;
 	  default:					/* Other media types handled by Tx timeouts. */
 		if (vortex_debug > 1)
 		  printk(KERN_DEBUG "%s: Media %s is has no indication, %x.\n",
 				 dev->name, media_tbl[dev->if_port].name, media_status);
 		ok = 1;
-	  }
-	  if ( ! ok) {
+	}
+	if ( ! ok) {
 		union wn3_config config;
 
 		do {
@@ -1260,8 +1247,7 @@
 			printk(KERN_DEBUG "%s: Media selection failed, now trying "
 				   "%s port.\n",
 				   dev->name, media_tbl[dev->if_port].name);
-		  vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
-		  add_timer(&vp->timer);
+		  next_tick = RUN_AT(media_tbl[dev->if_port].wait);
 		}
 		outw((media_status & ~(Media_10TP|Media_SQE)) |
 			 media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
@@ -1273,21 +1259,25 @@
 
 		outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
 			 ioaddr + EL3_CMD);
-	  }
-	  EL3WINDOW(old_window);
-	}   restore_flags(flags);
-	if (vortex_debug > 1)
+	}
+	EL3WINDOW(old_window);
+	enable_irq(dev->irq);
+
+	if (vortex_debug > 2)
 	  printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",
 			 dev->name, media_tbl[dev->if_port].name);
 
-#endif /* AUTOMEDIA*/
+	if (next_tick) {
+		vp->timer.expires = RUN_AT(next_tick);
+		add_timer(&vp->timer);
+	}
 	return;
 }
 
 static void vortex_tx_timeout(struct device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
-	int ioaddr = dev->base_addr;
+	long ioaddr = dev->base_addr;
 	int j;
 
 	printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
@@ -1301,7 +1291,7 @@
 		printk(KERN_ERR "%s: Interrupt posted but not delivered --"
 			   " IRQ blocked by another device?\n", dev->name);
 		/* Bad idea here.. but we might as well handle a few events. */
-		vortex_interrupt IRQ(dev->irq, dev, 0);
+		vortex_interrupt(dev->irq, dev, 0);
 	}
 	outw(TxReset, ioaddr + EL3_CMD);
 	for (j = 200; j >= 0 ; j--)
@@ -1320,8 +1310,8 @@
 		for (i = 0; i < TX_RING_SIZE; i++) {
 			printk(KERN_DEBUG "  %d: @%p  length %8.8x status %8.8x\n", i,
 				   &vp->tx_ring[i],
-				   vp->tx_ring[i].length,
-				   vp->tx_ring[i].status);
+				   le32_to_cpu(vp->tx_ring[i].length),
+				   le32_to_cpu(vp->tx_ring[i].status));
 		}
 	}
 #endif
@@ -1351,14 +1341,14 @@
 }
 
 /*
- * Handle uncommon interrupt sources.  This is a seperate routine to minimize
+ * Handle uncommon interrupt sources.  This is a separate routine to minimize
  * the cache impact.
  */
 static void
 vortex_error(struct device *dev, int status)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
-	int ioaddr = dev->base_addr;
+	long ioaddr = dev->base_addr;
 	int do_tx_reset = 0;
 	int i;
 
@@ -1398,8 +1388,10 @@
 			DoneDidThat++;
 		}
 	}
-	if (status & IntReq)		/* Restore all interrupt sources.  */
-		outw(ioaddr + EL3_CMD, vp->status_enable);
+	if (status & IntReq) {		/* Restore all interrupt sources.  */
+		outw(vp->status_enable, ioaddr + EL3_CMD);
+		outw(vp->intr_enable, ioaddr + EL3_CMD);
+	}
 	if (status & HostError) {
 		u16 fifo_diag;
 		EL3WINDOW(4);
@@ -1445,7 +1437,7 @@
 vortex_start_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
-	int ioaddr = dev->base_addr;
+	long ioaddr = dev->base_addr;
 
 	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
 		if (jiffies - dev->trans_start >= TX_TIMEOUT)
@@ -1455,7 +1447,6 @@
 
 	/* Put out the doubleword header... */
 	outl(skb->len, ioaddr + TX_FIFO);
-#ifdef VORTEX_BUS_MASTER
 	if (vp->bus_master) {
 		/* Set the bus-master controller to transfer the packet. */
 		outl(virt_to_bus(skb->data), ioaddr + Wn7_MasterAddr);
@@ -1473,16 +1464,6 @@
 			/* Interrupt us when the FIFO has room for max-sized packet. */
 			outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
 	}
-#else
-	/* ... and the packet rounded to a doubleword. */
-	outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-	DEV_FREE_SKB(skb);
-	if (inw(ioaddr + TxFree) > 1536) {
-		clear_bit(0, (void*)&dev->tbusy);
-	} else
-		/* Interrupt us when the FIFO has room for max-sized packet. */
-		outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
-#endif  /* bus master */
 
 	dev->trans_start = jiffies;
 
@@ -1517,7 +1498,7 @@
 boomerang_start_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
-	int ioaddr = dev->base_addr;
+	long ioaddr = dev->base_addr;
 
 	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
 		if (jiffies - dev->trans_start >= TX_TIMEOUT)
@@ -1539,13 +1520,12 @@
 				printk(KERN_WARNING "%s: Tx Ring full, refusing to send buffer.\n",
 					   dev->name);
 			return 1;
-		} 
-		/* end change 06/25/97 M. Sievers */	
+		}
 		vp->tx_skbuff[entry] = skb;
 		vp->tx_ring[entry].next = 0;
-		vp->tx_ring[entry].addr = virt_to_bus(skb->data);
-		vp->tx_ring[entry].length = skb->len | LAST_FRAG;
-		vp->tx_ring[entry].status = skb->len | TxIntrUploaded;
+		vp->tx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->data));
+		vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
+		vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
 
 		save_flags(flags);
 		cli();
@@ -1554,7 +1534,7 @@
 		for (i = 600; i >= 0 ; i--)
 			if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
 				break;
-		prev_entry->next = virt_to_bus(&vp->tx_ring[entry]);
+		prev_entry->next = cpu_to_le32(virt_to_bus(&vp->tx_ring[entry]));
 		if (inl(ioaddr + DownListPtr) == 0) {
 			outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr);
 			queued_packet++;
@@ -1566,7 +1546,7 @@
 		if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
 			vp->tx_full = 1;
 		else {					/* Clear previous interrupt enable. */
-			prev_entry->status &= ~TxIntrUploaded;
+			prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
 			clear_bit(0, (void*)&dev->tbusy);
 		}
 		dev->trans_start = jiffies;
@@ -1576,28 +1556,33 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
+static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-#ifdef SA_SHIRQ		/* Use the now-standard shared IRQ implementation. */
 	struct device *dev = dev_id;
-#else
-	struct device *dev = (struct device *)(irq2dev_map[irq]);
-#endif
-	struct vortex_private *vp;
-	int ioaddr, status;
-	int latency;
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr;
+	int latency, status;
 	int work_done = max_interrupt_work;
 
-	vp = (struct vortex_private *)dev->priv;
-	if (test_and_set_bit(0, (void*)&vp->in_interrupt)) {
+#if defined(__i386__)
+	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
+	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
+			   dev->name);
+		dev->interrupt = 0;	/* Avoid halting machine. */
+		return;
+	}
+#else
+	if (dev->interrupt) {
 		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
 		return;
 	}
+	dev->interrupt = 1;
+#endif
 
 	dev->interrupt = 1;
 	ioaddr = dev->base_addr;
 	latency = inb(ioaddr + Timer);
-
 	status = inw(ioaddr + EL3_STATUS);
 
 	if (vortex_debug > 4)
@@ -1646,17 +1631,23 @@
 				mark_bh(NET_BH);
 			}
 		}
-#ifdef VORTEX_BUS_MASTER
 		if (status & DMADone) {
-			outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
-			clear_bit(0, (void*)&dev->tbusy);
-			DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
-			mark_bh(NET_BH);
+			if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
+				outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
+				DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
+				if (inw(ioaddr + TxFree) > 1536) {
+					clear_bit(0, (void*)&dev->tbusy);
+					mark_bh(NET_BH);
+				} else /* Interrupt when FIFO has room for max-sized packet. */
+					outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+			}
 		}
-#endif
 		/* Check for all uncommon interrupts at once. */
-		if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq))
+		if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
+			if (status == 0xffff)
+				break;
 			vortex_error(dev, status);
+		}
 
 		if (--work_done < 0) {
 			if ((status & (0x7fe - (UpComplete | DownComplete))) == 0) {
@@ -1669,13 +1660,14 @@
 				/* Disable all pending interrupts. */
 				outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
 				outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
-				/* Set a timer to reenable interrupts. */
-				
+				/* The timer will reenable interrupts. */
 				break;
 			}
 		}
 		/* Acknowledge the IRQ. */
 		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+		if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */
+			writel(0x8000, vp->cb_fn_base + 4);
 
 	} while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
 
@@ -1683,16 +1675,18 @@
 		printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
 			   dev->name, status);
 
+#if defined(__i386__)
+	clear_bit(0, (void*)&dev->interrupt);
+#else
 	dev->interrupt = 0;
-	clear_bit(0, (void*)&vp->in_interrupt);
+#endif
 	return;
 }
 
-static int
-vortex_rx(struct device *dev)
+static int vortex_rx(struct device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
-	int ioaddr = dev->base_addr;
+	long ioaddr = dev->base_addr;
 	int i;
 	short rx_status;
 
@@ -1715,25 +1709,28 @@
 			int pkt_len = rx_status & 0x1fff;
 			struct sk_buff *skb;
 
-			skb = DEV_ALLOC_SKB(pkt_len + 5);
+			skb = dev_alloc_skb(pkt_len + 5);
 			if (vortex_debug > 4)
 				printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n",
 					   pkt_len, rx_status);
 			if (skb != NULL) {
 				skb->dev = dev;
-#if LINUX_VERSION_CODE >= 0x10300
 				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
 				/* 'skb_put()' points to the start of sk_buff data area. */
-				insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
-					 (pkt_len + 3) >> 2);
+				if (vp->bus_master &&
+					! (inw(ioaddr + Wn7_MasterStatus) & 0x8000)) {
+					outl(virt_to_bus(skb_put(skb, pkt_len)),
+						 ioaddr + Wn7_MasterAddr);
+					outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
+					outw(StartDMAUp, ioaddr + EL3_CMD);
+					while (inw(ioaddr + Wn7_MasterStatus) & 0x8000)
+						;
+				} else {
+					insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
+						 (pkt_len + 3) >> 2);
+				}
 				outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
 				skb->protocol = eth_type_trans(skb, dev);
-#else
-				skb->len = pkt_len;
-				/* 'skb->data' points to the start of sk_buff data area. */
-				insl(ioaddr + RX_FIFO, skb->data, (pkt_len + 3) >> 2);
-				outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
-#endif  /* KERNEL_1_3_0 */
 				netif_rx(skb);
 				dev->last_rx = jiffies;
 				vp->stats.rx_packets++;
@@ -1762,7 +1759,7 @@
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	int entry = vp->cur_rx % RX_RING_SIZE;
-	int ioaddr = dev->base_addr;
+	long ioaddr = dev->base_addr;
 	int rx_status;
 	int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx;
 
@@ -1770,8 +1767,9 @@
 		printk(KERN_DEBUG "  In boomerang_rx(), status %4.4x, rx_status "
 			   "%4.4x.\n",
 			   inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
-	while ((--rx_work_limit >= 0) &&
-			((rx_status = vp->rx_ring[entry].status) & RxDComplete)) {
+	while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){
+		if (--rx_work_limit < 0)
+			break;
 		if (rx_status & RxDError) { /* Error, update stats. */
 			unsigned char rx_error = rx_status >> 16;
 			if (vortex_debug > 2)
@@ -1794,41 +1792,28 @@
 			/* Check if the packet is long enough to just accept without
 			   copying to a properly sized skbuff. */
 			if (pkt_len < rx_copybreak
-				&& (skb = DEV_ALLOC_SKB(pkt_len + 2)) != 0) {
+				&& (skb = dev_alloc_skb(pkt_len + 2)) != 0) {
 				skb->dev = dev;
-#if LINUX_VERSION_CODE >= 0x10300
 				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
 				/* 'skb_put()' points to the start of sk_buff data area. */
 				memcpy(skb_put(skb, pkt_len),
-					   bus_to_virt(vp->rx_ring[entry].addr),
+					   bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)),
 					   pkt_len);
-#else
-				memcpy(skb->data, bus_to_virt(vp->rx_ring[entry].addr), pkt_len);
-				skb->len = pkt_len;
-#endif
 				rx_copy++;
-			} else{
+			} else {
 				void *temp;
 				/* Pass up the skbuff already on the Rx ring. */
 				skb = vp->rx_skbuff[entry];
-				if (skb == NULL) {
-					printk(KERN_WARNING "%s: in boomerang_rx -- attempt to use NULL skb caught\n", dev->name);
-					break;
-				}
 				vp->rx_skbuff[entry] = NULL;
-#if LINUX_VERSION_CODE >= 0x10300
 				temp = skb_put(skb, pkt_len);
-#else
-				temp = skb->data;
-#endif
 				/* Remove this checking code for final release. */
-				if (bus_to_virt(vp->rx_ring[entry].addr) != temp)
+				if (bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)) != temp)
 					printk(KERN_ERR "%s: Warning -- the skbuff addresses do not match"
 						   " in boomerang_rx: %p vs. %p.\n", dev->name,
-						   bus_to_virt(vp->rx_ring[entry].addr), temp);
+						   bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)),
+						   temp);
 				rx_nocopy++;
 			}
-#if LINUX_VERSION_CODE > 0x10300
 			skb->protocol = eth_type_trans(skb, dev);
 			{					/* Use hardware checksum info. */
 				int csum_bits = rx_status & 0xee000000;
@@ -1839,9 +1824,6 @@
 					rx_csumhits++;
 				}
 			}
-#else
-			skb->len = pkt_len;
-#endif
 			netif_rx(skb);
 			dev->last_rx = jiffies;
 			vp->stats.rx_packets++;
@@ -1853,29 +1835,17 @@
 		struct sk_buff *skb;
 		entry = vp->dirty_rx % RX_RING_SIZE;
 		if (vp->rx_skbuff[entry] == NULL) {
-			skb = DEV_ALLOC_SKB(PKT_BUF_SZ);
-			if (skb == NULL) {
-				printk(KERN_DEBUG "%s: in boomerang_rx -- could not allocate skbuff\n", dev->name);
+			skb = dev_alloc_skb(PKT_BUF_SZ);
+			if (skb == NULL)
 				break;			/* Bad news!  */
-			}
 			skb->dev = dev;			/* Mark as being used by this device. */
-#if LINUX_VERSION_CODE > 0x10300
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[entry].addr = virt_to_bus(skb->tail);
-#else
-			vp->rx_ring[entry].addr = virt_to_bus(skb->data);
-#endif
+			vp->rx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->tail));
 			vp->rx_skbuff[entry] = skb;
 		}
 		vp->rx_ring[entry].status = 0;	/* Clear complete bit. */
 		outw(UpUnstall, ioaddr + EL3_CMD);
 	}
-
-	if (vp->dirty_rx >= RX_RING_SIZE ) {
-		vp->cur_rx -= RX_RING_SIZE;
-		vp->dirty_rx -= RX_RING_SIZE;
-	}
-
 	return 0;
 }
 
@@ -1883,7 +1853,7 @@
 vortex_close(struct device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
-	int ioaddr = dev->base_addr;
+	long ioaddr = dev->base_addr;
 	int i;
 
 	dev->start = 0;
@@ -1910,12 +1880,7 @@
 		/* Turn off thinnet power.  Green! */
 		outw(StopCoax, ioaddr + EL3_CMD);
 
-#ifdef SA_SHIRQ
 	free_irq(dev->irq, dev);
-#else
-	free_irq(dev->irq);
-	irq2dev_map[dev->irq] = 0;
-#endif
 
 	outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
 
@@ -1945,8 +1910,7 @@
 	return 0;
 }
 
-static struct enet_statistics *
-vortex_get_stats(struct device *dev)
+static struct net_device_stats *vortex_get_stats(struct device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	unsigned long flags;
@@ -1967,7 +1931,7 @@
 	table.  This is done by checking that the ASM (!) code generated uses
 	atomic updates with '+='.
 	*/
-static void update_stats(int ioaddr, struct device *dev)
+static void update_stats(long ioaddr, struct device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 
@@ -1998,20 +1962,14 @@
 	return;
 }
 
-#ifdef HAVE_PRIVATE_IOCTL
 static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
-	int ioaddr = dev->base_addr;
+	long ioaddr = dev->base_addr;
 	u16 *data = (u16 *)&rq->ifr_data;
 	int phy = vp->phys[0] & 0x1f;
 
-	if (vortex_debug > 2)
-		printk(KERN_DEBUG "%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",
-			   dev->name, rq->ifr_ifrn.ifrn_name, cmd,
-			   data[0], data[1], data[2], data[3]);
-
-    switch(cmd) {
+	switch(cmd) {
 	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
 		data[0] = phy;
 	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
@@ -2021,22 +1979,20 @@
 	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
 		if (!suser())
 			return -EPERM;
+		EL3WINDOW(4);
 		mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
 		return 0;
 	default:
 		return -EOPNOTSUPP;
 	}
 }
-#endif  /* HAVE_PRIVATE_IOCTL */
 
-/* This new version of set_rx_mode() supports v1.4 kernels.
-   The Vortex chip has no documented multicast filter, so the only
+/* Pre-Cyclone chips have no documented multicast filter, so the only
    multicast setting is to receive all multicast frames.  At least
    the chip has a very clean way to set the mode, unlike many others. */
-static void
-set_rx_mode(struct device *dev)
+static void set_rx_mode(struct device *dev)
 {
-	int ioaddr = dev->base_addr;
+	long ioaddr = dev->base_addr;
 	int new_mode;
 
 	if (dev->flags & IFF_PROMISC) {
@@ -2050,14 +2006,6 @@
 
 	outw(new_mode, ioaddr + EL3_CMD);
 }
-#ifndef NEW_MULTICAST
-/* The old interface to set the Rx mode. */
-static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
-{
-	set_rx_mode(dev);
-}
-#endif
 
 
 /* MII transceiver control section.
@@ -2068,7 +2016,7 @@
 /* The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
    met by back-to-back PCI I/O cycles, but we insert a delay to avoid
    "overclocking" issues. */
-#define mdio_delay() udelay(1)
+#define mdio_delay() inl(mdio_addr)
 
 #define MDIO_SHIFT_CLK	0x01
 #define MDIO_DIR_WRITE	0x04
@@ -2079,11 +2027,11 @@
 
 /* Generate the preamble required for initial synchronization and
    a few older transceivers. */
-static void mdio_sync(int ioaddr, int bits)
+static void mdio_sync(long ioaddr, int bits)
 {
-	int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+	long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
 
-	/* Establish sync by sending at least 32 logic ones. */ 
+	/* Establish sync by sending at least 32 logic ones. */
 	while (-- bits >= 0) {
 		outw(MDIO_DATA_WRITE1, mdio_addr);
 		mdio_delay();
@@ -2092,12 +2040,12 @@
 	}
 }
 
-static int mdio_read(int ioaddr, int phy_id, int location)
+static int mdio_read(long ioaddr, int phy_id, int location)
 {
 	int i;
 	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
 	unsigned int retval = 0;
-	int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+	long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
 
 	if (mii_preamble_required)
 		mdio_sync(ioaddr, 32);
@@ -2118,13 +2066,17 @@
 		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
 		mdio_delay();
 	}
-	return retval>>1 & 0xffff;
+#if 0
+	return (retval>>1) & 0x1ffff;
+#else
+	return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff;
+#endif
 }
 
-static void mdio_write(int ioaddr, int phy_id, int location, int value)
+static void mdio_write(long ioaddr, int phy_id, int location, int value)
 {
 	int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
-	int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+	long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
 	int i;
 
 	if (mii_preamble_required)
@@ -2151,8 +2103,7 @@
 
 
 #ifdef MODULE
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
 	struct device *next_dev;
 
@@ -2162,11 +2113,14 @@
 
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_vortex_dev) {
-		next_dev = ((struct vortex_private *)root_vortex_dev->priv)->next_module;
+		struct vortex_private *vp=(void *)(root_vortex_dev->priv);
+		next_dev = vp->next_module;
 		unregister_netdev(root_vortex_dev);
 		outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD);
-		release_region(root_vortex_dev->base_addr, VORTEX_TOTAL_SIZE);
+		release_region(root_vortex_dev->base_addr,
+					   pci_tbl[vp->chip_id].io_size);
 		kfree(root_vortex_dev);
+		kfree(vp->priv_addr);
 		root_vortex_dev = next_dev;
 	}
 }
@@ -2177,7 +2131,7 @@
  * Local variables:
  *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
  *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c"
- *  compile-command-alt1: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c -o 3c59x_cb.o"
+ *  cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c -o 3c575_cb.o -I/usr/src/pcmcia-cs-3.0.5/include/"
  *  c-indent-level: 4
  *  c-basic-offset: 4
  *  tab-width: 4
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/82596.c linux/drivers/net/82596.c
--- v2.2.0-pre5/linux/drivers/net/82596.c	Thu Sep 17 17:53:36 1998
+++ linux/drivers/net/82596.c	Thu Jan  7 08:46:59 1999
@@ -67,7 +67,7 @@
 #endif
 
 /*
- * Define various macros for Channel Attention, word swapping etc., dependant
+ * Define various macros for Channel Attention, word swapping etc., dependent
  * on architecture.  MVME and BVME are 680x0 based, otherwise it is Intel.
  */
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.2.0-pre5/linux/drivers/net/8390.c	Mon Dec 28 15:00:52 1998
+++ linux/drivers/net/8390.c	Thu Jan  7 08:47:54 1999
@@ -1107,6 +1107,12 @@
 
 #ifdef MODULE
 
+EXPORT_SYMBOL(ei_open);
+EXPORT_SYMBOL(ei_close);
+EXPORT_SYMBOL(ei_interrupt);
+EXPORT_SYMBOL(ethdev_init);
+EXPORT_SYMBOL(NS8390_init);
+
 struct module *NS8390_module = NULL;
 
 int init_module(void)
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.2.0-pre5/linux/drivers/net/Makefile	Thu Dec 31 10:29:00 1998
+++ linux/drivers/net/Makefile	Thu Jan  7 08:47:54 1999
@@ -826,7 +826,7 @@
 L_OBJS += 8390.o
 else
   ifdef CONFIG_8390_MODULE
-  M_OBJS += 8390.o
+  MX_OBJS += 8390.o
   endif
 endif
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/acenic.c linux/drivers/net/acenic.c
--- v2.2.0-pre5/linux/drivers/net/acenic.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/acenic.c	Thu Jan  7 12:25:09 1999
@@ -7,6 +7,11 @@
  * Thanks to Alteon and 3Com for providing hardware and documentation
  * enabling me to write this driver.
  *
+ * A mailing list for discussing the use of this driver has been
+ * setup, please subscribe to the lists if you have any questions
+ * about the driver. Send mail to linux-acenic-help@sunsite.auc.dk to
+ * see how to subscribe.
+ *
  * 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
@@ -57,10 +62,6 @@
  * firmware. Also the programming interface is quite neat, except for
  * the parts dealing with the i2c eeprom on the card ;-)
  *
- * A number of standard Ethernet receive skb's are now allocated at
- * init time and not released before the driver is unloaded. This
- * makes it possible to do ifconfig down/up.
- *
  * Using jumbo frames:
  *
  * To enable jumbo frames, simply specify an mtu between 1500 and 9000
@@ -132,7 +133,7 @@
 static int max_tx_desc[8] = {0, };
 static int max_rx_desc[8] = {0, };
 
-static const char *version = "acenic.c: v0.19 12/17/98  Jes Sorensen (Jes.Sorensen@cern.ch)\n";
+static const char *version = "acenic.c: v0.22 01/07/99  Jes Sorensen (Jes.Sorensen@cern.ch)\n";
 
 static struct device *root_dev = NULL;
 
@@ -143,37 +144,28 @@
 	static int i = 0;
 	int boards_found = 0;
 	int version_disp;
-	u32 tmp;
 	struct ace_private *ap;
+	u8 pci_latency;
+#if 0
 	u16 vendor, device;
 	u8 pci_bus;
 	u8 pci_dev_fun;
-	u8 pci_latency;
 	u8 irq;
+#endif
+	struct pci_dev *pdev = NULL;
 
 	if (!pci_present())		/* is PCI support present? */
 		return -ENODEV;
 
 	version_disp = 0;
 
-	for (; i < 255; i++)
+	while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev)))
 	{
 		dev = NULL;
 
-		if (pcibios_find_class(PCI_CLASS_NETWORK_ETHERNET << 8,
-				       i, &pci_bus, &pci_dev_fun) !=
-		    PCIBIOS_SUCCESSFUL)
-			break;
-
-		pcibios_read_config_word(pci_bus, pci_dev_fun,
-					 PCI_VENDOR_ID, &vendor);
-
-		pcibios_read_config_word(pci_bus, pci_dev_fun,
-					 PCI_DEVICE_ID, &device);
-
-		if ((vendor != PCI_VENDOR_ID_ALTEON) &&
-		    !((vendor == PCI_VENDOR_ID_3COM) &&
-		      (device == PCI_DEVICE_ID_3COM_3C985)))
+		if ((pdev->vendor != PCI_VENDOR_ID_ALTEON) &&
+		    !((pdev->vendor == PCI_VENDOR_ID_3COM) &&
+		      (pdev->device == PCI_DEVICE_ID_3COM_3C985)))
 			continue;
 
 		dev = init_etherdev(dev, sizeof(struct ace_private));
@@ -188,37 +180,12 @@
 			dev->priv = kmalloc(sizeof(*ap), GFP_KERNEL);
 
 		ap = dev->priv;
-		ap->vendor = vendor;
-
-		/* Read register base address from
-		   PCI Configuration Space */
+		ap->pdev = pdev;
+		ap->vendor = pdev->vendor;
 
-		pcibios_read_config_dword(pci_bus, pci_dev_fun,
-					  PCI_BASE_ADDRESS_0, &tmp);
+		pci_set_master(pdev);
 
-		pcibios_read_config_byte(pci_bus, pci_dev_fun,
-					 PCI_INTERRUPT_LINE, &irq);
-
-		pcibios_read_config_word(pci_bus, pci_dev_fun,
-					 PCI_COMMAND, &ap->pci_command);
-
-		if (!(ap->pci_command & PCI_COMMAND_MASTER)){
-			ap->pci_command |= PCI_COMMAND_MASTER;
-
-			pcibios_write_config_word(pci_bus, pci_dev_fun,
-						  PCI_COMMAND,
-						  ap->pci_command);
-		}
-
-		if (!(ap->pci_command & PCI_COMMAND_MEMORY)){
-			printk(KERN_ERR "Shared mem not enabled - "
-			       "unable to configure AceNIC\n");
-			break;
-		}
-
-		dev->irq = irq;
-		ap->pci_bus = pci_bus;
-		ap->pci_dev_fun = pci_dev_fun;
+		dev->irq = pdev->irq;
 #ifdef __SMP__
 		spin_lock_init(&ap->lock);
 #endif
@@ -245,13 +212,13 @@
 			printk(version);
 		}
 
-		pcibios_read_config_byte(pci_bus, pci_dev_fun,
-					 PCI_LATENCY_TIMER, &pci_latency);
+		pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command);
+
+		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 		if (pci_latency <= 0x40){
 			pci_latency = 0x40;
-			pcibios_write_config_byte(pci_bus, pci_dev_fun,
-						  PCI_LATENCY_TIMER,
-						  pci_latency);
+			pci_write_config_byte(pdev, PCI_LATENCY_TIMER,
+					      pci_latency);
 		}
 
 		switch(ap->vendor){
@@ -268,14 +235,15 @@
 			printk(KERN_INFO "%s: Unknown AceNIC ", dev->name);
 			break;
 		}
-		printk("Gigabit Ethernet at 0x%08x, irq %i, PCI latency %i "
-		       "clks\n", tmp, dev->irq, pci_latency);
+		printk("Gigabit Ethernet at 0x%08lx, irq %i, PCI latency %i "
+		       "clks\n", pdev->base_address[0], dev->irq, pci_latency);
 
 		/*
 		 * Remap the regs into kernel space.
 		 */
 
-		ap->regs = (struct ace_regs *)ioremap(tmp, 0x4000);
+		ap->regs = (struct ace_regs *)ioremap(pdev->base_address[0],
+						      0x4000);
 		if (!ap->regs){
 			printk(KERN_ERR "%s:  Unable to map I/O register, "
 			       "AceNIC %i will be disabled.\n", dev->name, i);
@@ -404,7 +372,7 @@
 	struct ace_private *ap;
 	struct ace_regs *regs;
 	struct ace_info *info;
-	u32 tig_ver, mac1 = 0, mac2 = 0, tmp;
+	u32 tig_ver, mac1, mac2, tmp;
 	unsigned long tmp_ptr, myjif;
 	short i;
 
@@ -471,10 +439,12 @@
 		return -ENODEV;
 	}
 
+	mac1 = 0;
 	for(i = 0; i < 4; i++){
 		mac1 = mac1 << 8;
 		mac1 |= read_eeprom_byte(regs, 0x8c+i);
 	}
+	mac2 = 0;
 	for(i = 4; i < 8; i++){
 		mac2 = mac2 << 8;
 		mac2 |= read_eeprom_byte(regs, 0x8c+i);
@@ -527,10 +497,8 @@
 				       "supported, PCI write and invalidate "
 				       "disabled\n", L1_CACHE_BYTES);
 				ap->pci_command &= ~PCI_COMMAND_INVALIDATE;
-				pcibios_write_config_word(ap->pci_bus,
-							  ap->pci_dev_fun,
-							  PCI_COMMAND,
-							  ap->pci_command);
+				pci_write_config_word(ap->pdev, PCI_COMMAND,
+						      ap->pci_command);
 			}
 		}
 	}
@@ -646,10 +614,6 @@
 #if 0
 {
 	u32 tmp;
-	tmp = regs->AssistState;
-	tmp &= ~2;
-	tmp |= 1;
-	regs->AssistState = tmp;
 
 	tmp = regs->MacRxState;
 	tmp &= ~4;
@@ -659,35 +623,43 @@
 
 	regs->TuneStatTicks = 2 * TICKS_PER_SEC;
 
-	if ((board_idx < 8) && tx_coal_tick[board_idx])
-		regs->TuneTxCoalTicks = tx_coal_tick[board_idx] *
-			TICKS_PER_SEC / 1000;
-	else
+	if (board_idx >= 0) {
+		if ((board_idx < 8) && tx_coal_tick[board_idx])
+			regs->TuneTxCoalTicks = tx_coal_tick[board_idx] *
+				TICKS_PER_SEC / 1000;
+		else
+			regs->TuneTxCoalTicks = TICKS_PER_SEC / 500;
+		if ((board_idx < 8) && max_tx_desc[board_idx])
+			regs->TuneMaxTxDesc = max_tx_desc[board_idx];
+		else
+			regs->TuneMaxTxDesc = 7;
+
+		if ((board_idx < 8) && rx_coal_tick[board_idx])
+			regs->TuneRxCoalTicks = rx_coal_tick[board_idx] *
+				TICKS_PER_SEC / 1000;
+		else
+			regs->TuneRxCoalTicks = TICKS_PER_SEC / 10000;
+		if ((board_idx < 8) && max_rx_desc[board_idx])
+			regs->TuneMaxRxDesc = max_rx_desc[board_idx];
+		else
+			regs->TuneMaxRxDesc = 2;
+
+		if (board_idx < 8)
+			regs->TuneTrace = trace[board_idx];
+		else
+			regs->TuneTrace = 0;
+	}else{
 		regs->TuneTxCoalTicks = TICKS_PER_SEC / 500;
-	if ((board_idx < 8) && max_tx_desc[board_idx])
-		regs->TuneMaxTxDesc = max_tx_desc[board_idx];
-	else
 		regs->TuneMaxTxDesc = 7;
-
-	if ((board_idx < 8) && rx_coal_tick[board_idx])
-		regs->TuneRxCoalTicks = rx_coal_tick[board_idx] *
-			TICKS_PER_SEC / 1000;
-	else
 		regs->TuneRxCoalTicks = TICKS_PER_SEC / 10000;
-	if ((board_idx < 8) && max_rx_desc[board_idx])
-		regs->TuneMaxRxDesc = max_rx_desc[board_idx];
-	else
 		regs->TuneMaxRxDesc = 2;
-
-	if (board_idx < 8)
-		regs->TuneTrace = trace[board_idx];
-	else
 		regs->TuneTrace = 0;
+	}
 
 	tmp = LNK_ENABLE;
 
-	if ((board_idx > 7) || !(link[board_idx])){
-		if (board_idx > 8)
+	if ((board_idx > 7) || (board_idx < 0) || !(link[board_idx])){
+		if (board_idx > 7)
 			printk(KERN_WARNING "%s: more then 8 NICs detected, "
 			       "ignoring link options!\n", dev->name);
 		/*
@@ -700,6 +672,7 @@
 			tmp |= LNK_TX_FLOW_CTL_Y;
 	} else {
 		int option = link[board_idx];
+
 		if (option & 0x01){
 			printk(KERN_INFO "%s: Setting half duplex link\n",
 			       dev->name);
@@ -756,7 +729,7 @@
 	myjif = jiffies + 3 * HZ;
 	while (time_before(jiffies, myjif) && !ap->fw_running);
 	if (!ap->fw_running){
-		printk(KERN_ERR "%s: firmware NOT running!\n", dev->name);
+		printk(KERN_ERR "%s: Firmware NOT running!\n", dev->name);
 		ace_dump_trace(ap);
 		regs->CpuCtrl |= CPU_HALT;
 		return -EBUSY;
@@ -1501,11 +1474,14 @@
 }
 
 
-__initfunc(int ace_copy(struct ace_regs *regs, void *src, u32 dest, int size))
+__initfunc(void ace_copy(struct ace_regs *regs, void *src, u32 dest, int size))
 {
 	int tsize;
 	u32 tdest;
 
+	if (size <= 0)
+		return;
+
 	while(size > 0){
 		tsize = min(((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
 			    min(size, ACE_WINDOW_SIZE));
@@ -1524,15 +1500,18 @@
 		size -= tsize;
 	}
 
-	return 0;
+	return;
 }
 
 
-__initfunc(int ace_clear(struct ace_regs *regs, u32 dest, int size))
+__initfunc(void ace_clear(struct ace_regs *regs, u32 dest, int size))
 {
-	int tsize;
+	int tsize = 0;
 	u32 tdest;
 
+	if (size <= 0)
+		return;
+
 	while(size > 0){
 		tsize = min(((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
 			    min(size, ACE_WINDOW_SIZE));
@@ -1545,7 +1524,7 @@
 		size -= tsize;
 	}
 
-	return 0;
+	return;
 }
 
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/acenic.h linux/drivers/net/acenic.h
--- v2.2.0-pre5/linux/drivers/net/acenic.h	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/acenic.h	Thu Jan  7 12:25:09 1999
@@ -581,8 +581,11 @@
 	int			flags;
 	u16			vendor;
 	u16			pci_command;
+	struct pci_dev		*pdev;
+#if 0
 	u8			pci_bus;
 	u8			pci_dev_fun;
+#endif
 	char			name[24];
 	struct net_device_stats stats;
 };
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/acenic_firmware.h linux/drivers/net/acenic_firmware.h
--- v2.2.0-pre5/linux/drivers/net/acenic_firmware.h	Thu Jan  7 15:11:37 1999
+++ linux/drivers/net/acenic_firmware.h	Thu Jan  7 12:25:09 1999
@@ -2799,7 +2799,7 @@
 0x3c010001, 0x220821, 0xac317120, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, 
 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x0, 
 0x0 };
-u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __init = {
+u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = {
 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465, 0x6f6e2041, 
 0x63654e49, 0x43205600, 0x42424242, 0x0, 0x0, 0x0, 
 0x135430, 0x13e7fc, 0x0, 0x0, 0x0, 0x0, 
@@ -2814,7 +2814,7 @@
 0x12000060, 0x12000180, 0x120001e0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x30001, 0x1, 
 0x30201, 0x0, 0x0 };
-u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __init = {
+u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 
 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f66, 0x776d6169, 
 0x6e2e632c, 0x7620312e, 0x312e322e, 0x31312031, 0x3939382f, 0x30342f32, 
@@ -2939,7 +2939,7 @@
 int tigon2FwBssLen = 0x20c0;
 u32 tigon2FwSbssAddr = 0x134a0;
 int tigon2FwSbssLen = 0xa8;
-u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __init = {
+u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
 0x0, 0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, 
 0x8fbd3380, 0x3a0f021, 0x3c100000, 0x26104000, 0xc0010c0, 0x0, 
 0xd, 0x3c1d0001, 0x8fbd3384, 0x3a0f021, 0x3c100000, 0x26104000, 
@@ -5391,7 +5391,7 @@
 0xaf820044, 0x8f820044, 0x451024, 0xaf820044, 0x24630001, 0x28620008, 
 0x5440ffee, 0x641007, 0x3e00008, 0x0, 0x0, 0x0, 
 0x0 };
-u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __init = {
+u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __initdata = {
 0x1, 0x1, 0x1, 0xc001fc, 0x3ffc, 0xc00000, 
 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x0, 0x0, 
 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242, 0x0, 
@@ -5408,7 +5408,7 @@
 0x12000060, 0x12000180, 0x120001e0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x30001, 0x1, 
 0x30201, 0x0, 0x0 };
-u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __init = {
+u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 
 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x66776d61, 
 0x696e2e63, 0x2c762031, 0x2e312e34, 0x372e3420, 0x31393938, 0x2f31302f, 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/ariadne2.c linux/drivers/net/ariadne2.c
--- v2.2.0-pre5/linux/drivers/net/ariadne2.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/ariadne2.c	Thu Jan  7 08:41:54 1999
@@ -33,6 +33,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/amigaints.h>
+#include <asm/amigahw.h>
 
 #include "8390.h"
 
@@ -417,7 +418,7 @@
     unsigned int key = ((struct ei_device *)ariadne2_dev.priv)->priv;
     free_irq(IRQ_AMIGA_PORTS, &ariadne2_dev);
     unregister_netdev(&ariadne2_dev);
-    zorro_config_board(key, 0);
+    zorro_unconfig_board(key, 0);
     unlock_8390_module();
 }
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/at1700.c linux/drivers/net/at1700.c
--- v2.2.0-pre5/linux/drivers/net/at1700.c	Fri Nov 27 13:09:23 1998
+++ linux/drivers/net/at1700.c	Thu Jan  7 08:47:54 1999
@@ -838,10 +838,12 @@
 {
 	struct net_local *lp = dev_at1700.priv;
 	unregister_netdev(&dev_at1700);
+#ifdef CONFIG_MCA	
 	if(lp->mca_slot)
 	{
 		mca_mark_as_unused(lp->mca_slot);
 	}
+#endif	
 	kfree(dev_at1700.priv);
 	dev_at1700.priv = NULL;
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/cops.h linux/drivers/net/cops.h
--- v2.2.0-pre5/linux/drivers/net/cops.h	Thu Jun 26 12:33:39 1997
+++ linux/drivers/net/cops.h	Thu Jan  7 08:46:59 1999
@@ -34,7 +34,7 @@
 /* Same on both card types */
 #define COPS_CLEAR_INT  1
 
-/* LAP response codes recieved from the cards. */
+/* LAP response codes received from the cards. */
 #define LAP_INIT        1       /* Init cmd */
 #define LAP_INIT_RSP    2       /* Init response */
 #define LAP_WRITE       3       /* Write cmd */
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/dgrs_i82596.h linux/drivers/net/dgrs_i82596.h
--- v2.2.0-pre5/linux/drivers/net/dgrs_i82596.h	Sat Dec 21 07:23:21 1996
+++ linux/drivers/net/dgrs_i82596.h	Thu Jan  7 08:46:59 1999
@@ -393,7 +393,7 @@
 	/* cmd halfword values */
 #define	I596_SCB_ACK		0xF000	/* ACKNOWLEDGMENTS */
 #define	I596_SCB_ACK_CX		0x8000	/* Ack command completion */
-#define	I596_SCB_ACK_FR		0x4000	/* Ack recieved frame */
+#define	I596_SCB_ACK_FR		0x4000	/* Ack received frame */
 #define	I596_SCB_ACK_CNA	0x2000	/* Ack command unit not active */
 #define	I596_SCB_ACK_RNR	0x1000	/* Ack rcv unit not ready */
 #define	I596_SCB_ACK_ALL	0xF000	/* Ack everything */
@@ -419,7 +419,7 @@
 	/* status halfword values */
 #define	I596_SCB_STAT		0xF000	/* STATUS */
 #define	I596_SCB_CX		0x8000	/* command completion */
-#define	I596_SCB_FR		0x4000	/* recieved frame */
+#define	I596_SCB_FR		0x4000	/* received frame */
 #define	I596_SCB_CNA		0x2000	/* command unit not active */
 #define	I596_SCB_RNR		0x1000	/* rcv unit not ready */
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/eepro.c linux/drivers/net/eepro.c
--- v2.2.0-pre5/linux/drivers/net/eepro.c	Thu Dec 31 10:29:00 1998
+++ linux/drivers/net/eepro.c	Thu Jan  7 08:47:54 1999
@@ -23,10 +23,15 @@
 	This is a compatibility hardware problem.
 
 	Versions:
-	0.11b   Pascal Dupuis : works as a module under 2.1.xx
-	        debug messages are flagged as KERN_DEBUG to avoid console 
-		flooding 
-		added locking at critical parts
+	0.11d	added __initdata, __initfunc stuff; call spin_lock_init
+	        in eepro_probe1. Replaced "eepro" by dev->name. Augmented 
+		the code protected by spin_lock in interrupt routine 
+		(PdP, 12/12/1998)
+	0.11c   minor cleanup (PdP, RMC, 09/12/1998)  
+	0.11b   Pascal Dupuis (dupuis@lei.ucl.ac.be): works as a module 
+	        under 2.1.xx. Debug messages are flagged as KERN_DEBUG to 
+		avoid console flooding. Added locking at critical parts. Now 
+		the dawn thing is SMP safe.
 	0.11a   Attempt to get 2.1.xx support up (RMC)
 	0.11	Brian Candler added support for multiple cards. Tested as
 		a module, no idea if it works when compiled into kernel.
@@ -87,7 +92,7 @@
 */
 
 static const char *version =
-	"eepro.c: v0.11b 08/12/1998 dupuis@lei.ucl.ac.be\n";
+	"eepro.c: v0.11d 08/12/1998 dupuis@lei.ucl.ac.be\n";
 
 #include <linux/module.h>
 
@@ -127,9 +132,6 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-#include <asm/spinlock.h>
-#endif
 #include <linux/errno.h>
 
 #include <linux/netdevice.h>
@@ -147,6 +149,7 @@
 /* For linux 2.1.xx */
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
 
+#include <asm/spinlock.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 
@@ -154,6 +157,8 @@
 /* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
 #define SLOW_DOWN inb(0x80)
 /* udelay(2) */
+#define compat_init_func(X)  __initfunc(X)
+#define compat_init_data     __initdata
 
 #else 
 /* for 2.x */
@@ -161,13 +166,15 @@
 #define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb), (mode) )
 #define test_and_set_bit(a,b) set_bit((a),(b))
 #define SLOW_DOWN SLOW_DOWN_IO
+#define compat_init_func(X) X
+#define compat_init_data
 
 #endif
 
 
 /* First, a few definitions that the brave might change. */
 /* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int eepro_portlist[] =
+static unsigned int eepro_portlist[] compat_init_data =
    { 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
 /* note: 0x300 is default, the 595FX supports ALL IO Ports 
   from 0x000 to 0x3F0, some of which are reserved in PCs */
@@ -205,7 +212,7 @@
 				   version of the 82595 chip. */
 	int stepping;
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-        spinlock_t lock; /* to prevent interrupt within interrupts */ 
+	spinlock_t lock; /* Serializing lock  */ 
 #endif
 };
 
@@ -313,7 +320,7 @@
 static int	eepro_grab_irq(struct device *dev);
 
 /*
-  			Details of the i82595.
+			Details of the i82595.
 
 You will need either the datasheet or the user manual to understand what
 is going on here.  The 82595 is very different from the 82586, 82593.
@@ -344,7 +351,7 @@
 */
 #define	RAM_SIZE	0x8000
 #define	RCV_HEADER	8
-#define RCV_RAM         0x6000  /* 24KB default for RCV buffer */
+#define RCV_RAM 	0x6000  /* 24KB default for RCV buffer */
 #define RCV_LOWER_LIMIT 0x00    /* 0x0000 */
 /* #define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) */    /* 0x5ffe */
 #define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8)   
@@ -454,8 +461,7 @@
 struct netdev_entry netcard_drv =
 {"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};
 #else
-int
-eepro_probe(struct device *dev)
+compat_init_func(int eepro_probe(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -467,9 +473,9 @@
 	/* Wakeup: */
 	#define WakeupPort 0x279
 	#define WakeupSeq    {0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,\
-                              0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\
-                              0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\
-                              0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43}
+	                      0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\
+	                      0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\
+	                      0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43}
 
 	{
 		unsigned short int WS[32]=WakeupSeq;
@@ -485,19 +491,21 @@
 				outb_p(WS[i],WakeupPort);
 				if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]);
 			}
-		} else printk("Checkregion Failed!\n");
+		} else printk(KERN_WARNING "Checkregion Failed!\n");
 	}
 #endif
 
 
 	if (base_addr > 0x1ff)		/* Check a single specified location. */
 		return eepro_probe1(dev, base_addr);
+
 	else if (base_addr != 0)	/* Don't probe at all. */
 		return ENXIO;
 
 
 	for (i = 0; eepro_portlist[i]; i++) {
 		int ioaddr = eepro_portlist[i];
+
 		if (check_region(ioaddr, EEPRO_IO_EXTENT))
 			continue;
 		if (eepro_probe1(dev, ioaddr) == 0)
@@ -512,11 +520,11 @@
 {
 	unsigned short Word;
 	int i,j;
-  
+
 	for (i=0, j=ee_Checksum; i<ee_SIZE; i++)
 		j+=read_eeprom(ioaddr,i);
 	printk("Checksum: %#x\n",j&0xffff);
-     
+
 	Word=read_eeprom(ioaddr, 0);
 	printk(KERN_DEBUG "Word0:\n");
 	printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));
@@ -533,10 +541,10 @@
 		printk(KERN_DEBUG " TPE/AUI: %d\n", GetBit(Word,ee_TPE_AUI));
 		printk(KERN_DEBUG " Jabber: %d\n", GetBit(Word,ee_Jabber));
 		printk(KERN_DEBUG " AutoPort: %d\n", GetBit(!Word,ee_Jabber));
-		printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));  
+		printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
 	}
 
-  Word=read_eeprom(ioaddr, 5);
+	Word=read_eeprom(ioaddr, 5);
 	printk(KERN_DEBUG "Word5:\n");
 	printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
 	printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
@@ -546,18 +554,19 @@
 	if (GetBit(Word,ee_PortAUI)) printk("AUI ");
 	printk("port(s) \n");
 
-  Word=read_eeprom(ioaddr, 6);
+	Word=read_eeprom(ioaddr, 6);
 	printk(KERN_DEBUG "Word6:\n");
 	printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask);
 	printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID);
 
-  Word=read_eeprom(ioaddr, 7);
+	Word=read_eeprom(ioaddr, 7);
 	printk(KERN_DEBUG "Word7:\n");
 	printk(KERN_DEBUG " INT to IRQ:\n");
 
 	printk(KERN_DEBUG);
-  for (i=0, j=0; i<15; i++)
-     if (GetBit(Word,i)) printk(" INT%d -> IRQ %d;",j++,i);
+
+	for (i=0, j=0; i<15; i++)
+		if (GetBit(Word,i)) printk(" INT%d -> IRQ %d;",j++,i);
 
 	printk("\n");
 }
@@ -577,11 +586,10 @@
 	/* Now, we are going to check for the signature of the
 	   ID_REG (register 2 of bank 0) */
 
-
- id=inb(ioaddr + ID_REG);
+	id=inb(ioaddr + ID_REG);
  
- printk(KERN_DEBUG " id: %#x ",id);
- printk(" io: %#x ",ioaddr);
+	printk(KERN_DEBUG " id: %#x ",id);
+	printk(" io: %#x ",ioaddr);
  
 	if (((id) & ID_REG_MASK) == ID_REG_SIG) {
 
@@ -606,7 +614,7 @@
 			if (net_debug>3)
 				printEEPROMInfo(ioaddr);
 				
-		        if (read_eeprom(ioaddr,7)== ee_FX_INT2IRQ) { /* int to IRQ Mask */
+			if (read_eeprom(ioaddr,7)== ee_FX_INT2IRQ) { /* int to IRQ Mask */
 				eepro = 2;
 				printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", 
 					dev->name, ioaddr);
@@ -622,7 +630,7 @@
 					dev->name, ioaddr);
 			}
 
-   			/* Fill in the 'dev' fields. */
+			/* Fill in the 'dev' fields. */
 			dev->base_addr = ioaddr;
 			
 			for (i=0; i < 6; i++) {
@@ -641,24 +649,13 @@
 				printk(", %dK RCV buffer", (int)(dev->mem_end)/1024);
 				
 				
-//			outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
-//			id = inb(ioaddr + REG3);
-//			if (id & TPE_BIT)
-//				dev->if_port = TPE;
-//			else dev->if_port = BNC;
-			
-			
 			/* ............... */
 
-			if (GetBit(  read_eeprom(ioaddr, 5),ee_BNC_TPE))
+			if (GetBit( read_eeprom(ioaddr, 5),ee_BNC_TPE))
 				dev->if_port = BNC;
 			else dev->if_port = TPE;
-                
-			
-			/* ............... */
 
-//			if (net_debug>3) 
-//				printk("id: %x\n", id);
+			/* ............... */
 
 
 			if ((dev->irq < 2) && (eepro!=0)) {
@@ -668,14 +665,14 @@
 				
 				for (j=0; ((j<16) && (i>=0)); j++) {
 					if ((irqMask & (1<<j))!=0) {
-					        if (i==0) {
-					        	dev->irq = j;
-					        	break; /* found bit corresponding to irq */
-					        }
+						if (i==0) {
+							dev->irq = j;
+							break; /* found bit corresponding to irq */
+						}
 						i--; /* count bits set in irqMask */
- 					}
- 				}
- 				if (dev -> irq<2) {
+					}
+				}
+				if (dev -> irq<2) {
 					printk(" Duh! illegal interrupt vector stored in EEPROM.\n");
 						return ENODEV;
 				} else 
@@ -685,14 +682,10 @@
 				else if (dev->irq == 2)
 				dev->irq = 9;
 			}
-
+			
 			if (dev->irq > 2) {
 				printk(", IRQ %d, %s.\n", dev->irq,
 						ifmap[dev->if_port]);
-				/*if (request_irq(dev->irq, &eepro_interrupt, 0, "eepro", dev)) {
-					printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
-					return -EAGAIN;
-				}*/
 			}
 			else printk(", %s.\n", ifmap[dev->if_port]);
 			
@@ -702,7 +695,7 @@
 			if (net_debug > 3) {
 				i = read_eeprom(ioaddr, 5);
 				if (i & 0x2000) /* bit 13 of EEPROM word 5 */
-				  printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n",
+					printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n",
 						dev->name);
 			}
 
@@ -710,7 +703,7 @@
 				printk(version);
 
 			/* Grab the region so we can find another board if autoIRQ fails. */
-			request_region(ioaddr, EEPRO_IO_EXTENT, "eepro");
+			request_region(ioaddr, EEPRO_IO_EXTENT, dev->name);
 
 			/* Initialize the device structure */
 			dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL);
@@ -718,6 +711,9 @@
 				return -ENOMEM;
 			memset(dev->priv, 0, sizeof(struct eepro_local));
 
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+			spin_lock_init(&(((struct eepro_local *)dev->priv)->lock));
+#endif
 			dev->open               = eepro_open;
 			dev->stop               = eepro_close;
 			dev->hard_start_xmit    = eepro_send_packet;
@@ -754,11 +750,8 @@
 {
 	int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12 };
 	int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr;
-
-	outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
 	
-	/* Set the spinlock before activating  IRQ! */
-	((struct eepro_local *)dev->priv)->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+	outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
 
 	/* Enable the interrupt line. */
 	temp_reg = inb(ioaddr + REG1);
@@ -768,6 +761,7 @@
 
 	/* clear all interrupts */
 	outb(ALL_MASK, ioaddr + STATUS_REG);
+
 	/* Let EXEC event to interrupt */
 	outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG);
 
@@ -785,11 +779,8 @@
 
 			outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */
 				
-			if (*irqp == autoirq_report(2) )//&&  /* It's a good IRQ line */
-				/* We don't take irqs on detection anymore.
-					only when actually turning on the driver (ifconfig) */
-				/* //(request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro", dev) == 0)) */
-					break;
+			if (*irqp == autoirq_report(2))  /* It's a good IRQ line */
+				break;
 
 			/* clear all interrupts */
 			outb(ALL_MASK, ioaddr + STATUS_REG); 
@@ -821,14 +812,14 @@
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 
 	if (net_debug > 3)
-		printk(KERN_DEBUG "eepro: entering eepro_open routine.\n");
+		printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name);
 
 	if ((irqMask=read_eeprom(ioaddr,7))== ee_FX_INT2IRQ) /* INT to IRQ Mask */
 		{
-		  	lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
-		  	if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n"); 
+			lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
+			if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n"); 
 		}
-       
+
 	else if ((dev->dev_addr[0] == SA_ADDR0 &&
 			dev->dev_addr[1] == SA_ADDR1 &&
 			dev->dev_addr[2] == SA_ADDR2))
@@ -845,7 +836,7 @@
 		return -EAGAIN;
 	}
 		
-	if (request_irq(dev->irq , &eepro_interrupt, 0, "eepro", dev)) {
+	if (request_irq(dev->irq , &eepro_interrupt, 0, dev->name, dev)) {
 		printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
 		return -EAGAIN;
 	}
@@ -854,8 +845,8 @@
 	if  (((irq2dev_map[dev->irq] != 0)
 		|| (irq2dev_map[dev->irq] = dev) == 0) && 
 		(irq2dev_map[dev->irq]!=dev)) {
-	    /* printk("%s: IRQ map wrong\n", dev->name); */
-	 	return -EAGAIN;
+		/* printk("%s: IRQ map wrong\n", dev->name); */
+		return -EAGAIN;
 	}
 #endif
 
@@ -894,15 +885,14 @@
 	else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); 
 
 
-    temp_reg = inb(ioaddr + INT_NO_REG);
-    if (lp->eepro == 2)
-       outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
-    else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
-
-    if (net_debug > 3)
-       printk(KERN_DEBUG "eepro_open: content of INT Reg is %x\n", temp_reg);
-       
-       
+	temp_reg = inb(ioaddr + INT_NO_REG);
+	if (lp->eepro == 2)
+		outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
+	else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
+
+	if (net_debug > 3)
+		printk(KERN_DEBUG "eepro_open: content of INT Reg is %x\n", temp_reg);
+
 
 	/* Initialize the RCV and XMT upper and lower limits */
 	outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG); 
@@ -918,6 +908,7 @@
 
 	/* Let RX and TX events to interrupt */
 	outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
+
 	/* clear all interrupts */
 	outb(ALL_MASK, ioaddr + STATUS_REG); 
 
@@ -932,6 +923,7 @@
 	/* Check for the i82595TX and i82595FX */
 	old8 = inb(ioaddr + 8);
 	outb(~old8, ioaddr + 8);
+
 	if ((temp_reg = inb(ioaddr + 8)) == old8) {
 		if (net_debug > 3)
 			printk(KERN_DEBUG "i82595 detected!\n");
@@ -965,25 +957,26 @@
 			}
 		}
 		else if (net_debug > 3) {
-		        printk(KERN_DEBUG "temp_reg: %#x  ~old9: %#x\n",temp_reg,((~old9)&0xff));
+			printk(KERN_DEBUG "temp_reg: %#x  ~old9: %#x\n",temp_reg,((~old9)&0xff));
 			printk(KERN_DEBUG "i82595TX detected!\n");
 		}
 	}
 	
 	outb(SEL_RESET_CMD, ioaddr);
+
 	/* We are supposed to wait for 2 us after a SEL_RESET */
 	SLOW_DOWN;
 	SLOW_DOWN;
 
 	lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */
-	lp->tx_last = 0;  
+	lp->tx_last = 0;
 	
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
 
 	if (net_debug > 3)
-		printk(KERN_DEBUG "eepro: exiting eepro_open routine.\n");
+		printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name);
 
 	outb(RCV_ENABLE_CMD, ioaddr);
 
@@ -997,39 +990,43 @@
 	int ioaddr = dev->base_addr;
 	int rcv_ram = dev->mem_end;
 
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+	unsigned long flags;
+#endif
+	
 	if (net_debug > 5)
-	  printk(KERN_DEBUG  "eepro: entering eepro_send_packet routine.\n");
+		printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", dev->name);
 	
 	if (dev->tbusy) {
-	  /* If we get here, some higher level has decided we are broken.
-	     There should really be a "kick me" function call instead. */
-	  int tickssofar = jiffies - dev->trans_start;
-	  if (tickssofar < 40)
-	    return 1;
-	 
-	  /* if (net_debug > 1) */
-	  printk("%s: transmit timed out, %s?\n", dev->name, 
-		 "network cable problem");
-	  /* This is not a duplicate. One message for the console, one for the
-	     the log file  */
-	  printk(KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
-		 "network cable problem");
-	  lp->stats.tx_errors++;
-
-	  /* Try to restart the adaptor. */
-	  outb(SEL_RESET_CMD, ioaddr); 
-	  /* We are supposed to wait for 2 us after a SEL_RESET */
-	  SLOW_DOWN;
-	  SLOW_DOWN;
-	  
-	  /* Do I also need to flush the transmit buffers here? YES? */
-	  lp->tx_start = lp->tx_end = rcv_ram; 
-	  lp->tx_last = 0;
-	
-	  dev->tbusy=0;
-	  dev->trans_start = jiffies;
-	  
-	  outb(RCV_ENABLE_CMD, ioaddr);
+		/* If we get here, some higher level has decided we are broken.
+		   There should really be a "kick me" function call instead. */
+		int tickssofar = jiffies - dev->trans_start;
+		if (tickssofar < 40)
+			return 1;
+	
+		/* if (net_debug > 1) */
+		printk(KERN_ERR "%s: transmit timed out, %s?\n", dev->name, 
+			"network cable problem");
+		/* This is not a duplicate. One message for the console, 
+		   one for the the log file  */
+		printk(KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
+			"network cable problem");
+		lp->stats.tx_errors++;
+
+		/* Try to restart the adaptor. */
+		outb(SEL_RESET_CMD, ioaddr); 
+		/* We are supposed to wait for 2 us after a SEL_RESET */
+		SLOW_DOWN;
+		SLOW_DOWN;
+
+		/* Do I also need to flush the transmit buffers here? YES? */
+		lp->tx_start = lp->tx_end = rcv_ram; 
+		lp->tx_last = 0;
+	
+		dev->tbusy=0;
+		dev->trans_start = jiffies;
+
+		outb(RCV_ENABLE_CMD, ioaddr);
 
 	}
 
@@ -1037,37 +1034,35 @@
 	/* If some higher layer thinks we've missed an tx-done interrupt
 	   we are passed NULL. Caution: dev_tint() handles the cli()/sti()
 	   itself. */
-	//	if (skb == NULL) {
-	//	dev_tint(dev);
-	//	return 0;
-	// FIXME : what's this code for ?
-	}
+	/*	if (skb == NULL) {
+		dev_tint(dev);
+	  	return 0;
+	}*/
+	/* according to A. Cox, this is obsolete since 1.0 */
 #endif
 
-	/* Block a timer-based transmit from overlapping. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
-	  printk("%s: Transmitter access conflict.\n", dev->name);
-	else {
-          short length; unsigned char *buf;
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-	  unsigned long flags;
-
-	  /* Spin on the lock, until we're clear of an IRQ */
-	  spin_lock_irqsave(&lp->lock, flags);     
+	spin_lock_irqsave(&lp->lock, flags);
 #endif
-	  length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-	  buf = skb->data;
+
+	/* Block a timer-based transmit from overlapping. */
+	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
 
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-	  lp->stats.tx_bytes+=skb->len;
+		spin_unlock_irqrestore(&lp->lock, flags);
 #endif
-	  hardware_send_packet(dev, buf, length);
-	  
-	  dev->trans_start = jiffies;
+	} else {
+		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+		unsigned char *buf = skb->data;
 
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-	  spin_unlock_irqrestore(&lp->lock, flags);     
-#endif	
+		lp->stats.tx_bytes+=skb->len;
+#endif
+
+		hardware_send_packet(dev, buf, length);
+		dev->trans_start = jiffies;
+
 	}
 
 	compat_dev_kfree_skb (skb, FREE_WRITE);
@@ -1076,75 +1071,83 @@
 	/* lp->stats.tx_aborted_errors++; */
 
 	if (net_debug > 5)
-		printk(KERN_DEBUG "eepro: exiting eepro_send_packet routine.\n");
+		printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+	spin_unlock_irqrestore(&lp->lock, flags);
+#endif
 	
 	return 0;
 }
 
+
 /*	The typical workload of the driver:
 	Handle the network interface interrupts. */
+
 static void
 eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct device *dev =  (struct device *)dev_id;
 	                      /* (struct device *)(irq2dev_map[irq]);*/
-#ifdef __SMP__
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
-#endif	
 	int ioaddr, status, boguscount = 20;
 
-	if (test_and_set_bit(0, (void*)&dev->interrupt)) 
-	{
-		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-        		dev->name);
-		dev->interrupt = 0; /* Avoid halting machine. */
-        	return;
-	}
-
-	if (net_debug > 5)
-		printk(KERN_DEBUG "eepro: entering eepro_interrupt routine.\n");
-	
 	if (dev == NULL) {
-		printk ("eepro_interrupt(): irq %d for unknown device.\n", irq);
+                printk (KERN_ERR "eepro_interrupt(): irq %d for unknown device.\\n", irq);
+                return;
+        }
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+        spin_lock(&lp->lock);
+#endif
+
+	if (dev->interrupt) {
+		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+		spin_unlock(&lp->lock);
+		/* FIXME : with the lock, could this ever happen ? */
+#endif
+
 		return;
 	}
-	/* dev->interrupt = 1; */
+	dev->interrupt = 1;
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-	spin_lock(&lp->lock);
-#endif	
-        ioaddr = dev->base_addr;
+	if (net_debug > 5)
+		printk(KERN_DEBUG "%s: entering eepro_interrupt routine.\n", dev->name);
+	
+	ioaddr = dev->base_addr;
 
-        do { 
-	  status = inb(ioaddr + STATUS_REG);
+	do { 
+		status = inb(ioaddr + STATUS_REG);
 		
-	  if (status & RX_INT) {
-	    if (net_debug > 4)
-	      printk(KERN_DEBUG "eepro: packet received interrupt.\n");
-
-	    /* Acknowledge the RX_INT */
-	    outb(RX_INT, ioaddr + STATUS_REG);   
-	    /* Get the received packets */
-	    eepro_rx(dev);
-	  }
-
-	  else if (status & TX_INT) {
-	    if (net_debug > 4)
-	      printk(KERN_DEBUG "eepro: packet transmit interrupt.\n");
-
-	    /* Acknowledge the TX_INT */
-	    outb(TX_INT, ioaddr + STATUS_REG); 
-	    
-	    /* Process the status of transmitted packets */
-	    eepro_transmit_interrupt(dev);
-	  }
+		if (status & RX_INT) {
+			if (net_debug > 4)
+			printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name);
+
+			/* Acknowledge the RX_INT */
+			outb(RX_INT, ioaddr + STATUS_REG);
+			/* Get the received packets */
+			eepro_rx(dev);
+		}
+
+		else if (status & TX_INT) {
+			if (net_debug > 4)
+			printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name);
+
+			/* Acknowledge the TX_INT */
+			outb(TX_INT, ioaddr + STATUS_REG); 
+
+			/* Process the status of transmitted packets */
+			eepro_transmit_interrupt(dev);
+		}
 	
 	} while ((boguscount-- > 0) && (status & 0x06));
 
 	dev->interrupt = 0; 
 
 	if (net_debug > 5)
-		printk(KERN_DEBUG "eepro: exiting eepro_interrupt routine.\n");
+		printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name);
 
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
 	spin_unlock(&lp->lock);
@@ -1173,7 +1176,7 @@
 	/* Flush the Tx and disable Rx. */
 	outb(STOP_RCV_CMD, ioaddr); 
 	lp->tx_start = lp->tx_end = rcv_ram ;
-	lp->tx_last = 0;  
+	lp->tx_last = 0;
 
 	/* Mask all the interrupts. */
 	outb(ALL_MASK, ioaddr + INT_MASK_REG); 
@@ -1238,7 +1241,8 @@
 		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
 		outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
 		printk("%s: promiscuous mode enabled.\n", dev->name);
-	} 
+	}
+	
 	else if (dev->mc_count==0 ) 
 	{
 		outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
@@ -1248,6 +1252,7 @@
 		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
 		outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
 	}
+	
 	else 
 	{
 		unsigned short status, *eaddrs;
@@ -1269,6 +1274,7 @@
 		outw(0, ioaddr + IO_PORT);
 		outw(0, ioaddr + IO_PORT);
 		outw(6*(dev->mc_count + 1), ioaddr + IO_PORT);
+		
 		for (i = 0; i < dev->mc_count; i++) 
 		{
 			eaddrs=(unsigned short *)dmi->dmi_addr;
@@ -1277,6 +1283,7 @@
 			outw(*eaddrs++, ioaddr + IO_PORT);
 			outw(*eaddrs++, ioaddr + IO_PORT);
 		}
+		
 		eaddrs = (unsigned short *) dev->dev_addr;
 		outw(eaddrs[0], ioaddr + IO_PORT);
 		outw(eaddrs[1], ioaddr + IO_PORT);
@@ -1286,8 +1293,9 @@
 
 		/* Update the transmit queue */
 		i = lp->tx_end + XMT_HEADER + 6*(dev->mc_count + 1);
+		
 		if (lp->tx_start != lp->tx_end) 
-		{ 
+		{
 			/* update the next address and the chain bit in the 
 			   last packet */
 			outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
@@ -1309,14 +1317,15 @@
 			{
 				i = inb(ioaddr);
 				outb(0x08, ioaddr + STATUS_REG);
+				
 				if (i & 0x20) { /* command ABORTed */
 					printk("%s: multicast setup failed.\n", 
 						dev->name);
 					break;
 				} else if ((i & 0x0f) == 0x03)	{ /* MC-Done */
-				  printk("%s: set Rx mode to %d address%s.\n",
-					 dev->name, dev->mc_count,
-					 dev->mc_count > 1 ? "es":"");
+					printk("%s: set Rx mode to %d address%s.\n",
+						dev->name, dev->mc_count,
+						dev->mc_count > 1 ? "es":"");
 					break;
 				}
 			}
@@ -1333,7 +1342,7 @@
 /* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */
 
 /* The delay between EEPROM clock transitions. */
-#define eeprom_delay()	{ int _i = 40; while (--_i > 0) { SLOW_DOWN; }}
+#define eeprom_delay() { udelay(40); }
 #define EE_READ_CMD (6 << 6)
 
 int
@@ -1385,16 +1394,16 @@
 	unsigned status, tx_available, last, end, boguscount = 100;
 
 	if (net_debug > 5)
-		printk(KERN_DEBUG "eepro: entering hardware_send_packet routine.\n");
+		printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name);
 
 	while (boguscount-- > 0) {
 
 		/* Disable RX and TX interrupts.  Necessary to avoid
-	   	corruption of the HOST_ADDRESS_REG by interrupt
-	   	service routines. */
+		corruption of the HOST_ADDRESS_REG by interrupt
+		service routines. */
 		outb(ALL_MASK, ioaddr + INT_MASK_REG);
 
-		if (dev->interrupt == 1) {  
+		if (dev->interrupt == 1) {
 			/* Enable RX and TX interrupts */
 			outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
 			continue;
@@ -1421,12 +1430,15 @@
 		end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
 
 		if (end >= RAM_SIZE) { /* the transmit buffer is wrapped around */
+		
 			if ((RAM_SIZE - last) <= XMT_HEADER) {	
-			/* Arrrr!!!, must keep the xmt header together,
-			  several days were lost to chase this one down. */
+				/* Arrrr!!!, must keep the xmt header together,
+				several days were lost to chase this one down. */
+				
 				last = rcv_ram;
 				end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
-			}	
+			}
+			
 			else end = rcv_ram + (end - RAM_SIZE);
 		}
 
@@ -1454,18 +1466,20 @@
 			lp->tx_start = last;   /* I don't like to change tx_start here */
 		}
 		else {
-		  /* update the next address and the chain bit in the 
-		     last packet */
-		  if (lp->tx_end != last) {
-		    outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
-		    outw(last, ioaddr + IO_PORT); 
-		  }
-		  outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
-		  status = inw(ioaddr + IO_PORT); 
-		  outw(status | CHAIN_BIT, ioaddr + IO_PORT);
+			/* update the next address and the chain bit in the 
+			last packet */
+			
+			if (lp->tx_end != last) {
+				outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
+				outw(last, ioaddr + IO_PORT); 
+			}
+			
+			outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
+			status = inw(ioaddr + IO_PORT); 
+			outw(status | CHAIN_BIT, ioaddr + IO_PORT);
 
-		  /* Continue the transmit command */
-		  outb(RESUME_XMT_CMD, ioaddr);
+			/* Continue the transmit command */
+			outb(RESUME_XMT_CMD, ioaddr);
 		}
 
 		lp->tx_last = last;
@@ -1476,16 +1490,16 @@
 		}
 		
 		/* Enable RX and TX interrupts */
-                outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+		outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
 
 		if (net_debug > 5)
-			printk(KERN_DEBUG "eepro: exiting hardware_send_packet routine.\n");
+			printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
 		return;
 	}
 
 	dev->tbusy = 1;
 	if (net_debug > 5)
-		printk(KERN_DEBUG "eepro: exiting hardware_send_packet routine.\n");
+		printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
 }
 
 static void
@@ -1498,77 +1512,88 @@
 	unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
 
 	if (net_debug > 5)
-		printk(KERN_DEBUG "eepro: entering eepro_rx routine.\n");
+		printk(KERN_DEBUG "%s: entering eepro_rx routine.\n", dev->name);
 	
 	/* Set the read pointer to the start of the RCV */
 	outw(rcv_car, ioaddr + HOST_ADDRESS_REG);
+	
 	rcv_event = inw(ioaddr + IO_PORT);
 
 	while (rcv_event == RCV_DONE) {
-	  rcv_status = inw(ioaddr + IO_PORT); 
-	  rcv_next_frame = inw(ioaddr + IO_PORT);
-	  rcv_size = inw(ioaddr + IO_PORT); 
-
-	  if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) {
-	    /* Malloc up new buffer. */
-	    struct sk_buff *skb;
+	
+		rcv_status = inw(ioaddr + IO_PORT); 
+		rcv_next_frame = inw(ioaddr + IO_PORT);
+		rcv_size = inw(ioaddr + IO_PORT); 
+
+		if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) {
+		
+			/* Malloc up new buffer. */
+			struct sk_buff *skb;
 
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-	    lp->stats.rx_bytes+=rcv_size;
-#endif                        
-	    rcv_size &= 0x3fff;
-	    skb = dev_alloc_skb(rcv_size+5);
-	    if (skb == NULL) {
-	      printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-	      lp->stats.rx_dropped++;
-	      break;
-	    }
-	    skb->dev = dev;
-	    skb_reserve(skb,2);
-
-	    if (lp->version == LAN595)
-	      insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1);
-	    else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
-	      unsigned short temp = inb(ioaddr + INT_MASK_REG);
-	      outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
-	      insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size), 
-		   (rcv_size + 3) >> 2);
-	      outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
-	    }
-	
-	    skb->protocol = eth_type_trans(skb,dev);	
-	    netif_rx(skb);
-	    lp->stats.rx_packets++;
-	  }
-	  else { /* Not sure will ever reach here, 
-		    I set the 595 to discard bad received frames */
-	    lp->stats.rx_errors++;
-	    if (rcv_status & 0x0100)
-	      lp->stats.rx_over_errors++;
-	    else if (rcv_status & 0x0400)
-	      lp->stats.rx_frame_errors++;
-	    else if (rcv_status & 0x0800)
-	      lp->stats.rx_crc_errors++;
-	    printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n", 
-		   dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
-	  }
-	  if (rcv_status & 0x1000)
-	    lp->stats.rx_length_errors++;
-	  if (--boguscount == 0)
-	    break;
-	  
-	  rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
-	  lp->rx_start = rcv_next_frame;
-	  outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
-	  rcv_event = inw(ioaddr + IO_PORT);
-	  
+			lp->stats.rx_bytes+=rcv_size;
+#endif
+			rcv_size &= 0x3fff;
+			skb = dev_alloc_skb(rcv_size+5);
+			if (skb == NULL) {
+				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+				lp->stats.rx_dropped++;
+				break;
+			}
+			skb->dev = dev;
+			skb_reserve(skb,2);
+
+			if (lp->version == LAN595)
+				insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1);
+			else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
+				unsigned short temp = inb(ioaddr + INT_MASK_REG);
+				outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
+				insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size), 
+					(rcv_size + 3) >> 2);
+				outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
+			}
+	
+			skb->protocol = eth_type_trans(skb,dev);	
+			netif_rx(skb);
+			lp->stats.rx_packets++;
+		}
+		
+		else { /* Not sure will ever reach here, 
+			I set the 595 to discard bad received frames */
+			lp->stats.rx_errors++;
+			
+			if (rcv_status & 0x0100)
+				lp->stats.rx_over_errors++;
+			
+			else if (rcv_status & 0x0400)
+				lp->stats.rx_frame_errors++;
+			
+			else if (rcv_status & 0x0800)
+				lp->stats.rx_crc_errors++;
+			
+			printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n", 
+				dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
+		}
+
+		if (rcv_status & 0x1000)
+			lp->stats.rx_length_errors++;
+
+		if (--boguscount == 0)
+			break;
+
+		rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
+		lp->rx_start = rcv_next_frame;
+		outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
+		rcv_event = inw(ioaddr + IO_PORT);
+
 	} 
 	if (rcv_car == 0)
-	  rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff;
+		rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff;
+		
 	outw(rcv_car - 1, ioaddr + RCV_STOP);
 
 	if (net_debug > 5)
-	  printk(KERN_DEBUG "eepro: exiting eepro_rx routine.\n");
+		printk(KERN_DEBUG "%s: exiting eepro_rx routine.\n", dev->name);
 }
 
 static void
@@ -1581,47 +1606,53 @@
 	
 	/*
 	if (dev->tbusy == 0) {
-	  printk("%s: transmit_interrupt called with tbusy = 0 ??\n",
-		 dev->name);
-	  printk(KERN_DEBUG "%s: transmit_interrupt called with tbusy = 0 ??\n",
-		 dev->name);
+		printk("%s: transmit_interrupt called with tbusy = 0 ??\n",
+			dev->name);
+		printk(KERN_DEBUG "%s: transmit_interrupt called with tbusy = 0 ??\n",
+			dev->name);
 	}
 	*/
+
 	while (lp->tx_start != lp->tx_end) { 
-	  outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); 
-	  xmt_status = inw(ioaddr+IO_PORT);
-	  if ((xmt_status & TX_DONE_BIT) == 0) break;
-
-	  xmt_status = inw(ioaddr+IO_PORT); 
-	  lp->tx_start = inw(ioaddr+IO_PORT);
-
-	  dev->tbusy = 0;
-	  mark_bh(NET_BH);
-
-	  if (xmt_status & 0x2000)
-	    lp->stats.tx_packets++; 
-	  else {
-	    lp->stats.tx_errors++;
-	    if (xmt_status & 0x0400)
-	      lp->stats.tx_carrier_errors++;
-	    printk("%s: XMT status = %#x\n",
-		   dev->name, xmt_status);
-	    printk(KERN_DEBUG "%s: XMT status = %#x\n",
-		   dev->name, xmt_status);
-	  }
-	  if (xmt_status & 0x000f) {
-	    lp->stats.collisions += (xmt_status & 0x000f);
-	  }
-	  if ((xmt_status & 0x0040) == 0x0) {
-	    lp->stats.tx_heartbeat_errors++;
-	  }
-	  
-	  if (--boguscount == 0)
-	    break;  
+	
+		outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); 
+		xmt_status = inw(ioaddr+IO_PORT);
+		
+		if ((xmt_status & TX_DONE_BIT) == 0) break;
+
+		xmt_status = inw(ioaddr+IO_PORT); 
+		lp->tx_start = inw(ioaddr+IO_PORT);
+
+		dev->tbusy = 0;
+		mark_bh(NET_BH);
+
+		if (xmt_status & 0x2000)
+			lp->stats.tx_packets++; 
+		else {
+			lp->stats.tx_errors++;
+			if (xmt_status & 0x0400)
+				lp->stats.tx_carrier_errors++;
+			printk("%s: XMT status = %#x\n",
+				dev->name, xmt_status);
+			printk(KERN_DEBUG "%s: XMT status = %#x\n",
+				dev->name, xmt_status);
+		}
+		
+		if (xmt_status & 0x000f) {
+			lp->stats.collisions += (xmt_status & 0x000f);
+		}
+		
+		if ((xmt_status & 0x0040) == 0x0) {
+			lp->stats.tx_heartbeat_errors++;
+		}
+
+		if (--boguscount == 0)
+			break;
 	}
 }
 
 #ifdef MODULE
+
 #define MAX_EEPRO 8
 static char devicename[MAX_EEPRO][9];
 static struct device dev_eepro[MAX_EEPRO];
@@ -1655,10 +1686,12 @@
 MODULE_PARM(mem, "i");
 #endif 
 
-int init_module(void)
+int 
+init_module(void)
 {
 	if (io[0] == 0)
-		printk("eepro: You should not use auto-probing with insmod!\n");
+		printk("eepro_init_module: You should not use auto-probing with insmod!\n");
+
 	while (n_eepro < MAX_EEPRO && io[n_eepro] >= 0) {
 		struct device *d = &dev_eepro[n_eepro];
 		d->name		= devicename[n_eepro]; /* inserted by drivers/net/net_init.c */
@@ -1682,6 +1715,7 @@
 	for (i=0; i<n_eepro; i++) {
 		struct device *d = &dev_eepro[i];
 		unregister_netdev(d);
+
 		kfree_s(d->priv,sizeof(struct eepro_local));
 		d->priv=NULL;
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c
--- v2.2.0-pre5/linux/drivers/net/eexpress.c	Fri Oct  9 13:27:09 1998
+++ linux/drivers/net/eexpress.c	Thu Jan  7 15:47:03 1999
@@ -506,7 +506,7 @@
 	printk(KERN_DEBUG "%s: eexp_xmit()\n", dev->name);
 #endif
 
-	outb(SIRQ_dis|irqrmap[dev->irq],dev->base_addr+SET_IRQ);
+	disable_irq(dev->irq);
 
 	/* If dev->tbusy is set, all our tx buffers are full but the kernel
 	 * is calling us anyway.  Check that nothing bad is happening.
@@ -543,7 +543,7 @@
 	        eexp_hw_tx_pio(dev,data,length);
 	}
 	dev_kfree_skb(buf);
-	outb(SIRQ_en|irqrmap[dev->irq],dev->base_addr+SET_IRQ);
+	enable_irq(dev->irq);
 	return 0;
 }
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c
--- v2.2.0-pre5/linux/drivers/net/eth16i.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/net/eth16i.c	Thu Jan  7 08:46:59 1999
@@ -799,12 +799,12 @@
 		if( (jiffies - starttime) > TX_TIMEOUT) {
 
 			if(eth16i_debug > 1)
-				printk(KERN_DEBUG "Timeout occured waiting transmit packet received\n");
+				printk(KERN_DEBUG "Timeout occurred waiting transmit packet received\n");
 			starttime = jiffies;
 			while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
 				if( (jiffies - starttime) > TX_TIMEOUT) {
 					if(eth16i_debug > 1)
-						printk(KERN_DEBUG "Timeout occured waiting receive packet\n");
+						printk(KERN_DEBUG "Timeout occurred waiting receive packet\n");
 					return -1;
 				}
 			}
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/hp100.c linux/drivers/net/hp100.c
--- v2.2.0-pre5/linux/drivers/net/hp100.c	Thu Dec 31 10:29:00 1998
+++ linux/drivers/net/hp100.c	Thu Jan  7 08:46:59 1999
@@ -1365,7 +1365,7 @@
 /* They return how much memory the fragments need.            */
 static int hp100_init_rxpdl( struct device *dev, register hp100_ring_t *ringptr, register u32 *pdlptr )
 {
-  /* pdlptr is starting adress for this pdl */
+  /* pdlptr is starting address for this pdl */
 
   if( 0!=( ((unsigned)pdlptr) & 0xf) )
     printk("hp100: %s: Init rxpdl: Unaligned pdlptr 0x%x.\n",dev->name,(unsigned)pdlptr);
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/ne2.c linux/drivers/net/ne2.c
--- v2.2.0-pre5/linux/drivers/net/ne2.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/ne2.c	Thu Jan  7 09:21:53 1999
@@ -43,6 +43,9 @@
    - Added code that unregisters irq and proc-info
    - Version# bump
 
+   Mon Nov 16 15:28:23 CET 1998 (Wim Dumon)
+   - pass 'dev' as last parameter of request_irq in stead of 'NULL'   
+   
    *    WARNING
 	-------
 	This is alpha-test software.  It is not guaranteed to work. As a
@@ -51,8 +54,7 @@
 	If it doesn't work, be sure to send me a mail with the problems !
 */
 
-static const char *version =
-"ne2.c:v0.90 Oct 14 1998 David Weinehall <tao@acc.umu.se>\n";
+static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon <wimpie@kotnet.org>\n";
 
 #include <linux/module.h>
 #include <linux/version.h>
@@ -317,7 +319,7 @@
 	   share and the board will usually be enabled. */
 	{
 		int irqval = request_irq(dev->irq, ei_interrupt, 
-				0, name, NULL);
+				0, name, dev);
 		if (irqval) {
 			printk (" unable to get IRQ %d (irqval=%d).\n", 
 					dev->irq, +irqval);
@@ -330,7 +332,7 @@
 	/* Allocate dev->priv and fill in 8390 specific dev fields. */
 	if (ethdev_init(dev)) {
 		printk (" unable to get memory for dev->priv.\n");
-		free_irq(dev->irq, NULL);
+		free_irq(dev->irq, dev);
 		return -ENOMEM;
 	}
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/rcmtl.h linux/drivers/net/rcmtl.h
--- v2.2.0-pre5/linux/drivers/net/rcmtl.h	Tue Dec 22 14:16:56 1998
+++ linux/drivers/net/rcmtl.h	Thu Jan  7 09:21:53 1999
@@ -355,7 +355,7 @@
  /*
  ** Disable and Enable Adapter interrupts.  Adapter interrupts are enabled at 
  ** Init time but can be disabled and re-enabled through these two function calls.
- ** Packets will still be put into any posted recieved buffers and packets will
+ ** Packets will still be put into any posted received buffers and packets will
  ** be sent through RCSendPacket() functions.  Disabling Adapter interrupts
  ** will prevent hardware interrupt to host even though the outbound msg
  ** queue is not emtpy.
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/sdladrv.c linux/drivers/net/sdladrv.c
--- v2.2.0-pre5/linux/drivers/net/sdladrv.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/net/sdladrv.c	Thu Jan  7 09:21:53 1999
@@ -493,7 +493,7 @@
 }
 
 /*============================================================================
- * Map shared memory window into SDLA adress space.
+ * Map shared memory window into SDLA address space.
  */
 
 EXPORT_SYMBOL(sdla_mapmem);
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/sktr.c linux/drivers/net/sktr.c
--- v2.2.0-pre5/linux/drivers/net/sktr.c	Thu Dec 31 10:29:00 1998
+++ linux/drivers/net/sktr.c	Thu Jan  7 08:46:59 1999
@@ -1068,7 +1068,7 @@
 
 		if(!sktr_chk_ssb(tp, irq_type))
 		{
-			printk(KERN_INFO "%s: DATA LATE occured\n", dev->name);
+			printk(KERN_INFO "%s: DATA LATE occurred\n", dev->name);
 			break;
 		}
 
@@ -1583,7 +1583,7 @@
 			c |= ACL_SPEED16;		/* Set 16Mbps */
 	}
 
-	/* In case a comand is pending - forget it */
+	/* In case a command is pending - forget it */
 	tp->ScbInUse = 0;
 
 	c &= ~ACL_ARESET;		/* Clear adapter reset bit */
@@ -1672,7 +1672,7 @@
 	} while(retry_cnt > 0);
 
 	Status = inw(ioaddr + SIFSTS);
-	Status &= STS_ERROR_MASK;	/* Hardware error occured! */
+	Status &= STS_ERROR_MASK;	/* Hardware error occurred! */
 
 	printk(KERN_INFO "%s: Bring Up Diagnostics Error (%04X) occurred\n",
 		dev->name, Status);
@@ -1761,7 +1761,7 @@
 		{
 			if((Status & STS_ERROR) != 0)
 			{
-				/* Initialization error occured */
+				/* Initialization error occurred */
 				Status = inw(ioaddr + SIFSTS);
 				Status &= STS_ERROR_MASK;
 				/* ShowInitialisationErrorCode(Status); */
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/sktr_firmware.h linux/drivers/net/sktr_firmware.h
--- v2.2.0-pre5/linux/drivers/net/sktr_firmware.h	Wed Jun 24 22:54:07 1998
+++ linux/drivers/net/sktr_firmware.h	Thu Jan  7 08:46:59 1999
@@ -1,6 +1,6 @@
 /*
  * The firmware this driver downloads into the tokenring card is a
- * seperate program and is not GPL'd source code, even though the Linux
+ * separate program and is not GPL'd source code, even though the Linux
  * side driver and the routine that loads this data into the card are.
  *
  * This firmware is licensed to you strictly for use in conjunction
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/sonic.c linux/drivers/net/sonic.c
--- v2.2.0-pre5/linux/drivers/net/sonic.c	Tue Jul 28 14:21:08 1998
+++ linux/drivers/net/sonic.c	Thu Jan  7 08:46:59 1999
@@ -425,7 +425,7 @@
     lp->tda[entry].tx_frag_ptr_h = laddr >> 16;
     lp->tda[entry].tx_frag_size  = length;
     
-    /* if there are already packets queued, allow sending serveral packets at once */
+    /* if there are already packets queued, allow sending several packets at once */
     if (lp->dirty_tx != lp->cur_tx)
 	lp->tda[(lp->cur_tx-1) % SONIC_TDS_MASK].link &= ~SONIC_END_OF_LINKS;
     
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/tlan.c linux/drivers/net/tlan.c
--- v2.2.0-pre5/linux/drivers/net/tlan.c	Sun Nov  8 14:03:00 1998
+++ linux/drivers/net/tlan.c	Thu Jan  7 08:46:59 1999
@@ -2797,7 +2797,7 @@
 	 *
 	 *	Returns:
 	 *		No error = 0, else, the stage at which the error
-	 *		occured.
+	 *		occurred.
 	 *	Parms:
 	 *		io_base		The IO port base address for the
 	 *				TLAN device with the EEPROM to
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/z85230.c linux/drivers/net/z85230.c
--- v2.2.0-pre5/linux/drivers/net/z85230.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/net/z85230.c	Thu Jan  7 08:46:59 1999
@@ -227,7 +227,7 @@
  *	Receive handler. This is much like the async one but not quite the
  *	same or as complex
  *
- *	Note: Its intended that this handler can easily be seperated from
+ *	Note: Its intended that this handler can easily be separated from
  *	the main code to run realtime. That'll be needed for some machines
  *	(eg to ever clock 64kbits on a sparc ;)).
  *
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/net/znet.c linux/drivers/net/znet.c
--- v2.2.0-pre5/linux/drivers/net/znet.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/net/znet.c	Thu Jan  7 09:21:53 1999
@@ -207,11 +207,11 @@
 	char *p;
 
 	/* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */
-	for(p = (char *)0xf0000; p < (char *)0x100000; p++)
+	for(p = phys_to_virt(0xf0000); p < phys_to_virt(0x100000); p++)
 		if (*p == 'N'  &&  strncmp(p, "NETIDBLK", 8) == 0)
 			break;
 
-	if (p >= (char *)0x100000) {
+	if (p >= pyhs_to_virt(0x100000)) {
 		if (znet_debug > 1)
 			printk(KERN_INFO "No Z-Note ethernet adaptor found.\n");
 		return ENODEV;
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/pci/quirks.c linux/drivers/pci/quirks.c
--- v2.2.0-pre5/linux/drivers/pci/quirks.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/pci/quirks.c	Thu Jan  7 09:21:53 1999
@@ -129,7 +129,7 @@
     but VIA don't answer queries. If you happen to have good contacts at VIA
     ask them for me please -- Alan 
     
-    This appears to be BIOS not version dependant. So presumably there is a 
+    This appears to be BIOS not version dependent. So presumably there is a 
     chipset level fix */
     
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sbus/audio/amd7930.c linux/drivers/sbus/audio/amd7930.c
--- v2.2.0-pre5/linux/drivers/sbus/audio/amd7930.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/sbus/audio/amd7930.c	Thu Jan  7 09:21:53 1999
@@ -1021,7 +1021,7 @@
  *
  *       0 - successful reception
  *   non-0 - error value from chip's DER (D-Channel Error Register):
- *       1 - recieved packet abort
+ *       1 - received packet abort
  *       2 - framing error; non-integer number of bytes received
  *       8 - FCS error; CRC sequence indicated corrupted data
  *      16 - overflow error; packet exceeded size of buffer
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sbus/audio/dbri.h linux/drivers/sbus/audio/dbri.h
--- v2.2.0-pre5/linux/drivers/sbus/audio/dbri.h	Thu Nov 19 09:56:28 1998
+++ linux/drivers/sbus/audio/dbri.h	Thu Jan  7 09:21:53 1999
@@ -305,7 +305,7 @@
 #define DBRI_RD_M	(1<<14)	/* Marker interrupt */
 #define DBRI_RD_BCNT(v)	v	/* Buffer size */
 #define DBRI_RD_CRC	(1<<7)	/* 0: CRC is correct */
-#define DBRI_RD_BBC	(1<<6)	/* 1: Bad Byte recieved */
+#define DBRI_RD_BBC	(1<<6)	/* 1: Bad Byte received */
 #define DBRI_RD_ABT	(1<<5)	/* Abort: frame aborted */
 #define DBRI_RD_OVRN	(1<<3)	/* Overrun: data lost */
 #define DBRI_RD_STATUS(v)      ((v)&0xff)      /* Receive status */
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sbus/char/vfc_i2c.c linux/drivers/sbus/char/vfc_i2c.c
--- v2.2.0-pre5/linux/drivers/sbus/char/vfc_i2c.c	Tue May 13 22:41:12 1997
+++ linux/drivers/sbus/char/vfc_i2c.c	Thu Jan  7 09:21:53 1999
@@ -156,7 +156,7 @@
 	switch(mode) {
 	case VFC_I2C_READ:
 		dev->regs->i2c_reg=raddr=SHIFT((unsigned int)addr | 0x1);
-		VFC_I2C_DEBUG_PRINTK(("vfc%d: recieving from i2c addr 0x%x\n",
+		VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n",
 				  dev->instance,addr | 0x1));
 		break;
 	case VFC_I2C_WRITE:
@@ -255,7 +255,7 @@
 		if(!count) last=1;
 		if((ret=vfc_i2c_recv_byte(dev,buf,last))) {
 			printk(KERN_ERR "vfc%d: "
-			       "VFC error while recieving byte\n",
+			       "VFC error while receiving byte\n",
 			       dev->instance);
 			dev->regs->i2c_s1=SEND_I2C_STOP;
 			ret=-EINVAL;
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/scsi/README.ncr53c8xx linux/drivers/scsi/README.ncr53c8xx
--- v2.2.0-pre5/linux/drivers/scsi/README.ncr53c8xx	Wed Dec 16 10:32:55 1998
+++ linux/drivers/scsi/README.ncr53c8xx	Thu Jan  7 09:21:53 1999
@@ -33,7 +33,7 @@
       10.6 SCSI BUS checking boot option
 11. Some constants and flags of the ncr53c8xx.h header file
 12. Installation
-13. Architecture dependant features
+13. Architecture dependent features
 14. Known problems
       14.1 Tagged commands with Iomega Jaz device
       14.2 Device names change when another controller is added
@@ -948,7 +948,7 @@
       ftp://ftp.tux.org/pub/people/gerard-roudier/README
 
 
-13. Architecture dependant features.
+13. Architecture dependent features.
 
 <Not yet written>
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/scsi/aic7xxx/aic7xxx.reg linux/drivers/scsi/aic7xxx/aic7xxx.reg
--- v2.2.0-pre5/linux/drivers/scsi/aic7xxx/aic7xxx.reg	Fri Oct  9 13:27:10 1998
+++ linux/drivers/scsi/aic7xxx/aic7xxx.reg	Thu Jan  7 09:24:00 1999
@@ -461,7 +461,7 @@
  * Sequencer RAM Data (p. 3-34)
  * Single byte window into the Scratch Ram area starting at the address
  * specified by SEQADDR0 and SEQADDR1.  To write a full word, simply write
- * four bytes in sucessesion.  The SEQADDRs will increment after the most
+ * four bytes in succession.  The SEQADDRs will increment after the most
  * significant byte is written
  */
 register SEQRAM {
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/scsi/eata_dma_proc.c linux/drivers/scsi/eata_dma_proc.c
--- v2.2.0-pre5/linux/drivers/scsi/eata_dma_proc.c	Mon Jan  4 15:08:17 1999
+++ linux/drivers/scsi/eata_dma_proc.c	Thu Jan  7 09:28:47 1999
@@ -1,5 +1,3 @@
-#include <linux/config.h>
-
 void swap_statistics(u8 *p)
 {
     u32 y;
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/scsi/eata_pio_proc.c linux/drivers/scsi/eata_pio_proc.c
--- v2.2.0-pre5/linux/drivers/scsi/eata_pio_proc.c	Mon Jan  4 15:08:17 1999
+++ linux/drivers/scsi/eata_pio_proc.c	Thu Jan  7 09:28:47 1999
@@ -1,5 +1,3 @@
-#include <linux/config.h>
-
 /*
  * eata_set_info
  * buffer : pointer to the data that has been written to the hostfile
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/scsi/imm.h linux/drivers/scsi/imm.h
--- v2.2.0-pre5/linux/drivers/scsi/imm.h	Mon Jan  4 15:08:17 1999
+++ linux/drivers/scsi/imm.h	Fri Jan  8 15:53:56 1999
@@ -63,6 +63,7 @@
 /* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
 
 #ifdef IMM_CODE
+#include  <linux/config.h>
 #include  <linux/stddef.h>
 #include  <linux/module.h>
 #include  <linux/kernel.h>
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/scsi/ppa.h linux/drivers/scsi/ppa.h
--- v2.2.0-pre5/linux/drivers/scsi/ppa.h	Mon Jan  4 15:08:17 1999
+++ linux/drivers/scsi/ppa.h	Fri Jan  8 15:53:56 1999
@@ -55,6 +55,7 @@
 /* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
 
 #ifdef PPA_CODE
+#include  <linux/config.h>
 #include  <linux/stddef.h>
 #include  <linux/module.h>
 #include  <linux/kernel.h>
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.2.0-pre5/linux/drivers/scsi/scsi.c	Thu Jan  7 15:11:37 1999
+++ linux/drivers/scsi/scsi.c	Thu Jan  7 09:24:00 1999
@@ -531,7 +531,7 @@
       for (dev = 0; dev < shpnt->max_id; ++dev) {
         if( shpnt->reverse_ordering)
         	/* Shift to scanning 15,14,13... or 7,6,5,4, */
-        	order_dev = shpnt->max_channel-dev-1;
+        	order_dev = shpnt->max_id-dev-1;
         else
         	order_dev = dev;
         	
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c
--- v2.2.0-pre5/linux/drivers/scsi/scsi_error.c	Mon Dec 28 15:00:52 1998
+++ linux/drivers/scsi/scsi_error.c	Thu Jan  7 09:24:00 1999
@@ -969,7 +969,7 @@
       /*
        * Note - this means that we just report the status back to the
        * top level driver, not that we actually think that it indicates
-       * sucess.
+       * success.
        */
       return SUCCESS;
       /*
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c
--- v2.2.0-pre5/linux/drivers/scsi/wd7000.c	Thu Dec 31 10:29:01 1998
+++ linux/drivers/scsi/wd7000.c	Thu Jan  7 09:24:00 1999
@@ -105,7 +105,7 @@
  *  08/24/1996.
  *
  *  Enhancement for wd7000_detect function has been made, so you don't have
- *  to enter BIOS ROM adress in initialisation data (see struct Config).
+ *  to enter BIOS ROM address in initialisation data (see struct Config).
  *  We cannot detect IRQ, DMA and I/O base address for now, so we have to
  *  enter them as arguments while wd_7000 is detected. If someone has IRQ,
  *  DMA or I/O base address set to some other value, he can enter them in
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
--- v2.2.0-pre5/linux/drivers/sound/ad1848.c	Thu Jan  7 15:11:37 1999
+++ linux/drivers/sound/ad1848.c	Thu Jan  7 09:24:00 1999
@@ -52,7 +52,7 @@
 	int             dma1, dma2;
 	int             dual_dma;	/* 1, when two DMA channels allocated */
 	unsigned char   MCE_bit;
-	unsigned char   saved_regs[16];
+	unsigned char   saved_regs[32];
 	int             debug_flag;
 
 	int             audio_flags;
@@ -1601,6 +1601,9 @@
 				/*
 				 *      It's at least CS4231
 				 */
+
+				devc->chip_name = "CS4231";
+				devc->model = MD_4231;
 				
 				/*
 				 * It could be an AD1845 or CS4231A as well.
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h
--- v2.2.0-pre5/linux/drivers/sound/dev_table.h	Tue Dec 22 14:16:56 1998
+++ linux/drivers/sound/dev_table.h	Thu Jan  7 09:24:00 1999
@@ -33,6 +33,7 @@
 #define SNDCARD_WAVEFRONT               41
 #define SNDCARD_OPL3SA2                 42
 #define SNDCARD_OPL3SA2_MPU             43
+#define SNDCARD_WAVEARTIST		44
 #define SNDCARD_AD1816                  88
 
 void attach_opl3sa_wss (struct address_info *hw_config);
@@ -503,6 +504,9 @@
 #ifdef CONFIG_SOUND_VIDC
 	{"VIDC", 0, SNDCARD_VIDC, "ARM VIDC 16-bit D/A", attach_vidc, probe_vidc, unload_vidc },
 #endif
+#ifdef CONFIG_SOUND_WAVEARTIST
+	{"WaveArtist", 0, SNDCARD_WAVEARTIST, "NetWinder WaveArtist", attach_waveartist, probe_waveartist, unload_waveartist },
+#endif
 	{NULL, 0, 0,		"*?*",			NULL, NULL, NULL}
 };
 
@@ -677,6 +681,10 @@
 
 #ifdef CONFIG_SOUND_VIDC
 	{ SNDCARD_VIDC, {0, 0, 0, 0}, SND_DEFAULT_ENABLE },
+#endif
+
+#ifdef CONFIG_SOUND_WAVEARTIST
+	{ SNDCARD_WAVEARTIST, { CONFIG_WAVEARTIST_BASE, CONFIG_WAVEARTIST_IRQ, CONFIG_WAVEARTIST_DMA, CONFIG_WAVEARTIST_DMA2 }, SND_DEFAULT_ENABLE },
 #endif
 	{0, {0}, 0}
 };
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.2.0-pre5/linux/drivers/sound/es1370.c	Thu Jan  7 15:11:37 1999
+++ linux/drivers/sound/es1370.c	Thu Jan  7 09:24:00 1999
@@ -81,6 +81,8 @@
  *		       -- Oliver Neukum <c188@org.chemie.uni-muenchen.de>
  *    10.12.98   0.15  Fix drain_dac trying to wait on not yet initialized DMA
  *    16.12.98   0.16  Don't wake up app until there are fragsize bytes to read/write
+ *    06.01.99   0.17  remove the silly SA_INTERRUPT flag.
+ *                     hopefully killed the egcs section type conflict
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -2241,7 +2243,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static const struct initvol {
+static struct initvol {
 	int mixch;
 	int vol;
 } initvol[] __initdata = {
@@ -2270,7 +2272,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1370: version v0.16 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1370: version v0.17 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
 		if (pcidev->base_address[0] == 0 || 
@@ -2298,7 +2300,7 @@
 			goto err_region;
 		}
 		request_region(s->io, ES1370_EXTENT, "es1370");
-		if (request_irq(s->irq, es1370_interrupt, SA_INTERRUPT|SA_SHIRQ, "es1370", s)) {
+		if (request_irq(s->irq, es1370_interrupt, SA_SHIRQ, "es1370", s)) {
 			printk(KERN_ERR "es1370: irq %u in use\n", s->irq);
 			goto err_irq;
 		}
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.2.0-pre5/linux/drivers/sound/es1371.c	Thu Jan  7 15:11:38 1999
+++ linux/drivers/sound/es1371.c	Thu Jan  7 09:24:00 1999
@@ -52,6 +52,8 @@
  *    10.12.98   0.6   Fix drain_dac trying to wait on not yet initialized DMA
  *    23.12.98   0.7   Fix a few f_file & FMODE_ bugs
  *                     Don't wake up app until there are fragsize bytes to read/write
+ *    06.01.99   0.8   remove the silly SA_INTERRUPT flag.
+ *                     hopefully killed the egcs section type conflict
  *
  */
 
@@ -2710,7 +2712,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1371: version v0.7 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1371: version v0.8 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
 		if (pcidev->base_address[0] == 0 || 
@@ -2738,7 +2740,7 @@
 			goto err_region;
 		}
 		request_region(s->io, ES1371_EXTENT, "es1371");
-		if (request_irq(s->irq, es1371_interrupt, SA_INTERRUPT|SA_SHIRQ, "es1371", s)) {
+		if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
 			printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
 			goto err_irq;
 		}
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/gus_card.c linux/drivers/sound/gus_card.c
--- v2.2.0-pre5/linux/drivers/sound/gus_card.c	Thu May 14 19:47:42 1998
+++ linux/drivers/sound/gus_card.c	Thu Jan  7 09:24:00 1999
@@ -128,17 +128,20 @@
 {
 	unsigned char src;
 	extern int gus_timer_enabled;
-	struct address_info *hw_config=dev_id;
 
 	sti();
 
 #ifdef CONFIG_GUSMAX
-	if (have_gus_max)
+	if (have_gus_max) {
+		struct address_info *hw_config = dev_id;
 		adintr(irq, (void *)hw_config->slots[1], NULL);
+	}
 #endif
 #ifdef CONFIG_GUS16
-	if (db16)
+	if (db16) {
+		struct address_info *hw_config = dev_id;
 		adintr(irq, (void *)hw_config->slots[3], NULL);
+	}
 #endif
 
 	while (1)
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c
--- v2.2.0-pre5/linux/drivers/sound/gus_wave.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/sound/gus_wave.c	Thu Jan  7 09:24:00 1999
@@ -2932,7 +2932,6 @@
 	int gus_type = 0x24;	/* 2.4 */
 
 	int irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2;
-	int dev;
 	int sdev;
 
 	hw_config->slots[0] = -1;	/* No wave */
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/lowlevel/awe_compat.h linux/drivers/sound/lowlevel/awe_compat.h
--- v2.2.0-pre5/linux/drivers/sound/lowlevel/awe_compat.h	Tue Dec 22 14:16:56 1998
+++ linux/drivers/sound/lowlevel/awe_compat.h	Thu Jan  7 09:24:00 1999
@@ -150,7 +150,6 @@
 #define my_malloc_init(memptr)	_mem_start = (memptr)
 #define my_malloc_memptr()	_mem_start
 #define my_free(ptr)	/* do nothing */
-#define my_realloc(buf,oldsize,size)	NULL	/* no realloc */
 
 static void *my_malloc(int size)
 {
@@ -176,16 +175,6 @@
 #define my_free(ptr)		if (ptr) {vfree(ptr);}
 #define my_kmalloc(size)	kmalloc(size,GFP_KERNEL)
 #define my_kfree(ptr)		kfree(ptr)
-
-static void *my_realloc(void *buf, int oldsize, int size)
-{
-	void *ptr;
-	if ((ptr = vmalloc(size)) == NULL)
-		return NULL;
-	memcpy(ptr, buf, ((oldsize < size) ? oldsize : size) );
-	vfree(buf);
-	return ptr;
-}
 
 /* do not allocate buffer at beginning */
 #define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c
--- v2.2.0-pre5/linux/drivers/sound/mad16.c	Mon Dec 28 15:00:52 1998
+++ linux/drivers/sound/mad16.c	Thu Jan  7 09:24:00 1999
@@ -495,17 +495,24 @@
 
 				for (i = 0xf8d; i <= 0xf93; i++)
 					DDB(printk("port %03x = %02x\n", i, mad_read(i)));
+                                if(!detect_mad16()) {
+
+				  /* The C931 has the password reg at F8D */
+				  outb((0xE4), 0xF8D);
+				  outb((0x80), 0xF8D);
+				  DDB(printk("Detect using password = 0xE4 for C931\n"));
 
-				if (!detect_mad16()) {
-				  board_type = C924;
-				  c924pnp++;
-				  DDB(printk("Detect using password = 0xE5 (again), port offset -0x80\n"));
 				  if (!detect_mad16()) {
-				    c924pnp=0;
-				    return 0;
-				  }
+				    board_type = C924;
+				    c924pnp++;
+				    DDB(printk("Detect using password = 0xE5 (again), port offset -0x80\n"));
+				    if (!detect_mad16()) {
+				      c924pnp=0;
+				      return 0;
+				    }
 				  
-				  DDB(printk("mad16.c: 82C924 PnP detected\n"));
+				    DDB(printk("mad16.c: 82C924 PnP detected\n"));
+				  }
 				}
 				else
 				  DDB(printk("mad16.c: 82C930 detected\n"));
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/opl3sa2.c linux/drivers/sound/opl3sa2.c
--- v2.2.0-pre5/linux/drivers/sound/opl3sa2.c	Thu Jan  7 15:11:38 1999
+++ linux/drivers/sound/opl3sa2.c	Thu Jan  7 09:24:00 1999
@@ -4,7 +4,7 @@
  * A low level driver for Yamaha OPL3-SA2 and SA3 cards.
  * SAx cards should work, as they are just variants of the SA3.
  *
- * Copyright 1998 Scott Murray <scottm@interlog.com>
+ * Copyright 1998, 1999 Scott Murray <scottm@interlog.com>
  *
  * Originally based on the CS4232 driver (in cs4232.c) by Hannu Savolainen
  * and others.  Now incorporates code/ideas from pss.c, also by Hannu
@@ -29,6 +29,9 @@
  * Scott Murray            Changed detection code to be more forgiving,
  *                         added force option as last resort,
  *                         fixed ioctl return values. (Dec 30, 1998)
+ * Scott Murray            Simpler detection code should work all the time now
+ *                         (with thanks to Ben Hutchings for the heuristic),
+ *                         removed now unnecessary force option. (Jan 5, 1999)
  *
  */
 
@@ -53,12 +56,12 @@
 #define DEFAULT_MIC    50
 #define DEFAULT_TIMBRE 0
 
+#define CHIPSET_UNKNOWN -1
+
 /*
- * NOTE: CHIPSET_UNKNOWN should match the default value of
- *       CONFIG_OPL3SA2_CHIPSET in Config.in to make everything
- *       work right in all situations.
+ * These are used both as masks against what the card returns,
+ * and as constants.
  */
-#define CHIPSET_UNKNOWN -1
 #define CHIPSET_OPL3SA2  1
 #define CHIPSET_OPL3SA3  2
 #define CHIPSET_OPL3SAX  4
@@ -67,12 +70,7 @@
 #ifdef CONFIG_OPL3SA2
 
 /* What's my version? */
-#ifdef CONFIG_OPL3SA2_CHIPSET
-/* Set chipset if compiled into the kernel */
-static int chipset = CONFIG_OPL3SA2_CHIPSET;
-#else
 static int chipset = CHIPSET_UNKNOWN;
-#endif
 
 /* Oh well, let's just cache the name */
 static char chipset_name[16];
@@ -526,14 +524,6 @@
 
 int probe_opl3sa2(struct address_info *hw_config)
 {
-	unsigned char chipsets[8] = { CHIPSET_UNKNOWN, /* 0 */
-				      CHIPSET_OPL3SA2, /* 1 */
-				      CHIPSET_OPL3SA3, /* 2 */
-				      CHIPSET_UNKNOWN, /* 3 */
-				      CHIPSET_OPL3SAX, /* 4 */
-				      CHIPSET_OPL3SAX, /* 5 */
-				      CHIPSET_UNKNOWN, /* 6 */
-				      CHIPSET_OPL3SA3, /* 7 */ };
 	unsigned char version = 0;
 	char tag;
 
@@ -551,107 +541,55 @@
 
 	/*
 	 * Determine chipset type (SA2, SA3, or SAx)
-	 *
-	 * Have to handle two possible override situations:
-	 * 1) User compiled driver into the kernel and forced chipset type
-	 * 2) User built a module, but wants to override the chipset type
 	 */
-	if(chipset == CHIPSET_UNKNOWN)
+
+	/*
+	 * Look at chipset version in lower 3 bits of index 0x0A, miscellaneous
+	 */
+	opl3sa2_read(hw_config->io_base,
+		     OPL3SA2_MISC,
+		     (unsigned char*) &version);
+	version &= 0x07;
+
+	/* Match version number to appropiate chipset */
+	if(version & CHIPSET_OPL3SAX)
+	{
+		chipset = CHIPSET_OPL3SAX;
+		tag = 'x';
+		printk(KERN_INFO "Found OPL3-SAx (YMF719)\n");
+	}
+	else
 	{
-		if(hw_config->card_subtype == CHIPSET_UNKNOWN)
+ 		if(version & CHIPSET_OPL3SA3)
 		{
-			/*
-			 * Look at chipset version in lower 3 bits of index 0x0A, miscellaneous
-			 */
-			opl3sa2_read(hw_config->io_base,
-				     OPL3SA2_MISC,
-				     (unsigned char*) &version);
-			version &= 0x07;
-
-			/* Match version number to appropiate chipset */
-			chipset = chipsets[version];
+			chipset = CHIPSET_OPL3SA3;
+			tag = '3';
+			printk(KERN_INFO "Found OPL3-SA3 (YMF715)\n");
 		}
 		else
 		{
-			/* Use user specified chipset */
-			switch(hw_config->card_subtype)
+			if(version & CHIPSET_OPL3SA2)
 			{
-				case 2:
-					chipset = CHIPSET_OPL3SA2;
-					break;
-
-				case 3:
-					chipset = CHIPSET_OPL3SA3;
-					break;
-
-				default:
-					printk(KERN_ERR "%s: Unknown chipset %d\n",
-					       __FILE__,
-					       hw_config->card_subtype);
-					chipset = CHIPSET_UNKNOWN;
-					break;
-			}
-		}
-	}
-	else
-	{
-		/* Use user compiled in chipset */
-		switch(chipset)
-		{
-			case 2:
 				chipset = CHIPSET_OPL3SA2;
-				break;
-				
-			case 3:
-				chipset = CHIPSET_OPL3SA3;
-				break;
-
-			default:
-				printk(KERN_ERR "%s: Unknown chipset %d\n",
-				       __FILE__,
-				       chipset);
-				chipset = CHIPSET_UNKNOWN;
-				break;
-		}
-	}
-
-	/* Do chipset specific stuff: */
-	switch(chipset)
-	{
-		case CHIPSET_OPL3SA2:
-			printk(KERN_INFO "Found OPL3-SA2 (YMF711)\n");
-			tag = '2';
-			break;
-
-		case CHIPSET_OPL3SA3:
-			printk(KERN_INFO "Found OPL3-SA3 (YMF715)\n");
-			tag = '3';
-			break;
-
-		case CHIPSET_OPL3SAX:
-			printk(KERN_INFO "Found OPL3-SAx (YMF719)\n");
-			tag = 'x';
-			break;
-
-		default:
-			printk(KERN_ERR "No Yamaha audio controller found\n");
-
-			/* If we've actually checked the version, print it out */
-			if(version)
+				tag = '2';
+				printk(KERN_INFO "Found OPL3-SA2 (YMF711)\n");
+			}
+			else
 			{
+				chipset = CHIPSET_UNKNOWN;
+				tag = '?';
+				printk(KERN_ERR
+				       "Unknown Yamaha audio controller version\n");
 				printk(KERN_INFO
 				       "%s: chipset version = %x\n",
 				       __FILE__,
 				       version);
 			}
-			
-			/* Set some sane values */
-			chipset = CHIPSET_UNKNOWN;
-			tag = '?';
-			break;
+		}
 	}
 
-	if(chipset != CHIPSET_UNKNOWN) {
+	if(chipset != CHIPSET_UNKNOWN)
+	{
 		/* Generate a pretty name */
 		sprintf(chipset_name, "OPL3-SA%c", tag);
 		return 1;
@@ -687,7 +625,6 @@
 int irq     = -1;
 int dma     = -1;
 int dma2    = -1;
-int force   = -1;
 
 MODULE_PARM(io, "i");
 MODULE_PARM_DESC(io, "Set i/o base of OPL3-SA2 or SA3 card (usually 0x370)");
@@ -707,9 +644,6 @@
 MODULE_PARM(dma2, "i");
 MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");
 
-MODULE_PARM(force, "i");
-MODULE_PARM_DESC(force, "Force audio controller chipset (2, 3)");
-
 MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver).");
 MODULE_AUTHOR("Scott Murray <scottm@interlog.com>");
 
@@ -731,7 +665,8 @@
 
 	if(io == -1 || irq == -1 || dma == -1 || dma2 == -1 || mss_io == -1)
 	{
-		printk(KERN_ERR "%s: io, mss_io, irq, dma, and dma2 must be set.\n",
+		printk(KERN_ERR
+		       "%s: io, mss_io, irq, dma, and dma2 must be set.\n",
 		       __FILE__);
 		return -EINVAL;
 	}
@@ -742,12 +677,6 @@
 	cfg.dma     = dma;
 	cfg.dma2    = dma2;
 	
-	/* Does the user want to override the chipset type? */
-	if(force != -1)
-		cfg.card_subtype = force;
-	else
-		cfg.card_subtype = CHIPSET_UNKNOWN;
-
         /* The MSS config: */
 	mss_cfg.io_base      = mss_io;
 	mss_cfg.irq          = irq;
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/sb.h linux/drivers/sound/sb.h
--- v2.2.0-pre5/linux/drivers/sound/sb.h	Thu Jan  7 15:11:38 1999
+++ linux/drivers/sound/sb.h	Thu Jan  7 09:24:00 1999
@@ -48,10 +48,11 @@
 #define MDL_ES1868MIDI	14	/* MIDI port of ESS1868 */
 #define MDL_AEDSP	15	/* Audio Excel DSP 16 */
 
-#define SUBMDL_ES188X	0x10	/* Subtype ES188X for specific handling */
+#define SUBMDL_ES1788	0x10	/* Subtype ES1788 for specific handling */
 #define SUBMDL_ES1868	0x11	/* Subtype ES1868 for specific handling */
 #define SUBMDL_ES1869	0x12	/* Subtype ES1869 for specific handling */
 #define SUBMDL_ES1878	0x13	/* Subtype ES1878 for specific handling */
+#define SUBMDL_ES188X	0x14	/* Subtype ES1887 for specific handling */
 #define SUBMDL_ALS007	42	/* ALS-007 differs from SB16 only in mixer */
 				/* register assignment */
 /*
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/sb_audio.c linux/drivers/sound/sb_audio.c
--- v2.2.0-pre5/linux/drivers/sound/sb_audio.c	Thu Jan  7 15:11:38 1999
+++ linux/drivers/sound/sb_audio.c	Thu Jan  7 09:24:00 1999
@@ -67,7 +67,12 @@
 	devc->fullduplex = devc->duplex &&
 		((mode & OPEN_READ) && (mode & OPEN_WRITE));
 	sb_dsp_reset(devc);
-	ess_mixer_reload (devc, SOUND_MIXER_RECLEV);
+
+	/* At first glance this check isn't enough, some ESS chips might not 
+	 * have a RECLEV. However if they don't common_mixer_set will refuse 
+	 * cause devc->iomap has no register mapping for RECLEV
+	 */
+	if (devc->model == MDL_ESS) ess_mixer_reload (devc, SOUND_MIXER_RECLEV);
 
 	/* The ALS007 seems to require that the DSP be removed from the output */
 	/* in order for recording to be activated properly.  This is done by   */
@@ -659,6 +664,43 @@
 	return;
 }
 
+static void ess_change
+	(sb_devc *devc, unsigned int reg, unsigned int mask, unsigned int val)
+{
+	int value;
+
+	value = ess_read(devc, reg);
+	value = (value & ~mask) | (val & mask);
+	ess_write(devc, reg, value);
+}
+
+struct ess_command {int cmd; int data;};
+
+static void ess_exec_commands
+	(sb_devc *devc, struct ess_command *cmdtab[])
+{
+	struct ess_command *cmd;
+
+	cmd = cmdtab [ ((devc->channels != 1) << 1) + (devc->bits != AFMT_U8) ];
+
+	while (cmd->cmd != -1) {
+		ess_write (devc, cmd->cmd, cmd->data);
+		cmd++;
+	}
+}
+
+static struct ess_command ess_i08m[] =		/* input 8 bit mono */
+	{ {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} };
+static struct ess_command ess_i16m[] =		/* input 16 bit mono */
+	{ {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} };
+static struct ess_command ess_i08s[] =		/* input 8 bit stereo */
+	{ {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} };
+static struct ess_command ess_i16s[] =		/* input 16 bit stereo */
+	{ {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} };
+
+static struct ess_command *ess_inp_cmds[] =
+	{ ess_i08m, ess_i16m, ess_i08s, ess_i16s };
+
 static int ess_audio_prepare_for_input(int dev, int bsize, int bcount)
 {
 	sb_devc *devc = audio_devs[dev]->devc;
@@ -666,46 +708,31 @@
 	sb_dsp_command(devc, DSP_CMD_SPKOFF);
 
 	ess_write(devc, 0xb8, 0x0e);	/* Auto init DMA mode */
-	ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) | (3 - devc->channels));	/* Mono/stereo */
+	ess_change (devc, 0xa8, 0x03, 3 - devc->channels);	/* Mono/stereo */
 	ess_write(devc, 0xb9, 2);	/* Demand mode (4 bytes/DMA request) */
 
-	if (devc->channels == 1)
-	{
-		if (devc->bits == AFMT_U8)
-		{	
-			/* 8 bit mono */
-			ess_write(devc, 0xb7, 0x51);
-			ess_write(devc, 0xb7, 0xd0);
-		}
-		else
-		{
-			/* 16 bit mono */
-			ess_write(devc, 0xb7, 0x71);
-			ess_write(devc, 0xb7, 0xf4);
-		}
-	}
-	else
-	{	
-		/* Stereo */
-		if (devc->bits == AFMT_U8)
-		{
-			/* 8 bit stereo */
-			ess_write(devc, 0xb7, 0x51);
-			ess_write(devc, 0xb7, 0x98);
-		}
-		else
-		{	
-			/* 16 bit stereo */
-			ess_write(devc, 0xb7, 0x71);
-			ess_write(devc, 0xb7, 0xbc);
-		}
-	}
-	ess_write(devc, 0xb1, (ess_read(devc, 0xb1) & 0x0f) | 0x50);
-	ess_write(devc, 0xb2, (ess_read(devc, 0xb2) & 0x0f) | 0x50);
+	ess_exec_commands (devc, ess_inp_cmds);
+
+	ess_change (devc, 0xb1, 0xf0, 0x50);
+	ess_change (devc, 0xb2, 0xf0, 0x50);
+
 	devc->trigger_bits = 0;
 	return 0;
 }
 
+static struct ess_command ess_o08m[] =          /* output 8 bit mono */
+        { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} };
+static struct ess_command ess_o16m[] =          /* output 16 bit mono */
+        { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} };
+static struct ess_command ess_o08s[] =          /* output 8 bit stereo */
+        { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} };
+static struct ess_command ess_o16s[] =          /* output 16 bit stereo */
+        { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} };
+
+
+static struct ess_command *ess_out_cmds[] =
+        { ess_o08m, ess_o16m, ess_o08s, ess_o16s };
+
 static int ess_audio_prepare_for_output(int dev, int bsize, int bcount)
 {
 	sb_devc *devc = audio_devs[dev]->devc;
@@ -714,42 +741,14 @@
 	ess_speed(devc);
 
 	ess_write(devc, 0xb8, 4);	/* Auto init DMA mode */
-	ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) | (3 - devc->channels));	/* Mono/stereo */
+	ess_change (devc, 0xa8, 0x03, 3 - devc->channels);	/* Mono/stereo */
 	ess_write(devc, 0xb9, 2);	/* Demand mode (4 bytes/request) */
 
-	if (devc->channels == 1)
-	{
-		if (devc->bits == AFMT_U8)
-		{	/* 8 bit mono */
-			ess_write(devc, 0xb6, 0x80);
-			ess_write(devc, 0xb7, 0x51);
-			ess_write(devc, 0xb7, 0xd0);
-		}
-		else
-		{	/* 16 bit mono */
-			ess_write(devc, 0xb6, 0x00);
-			ess_write(devc, 0xb7, 0x71);
-			ess_write(devc, 0xb7, 0xf4);
-		}
-	}
-	else
-	{	/* Stereo */
-		if (devc->bits == AFMT_U8)
-		{	/* 8 bit stereo */
-			ess_write(devc, 0xb6, 0x80);
-			ess_write(devc, 0xb7, 0x51);
-			ess_write(devc, 0xb7, 0x98);
-		}
-		else
-		{		/* 16 bit stereo */
-			ess_write(devc, 0xb6, 0x00);
-			ess_write(devc, 0xb7, 0x71);
-			ess_write(devc, 0xb7, 0xbc);
-		}
-	}
+	ess_exec_commands (devc, ess_out_cmds);
+
+	ess_change (devc, 0xb1, 0xf0, 0x50);
+	ess_change (devc, 0xb2, 0xf0, 0x50);
 
-	ess_write(devc, 0xb1, (ess_read(devc, 0xb1) & 0x0f) | 0x50);
-	ess_write(devc, 0xb2, (ess_read(devc, 0xb2) & 0x0f) | 0x50);
 	sb_dsp_command(devc, DSP_CMD_SPKON);
 
 	devc->trigger_bits = 0;
@@ -774,7 +773,7 @@
 	ess_write(devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
 	ess_write(devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
 
-	ess_write(devc, 0xb8, ess_read(devc, 0xb8) | 0x05);	/* Go */
+	ess_change (devc, 0xb8, 0x05, 0x05);	/* Go */
 	devc->intr_active = 1;
 }
 
@@ -798,8 +797,8 @@
 
 	ess_write(devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
 	ess_write(devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
-
-	ess_write(devc, 0xb8, ess_read(devc, 0xb8) | 0x0f);	/* Go */
+ 
+	ess_change (devc, 0xb8, 0x0f, 0x0f);	/* Go */
 	devc->intr_active = 1;
 }
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
--- v2.2.0-pre5/linux/drivers/sound/sb_common.c	Thu Jan  7 15:11:38 1999
+++ linux/drivers/sound/sb_common.c	Thu Jan  7 09:24:00 1999
@@ -13,7 +13,7 @@
 /*
  * Daniel J. Rodriksson: Modified sbintr to handle 8 and 16 bit interrupts
  *                       for full duplex support ( only sb16 by now )
- * Rolf Fokkens:	 Added (BETA?) support for ES188x chips.
+ * Rolf Fokkens:	 Added (BETA?) support for ES1887 chips.
  * (fokkensr@vertis.nl)	 Which means: You can adjust the recording levels.
  */
 #include <linux/config.h>
@@ -554,6 +554,15 @@
 	/*
 	 * This the detection heuristic of ESS technology, though somewhat
 	 * changed to actually make it work.
+	 * This results in the following detection steps:
+	 * - distinct between ES688 and ES1688+ (as always done in this driver)
+	 *   if ES688 we're ready
+	 * - try to detect ES1868, ES1869 or ES1878 (ess_identify)
+	 *   if successful we're ready
+	 * - try to detect ES1888, ES1887 or ES1788 (aim: detect ES1887)
+	 *   if successful we're ready
+	 * - Dunno. Must be 1688. Will do in general
+	 *
 	 * This is the most BETA part of the software: Will the detection
          * always work?
 	 */
@@ -568,7 +577,7 @@
 			chip = "ES688";
 		};
 		if (chip == NULL) {
-			int type, dummy;
+			int type;
 
 			type = ess_identify (devc);
 
@@ -587,12 +596,18 @@
 				break;
 			};
 		};
-		if (chip == NULL) {
-			if (  !ess_probe (devc, 0x64, (1 << 3))
-			    && ess_probe (devc, 0x70, 0x7f)) {
-				chip = "ES188x";
+		if (chip == NULL && !ess_probe(devc, 0x64, (1 << 3))) {
+			if (ess_probe (devc, 0x70, 0x7f)) {
+				if (ess_probe (devc, 0x64, (1 << 5))) {
+					chip = "ES1887";
+				} else {
+					chip = "ES1888";
+				}
 				devc->submodel = SUBMDL_ES188X;
-			};
+			} else {
+				chip = "ES1788";
+				devc->submodel = SUBMDL_ES1788;
+			}
 		};
 		if (chip == NULL) {
 			chip = "ES1688";
@@ -1066,7 +1081,7 @@
 /*
  *	Mixer access routines
  *
- *	ES188x modifications: some mixer registers reside in the
+ *	ES1887 modifications: some mixer registers reside in the
  *	range above 0xa0. These must be accessed in another way.
  */
 
@@ -1107,7 +1122,10 @@
 
 	return val;
 }
-
+/*
+ * Some PnP chips can be identified by repeatedly reading mixer register 0x40.
+ * This is done by ess_identify
+ */
 static unsigned int ess_identify (sb_devc * devc)
 {
 	unsigned int val;
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/sb_mixer.c linux/drivers/sound/sb_mixer.c
--- v2.2.0-pre5/linux/drivers/sound/sb_mixer.c	Thu Jan  7 15:11:38 1999
+++ linux/drivers/sound/sb_mixer.c	Thu Jan  7 09:24:00 1999
@@ -14,31 +14,82 @@
  *
  * Thomas Sailer		: ioctl code reworked (vmalloc/vfree removed)
  * Rolf Fokkens (Dec 20 1998)	: ES188x recording level support on a per
- *				  input basis
- *              (Dec 24 1998)	: Recognition of ES188x (?), ES1868, ES1869
- *				  and ES1878. Could be used for specific
- *				  handling in the future. All except ES188x
- *				  and ES688 are handled like ES1688
- *              (Dec 27 1998)	: RECLEV for all (?) ES1688+ chips, see 
- *				  ess_mixer_reload for more info. ES188x now
- *				  has the "Dec 20" support + RECLEV
+ *				  input basis.
+ *              (Dec 24 1998)	: Recognition of ES1788, ES1887, ES1888,
+ *				  ES1868, ES1869 and ES1878. Could be used for
+ *				  specific handling in the future. All except
+ *				  ES1887 and ES1888 and ES688 are handled like
+ *				  ES1688.
+ *              (Dec 27 1998)	: RECLEV for all (?) ES1688+ chips. ES188x now
+ *				  have the "Dec 20" support + RECLEV
  */
 
 /*
- * About ES188x support:
+ * About the documentation
+ *
+ * I don't know if the chips all are OK, but the documentation is buggy. 'cause
+ * I don't have all the cips myself, there's a lot I cannot verify. I'll try to
+ * keep track of my latest insights about his here. If you have additional info,
+ * please enlighten me (fokkensr@vertis.nl)!
  *
- * The standard ES1688 support doesn't take care of the ES188x recording
- * levels very well. Whenever a device is selected (recmask) for recording
- * it's recording level is loud, and it cannot be changed.
+ * I had the impression that ES1688 also has 6 bit master volume control. The
+ * documentation about ES1888 (rev C, october '95) claims that ES1888 has
+ * the following features ES1688 doesn't have:
+ * - 6 bit master volume
+ * - Full Duplex
+ * So ES1688 apparently doesn't have 6 bit master volume control, but the
+ * ES1688 does have RECLEV control. Makes me wonder: does ES688 have it too?
+ * Without RECLEV ES688 won't be much fun I guess.
  *
- * The ES188x has separate registers to control the recording levels. The
- * ES188x specific software makes these level the same as their corresponding
- * playback levels, unless recmask says they aren't recorded. In the latter
- * case the recording volumes are 0.
+ * From the ES1888 (rev C, october '95) documentation I got the impression
+ * that registers 0x68 to 0x6e don't exist which means: no recording volume
+ * controls. To my surprise the ES888 documentation (1/14/96) claims that
+ * ES888 does have these record mixer registers, but that ES1888 doesn't have
+ * 0x69 and 0x6b. So the rest should be there.
+ * 
+ */
+
+/*
+ * About recognition of ESS chips
+ *
+ * The distinction of ES688, ES1688, ES1788, ES1887 and ES1888 is described in
+ * a (preliminary ??) datasheet on ES1887. It's aim is to identify ES1887, but
+ * during detection the text claims that "this chip may be ..." when a step
+ * fails. This scheme is used to distinct between the above chips.
+ * It appears however that some PnP chips like ES1868 are recognized as ES1788
+ * by the ES1887 detection scheme. These PnP chips can be detected in another
+ * way however: ES1868, ES1869 and ES1878 can be recognized (full proof I think)
+ * by repeatedly reading mixer register 0x40. This is done by ess_identify in
+ * sb_common.c.
+ * This results in the following detection steps:
+ * - distinct between ES688 and ES1688+ (as always done in this driver)
+ *   if ES688 we're ready
+ * - try to detect ES1868, ES1869 or ES1878
+ *   if successful we're ready
+ * - try to detect ES1888, ES1887 or ES1788
+ *   if successful we're ready
+ * - Dunno. Must be 1688. Will do in general
+ *
+ * About RECLEV support:
+ *
+ * The existing ES1688 support didn't take care of the ES1688+ recording
+ * levels very well. Whenever a device was selected (recmask) for recording
+ * it's recording level was loud, and it couldn't be changed. The fact that
+ * internal register 0xb4 could take care of RECLEV, didn't work meaning until
+ * it's value was restored every time the chip was reset; this reset the
+ * value of 0xb4 too. I guess that's what 4front also had (have?) trouble with.
+ *
+ * About ES188x support:
  *
+ * The ES188x has separate registers to control the recording levels, for all
+ * inputs. The ES188x specific software makes these levels the same as their
+ * corresponding playback levels, unless recmask says they aren't recorded. In
+ * the latter case the recording volumes are 0.
  * Now recording levels of inputs can be controlled, by changing the playback
  * levels. Futhermore several devices can be recorded together (which is not
  * possible with the ES1688.
+ * Besides the separate recording level control for each input, the common
+ * recordig level can also be controlled by RECLEV as described above.
  */
 
 #include <linux/config.h>
@@ -50,6 +101,77 @@
 #include "sb.h"
 #include "sb_mixer.h"
 
+#define SBPRO_RECORDING_DEVICES	(SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
+
+/* Same as SB Pro, unless I find otherwise */
+#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
+
+#define SBPRO_MIXER_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+					 SOUND_MASK_CD | SOUND_MASK_VOLUME)
+
+/* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
+ * channel is the COVOX/DisneySoundSource emulation volume control
+ * on the mixer. It does NOT control speaker volume. Should have own
+ * mask eventually?
+ */
+#define SGNXPRO_MIXER_DEVICES	(SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
+				 SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
+
+#define SB16_RECORDING_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+					 SOUND_MASK_CD)
+
+#define SB16_OUTFILTER_DEVICES		(SOUND_MASK_LINE | SOUND_MASK_MIC | \
+					 SOUND_MASK_CD)
+
+#define ES688_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
+#define ES688_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER)
+
+#define ES1688_RECORDING_DEVICES ES688_RECORDING_DEVICES
+#define ES1688_MIXER_DEVICES (ES688_MIXER_DEVICES|SOUND_MASK_RECLEV)
+
+#define ES188X_RECORDING_DEVICES	(ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 \
+					 |SOUND_MASK_SYNTH)
+#define ES188X_MIXER_DEVICES (ES1688_MIXER_DEVICES)
+
+#define SB16_MIXER_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+					 SOUND_MASK_CD | \
+					 SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
+					 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
+					SOUND_MASK_IMIX)
+
+/* These are the only devices that are working at the moment.  Others could
+ * be added once they are identified and a method is found to control them.
+ */
+#define ALS007_MIXER_DEVICES	(SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
+				 SOUND_MASK_PCM | SOUND_MASK_MIC | \
+				 SOUND_MASK_CD | \
+				 SOUND_MASK_VOLUME)
+
+/*
+ * Mixer registers of ES188x
+ *
+ * These registers specifically take care of recording levels. To make the
+ * mapping from playback devices to recording devices every recording
+ * devices = playback device + ES188X_MIXER_RECDIFF
+ */
+#define ES188X_MIXER_RECBASE	(SOUND_MIXER_LINE3 + 1)
+#define ES188X_MIXER_RECDIFF	(ES188X_MIXER_RECBASE - SOUND_MIXER_SYNTH)
+
+#define ES188X_MIXER_RECSYNTH	(SOUND_MIXER_SYNTH	+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECPCM	(SOUND_MIXER_PCM	+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECSPEAKER	(SOUND_MIXER_SPEAKER	+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE	(SOUND_MIXER_LINE	+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECMIC	(SOUND_MIXER_MIC	+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECCD	(SOUND_MIXER_CD		+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECIMIX	(SOUND_MIXER_IMIX	+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECALTPCM	(SOUND_MIXER_ALTPCM	+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECRECLEV	(SOUND_MIXER_RECLEV	+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECIGAIN	(SOUND_MIXER_IGAIN	+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECOGAIN	(SOUND_MIXER_OGAIN	+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE1	(SOUND_MIXER_LINE1	+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE2	(SOUND_MIXER_LINE2	+ ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE3	(SOUND_MIXER_LINE3	+ ES188X_MIXER_RECDIFF)
+
 static mixer_tab sbpro_mix = {
 MIX_ENT(SOUND_MIXER_VOLUME,	0x22, 7, 4, 0x22, 3, 4),
 MIX_ENT(SOUND_MIXER_BASS,	0x00, 0, 0, 0x00, 0, 0),
@@ -88,11 +210,12 @@
 /*
  * The ES1688 specifics... hopefully correct...
  * - 6 bit master volume
+ *   I was wrong, ES1888 docs say ES1688 didn't have it.
  * - RECLEV control
  * These may apply to ES688 too. I have no idea.
  */
 static mixer_tab es1688_mix = {
-MIX_ENT(SOUND_MIXER_VOLUME,	0x60, 5, 6, 0x62, 5, 6),
+MIX_ENT(SOUND_MIXER_VOLUME,	0x32, 7, 4, 0x32, 3, 4),
 MIX_ENT(SOUND_MIXER_BASS,	0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_TREBLE,	0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_SYNTH,	0x36, 7, 4, 0x36, 3, 4),
@@ -111,11 +234,30 @@
 MIX_ENT(SOUND_MIXER_LINE3,	0x00, 0, 0, 0x00, 0, 0)
 };
 
+static mixer_tab es1688later_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME,     0x60, 5, 6, 0x62, 5, 6),
+MIX_ENT(SOUND_MIXER_BASS,       0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE,     0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH,      0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM,        0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER,    0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE,       0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC,        0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD,         0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX,       0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM,     0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV,     0xb4, 7, 4, 0xb4, 3, 4),
+MIX_ENT(SOUND_MIXER_IGAIN,      0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN,      0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1,      0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2,      0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3,      0x00, 0, 0, 0x00, 0, 0)
+};
+
 /*
  * The ES188x specifics.
  * Note that de master volume unlike ES688 is now controlled by two 6 bit
- * registers. These seem to work OK on 1868 too, but I have no idea if it's
- * compatible to 688 or 1688....
+ * registers. These seem to work OK on 1868 too.
  * Also Note that the recording levels (ES188X_MIXER_REC...) have own 
  * entries as if they were playback devices. They are used internally in the
  * driver only!
@@ -314,78 +456,6 @@
   0x00				/* SOUND_MIXER_LINE3 */
 };
 
-#define SBPRO_RECORDING_DEVICES	(SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
-
-/* Same as SB Pro, unless I find otherwise */
-#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
-
-#define SBPRO_MIXER_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
-					 SOUND_MASK_CD | SOUND_MASK_VOLUME)
-
-/* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
- * channel is the COVOX/DisneySoundSource emulation volume control
- * on the mixer. It does NOT control speaker volume. Should have own
- * mask eventually?
- */
-#define SGNXPRO_MIXER_DEVICES	(SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
-				 SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
-
-#define SB16_RECORDING_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
-					 SOUND_MASK_CD)
-
-#define SB16_OUTFILTER_DEVICES		(SOUND_MASK_LINE | SOUND_MASK_MIC | \
-					 SOUND_MASK_CD)
-
-#define ES688_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
-#define ES688_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER)
-
-#define ES1688_RECORDING_DEVICES ES688_RECORDING_DEVICES
-#define ES1688_MIXER_DEVICES (ES688_MIXER_DEVICES|SOUND_MASK_RECLEV)
-
-#define ES188X_RECORDING_DEVICES	(ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 \
-					 |SOUND_MASK_SYNTH)
-#define ES188X_MIXER_DEVICES (ES1688_MIXER_DEVICES)
-
-#define SB16_MIXER_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
-					 SOUND_MASK_CD | \
-					 SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
-					 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
-					SOUND_MASK_IMIX)
-
-/* These are the only devices that are working at the moment.  Others could
- * be added once they are identified and a method is found to control them.
- */
-#define ALS007_MIXER_DEVICES	(SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
-				 SOUND_MASK_PCM | SOUND_MASK_MIC | \
-				 SOUND_MASK_CD | \
-				 SOUND_MASK_VOLUME)
-
-/*
- * Mixer registers of ES188x
- *
- * These registers specifically take care of recording levels. To make the
- * mapping from playback devices to recording devices every recording
- * devices = playback device + ES188X_MIXER_RECDIFF
- */
-#define ES188X_MIXER_RECBASE	(SOUND_MIXER_LINE3 + 1)
-#define ES188X_MIXER_RECDIFF	(ES188X_MIXER_RECBASE - SOUND_MIXER_SYNTH)
-
-#define ES188X_MIXER_RECSYNTH	(SOUND_MIXER_SYNTH	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECPCM	(SOUND_MIXER_PCM	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECSPEAKER	(SOUND_MIXER_SPEAKER	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE	(SOUND_MIXER_LINE	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECMIC	(SOUND_MIXER_MIC	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECCD	(SOUND_MIXER_CD		+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECIMIX	(SOUND_MIXER_IMIX	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECALTPCM	(SOUND_MIXER_ALTPCM	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECRECLEV	(SOUND_MIXER_RECLEV	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECIGAIN	(SOUND_MIXER_IGAIN	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECOGAIN	(SOUND_MIXER_OGAIN	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE1	(SOUND_MIXER_LINE1	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE2	(SOUND_MIXER_LINE2	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE3	(SOUND_MIXER_LINE3	+ ES188X_MIXER_RECDIFF)
-
-
 static int      sbmixnum = 1;
 
 static void     sb_mixer_reset(sb_devc * devc);
@@ -944,11 +1014,19 @@
 						= ES688_RECORDING_DEVICES;
 					devc->iomap = &es688_mix;
 				} else {
+					/*
+					 * es1688 has 4 bits master vol.
+					 * later chips have 6 bits (?)
+					 */
 					devc->supported_devices
 						= ES1688_MIXER_DEVICES;
 					devc->supported_rec_devices
 						= ES1688_RECORDING_DEVICES;
-					devc->iomap = &es1688_mix;
+					if (devc->submodel < 0x10) {
+						devc->iomap = &es1688_mix;
+					} else {
+						devc->iomap = &es1688later_mix;
+					}
 				}
 			}
 
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/sb_mixer.h linux/drivers/sound/sb_mixer.h
--- v2.2.0-pre5/linux/drivers/sound/sb_mixer.h	Thu Jan  7 15:11:38 1999
+++ linux/drivers/sound/sb_mixer.h	Thu Jan  7 09:24:00 1999
@@ -28,51 +28,6 @@
 
 #ifdef CONFIG_SBDSP
 
-#define SBPRO_RECORDING_DEVICES	(SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
-
-/* Same as SB Pro, unless I find otherwise */
-#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
-
-#define SBPRO_MIXER_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
-					 SOUND_MASK_CD | SOUND_MASK_VOLUME)
-
-/* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
- * channel is the COVOX/DisneySoundSource emulation volume control
- * on the mixer. It does NOT control speaker volume. Should have own
- * mask eventually?
- */
-#define SGNXPRO_MIXER_DEVICES	(SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
-				 SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
-
-#define SB16_RECORDING_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
-					 SOUND_MASK_CD)
-
-#define SB16_OUTFILTER_DEVICES		(SOUND_MASK_LINE | SOUND_MASK_MIC | \
-					 SOUND_MASK_CD)
-
-#define ES688_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
-#define ES688_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER)
-
-#define ES1688_RECORDING_DEVICES ES688_RECORDING_DEVICES
-#define ES1688_MIXER_DEVICES (ES688_MIXER_DEVICES|SOUND_MASK_RECLEV)
-
-#define ES188X_RECORDING_DEVICES	(ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 \
-					 |SOUND_MASK_SYNTH)
-#define ES188X_MIXER_DEVICES (ES1688_MIXER_DEVICES)
-
-#define SB16_MIXER_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
-					 SOUND_MASK_CD | \
-					 SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
-					 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
-					SOUND_MASK_IMIX)
-
-/* These are the only devices that are working at the moment.  Others could
- * be added once they are identified and a method is found to control them.
- */
-#define ALS007_MIXER_DEVICES	(SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
-				 SOUND_MASK_PCM | SOUND_MASK_MIC | \
-				 SOUND_MASK_CD | \
-				 SOUND_MASK_VOLUME)
 /*
  * Mixer registers
  * 
@@ -123,31 +78,6 @@
 #define RIGHT_CHN	1
 
 /*
- * Mixer registers of ES188x
- *
- * These registers specifically take care of recording levels. To make the
- * mapping from playback devices to recording devices every recording
- * devices = playback device + ES188X_MIXER_RECDIFF
- */
-#define ES188X_MIXER_RECBASE	(SOUND_MIXER_LINE3 + 1)
-#define ES188X_MIXER_RECDIFF	(ES188X_MIXER_RECBASE - SOUND_MIXER_SYNTH)
-
-#define ES188X_MIXER_RECSYNTH	(SOUND_MIXER_SYNTH	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECPCM	(SOUND_MIXER_PCM	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECSPEAKER	(SOUND_MIXER_SPEAKER	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE	(SOUND_MIXER_LINE	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECMIC	(SOUND_MIXER_MIC	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECCD	(SOUND_MIXER_CD		+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECIMIX	(SOUND_MIXER_IMIX	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECALTPCM	(SOUND_MIXER_ALTPCM	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECRECLEV	(SOUND_MIXER_RECLEV	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECIGAIN	(SOUND_MIXER_IGAIN	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECOGAIN	(SOUND_MIXER_OGAIN	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE1	(SOUND_MIXER_LINE1	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE2	(SOUND_MIXER_LINE2	+ ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE3	(SOUND_MIXER_LINE3	+ ES188X_MIXER_RECDIFF)
-
-/*
  * Mixer registers of ALS007
  */
 #define ALS007_RECORD_SRC	0x6c
@@ -175,3 +105,4 @@
 #define ALS007_SYNTH	7
 
 #endif
+
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.2.0-pre5/linux/drivers/sound/sonicvibes.c	Thu Jan  7 15:11:38 1999
+++ linux/drivers/sound/sonicvibes.c	Thu Jan  7 09:24:00 1999
@@ -49,6 +49,8 @@
  *    31.08.98   0.7   Fix realplayer problems - dac.count issues
  *    10.12.98   0.8   Fix drain_dac trying to wait on not yet initialized DMA
  *    16.12.98   0.9   Fix a few f_file & FMODE_ bugs
+ *    06.01.99   0.10  remove the silly SA_INTERRUPT flag.
+ *                     hopefully killed the egcs section type conflict
  *
  */
 
@@ -2243,7 +2245,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static const struct initvol {
+static struct initvol {
 	int mixch;
 	int vol;
 } initvol[] __initdata = {
@@ -2271,7 +2273,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "sv: version v0.9 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "sv: version v0.10 time " __TIME__ " " __DATE__ "\n");
 #if 0
 	if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
 		printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
@@ -2382,7 +2384,7 @@
 		wrindir(s, SV_CIPCMSR1, ((8000 * 65536 / FULLRATE) >> 8) & 0xff);
 		wrindir(s, SV_CIADCOUTPUT, 0);
 		/* request irq */
-		if (request_irq(s->irq, sv_interrupt, SA_INTERRUPT|SA_SHIRQ, "S3 SonicVibes", s)) {
+		if (request_irq(s->irq, sv_interrupt, SA_SHIRQ, "S3 SonicVibes", s)) {
 			printk(KERN_ERR "sv: irq %u in use\n", s->irq);
 			goto err_irq;
 		}
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c
--- v2.2.0-pre5/linux/drivers/sound/sound_core.c	Thu Jan  7 15:11:38 1999
+++ linux/drivers/sound/sound_core.c	Thu Jan  7 09:24:00 1999
@@ -349,14 +349,13 @@
 	return -ENODEV;
 }
 
+extern int mod_firmware_load(const char *, char **);
+EXPORT_SYMBOL(mod_firmware_load);
+
 #ifdef MODULE
 
 MODULE_DESCRIPTION("Core sound module");
 MODULE_AUTHOR("Alan Cox");
-
-extern int mod_firmware_load(const char *, char **);
-EXPORT_SYMBOL(mod_firmware_load);
-
 
 void cleanup_module(void)
 {
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/waveartist.c linux/drivers/sound/waveartist.c
--- v2.2.0-pre5/linux/drivers/sound/waveartist.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/waveartist.c	Thu Jan  7 09:24:00 1999
@@ -0,0 +1,1956 @@
+/*
+ * drivers/sound/waveartist.c
+ *
+ * The low level driver for the RWA010 Rockwell Wave Artist
+ * codec chip used in the Corel Computer NetWinder.
+ *
+ * Cleaned up and integrated into 2.1 by Russell King (rmk@arm.linux.org.uk)
+ */
+
+/*
+ * Copyright (C) by Corel Computer 1998
+ *
+ * RWA010 specs received under NDA from Rockwell
+ *
+ * Copyright (C) by Hannu Savolainen 1993-1997
+ *
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info.
+ */
+
+/* Debugging */
+#define DEBUG_CMD	1
+#define DEBUG_OUT	2
+#define DEBUG_IN	4
+#define DEBUG_INTR	8
+#define DEBUG_MIXER	16
+#define DEBUG_TRIGGER	32
+
+#define debug_flg (0)
+
+#define DEB(x)
+#define DDB(x)
+#define DEB1(x)
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+
+#include <asm/hardware.h>
+
+#include "soundmodule.h"
+#include "sound_config.h"
+#include "waveartist.h"
+
+#define	VNC_TIMER_PERIOD (HZ/4)	//check slider 4 times/sec
+
+#define	MIXER_PRIVATE3_RESET	0x53570000
+#define	MIXER_PRIVATE3_READ	0x53570001
+#define	MIXER_PRIVATE3_WRITE	0x53570002
+
+#define	VNC_INTERNAL_SPKR	0x01	//the sw mute on/off control bit
+#define	VNC_INTERNAL_MIC	0x10	//the hw internal/handset mic bit
+
+/* Use RECSRC = speaker to mark the internal microphone
+ *
+ * Some cheating involved here: there is no way to relay
+ * to the system, which microphone in in use
+ * (left = handset, or right = internal)
+ *
+ * So while I do not flag SPEAKER in the Recording Devices
+ * Mask, when on internal
+ *
+ * mike - I set the speaker bit hi. Some mixers can be
+ * confused a bit...
+ */
+
+#define POSSIBLE_RECORDING_DEVICES	(SOUND_MASK_LINE |\
+					 SOUND_MASK_MIC |\
+					 SOUND_MASK_LINE1)	//Line1 = analog phone
+
+#define SUPPORTED_MIXER_DEVICES		(SOUND_MASK_SYNTH |\
+					 SOUND_MASK_PCM |\
+					 SOUND_MASK_LINE |\
+					 SOUND_MASK_MIC | \
+					 SOUND_MASK_LINE1 |\
+					 SOUND_MASK_RECLEV |\
+					 SOUND_MASK_VOLUME)
+
+static unsigned short levels[SOUND_MIXER_NRDEVICES] = {
+	0x5555,		/* Master Volume	 */
+	0x0000,		/* Bass			 */
+	0x0000,		/* Treble		 */
+	0x5555,		/* Synth (FM)		 */
+	0x4b4b,		/* PCM			 */
+	0x0000,		/* PC Speaker		 */
+	0x0000,		/* Ext Line		 */
+	0x0000,		/* Mic			 */
+	0x0000,		/* CD			 */
+	0x0000,		/* Recording monitor	 */
+	0x0000,		/* SB PCM (ALT PCM)	 */
+	0x0000,		/* Recording level	 */
+	0x0000,		/* Input gain		 */
+	0x0000,		/* Output gain		 */
+	0x0000,		/* Line1 (Aux1)		 */
+	0x0000,		/* Line2 (Aux2)		 */
+	0x0000,		/* Line3 (Aux3)		 */
+	0x0000,		/* Digital1		 */
+	0x0000,		/* Digital2		 */
+	0x0000,		/* Digital3		 */
+	0x0000,		/* Phone In		 */
+	0x0000,		/* Phone Out		 */
+	0x0000,		/* Video		 */
+	0x0000,		/* Radio		 */
+	0x0000		/* Monitor		 */
+};
+
+typedef struct {
+	struct address_info  hw;	/* hardware */
+	char		*chip_name;
+
+	int		xfer_count;
+	int		audio_mode;
+	int		open_mode;
+	int		audio_flags;
+	int		record_dev;
+	int		playback_dev;
+	int		dev_no;
+
+	/* Mixer parameters */
+	unsigned short	*levels;
+	int		handset_state;
+	signed int	slider_vol;	   /* hardware slider volume */
+	int		recmask;	   /* currently enabled recording device! */
+	int             supported_devices; /* SUPPORTED_MIXER_DEVICES */
+	int             rec_devices;	   /* POSSIBLE_RECORDING_DEVICES */
+	int		handset_mute_sw	:1;/* 1 - handset controlled in sw */
+	int		use_slider	:1;/* use slider setting for o/p vol */
+	int		mute_state	:1;
+} wavnc_info;
+
+typedef struct wavnc_port_info {
+	int		open_mode;
+	int		speed;
+	int		channels;
+	int		audio_format;
+} wavnc_port_info;
+
+static int		 nr_waveartist_devs;
+static wavnc_info	 adev_info[MAX_AUDIO_DEV];
+static struct timer_list vnc_timer;
+
+
+static inline void
+waveartist_set_ctlr(struct address_info *hw, unsigned char clear, unsigned char set)
+{
+	unsigned int ctlr_port = hw->io_base + CTLR;
+
+	clear = ~clear & inb(ctlr_port);
+
+	outb(clear | set, ctlr_port);
+}
+
+/* Toggle IRQ acknowledge line
+ */
+static inline void
+waveartist_iack(wavnc_info *devc)
+{
+	unsigned int ctlr_port = devc->hw.io_base + CTLR;
+	int old_ctlr;
+
+	old_ctlr = inb(ctlr_port) & ~IRQ_ACK;
+
+	outb(old_ctlr | IRQ_ACK, ctlr_port);
+	outb(old_ctlr, ctlr_port);
+}
+
+static inline int
+waveartist_sleep(int timeout_ms)
+{
+	unsigned int timeout = timeout_ms * 10 * HZ / 100;
+
+	do {
+		current->state = TASK_INTERRUPTIBLE;
+		timeout = schedule_timeout(timeout);
+	} while (timeout);
+
+	return 0;
+}
+
+static int
+waveartist_reset(wavnc_info *devc)
+{
+	struct address_info *hw = &devc->hw;
+	unsigned int timeout, res = -1;
+
+	waveartist_set_ctlr(hw, -1, RESET);
+	waveartist_sleep(2);
+	waveartist_set_ctlr(hw, RESET, 0);
+
+	timeout = 500;
+	do {
+		mdelay(2);
+
+		if (inb(hw->io_base + STATR) & CMD_RF) {
+			res = inw(hw->io_base + CMDR);
+			if (res == 0x55aa)
+				break;
+		}
+	} while (timeout--);
+
+	if (timeout == 0) {
+		printk("WaveArtist: reset timeout ");
+		if (res != (unsigned int)-1)
+			printk("(res=%04X)", res);
+		printk("\n");
+		return 1;
+	}
+	return 0;
+}
+
+static int
+waveartist_cmd(wavnc_info *devc,
+		int nr_cmd, unsigned int *cmd,
+		int nr_resp, unsigned int *resp)
+{
+	unsigned int io_base = devc->hw.io_base;
+	unsigned int timed_out = 0;
+	unsigned int i;
+
+	if (debug_flg & DEBUG_CMD) {
+		printk("waveartist_cmd: cmd=");
+
+		for (i = 0; i < nr_cmd; i++)
+			printk("%04X ", cmd[i]);
+
+		printk("\n");
+	}
+
+	if (inb(io_base + STATR) & CMD_RF) {
+		int old_data;
+
+		/* flush the port
+		 */
+
+		old_data = inw(io_base + CMDR);
+
+		if (debug_flg & DEBUG_CMD)
+			printk("flushed %04X...", old_data);
+
+		udelay(10);
+	}
+
+	for (i = 0; !timed_out && i < nr_cmd; i++) {
+		int count;
+
+		for (count = 5000; count; count--)
+			if (inb(io_base + STATR) & CMD_WE)
+				break;
+
+		if (!count)
+			timed_out = 1;
+		else
+			outw(cmd[i], io_base + CMDR);
+	}
+
+	for (i = 0; !timed_out && i < nr_resp; i++) {
+		int count;
+
+		for (count = 5000; count; count--)
+			if (inb(io_base + STATR) & CMD_RF)
+				break;
+
+		if (!count)
+			timed_out = 1;
+		else
+			resp[i] = inw(io_base + CMDR);
+	}
+
+	if (debug_flg & DEBUG_CMD) {
+		if (!timed_out) {
+			printk("waveartist_cmd: resp=");
+
+			for (i = 0; i < nr_resp; i++)
+				printk("%04X ", resp[i]);
+
+			printk("\n");
+		} else
+			printk("waveartist_cmd: timed out\n");
+	}
+
+	return timed_out ? 1 : 0;
+}
+
+static inline int
+waveartist_cmd2(wavnc_info *devc, unsigned int cmd, unsigned int arg)
+{
+	unsigned int vals[2];
+
+	vals[0] = cmd;
+	vals[1] = arg;
+
+	waveartist_cmd(devc, 2, vals, 1, vals);
+
+	return 0;
+}
+
+static inline int
+waveartist_cmd3(wavnc_info *devc, unsigned int cmd,
+		unsigned int arg1, unsigned int arg2)
+{
+	unsigned int vals[3];
+
+	vals[0] = cmd;
+	vals[1] = arg1;
+	vals[2] = arg2;
+
+	return waveartist_cmd(devc, 3, vals, 0, NULL);
+}
+
+static int
+waveartist_sendcmd(struct address_info *hw, unsigned int cmd)
+{
+	int count;
+
+	if (debug_flg & DEBUG_CMD)
+		printk("waveartist_sendcmd: cmd=0x%04X...", cmd);
+
+	udelay(10);
+
+	if (inb(hw->io_base + STATR) & CMD_RF) {
+		/*
+		 * flush the port
+		 */
+		count = inw(hw->io_base + CMDR);
+
+		udelay(10);
+
+		if (debug_flg & DEBUG_CMD)
+			printk(" flushed %04X...", count);
+	}
+
+	/*
+	 * preset timeout at 5000 loops
+	 */
+	count = 5000;
+
+	while (count --)
+		if (inb(hw->io_base + STATR) & CMD_WE) {
+			/* wait till CMD_WE is high
+			 * then output the command
+			 */
+			outw(cmd, hw->io_base + CMDR);
+			break;
+		}
+
+	/* ready BEFORE timeout?
+	 */
+	if (debug_flg & DEBUG_CMD)
+		printk(" %s\n", count ? "Done OK." : "Error!");
+
+	udelay(10);
+
+	return count ? 0 : 1;
+}
+
+static int
+waveartist_getrev(struct address_info *hw, char *rev)
+{
+	int temp;
+
+	waveartist_sendcmd(hw, 0);
+	udelay(20);
+	temp = inw(hw->io_base + CMDR);
+	udelay(20);
+	inw(hw->io_base + CMDR);	// discard second word == 0
+
+	rev[0] = temp >> 8;
+	rev[1] = temp & 255;
+	rev[2] = '\0';
+
+	return temp;
+}
+
+inline void
+waveartist_mute(wavnc_info *devc, int mute)
+{
+}
+
+static void waveartist_halt_output(int dev);
+static void waveartist_halt_input(int dev);
+static void waveartist_halt(int dev);
+static void waveartist_trigger(int dev, int state);
+
+static int
+waveartist_open(int dev, int mode)
+{
+	wavnc_info	*devc;
+	wavnc_port_info	*portc;
+	unsigned long	flags;
+
+	if (dev < 0 || dev >= num_audiodevs)
+		return -ENXIO;
+
+	devc  = (wavnc_info *) audio_devs[dev]->devc;
+	portc = (wavnc_port_info *) audio_devs[dev]->portc;
+
+	save_flags(flags);
+	cli();
+	if (portc->open_mode || (devc->open_mode & mode)) {
+		restore_flags(flags);
+		return -EBUSY;
+	}
+
+	devc->audio_mode  = 0;
+	devc->open_mode  |= mode;
+	portc->open_mode  = mode;
+	waveartist_trigger(dev, 0);
+
+	if (mode & OPEN_READ)
+		devc->record_dev = dev;
+	if (mode & OPEN_WRITE)
+		devc->playback_dev = dev;
+	restore_flags(flags);
+
+	/*
+	 * Mute output until the playback really starts. This
+	 * decreases clicking (hope so).
+	 */
+	waveartist_mute(devc, 1);
+
+	return 0;
+}
+
+static void
+waveartist_close(int dev)
+{
+	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;
+	wavnc_port_info	*portc = (wavnc_port_info *) audio_devs[dev]->portc;
+	unsigned long	flags;
+
+	save_flags(flags);
+	cli();
+
+	waveartist_halt(dev);
+
+	devc->audio_mode = 0;
+	devc->open_mode &= ~portc->open_mode;
+	portc->open_mode = 0;
+
+	waveartist_mute(devc, 1);
+
+	restore_flags(flags);
+}
+
+static void
+waveartist_output_block(int dev, unsigned long buf, int __count, int intrflag)
+{
+	wavnc_port_info	*portc = (wavnc_port_info *) audio_devs[dev]->portc;
+	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;
+	unsigned long	flags;
+	unsigned int	count = __count; 
+
+	if (debug_flg & DEBUG_OUT)
+		printk("waveartist: output block, buf=0x%lx, count=0x%x...\n",
+			buf, count);
+	/*
+	 * 16 bit data
+	 */
+	if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE))
+		count >>= 1;
+
+	if (portc->channels > 1)
+		count >>= 1;
+
+	count -= 1;
+
+	if (devc->audio_mode & PCM_ENABLE_OUTPUT &&
+	    audio_devs[dev]->flags & DMA_AUTOMODE &&
+	    intrflag &&
+	    count == devc->xfer_count) {
+		devc->audio_mode |= PCM_ENABLE_OUTPUT;
+		return;	/*
+			 * Auto DMA mode on. No need to react
+			 */
+	}
+
+	save_flags(flags);
+	cli();
+
+	/*
+	 * set sample count
+	 */
+	waveartist_cmd2(devc, 0x0024, count);
+
+	devc->xfer_count = count;
+	devc->audio_mode |= PCM_ENABLE_OUTPUT;
+
+	restore_flags(flags);
+}
+
+static void
+waveartist_start_input(int dev, unsigned long buf, int __count, int intrflag)
+{
+	wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;
+	unsigned long	flags;
+	unsigned int	count = __count;
+
+	if (debug_flg & DEBUG_IN)
+		printk("waveartist: start input, buf=0x%lx, count=0x%x...\n",
+			buf, count);
+
+	if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE))	/* 16 bit data */
+		count >>= 1;
+
+	if (portc->channels > 1)
+		count >>= 1;
+
+	count -= 1;
+
+	if (devc->audio_mode & PCM_ENABLE_INPUT &&
+	    audio_devs[dev]->flags & DMA_AUTOMODE &&
+	    intrflag &&
+	    count == devc->xfer_count) {
+		devc->audio_mode |= PCM_ENABLE_INPUT;
+		return;	/*
+			 * Auto DMA mode on. No need to react
+			 */
+	}
+
+	save_flags(flags);
+	cli();
+
+	/*
+	 * set sample count
+	 */
+	waveartist_cmd2(devc, 0x0014, count);
+	waveartist_mute(devc, 0);
+
+	devc->xfer_count = count;
+	devc->audio_mode |= PCM_ENABLE_INPUT;
+
+	restore_flags(flags);
+}
+
+static int
+waveartist_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+	return -EINVAL;
+}
+
+static unsigned int
+waveartist_get_speed(wavnc_port_info *portc)
+{
+	unsigned int speed;
+
+	/*
+	 * program the speed, channels, bits
+	 */
+	if (portc->speed == 8000)
+		speed = 0x2E71;
+	else if (portc->speed == 11025)
+		speed = 0x4000;
+	else if (portc->speed == 22050)
+		speed = 0x8000;
+	else if (portc->speed == 44100)
+		speed = 0x0;
+	else {
+		/*
+		 * non-standard - just calculate
+		 */
+		speed = portc->speed << 16;
+
+		speed = (speed / 44100) & 65535;
+	}
+
+	return speed;
+}
+
+static unsigned int
+waveartist_get_bits(wavnc_port_info *portc)
+{
+	unsigned int bits;
+
+	if (portc->audio_format == AFMT_S16_LE)
+		bits = 1;
+	else if (portc->audio_format == AFMT_S8)
+		bits = 0;
+	else
+		bits = 2;	//default AFMT_U8
+
+	return bits;
+}
+
+static int
+waveartist_prepare_for_input(int dev, int bsize, int bcount)
+{
+	unsigned long	flags;
+	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;
+	wavnc_port_info	*portc = (wavnc_port_info *) audio_devs[dev]->portc;
+	unsigned int	speed, bits;
+
+	if (devc->audio_mode)
+		return 0;
+
+	speed = waveartist_get_speed(portc);
+	bits  = waveartist_get_bits(portc);
+
+	save_flags(flags);
+	cli();
+
+	if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits))
+		printk("waveartist: error setting the record format to %d\n",
+		       portc->audio_format);
+
+	if (waveartist_cmd2(devc, WACMD_INPUTCHANNELS, portc->channels))
+		printk("waveartist: error setting record to %d channels\n",
+		       portc->channels);
+
+	/*
+	 * write cmd SetSampleSpeedTimeConstant
+	 */
+	if (waveartist_cmd2(devc, WACMD_INPUTSPEED, speed))
+		printk("waveartist: error setting the record speed "
+		       "to %dHz.\n", portc->speed);
+
+	if (waveartist_cmd2(devc, WACMD_INPUTDMA, 1))
+		printk("waveartist: error setting the record data path "
+		       "to 0x%X\n", 1);
+
+	if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits))
+		printk("waveartist: error setting the record format to %d\n",
+		       portc->audio_format);
+
+	devc->xfer_count = 0;
+	restore_flags(flags);
+	waveartist_halt_input(dev);
+
+	if (debug_flg & DEBUG_INTR) {
+		printk("WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR));
+		printk("WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR));
+		printk("WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT));
+	}
+
+	return 0;
+}
+
+static int
+waveartist_prepare_for_output(int dev, int bsize, int bcount)
+{
+	unsigned long	flags;
+	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;
+	wavnc_port_info	*portc = (wavnc_port_info *) audio_devs[dev]->portc;
+	unsigned int	speed, bits;
+
+	/*
+	 * program the speed, channels, bits
+	 */
+	speed = waveartist_get_speed(portc);
+	bits  = waveartist_get_bits(portc);
+
+	save_flags(flags);
+	cli();
+
+	if (waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed) &&
+	    waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed))
+		printk("waveartist: error setting the playback speed "
+		       "to %dHz.\n", portc->speed);
+
+	if (waveartist_cmd2(devc, WACMD_OUTPUTCHANNELS, portc->channels))
+		printk("waveartist: error setting the playback to"
+		       " %d channels\n", portc->channels);
+
+	if (waveartist_cmd2(devc, WACMD_OUTPUTDMA, 0))
+		printk("waveartist: error setting the playback data path "
+		       "to 0x%X\n", 0);
+
+	if (waveartist_cmd2(devc, WACMD_OUTPUTFORMAT, bits))
+		printk("waveartist: error setting the playback format to %d\n",
+		       portc->audio_format);
+
+	devc->xfer_count = 0;
+	restore_flags(flags);
+	waveartist_halt_output(dev);
+
+	if (debug_flg & DEBUG_INTR) {
+		printk("WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR));
+		printk("WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR));
+		printk("WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT));
+	}
+
+	return 0;
+}
+
+static void
+waveartist_halt(int dev)
+{
+	wavnc_port_info	*portc = (wavnc_port_info *) audio_devs[dev]->portc;
+	wavnc_info	*devc;
+
+
+	if (portc->open_mode & OPEN_WRITE)
+		waveartist_halt_output(dev);
+
+	if (portc->open_mode & OPEN_READ)
+		waveartist_halt_input(dev);
+
+	devc = (wavnc_info *) audio_devs[dev]->devc;
+	devc->audio_mode = 0;
+}
+
+static void
+waveartist_halt_input(int dev)
+{
+	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;
+	unsigned long	flags;
+
+	save_flags(flags);
+	cli();
+
+	waveartist_mute(devc, 1);
+
+//RMK	disable_dma(audio_devs[dev]->dmap_in->dma);
+
+	/*
+	 * Stop capture
+	 */
+	waveartist_sendcmd(&devc->hw, 0x17);
+
+//RMK	enable_dma(audio_devs[dev]->dmap_in->dma);
+	devc->audio_mode &= ~PCM_ENABLE_INPUT;
+
+	/*
+	 * Clear interrupt by toggling
+	 * the IRQ_ACK bit in CTRL
+	 */
+	if (inb(devc->hw.io_base + STATR) & IRQ_REQ)
+		waveartist_iack(devc);
+
+//	devc->audio_mode &= ~PCM_ENABLE_INPUT;
+
+	restore_flags(flags);
+}
+
+static void
+waveartist_halt_output(int dev)
+{
+	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;
+	unsigned long	flags;
+
+	save_flags(flags);
+	cli();
+
+	waveartist_mute(devc, 1);
+
+//RMK	disable_dma(audio_devs[dev]->dmap_out->dma);
+
+	waveartist_sendcmd(&devc->hw, 0x27);
+
+//RMK	enable_dma(audio_devs[dev]->dmap_out->dma);
+
+	devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
+
+	/*
+	 * Clear interrupt by toggling
+	 * the IRQ_ACK bit in CTRL
+	 */
+	if (inb(devc->hw.io_base + STATR) & IRQ_REQ)
+		waveartist_iack(devc);
+
+//	devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
+
+	restore_flags(flags);
+}
+
+static void
+waveartist_trigger(int dev, int state)
+{
+	wavnc_info	*devc = (wavnc_info *) audio_devs[dev]->devc;
+	wavnc_port_info	*portc = (wavnc_port_info *) audio_devs[dev]->portc;
+	unsigned long	flags;
+
+	if (debug_flg & DEBUG_TRIGGER) {
+		printk("wavnc: audio trigger ");
+		if (state & PCM_ENABLE_INPUT)
+			printk("in ");
+		if (state & PCM_ENABLE_OUTPUT)
+			printk("out");
+		printk("\n");
+	}
+
+	save_flags(flags);
+	cli();
+
+	state &= devc->audio_mode;
+
+	if (portc->open_mode & OPEN_READ &&
+	    state & PCM_ENABLE_INPUT)
+		/*
+		 * enable ADC Data Transfer to PC
+		 */
+		waveartist_sendcmd(&devc->hw, 0x15);
+
+	if (portc->open_mode & OPEN_WRITE &&
+	    state & PCM_ENABLE_OUTPUT)
+		/*
+		 * enable DAC data transfer from PC
+		 */
+		waveartist_sendcmd(&devc->hw, 0x25);
+
+	waveartist_mute(devc, 0);
+
+	restore_flags(flags);
+}
+
+static int
+waveartist_set_speed(int dev, int arg)
+{
+	wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+
+	if (arg <= 0)
+		return portc->speed;
+
+	if (arg < 5000)
+		arg = 5000;
+	if (arg > 44100)
+		arg = 44100;
+
+	portc->speed = arg;
+	return portc->speed;
+
+}
+
+static short
+waveartist_set_channels(int dev, short arg)
+{
+	wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+
+	if (arg != 1 && arg != 2)
+		return portc->channels;
+
+	portc->channels = arg;
+	return arg;
+}
+
+static unsigned int
+waveartist_set_bits(int dev, unsigned int arg)
+{
+	wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+
+	if (arg == 0)
+		return portc->audio_format;
+
+	if ((arg != AFMT_U8) && (arg != AFMT_S16_LE) && (arg != AFMT_S8))
+		arg = AFMT_U8;
+
+	portc->audio_format = arg;
+
+	return arg;
+}
+
+static struct audio_driver waveartist_audio_driver = {
+	waveartist_open,
+	waveartist_close,
+	waveartist_output_block,
+	waveartist_start_input,
+	waveartist_ioctl,
+	waveartist_prepare_for_input,
+	waveartist_prepare_for_output,
+	waveartist_halt,
+	NULL,
+	NULL,
+	waveartist_halt_input,
+	waveartist_halt_output,
+	waveartist_trigger,
+	waveartist_set_speed,
+	waveartist_set_bits,
+	waveartist_set_channels
+};
+
+
+static void
+waveartist_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	wavnc_info *devc = (wavnc_info *)dev_id;
+	int	   irqstatus, status;
+
+	irqstatus = inb(devc->hw.io_base + IRQSTAT);
+	status    = inb(devc->hw.io_base + STATR);
+
+	if (debug_flg & DEBUG_INTR)
+		printk("waveartist_intr: stat=%02x, irqstat=%02x\n",
+		       status, irqstatus);
+
+	if (status & IRQ_REQ)	/* Clear interrupt */
+		waveartist_iack(devc);
+	else
+		printk("waveartist: unexpected interrupt\n");
+
+#ifdef CONFIG_AUDIO
+	if (irqstatus & 0x01) {
+		int temp = 1;
+
+		/* PCM buffer done
+		 */
+		if ((status & DMA0) && (devc->audio_mode & PCM_ENABLE_OUTPUT)) {
+			DMAbuf_outputintr(devc->playback_dev, 1);
+			temp = 0;
+		}
+		if ((status & DMA1) && (devc->audio_mode & PCM_ENABLE_INPUT)) {
+			DMAbuf_inputintr(devc->record_dev);
+			temp = 0;
+		}
+		if (temp)	//default:
+			printk("WaveArtist: Unknown interrupt\n");
+	}
+#endif
+	if (irqstatus & 0x2)
+		// We do not use SB mode natively...
+		printk("WaveArtist: Unexpected SB interrupt...\n");
+}
+
+/* -------------------------------------------------------------------------
+ * Mixer stuff
+ */
+static void
+waveartist_mixer_update(wavnc_info *devc, int whichDev)
+{
+	unsigned int mask, reg_l, reg_r;
+	unsigned int lev_left, lev_right;
+	unsigned int vals[3];
+
+	lev_left  = devc->levels[whichDev] & 0xff;
+	lev_right = devc->levels[whichDev] >> 8;
+
+#define SCALE(lev,max)	((lev) * (max) / 100)
+
+	switch(whichDev) {
+	case SOUND_MIXER_VOLUME:
+		mask  = 0x000e;
+		reg_l = 0x200;
+		reg_r = 0x600;
+		lev_left  = SCALE(lev_left,  7) << 1;
+		lev_right = SCALE(lev_right, 7) << 1;
+		break;
+
+	case SOUND_MIXER_LINE:
+		mask  = 0x07c0;
+		reg_l = 0x000;
+		reg_r = 0x400;
+		lev_left  = SCALE(lev_left,  31) << 6;
+		lev_right = SCALE(lev_right, 31) << 6;
+		break;
+
+	case SOUND_MIXER_MIC:
+		mask  = 0x0030;
+		reg_l = 0x200;
+		reg_r = 0x600;
+		lev_left  = SCALE(lev_left,  3) << 4;
+		lev_right = SCALE(lev_right, 3) << 4;
+		break;
+
+	case SOUND_MIXER_RECLEV:
+		mask  = 0x000f;
+		reg_l = 0x300;
+		reg_r = 0x700;
+		lev_left  = SCALE(lev_left,  10);
+		lev_right = SCALE(lev_right, 10);
+		break;
+
+	case SOUND_MIXER_LINE1:
+		mask  = 0x003e;
+		reg_l = 0x000;
+		reg_r = 0x400;
+		lev_left  = SCALE(lev_left,  31) << 1;
+		lev_right = SCALE(lev_right, 31) << 1;
+		break;
+
+	case SOUND_MIXER_PCM:
+		waveartist_cmd3(devc, 0x0031, SCALE(lev_left,  32767),
+				SCALE(lev_right, 32767));
+		return;
+
+	case SOUND_MIXER_SYNTH:
+		waveartist_cmd3(devc, 0x0131, SCALE(lev_left,  32767),
+				SCALE(lev_right, 32767));
+		return;
+
+	default:
+		return;
+	}
+
+	/* read left setting */
+	vals[0] = reg_l + 0x30;
+	waveartist_cmd(devc, 1, vals, 1, vals + 1);
+
+	/* read right setting */
+	vals[0] = reg_r + 0x30;
+	waveartist_cmd(devc, 1, vals, 1, vals + 2);
+
+	vals[1] = (vals[1] & ~mask) | (lev_left  & mask);
+	vals[2] = (vals[2] & ~mask) | (lev_right & mask);
+
+	/* write left,right back */
+	vals[0] = 0x32;
+	waveartist_cmd(devc, 3, vals, 0, NULL);
+}
+
+static void
+waveartist_select_input(wavnc_info *devc, unsigned int input)
+{
+	unsigned int vals[3];
+#if 1
+	/* New mixer programming - switch recording source
+	 * using R/L_ADC_Mux_Select.  We are playing with
+	 * left/right mux bit fields in reg 9.
+	 *
+	 * We can not switch Mux_Select while recording, so
+	 * for microphones, enable both left and right and
+	 * play with levels only!
+	 *
+	 * Unfortunately, we need to select the src of mono
+	 * recording (left or right) before starting the
+	 * recording - so can not dynamically switch between
+	 * handset amd internal microphones...
+	 */
+
+	/*
+	 * Get reg 9
+	 */
+	vals[0] = 0x0830;
+	waveartist_cmd(devc, 1, vals, 1, vals + 1);
+
+	/*
+	 * Get reg 10, only so that we can write it back.
+	 */
+	vals[0] = 0x0930;
+	waveartist_cmd(devc, 1, vals, 1, vals + 2);
+
+	if (debug_flg & DEBUG_MIXER)
+		printk("RECSRC: old left: 0x%04X, old right: 0x%04X.\n",
+			vals[1] & 0x07, (vals[1] >> 3) & 0x07);
+
+	vals[1] &= ~0x03F;	//kill current left/right mux input select
+
+	switch (input) {
+		/*
+		 * Handset or internal MIC
+		 */
+	case SOUND_MASK_MIC:
+		/*
+		 * handset not plugged in?
+		 */
+		if (devc->handset_state & VNC_INTERNAL_MIC) {
+			/*
+			 * set mono recording from right mic
+			 */
+			waveartist_sendcmd(&devc->hw, 0x0134);
+#if 0
+			/*
+			 * right=mic, left=none
+			 */
+			vals[1] |= 0x0028;
+			/*
+			 * pretend int mic
+			 */
+			devc->rec_devices |= SOUND_MASK_SPEAKER;
+#endif
+		} else {
+			/*
+			 * set mono rec from left mic
+			 */
+			waveartist_sendcmd(&devc->hw, 0x0034);
+#if 0
+			/*
+			 * right=none, left=mic
+			 */
+			vals[1] |= 0x0005;
+			/*
+			 * show no int mic
+			 */
+			devc->rec_devices &= ~SOUND_MASK_SPEAKER;
+#endif
+		}
+		/*
+		 * right=mic, left=mic
+		 */
+		vals[1] |= 0x002D;
+		break;
+
+	case SOUND_MASK_LINE1:
+		/*
+		 * set mono rec from left aux1
+		 */
+		waveartist_sendcmd(&devc->hw, 0x0034);
+		/*
+		 * right=none, left=Aux1;
+		 */
+		vals[1] |= 0x0004;
+		break;
+
+	case SOUND_MASK_LINE:
+		/*
+		 * set mono rec from left (default)
+		 */
+		waveartist_sendcmd(&devc->hw, 0x0034);
+		/*
+		 * right=Line, left=Line;
+		 */
+		vals[1] |= 0x0012;
+		break;
+	}
+
+	if (debug_flg & DEBUG_MIXER)
+		printk("RECSRC %d: left=0x%04X, right=0x%04X.\n", input,
+			vals[1] & 0x07, (vals[1] >> 3) & 0x07);
+
+#else
+	/* This part is good, if input connected to
+	 * a mixer, so can be used for record-only modes...
+	 */
+
+	/*
+	 * get reg 4
+	 */
+	vals[0] = 0x0330;
+	waveartist_cmd(devc, 1, vals, 1, vals + 1);
+
+	/*
+	 * get reg 8
+	 */
+	vals[0] = 0x0730;
+	waveartist_cmd(devc, 1, vals, 1, vals + 2);
+
+	if (debug_flg & DEBUG_MIXER)
+		printk("RECSRC: old left: 0x%04X, old right: 0x%04X.\n",
+			vals[1], vals[2]);
+
+	/*
+	 * kill current left/right mux input select
+	 */
+	vals[1] &= ~0x07F8;
+	vals[2] &= ~0x07F8;
+
+	switch (input) {
+		/*
+		 * handset or internal mic
+		 */
+	case SOUND_MASK_MIC:
+		/*
+		 * handset not plugged in?
+		 */
+		if (devc->handset_state & VNC_INTERNAL_MIC) {
+			/*
+			 * set mono recording from right mic
+			 */
+			waveartist_sendcmd(&devc->hw, 0x0134);
+			/*
+			 * left = none, right = mic, RX filter gain
+			 */
+			vals[1] |= 0x0C00;
+			vals[2] |= 0x0C88;
+			/*
+			 * pretend int mic
+			 */
+			devc->rec_devices |= SOUND_MASK_SPEAKER;
+		} else {
+			/*
+			 * set mono rec from left mic
+			 */
+			waveartist_sendcmd(&devc->hw, 0x0034);
+			/*
+			 * left = mic, RX filter gain, right = none;
+			 */
+			vals[1] |= 0x0C88;
+			vals[2] |= 0x0C00;
+			/*
+			 * show no int mic
+			 */
+			devc->rec_devices &= ~SOUND_MASK_SPEAKER;
+		}
+		break;
+
+	case SOUND_MASK_LINE1:
+		/*
+		 * set mono rec from left aux1
+		 */
+		waveartist_sendcmd(&devc->hw, 0x0034);
+		/*
+		 * left = Aux1, right = none
+		 */
+		vals[1] |= 0x0C40;
+		vals[2] |= 0x0C00;
+		break;
+	
+	case SOUND_MASK_LINE:
+		/*
+		 * left = Line, right = Line
+		 */
+		vals[1] |= 0x0C10;
+		vals[2] |= 0x0C10;
+		break;
+	}
+
+	if (debug_flg & DEBUG_MIXER)
+		printk("RECSRC %d: left(4) 0x%04X, right(8) 0x%04X.\n",
+			level, vals[1], vals[2]);
+#endif
+	/*
+	 * and finally - write the reg pair back....
+	 */
+	vals[0] = 0x32;
+
+	waveartist_cmd(devc, 3, vals, 0, NULL);
+}
+
+static int
+waveartist_mixer_set(wavnc_info *devc, int whichDev, unsigned int level)
+{
+	unsigned int lev_left  = level & 0x007f;
+	unsigned int lev_right = (level & 0x7f00) >> 8;
+
+	int left, right, devmask, changed, i;
+
+	left = level & 0x7f;
+	right = (level & 0x7f00) >> 8;
+
+	if (debug_flg & DEBUG_MIXER)
+		printk("wa_mixer_set(dev=%d, level=%X)\n",
+			whichDev, level);
+
+	switch (whichDev) {
+	/* Master volume (0-7)
+	 * We have 3 bits on the Left/Right Mixer Gain,
+	 * bits 3,2,1 on 3 and 7
+	 */
+	case SOUND_MIXER_VOLUME:
+		devc->levels[whichDev] = lev_left | lev_right << 8;
+		waveartist_mixer_update(devc, whichDev);
+		break;
+
+
+	/* External line (0-31)
+	 * use LOUT/ROUT bits 10...6, reg 1 and 5
+	 */
+	case SOUND_MIXER_LINE:
+		devc->levels[whichDev] = lev_left | lev_right << 8;
+		waveartist_mixer_update(devc, whichDev);
+		break;
+
+	/* Mono microphone (0-3) mute,
+	 * 0db,10db,20db
+	 */
+	case SOUND_MIXER_MIC:
+#if 1
+		devc->levels[whichDev] = lev_left | lev_right << 8;
+#else
+		/* we do not need to mute volume of
+		 * an unused mic - it is simply unused...
+		 */
+		if (devc->handset_state & VNC_INTERNAL_MIC)
+			devc->levels[whichDev] = lev_right << 8;
+		else
+			levels[whichDev] = lev_left;
+#endif
+		waveartist_mixer_update(devc, whichDev);
+		break;
+
+	/* Recording level (0-7)
+	 */
+	case SOUND_MIXER_RECLEV:
+		devc->levels[whichDev] = lev_left | lev_right << 8;
+		waveartist_mixer_update(devc, whichDev);
+		break;
+
+	/* Mono External Aux1 (0-31)
+	 * use LINE1 bits 5...1, reg 1 and 5
+	 */
+	case SOUND_MIXER_LINE1:
+		devc->levels[whichDev] = lev_left | lev_right << 8;
+		waveartist_mixer_update(devc, whichDev);
+		break;
+
+	/* WaveArtist PCM (0-32767)
+	 */
+	case SOUND_MIXER_PCM:
+		devc->levels[whichDev] = lev_left | lev_right << 8;
+		waveartist_mixer_update(devc, whichDev);
+		break;
+
+	/* Internal synthesizer (0-31)
+	 */
+	case SOUND_MIXER_SYNTH:
+		devc->levels[whichDev] = lev_left | lev_right << 8;
+		waveartist_mixer_update(devc, whichDev);
+		break;
+
+
+	/* Select recording input source
+	 */
+	case SOUND_MIXER_RECSRC:
+		devmask = level & POSSIBLE_RECORDING_DEVICES;
+
+		changed = devmask ^ devc->recmask;
+		devc->recmask = devmask;
+
+		for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+			if (changed & (1 << i))
+				waveartist_mixer_update(devc, i);
+
+		waveartist_select_input(devc, level);
+		/*
+		 * do not save in "levels", return current setting
+		 */
+		return devc->recmask;
+
+	default:
+		return -EINVAL;
+	}
+
+	return devc->levels[whichDev];
+}
+
+static void
+waveartist_mixer_reset(wavnc_info *devc)
+{
+	int i;
+
+	if (debug_flg & DEBUG_MIXER)
+		printk("%s: mixer_reset\n", devc->hw.name);
+
+	/*
+	 * reset mixer cmd
+	 */
+	waveartist_sendcmd(&devc->hw, 0x33);
+
+	/*
+	 * set input for ADC to come from
+	 * a mux (left and right) == reg 9,
+	 * initially none
+	 */
+	waveartist_cmd3(devc, 0x0032, 0x9800, 0xa836);
+
+	/*
+	 * set mixer input select to none, RX filter gains 0 db
+	 */
+	waveartist_cmd3(devc, 0x0032, 0x4c00, 0x8c00);
+
+	/*
+	 * set bit 0 reg 2 to 1 - unmute MonoOut
+	 */
+	waveartist_cmd3(devc, 0x0032, 0x2801, 0x6800);
+
+	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+		waveartist_mixer_update(devc, i);
+
+	/* set default input device = internal mic
+	 * current recording device = none
+	 * no handset
+	 */
+	devc->recmask = 0;
+	devc->handset_state = VNC_INTERNAL_MIC;
+//	waveartist_mixer_set(devc, SOUND_MIXER_RECSRC, SOUND_MASK_MIC);
+
+	/*
+	 * start from enabling the hw setting
+	 */
+	devc->handset_mute_sw = 0;
+	devc->supported_devices = SUPPORTED_MIXER_DEVICES;
+	devc->rec_devices = POSSIBLE_RECORDING_DEVICES;
+}
+
+static int
+waveartist_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+	wavnc_info *devc = (wavnc_info *)audio_devs[dev]->devc;
+#if 0
+	//use this call to override the automatic handset behaviour - ignore handset
+	//bit 0x80 = total control over handset - do not react to plug/unplug
+	//bit 0x10 = 1 == internal mic, otherwise handset mic
+	//bit 0x01 = 1 == mute internal speaker, otherwise unmute
+
+	if (cmd == SOUND_MIXER_PRIVATE1) {
+		int             val, temp;
+
+		val = *(int *) arg;
+
+//		printk("MIXER_PRIVATE1: passed parameter = 0x%X.\n",val);
+		return -EINVAL;		//check if parameter is logical...
+
+		devc->soft_mute_flag = val;
+
+		temp = val & VNC_INTERNAL_SPKR;
+		if (temp != devc->mute_state) {
+//			printk("MIXER_PRIVATE1: mute_mono(0x%X).\n",temp);
+			vnc_mute(devc, temp);
+		}
+
+//		temp = devc->handset_state;
+
+		// do not check if it is not already in
+		// the right setting, since we are
+		// laying about the current state...
+
+//		if ((val & VNC_INTERNAL_MIC) != temp) {
+			devc->handset_state = val & VNC_INTERNAL_MIC;
+//			printk("MIXER_PRIVATE1: mixer_set(0x%X).\n",devc->handset_state);
+			wa_mixer_set(devc, SOUND_MIXER_RECSRC, SOUND_MASK_MIC);
+//			devc->handset_state = temp;
+		}
+		return 0;
+	}
+#if 0
+	if (cmd == SOUND_MIXER_PRIVATE2) {
+#define VNC_SOUND_PAUSE         0x53    //to pause the DSP
+#define VNC_SOUND_RESUME        0x57    //to unpause the DSP
+		int             val;
+
+		val = *(int *) arg;
+
+		printk("MIXER_PRIVATE2: passed parameter = 0x%X.\n",val);
+
+		if (val == VNC_SOUND_PAUSE) {
+			wa_sendcmd(0x16);    //PAUSE the ADC
+		} else if (val == VNC_SOUND_RESUME) {
+			wa_sendcmd(0x18);    //RESUME the ADC
+		} else {
+			return -EINVAL;      //invalid parameters...
+		}
+		return 0;
+	}
+#endif
+
+	if (cmd == SOUND_MIXER_PRIVATE3) {
+		long unsigned   flags;
+		int             mixer_reg[15];	//reg 14 is actually a command: read,write,reset
+
+		int             val;
+		int             i;
+
+		val = *(int *) arg;
+
+		if (verify_area(VERIFY_READ, (void *) val, sizeof(mixer_reg) == -EFAULT))
+			return (-EFAULT);
+
+		memcpy_fromfs(&mixer_reg, (void *) val, sizeof(mixer_reg));
+
+		if (mixer_reg[0x0E] == MIXER_PRIVATE3_RESET) { 	//reset command??
+			wavnc_mixer_reset(devc);
+			return (0);
+		} else if (mixer_reg[0x0E] == MIXER_PRIVATE3_WRITE) {	//write command??
+//			printk("WaveArtist Mixer: Private write command.\n");
+
+			wa_sendcmd(0x32);	//Pair1 - word 1 and 5
+			wa_sendcmd(mixer_reg[0]);
+			wa_sendcmd(mixer_reg[4]);
+
+			wa_sendcmd(0x32);	//Pair2 - word 2 and 6
+			wa_sendcmd(mixer_reg[1]);
+			wa_sendcmd(mixer_reg[5]);
+
+			wa_sendcmd(0x32);	//Pair3 - word 3 and 7
+			wa_sendcmd(mixer_reg[2]);
+			wa_sendcmd(mixer_reg[6]);
+
+			wa_sendcmd(0x32);	//Pair4 - word 4 and 8
+			wa_sendcmd(mixer_reg[3]);
+			wa_sendcmd(mixer_reg[7]);
+
+			wa_sendcmd(0x32);	//Pair5 - word 9 and 10
+			wa_sendcmd(mixer_reg[8]);
+			wa_sendcmd(mixer_reg[9]);
+
+			wa_sendcmd(0x0031);		//set left and right PCM
+			wa_sendcmd(mixer_reg[0x0A]);
+			wa_sendcmd(mixer_reg[0x0B]);
+
+			wa_sendcmd(0x0131);		//set left and right FM
+			wa_sendcmd(mixer_reg[0x0C]);
+			wa_sendcmd(mixer_reg[0x0D]);
+
+			return 0;
+		} else if (mixer_reg[0x0E] == MIXER_PRIVATE3_READ) {	//read command?
+//			printk("WaveArtist Mixer: Private read command.\n");
+
+			//first read all current values...
+			save_flags(flags);
+			cli();
+
+			for (i = 0; i < 14; i++) {
+				wa_sendcmd((i << 8) + 0x30);	// get ready for command nn30H
+
+				while (!(inb(STATR) & CMD_RF)) {
+				};	//wait for response ready...
+
+				mixer_reg[i] = inw(CMDR);
+			}
+			restore_flags(flags);
+
+			if (verify_area(VERIFY_WRITE, (void *) val, sizeof(mixer_reg) == -EFAULT))
+				return (-EFAULT);
+
+			memcpy_tofs((void *) val, &mixer_reg, sizeof(mixer_reg));
+			return 0;
+		} else
+			return -EINVAL;
+	}
+#endif
+	if (((cmd >> 8) & 0xff) == 'M') {
+		if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
+			int val;
+
+			if (get_user(val, (int *)arg))
+				return -EFAULT;
+
+			/*
+			 * special case for master volume: if we
+			 * received this call - switch from hw
+			 * volume control to a software volume
+			 * control, till the hw volume is modified
+			 * to signal that user wants to be back in
+			 * hardware...
+			 */
+			if ((cmd & 0xff) == SOUND_MIXER_VOLUME)
+				devc->use_slider = 0;
+
+			return waveartist_mixer_set(devc, cmd & 0xff, val);
+		} else {
+			int ret;
+
+			/*
+			 * Return parameters
+			 */
+			switch (cmd & 0xff) {
+			case SOUND_MIXER_RECSRC:
+				ret = devc->recmask;
+
+				if (devc->handset_state & VNC_INTERNAL_MIC)
+					ret |= SOUND_MASK_SPEAKER;
+				break;
+
+			case SOUND_MIXER_DEVMASK:
+				ret = devc->supported_devices;
+				break;
+
+			case SOUND_MIXER_STEREODEVS:
+				ret = devc->supported_devices &
+					~(SOUND_MASK_SPEAKER|SOUND_MASK_IMIX);
+				break;
+
+			case SOUND_MIXER_RECMASK:
+				ret = devc->rec_devices;
+				break;
+
+			case SOUND_MIXER_CAPS:
+				ret = SOUND_CAP_EXCL_INPUT;
+				break;
+
+			default:
+				if ((cmd & 0xff) < SOUND_MIXER_NRDEVICES)
+					ret = devc->levels[cmd & 0xff];
+				else
+					return -EINVAL;
+			}
+
+			return put_user(ret, (int *)arg) ? -EINVAL : 0;
+		}
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static struct mixer_operations waveartist_mixer_operations =
+{
+	"WaveArtist",
+	"WaveArtist NetWinder",
+	waveartist_mixer_ioctl
+};
+
+static int
+waveartist_init(wavnc_info *devc)
+{
+	wavnc_port_info *portc;
+	char rev[3], dev_name[64];
+	int my_dev;
+
+	waveartist_reset(devc);
+
+	sprintf(dev_name, "%s (%s", devc->hw.name, devc->chip_name);
+
+	if (waveartist_getrev(&devc->hw, rev)) {
+		strcat(dev_name, " rev. ");
+		strcat(dev_name, rev);
+	}
+	strcat(dev_name, ")");
+
+	conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq,
+		     devc->hw.dma, devc->hw.dma2);
+
+	portc = (wavnc_port_info *)kmalloc(sizeof(wavnc_port_info), GFP_KERNEL);
+	if (portc == NULL)
+		goto nomem;
+
+	memset(portc, 0, sizeof(wavnc_port_info));
+
+	my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, dev_name,
+			&waveartist_audio_driver, sizeof(struct audio_driver),
+			devc->audio_flags, AFMT_U8 | AFMT_S16_LE | AFMT_S8,
+			devc, devc->hw.dma, devc->hw.dma2);
+
+	if (my_dev < 0)
+		goto free;
+
+	audio_devs[my_dev]->portc = portc;
+
+	waveartist_mixer_reset(devc);
+
+	/*
+	 * clear any pending interrupt
+	 */
+	waveartist_iack(devc);
+
+	if (request_irq(devc->hw.irq, waveartist_intr, 0, devc->hw.name, devc) < 0) {
+		printk("%s: IRQ %d in use\n",
+			devc->hw.name, devc->hw.irq);
+		goto uninstall;
+	}
+
+	if (sound_alloc_dma(devc->hw.dma, devc->hw.name)) {
+		printk("%s: Can't allocate DMA%d\n",
+			devc->hw.name, devc->hw.dma);
+		goto uninstall_irq;
+	}
+
+	if (devc->hw.dma != devc->hw.dma2 && devc->hw.dma2 != NO_DMA)
+		if (sound_alloc_dma(devc->hw.dma2, devc->hw.name)) {
+			printk("%s: can't allocate DMA%d\n",
+				devc->hw.name, devc->hw.dma2);
+			goto uninstall_dma;
+		}
+
+	waveartist_set_ctlr(&devc->hw, 0, DMA1_IE | DMA0_IE);
+
+	audio_devs[my_dev]->mixer_dev =
+		sound_install_mixer(MIXER_DRIVER_VERSION,
+				dev_name,
+				&waveartist_mixer_operations,
+				sizeof(struct mixer_operations),
+				devc);
+
+	return my_dev;
+
+uninstall_dma:
+	sound_free_dma(devc->hw.dma);
+
+uninstall_irq:
+	free_irq(devc->hw.irq, devc);
+
+uninstall:
+	sound_unload_audiodev(my_dev);
+
+free:
+	kfree(portc);
+
+nomem:
+	return -1;
+}
+
+/*
+ * Corel Netwinder specifics...
+ */
+static void
+vnc_mute(wavnc_info *devc, int mute)
+{
+	extern spinlock_t gpio_lock;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+	cpld_modify(CPLD_UNMUTE, mute ? 0 : CPLD_UNMUTE);
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	devc->mute_state = mute;
+}
+
+static int
+vnc_volume_slider(wavnc_info *devc)
+{
+	static signed int old_slider_volume;
+	unsigned long flags;
+	signed int volume = 255;
+
+	*CSR_TIMER1_LOAD = 0x00ffffff;
+
+	save_flags(flags);
+	cli();
+
+	outb(0xFF, 0x201);
+	*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV1;
+
+	while (volume && (inb(0x201) & 0x01))
+		volume--;
+
+	*CSR_TIMER1_CNTL = 0;
+
+	restore_flags(flags);
+	
+	volume = 0x00ffffff - *CSR_TIMER1_VALUE;
+
+
+#ifndef REVERSE
+	volume = 150 - (volume >> 5);
+#else
+	volume = (volume >> 6) - 25;
+#endif
+
+	if (volume < 0)
+		volume = 0;
+
+	if (volume > 100)
+		volume = 100;
+
+	/*
+	 * slider quite often reads +-8, so debounce this random noise
+	 */
+	if ((volume - old_slider_volume) > 7 ||
+	    (old_slider_volume - volume) > 7) {
+		old_slider_volume = volume;
+
+		DEB(printk("Slider volume: %d.\n", old_slider_volume));
+	}
+
+	return old_slider_volume;
+}
+
+static int
+vnc_slider(wavnc_info *devc)
+{
+	signed int slider_volume;
+	unsigned int temp;
+
+	/*
+	 * read the "buttons" state.
+	 *  Bit 4 = handset present,
+	 *  Bit 5 = offhook
+	 */
+	// the state should be "querable" via a private IOCTL call
+	temp = inb(0x201) & 0x30;
+
+	if (!devc->handset_mute_sw &&
+	    (temp ^ devc->handset_state) & VNC_INTERNAL_MIC) {
+		devc->handset_state = temp;
+		devc->handset_mute_sw = 0;
+
+		vnc_mute(devc, (temp & VNC_INTERNAL_MIC) ? 1 : 0);
+	}
+
+	slider_volume = vnc_volume_slider(devc);
+
+	/*
+	 * If we're using software controlled volume, and
+	 * the slider moves by more than 20%, then we
+	 * switch back to slider controlled volume.
+	 */
+	if (devc->slider_vol > slider_volume) {
+		if (devc->slider_vol - slider_volume > 20)
+			devc->use_slider = 1;
+	} else {
+		if (slider_volume - devc->slider_vol > 20)
+			devc->use_slider = 1;
+	}
+
+	/*
+	 * use only left channel
+	 */
+	temp = levels[SOUND_MIXER_VOLUME] & 0xFF;
+
+	if (slider_volume != temp && devc->use_slider) {
+		devc->slider_vol = slider_volume;
+
+		waveartist_mixer_set(devc, SOUND_MIXER_VOLUME,
+			slider_volume | slider_volume << 8);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+static void
+vnc_slider_tick(unsigned long data)
+{
+	int next_timeout;
+
+	if (vnc_slider(adev_info + data))
+		next_timeout = 5;	// mixer reported change
+	else
+		next_timeout = VNC_TIMER_PERIOD;
+
+	mod_timer(&vnc_timer, jiffies + next_timeout);
+}
+
+int
+probe_waveartist(struct address_info *hw_config)
+{
+	wavnc_info *devc = &adev_info[nr_waveartist_devs];
+
+	if (nr_waveartist_devs >= MAX_AUDIO_DEV) {
+		printk("waveartist: too many audio devices\n");
+		return 0;
+	}
+
+	if (check_region(hw_config->io_base, 15))  {
+		printk("WaveArtist: I/O port conflict\n");
+		return 0;
+	}
+
+	if (hw_config->irq > 31 || hw_config->irq < 16) {
+		printk("WaveArtist: Bad IRQ %d\n", hw_config->irq);
+		return 0;
+	}
+
+	if (hw_config->dma != 3) {
+		printk("WaveArtist: Bad DMA %d\n", hw_config->dma);
+		return 0;
+	}
+
+	hw_config->name = "WaveArtist";
+	devc->hw = *hw_config;
+	devc->open_mode = 0;
+	devc->chip_name = "RWA-010";
+
+	return 1;
+}
+
+void
+attach_waveartist(struct address_info *hw)
+{
+	wavnc_info *devc = &adev_info[nr_waveartist_devs];
+
+	/*
+	 * NOTE! If irq < 0, there is another driver which has allocated the
+	 *   IRQ so that this driver doesn't need to allocate/deallocate it.
+	 *   The actually used IRQ is ABS(irq).
+	 */
+	devc->hw = *hw;
+	devc->hw.irq = (hw->irq > 0) ? hw->irq : 0;
+	devc->open_mode = 0;
+	devc->playback_dev = 0;
+	devc->record_dev = 0;
+	devc->audio_flags = DMA_AUTOMODE;
+	devc->levels = levels;
+
+	if (hw->dma != hw->dma2 && hw->dma2 != NO_DMA)
+		devc->audio_flags |= DMA_DUPLEX;
+
+	request_region(hw->io_base, 15, devc->hw.name);
+
+	devc->dev_no = waveartist_init(devc);
+
+	if (devc->dev_no < 0)
+		release_region(hw->io_base, 15);
+	else {
+		init_timer(&vnc_timer);
+		vnc_timer.function = vnc_slider_tick;
+		vnc_timer.expires  = jiffies;
+		vnc_timer.data     = nr_waveartist_devs;
+		add_timer(&vnc_timer);
+
+		nr_waveartist_devs += 1;
+
+		vnc_mute(devc, 0);
+	}
+}
+
+void
+unload_waveartist(struct address_info *hw)
+{
+	wavnc_info *devc = NULL;
+	int i;
+
+	for (i = 0; i < nr_waveartist_devs; i++)
+		if (hw->io_base == adev_info[i].hw.io_base) {
+			devc = adev_info + i;
+			break;
+		}
+
+	if (devc != NULL) {
+		int mixer;
+
+		release_region(devc->hw.io_base, 15);
+
+		waveartist_set_ctlr(&devc->hw, DMA1_IE|DMA0_IE, 0);
+
+		if (devc->hw.irq >= 0)
+			free_irq(devc->hw.irq, devc);
+
+		sound_free_dma(devc->hw.dma);
+
+		if (devc->hw.dma != devc->hw.dma2 &&
+		    devc->hw.dma2 != NO_DMA)
+			sound_free_dma(devc->hw.dma2);
+
+		del_timer(&vnc_timer);
+
+		mixer = audio_devs[devc->dev_no]->mixer_dev;
+
+		if (mixer >= 0)
+			sound_unload_mixerdev(mixer);
+
+		if (devc->dev_no >= 0)
+			sound_unload_audiodev(devc->dev_no);
+
+		nr_waveartist_devs -= 1;
+
+		for (; i < nr_waveartist_devs; i++)
+			adev_info[i] = adev_info[i + 1];
+	} else
+		printk("waveartist: can't find device to unload\n");
+}
+
+#ifdef MODULE
+
+MODULE_PARM(io, "i");		/* IO base */
+MODULE_PARM(irq, "i");		/* IRQ */
+MODULE_PARM(dma, "i");		/* DMA */
+MODULE_PARM(dma2, "i");		/* DMA2 */
+
+int io   = CONFIG_WAVEARTIST_BASE;
+int irq  = CONFIG_WAVEARTIST_IRQ;
+int dma  = CONFIG_WAVEARTIST_DMA;
+int dma2 = CONFIG_WAVEARTIST_DMA2;
+
+static int attached;
+
+struct address_info hw_config;
+
+int init_module(void)
+{
+	hw_config.io_base = io;
+	hw_config.irq = irq;
+	hw_config.dma = dma;
+	hw_config.dma2 = dma2;
+
+	if (!probe_waveartist(&hw_config))
+		return -ENODEV;
+
+	attach_waveartist(&hw_config);
+	attached = 1;
+
+	SOUND_LOCK;
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	if (attached) {
+		SOUND_LOCK_END;
+
+		unload_waveartist(&hw_config);
+	}
+}
+#endif
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/sound/waveartist.h linux/drivers/sound/waveartist.h
--- v2.2.0-pre5/linux/drivers/sound/waveartist.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/waveartist.h	Thu Jan  7 09:24:00 1999
@@ -0,0 +1,68 @@
+
+// def file for Rockwell RWA010 chip set, as installed in Corel NetWinder
+
+//registers
+#define	WA_BASE	0
+//x250
+
+#define CMDR	WA_BASE+0
+#define DATR	WA_BASE+2
+
+#define CTLR	WA_BASE+4
+#define	STATR	WA_BASE+5
+
+#define	IRQSTAT	WA_BASE+12
+
+//bit defs
+//reg STATR
+#define	CMD_WE	0x80
+#define	CMD_RF	0x40
+#define	DAT_WE	0x20
+#define	DAT_RF	0x10
+
+#define	IRQ_REQ	0x08
+#define	DMA1	0x04
+#define	DMA0	0x02
+
+//bit defs
+//reg CTLR
+#define	CMD_WEIE	0x80
+#define	CMD_RFIE	0x40
+#define	DAT_WEIE	0x20
+#define	DAT_RFIE	0x10
+
+#define	RESET	0x08
+#define	DMA1_IE	0x04
+#define	DMA0_IE	0x02
+#define	IRQ_ACK	0x01
+
+//commands
+
+#define	WACMD_SYSTEMID	0
+#define	WACMD_INPUTFORMAT	0x10	//0-8S, 1-16S, 2-8U
+#define	WACMD_INPUTCHANNELS	0x11	//1-Mono, 2-Stereo
+#define	WACMD_INPUTSPEED	0x12	//sampling rate
+#define	WACMD_INPUTDMA		0x13	//0-8bit, 1-16bit, 2-PIO
+#define	WACMD_INPUTSIZE		0x14	//samples to interrupt
+#define	WACMD_INPUTSTART	0x15	//start ADC
+#define	WACMD_INPUTPAUSE	0x16	//pause ADC
+#define	WACMD_INPUTSTOP		0x17	//stop ADC
+#define	WACMD_INPUTRESUME	0x18	//resume ADC
+#define	WACMD_INPUTPIO		0x19	//PIO ADC
+
+#define	WACMD_OUTPUTFORMAT	0x20	//0-8S, 1-16S, 2-8U
+#define	WACMD_OUTPUTCHANNELS	0x21	//1-Mono, 2-Stereo
+#define	WACMD_OUTPUTSPEED	0x22	//sampling rate
+#define	WACMD_OUTPUTDMA		0x23	//0-8bit, 1-16bit, 2-PIO
+#define	WACMD_OUTPUTSIZE	0x24	//samples to interrupt
+#define	WACMD_OUTPUTSTART	0x25	//start ADC
+#define	WACMD_OUTPUTPAUSE	0x26	//pause ADC
+#define	WACMD_OUTPUTSTOP	0x27	//stop ADC
+#define	WACMD_OUTPUTRESUME	0x28	//resume ADC
+#define	WACMD_OUTPUTPIO		0x29	//PIO ADC
+
+
+
+
+int             wa_sendcmd(unsigned int cmd);
+int             wa_writecmd(unsigned int cmd, unsigned int arg);
diff -u --recursive --new-file v2.2.0-pre5/linux/drivers/video/matroxfb.c linux/drivers/video/matroxfb.c
--- v2.2.0-pre5/linux/drivers/video/matroxfb.c	Thu Jan  7 15:11:38 1999
+++ linux/drivers/video/matroxfb.c	Thu Jan  7 12:20:05 1999
@@ -100,6 +100,7 @@
 
 #include <asm/io.h>
 #include <asm/spinlock.h>
+#include <asm/unaligned.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 #endif
@@ -111,7 +112,7 @@
 #include <video/fbcon-cfb24.h>
 #include <video/fbcon-cfb32.h>
 
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_FB_OF)
 #if defined(CONFIG_FB_COMPAT_XPMAC)
 #include <asm/vc_ioctl.h>
 #endif
@@ -169,7 +170,7 @@
 /* I benchmarked PII/350MHz with G200... MEMCPY, MEMCPYTOIO and WRITEL are on same speed ( <2% diff) */
 /* so that means that G200 speed (or AGP speed?) is our limit... I do not have benchmark to test, how */
 /* much of PCI bandwidth is used during transfers... */
-#if defined(__i386__) || defined(__ppc__)
+#if defined(__i386__)
 #define MEMCPYTOIO_MEMCPY
 #else
 #define MEMCPYTOIO_WRITEL
@@ -180,11 +181,17 @@
 #error "Sorry, I have no idea how to do this on sparc... There is mapioaddr... With bus_type parameter..."
 #endif
 
-#ifdef __m68k__
+#if defined(__m68k__)
 #define MAP_BUSTOVIRT
 #else
+#if defined(CONFIG_PPC) && defined(CONFIG_PREP) && defined(_ISA_MEM_BASE)
+/* do not tell me that PPC is not broken... if ioremap() oops with
+   invalid value written to msr... */
+#define MAP_ISAMEMBASE
+#else
 #define MAP_IOREMAP
 #endif
+#endif
 
 #ifdef DEBUG
 #define dprintk(X...)	printk(X)
@@ -344,9 +351,13 @@
 #ifdef MAP_BUSTOVIRT
 	virt->vaddr = bus_to_virt(phys);
 #else
+#ifdef MAP_ISAMEMBASE
+	virt->vaddr = (void*)(phys + _ISA_MEM_BASE);
+#else
 #error "Your architecture does not have neither ioremap nor bus_to_virt... Giving up"
 #endif
 #endif
+#endif
 	return (virt->vaddr == 0); /* 0, !0... 0, error_code in future */
 }
 
@@ -554,6 +565,7 @@
 		int		inverse;
 		int		hwcursor;
 		int		blink;
+		int		sgram;
 
 		int		accelerator;
 		int		text_type_aux;
@@ -592,15 +604,13 @@
 	} cmap;
 #endif
 	struct { unsigned red, green, blue, transp; } palette[256];
-#if defined(CONFIG_PPC) && defined(CONFIG_FB_COMPAT_XPMAC)
+#if defined(CONFIG_FB_OF) && defined(CONFIG_FB_COMPAT_XPMAC)
 	char	matrox_name[32];
 #endif
 };
 
-#if defined(CONFIG_PPC)
-unsigned char nvram_read_byte(int);
-#endif
 #if defined(CONFIG_FB_OF)
+unsigned char nvram_read_byte(int);
 int matrox_of_init(struct device_node *dp);
 #endif
 
@@ -3116,7 +3126,7 @@
 		0x00, 0,  
 		M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL, 
 		M1064_XGENCTRL_VS_0 | M1064_XGENCTRL_ALPHA_DIS | M1064_XGENCTRL_BLACK_0IRE | M1064_XGENCTRL_NO_SYNC_ON_GREEN, 
-		M1064_XMISCCTRL_DAC_EN | M1064_XMISCCTRL_MFC_VGA | M1064_XMISCCTRL_DAC_8BIT | M1064_XMISCCTRL_LUT_EN,
+		M1064_XMISCCTRL_DAC_EN | M1064_XMISCCTRL_MFC_DIS | M1064_XMISCCTRL_DAC_8BIT | M1064_XMISCCTRL_LUT_EN,
 		0x10, 0x3F, M1064_XZOOMCTRL_1, M1064_XSENSETEST_BCOMP | M1064_XSENSETEST_GCOMP | M1064_XSENSETEST_RCOMP | M1064_XSENSETEST_PDOWN, 
 		0x00,
 		0x00, 0x00, 0xFF, 0xFF};
@@ -3200,7 +3210,7 @@
 	memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
 	if (p->type == FB_TYPE_TEXT) {
 		hw->DACreg[POS1064_XMISCCTRL] = M1064_XMISCCTRL_DAC_EN
-					      | M1064_XMISCCTRL_MFC_VGA
+					      | M1064_XMISCCTRL_MFC_DIS
 					      | M1064_XMISCCTRL_DAC_6BIT
 					      | M1064_XMISCCTRL_LUT_EN;
 		hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP 
@@ -3969,10 +3979,8 @@
 	pci_read_config_dword(ACCESS_FBINFO(pcidev), 0x50, &reg50);
 	reg50 &= ~0x3000;
 	pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50);
-	if (!(x7AF4 & 0x10))
-		hw->MXoptionReg |= 0x4000;
 	if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100) {
-		hw->MXoptionReg |= 0x1080;
+		hw->MXoptionReg |= 0x5080;
 		pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
 		mga_outl(M_CTLWTST, 0x01032521);
 		/* mga_outl(M_CTLWTST, 0x03258A31); */ 
@@ -3999,6 +4007,8 @@
 		}
 	} else {
 		hw->MXoptionReg |= 0x00000C00;
+		if (ACCESS_FBINFO(devflags.sgram))
+			hw->MXoptionReg |= 0x4000;
 		mga_outl(M_CTLWTST, 0x042450A1);
 		mga_outb(0x1E47, 0x00);
 		mga_outb(0x1E46, 0x00);
@@ -4513,7 +4523,7 @@
 			ACCESS_FBINFO(newhw) = ohw;
 			matrox_cfbX_init(PMINFO display);
 			do_install_cmap(PMINFO display);
-#if defined(CONFIG_PPC) && defined(CONFIG_FB_COMPAT_XPMAC)
+#if defined(CONFIG_FB_OF) && defined(CONFIG_FB_COMPAT_XPMAC)
 			if (console_fb_info == &ACCESS_FBINFO(fbcon)) {
 				int vmode, cmode;
 
@@ -4531,7 +4541,7 @@
 				display_info.cmap_data_address = 0;
 				display_info.disp_reg_address = ACCESS_FBINFO(mmio.base);
 			}
-#endif /* CONFIG_PPC && CONFIG_FB_COMPAT_XPMAC */
+#endif /* CONFIG_FB_OF && CONFIG_FB_COMPAT_XPMAC */
 		}
 	}
 	return 0;
@@ -4845,6 +4855,8 @@
 static int inverse = 0;			/* "matrox:inverse" */
 static int hwcursor = 1;		/* "matrox:nohwcursor" */
 static int blink = 1;			/* "matrox:noblink" */
+static int sgram = 0;			/* "matrox:sgram" */
+static int mtrr = 1;			/* "matrox:nomtrr" */
 static int grayscale = 0;		/* "matrox:grayscale" */
 static unsigned int fastfont = 0;	/* "matrox:fastfont:xxxxx" */
 static int dev = -1;			/* "matrox:dev:xxxxx" */
@@ -4935,6 +4947,10 @@
 			disabled = 1;
 		else if (!strcmp(this_opt, "enabled"))	/* noenabled does not exist */
 			disabled = 0;
+		else if (!strcmp(this_opt, "sgram"))	/* nosgram == sdram */
+			sgram = 1;
+		else if (!strcmp(this_opt, "sdram"))
+			sgram = 0;
 		else {
 			int value = 1;
 	
@@ -4956,6 +4972,8 @@
 				nobios = !value;
 			else if (!strcmp(this_opt, "init"))
 				noinit = !value;
+			else if (!strcmp(this_opt, "mtrr"))
+				mtrr = value;
 			else if (!strcmp(this_opt, "inv24"))
 				inv24 = value;
 			else if (!strcmp(this_opt, "cross4MB"))
@@ -5441,9 +5459,11 @@
 	if (ACCESS_FBINFO(video.len_usable) > 0x08000000)
 		ACCESS_FBINFO(video.len_usable) = 0x08000000;
 #ifdef CONFIG_MTRR
-	ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1);
-	ACCESS_FBINFO(mtrr.vram_valid) = 1;
-	printk(KERN_INFO "matroxfb: MTRR's turned on\n");
+	if (mtrr) {
+		ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1);
+		ACCESS_FBINFO(mtrr.vram_valid) = 1;
+		printk(KERN_INFO "matroxfb: MTRR's turned on\n");
+	}
 #endif	/* CONFIG_MTRR */
 
 /* validate params, autodetect k, M */
@@ -5563,7 +5583,7 @@
 	ACCESS_FBINFO(fbcon.flags) = FBINFO_FLAG_DEFAULT;
 	ACCESS_FBINFO(hw_switch->reset(PMINFO hw));
 	ACCESS_FBINFO(video.len_usable) &= PAGE_MASK;
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_FB_OF)
 #if defined(CONFIG_FB_COMPAT_XPMAC)
 	strcpy(ACCESS_FBINFO(matrox_name), "MTRX,");	/* OpenFirmware naming convension */
 	strncat(ACCESS_FBINFO(matrox_name), b->name, 26);
@@ -5679,6 +5699,7 @@
 				ACCESS_FBINFO(devflags.precise_width) = option_precise_width;
 				ACCESS_FBINFO(devflags.hwcursor) = hwcursor;
 				ACCESS_FBINFO(devflags.blink) = blink;
+				ACCESS_FBINFO(devflags.sgram) = sgram;
 				ACCESS_FBINFO(capable.cross4MB) = cross4MB;
 
 				ACCESS_FBINFO(fastfont.size) = fastfont;
@@ -5756,6 +5777,10 @@
 MODULE_PARM_DESC(nobios, "Disables ROM BIOS (0 or 1=disabled) (default=do not change BIOS state)"); 
 MODULE_PARM(noinit, "i");
 MODULE_PARM_DESC(noinit, "Disables W/SG/SD-RAM and bus interface initialization (0 or 1=do not initialize) (default=0)");
+MODULE_PARM(mtrr, "i");
+MODULE_PARM_DESC(mtrr, "This speeds up video memory accesses (0=disabled or 1) (default=1)");
+MODULE_PARM(sgram, "i");
+MODULE_PARM_DESC(sgram, "Indicates that G200 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)");
 MODULE_PARM(inv24, "i");
 MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
 MODULE_PARM(inverse, "i");
diff -u --recursive --new-file v2.2.0-pre5/linux/fs/buffer.c linux/fs/buffer.c
--- v2.2.0-pre5/linux/fs/buffer.c	Thu Jan  7 15:11:38 1999
+++ linux/fs/buffer.c	Thu Jan  7 15:06:59 1999
@@ -60,7 +60,7 @@
  */
 static unsigned long bh_hash_mask = 0;
 
-static int grow_buffers(int pri, int size);
+static int grow_buffers(int size);
 
 static struct buffer_head ** hash_table;
 static struct buffer_head * lru_list[NR_LIST] = {NULL, };
@@ -689,7 +689,7 @@
  */
 static void refill_freelist(int size)
 {
-	if (!grow_buffers(GFP_KERNEL, size)) {
+	if (!grow_buffers(size)) {
 		wakeup_bdflush(1);
 		current->policy |= SCHED_YIELD;
 		schedule();
@@ -1396,7 +1396,7 @@
  * Try to increase the number of buffers available: the size argument
  * is used to determine what kind of buffers we want.
  */
-static int grow_buffers(int pri, int size)
+static int grow_buffers(int size)
 {
 	unsigned long page;
 	struct buffer_head *bh, *tmp;
@@ -1408,7 +1408,7 @@
 		return 0;
 	}
 
-	if (!(page = __get_free_page(pri)))
+	if (!(page = __get_free_page(GFP_BUFFER)))
 		return 0;
 	bh = create_buffers(page, size, 0);
 	if (!bh) {
@@ -1571,7 +1571,7 @@
 	}
 
 	lru_list[BUF_CLEAN] = 0;
-	grow_buffers(GFP_KERNEL, BLOCK_SIZE);
+	grow_buffers(BLOCK_SIZE);
 }
 
 
diff -u --recursive --new-file v2.2.0-pre5/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.2.0-pre5/linux/fs/coda/psdev.c	Tue Dec 22 14:16:57 1998
+++ linux/fs/coda/psdev.c	Thu Jan  7 13:40:57 1999
@@ -375,7 +375,7 @@
 int init_module(void)
 {
 	int status;
-	printk(KERN_INFO "Coda Kernel/Venus communications (module), v4.7.5, braam@cs.cmu.edu.\n");
+	printk(KERN_INFO "Coda Kernel/Venus communications (module), v5.0-pre1, braam@cs.cmu.edu.\n");
 
 	status = init_coda_psdev();
 	if ( status ) {
diff -u --recursive --new-file v2.2.0-pre5/linux/fs/coda/upcall.c linux/fs/coda/upcall.c
--- v2.2.0-pre5/linux/fs/coda/upcall.c	Tue Dec 22 14:16:57 1998
+++ linux/fs/coda/upcall.c	Thu Jan  7 13:40:57 1999
@@ -807,7 +807,7 @@
 {
 
 	/* Handle invalidation requests. */
-          if ( !sb ) { 
+          if ( !sb || !sb->s_root || !sb->s_root->d_inode) { 
 	          printk("coda_downcall: opcode %d, no sb!\n", opcode);
 		  return 0; 
 	  }
diff -u --recursive --new-file v2.2.0-pre5/linux/fs/dcache.c linux/fs/dcache.c
--- v2.2.0-pre5/linux/fs/dcache.c	Thu Jan  7 15:11:38 1999
+++ linux/fs/dcache.c	Thu Jan  7 13:24:07 1999
@@ -166,10 +166,26 @@
  */
 int d_invalidate(struct dentry * dentry)
 {
-	/* Check whether to do a partial shrink_dcache */
+	/*
+	 * Check whether to do a partial shrink_dcache
+	 * to get rid of unused child entries.
+	 */
 	if (!list_empty(&dentry->d_subdirs)) {
 		shrink_dcache_parent(dentry);
-		if (!list_empty(&dentry->d_subdirs))
+	}
+
+	/*
+	 * Somebody still using it?
+	 *
+	 * If it's a directory, we can't drop it
+	 * for fear of somebody re-populating it
+	 * with children (even though dropping it
+	 * would make it unreachable from the root,
+	 * we might still populate it if it was a
+	 * working directory or similar).
+	 */
+	if (dentry->d_count) {
+		if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
 			return -EBUSY;
 	}
 
diff -u --recursive --new-file v2.2.0-pre5/linux/fs/nfsd/stats.c linux/fs/nfsd/stats.c
--- v2.2.0-pre5/linux/fs/nfsd/stats.c	Mon Jan  4 15:08:17 1999
+++ linux/fs/nfsd/stats.c	Thu Jan  7 09:28:47 1999
@@ -13,7 +13,6 @@
  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
diff -u --recursive --new-file v2.2.0-pre5/linux/fs/super.c linux/fs/super.c
--- v2.2.0-pre5/linux/fs/super.c	Thu Nov 19 09:56:29 1998
+++ linux/fs/super.c	Wed Jan  6 15:01:25 1999
@@ -1129,17 +1129,16 @@
 		if ((fs_type = get_fs_type("nfs"))) {
 			sb = get_empty_super(); /* "can't fail" */
 			sb->s_dev = get_unnamed_dev();
-			sb->s_flags = root_mountflags & ~MS_RDONLY;
+			sb->s_flags = root_mountflags;
 			vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
 			if (vfsmnt) {
 				if (nfs_root_mount(sb) >= 0) {
-					sb->s_rd_only = 0;
 					sb->s_dirt = 0;
 					sb->s_type = fs_type;
 					current->fs->root = dget(sb->s_root);
 					current->fs->pwd = dget(sb->s_root);
 					ROOT_DEV = sb->s_dev;
-					printk (KERN_NOTICE "VFS: Mounted root (nfs filesystem).\n");
+			                printk (KERN_NOTICE "VFS: Mounted root (NFS filesystem)%s.\n", (sb->s_flags & MS_RDONLY) ? " readonly" : "");
 					return;
 				}
 				remove_vfsmnt(sb->s_dev);
diff -u --recursive --new-file v2.2.0-pre5/linux/fs/ufs/dir.c linux/fs/ufs/dir.c
--- v2.2.0-pre5/linux/fs/ufs/dir.c	Thu Nov 12 16:21:23 1998
+++ linux/fs/ufs/dir.c	Thu Jan  7 10:31:07 1999
@@ -110,9 +110,7 @@
 				brelse(bh);
 				return stored;
 			}
-#if 0 /* XXX */
-			if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
-			/* XXX - beware about de having to be swabped somehow */
+			if (!ufs_check_dir_entry ("ufs_readdir", inode, de,
 						   bh, offset)) {
 				/* On error, skip the f_pos to the
 				   next block. */
@@ -122,7 +120,6 @@
 				brelse (bh);
 				return stored;
 			}
-#endif /* XXX */
 			offset += SWAB16(de->d_reclen);
 			if (de->d_ino) {
 			/* SWAB16() was unneeded -- compare to 0 */
diff -u --recursive --new-file v2.2.0-pre5/linux/fs/ufs/super.c linux/fs/ufs/super.c
--- v2.2.0-pre5/linux/fs/ufs/super.c	Thu Jan  7 15:11:40 1999
+++ linux/fs/ufs/super.c	Thu Jan  7 10:31:07 1999
@@ -58,6 +58,7 @@
  */
 
 
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <stdarg.h>
@@ -274,6 +275,8 @@
 				ufs_set_opt (*mount_options, UFSTYPE_44BSD);
 			else if (!strcmp (value, "next"))
 				ufs_set_opt (*mount_options, UFSTYPE_NEXT);
+			else if (!strcmp (value, "openstep"))
+				ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP);
 			else {
 				printk ("UFS-fs: Invalid type option: %s\n", value);
 				return 0;
@@ -464,7 +467,7 @@
 	}
 	if (!(sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE)) {
 		printk("You didn't specify type of your ufs file system\n\n"
-		"       mount -t ufs -o ufstype=sun|44bsd|old|next ....\n\n"
+		"       mount -t ufs -o ufstype=sun|44bsd|old|next|openstep ....\n\n"
 		"!!! WARNING !!! wrong value may corrupt you file system\n"
 		"default value is ufstype=old\n");
 		ufs_set_opt (sb->u.ufs_sb.s_mount_opt, UFSTYPE_OLD);
@@ -506,7 +509,7 @@
 		flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
 		if (!(sb->s_flags & MS_RDONLY)) {
 			printk("old type of ufs is supported read-only\n"); 
-			goto failed;
+			sb->s_flags |= MS_RDONLY;
 		}
 		break;
 	
@@ -520,10 +523,23 @@
 		flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
 		if (!(sb->s_flags & MS_RDONLY)) {
 			printk("nextstep type of ufs is supported read-only\n");
-			goto failed;
+			sb->s_flags |= MS_RDONLY;
 		}
 		break;
 	
+	case UFS_MOUNT_UFSTYPE_OPENSTEP:
+		UFSD(("openstep ufstype\n"))
+		uspi->s_fsize = block_size = 1024;
+		uspi->s_fmask = ~(1024 - 1);
+		uspi->s_fshift = 10;
+		uspi->s_sbsize = super_block_size = 2048;
+		uspi->s_sbbase = 0;
+		flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
+		if (!(sb->s_flags & MS_RDONLY)) {
+			printk("openstep type of ufs is supported read-only\n");
+			sb->s_flags |= MS_RDONLY;
+		}
+		break;
 	
 	default:
 		printk("this fs type of ufs is not supported\n");
@@ -567,8 +583,10 @@
 	}
 #endif
 
-	if ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) == 
-	UFS_MOUNT_UFSTYPE_NEXT && uspi->s_sbbase < 256) {
+	if ((((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) == 
+	UFS_MOUNT_UFSTYPE_NEXT) ||
+	((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) ==
+	UFS_MOUNT_UFSTYPE_OPENSTEP)) && uspi->s_sbbase < 256) {
 		ubh_brelse_uspi(uspi);
 		ubh = NULL;
 		uspi->s_sbbase += 8;
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-alpha/pci.h linux/include/asm-alpha/pci.h
--- v2.2.0-pre5/linux/include/asm-alpha/pci.h	Fri Nov 27 13:09:28 1998
+++ linux/include/asm-alpha/pci.h	Thu Jan  7 09:25:02 1999
@@ -8,7 +8,7 @@
 /*
  * The following structure is used to manage multiple PCI busses.
  *
- * XXX: We should solve thos problem in an architecture independant
+ * XXX: We should solve this problem in an architecture independent
  * way, rather than hacking something up here.
  */
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-alpha/termbits.h linux/include/asm-alpha/termbits.h
--- v2.2.0-pre5/linux/include/asm-alpha/termbits.h	Sat Nov 23 03:59:01 1996
+++ linux/include/asm-alpha/termbits.h	Fri Jan  8 11:11:45 1999
@@ -125,6 +125,17 @@
 #define  B115200  00021
 #define  B230400  00022
 #define  B460800  00023
+#define  B500000  00024
+#define  B576000  00025
+#define  B921600  00026
+#define B1000000  00027
+#define B1152000  00030
+#define B1500000  00031
+#define B2000000  00032
+#define B2500000  00033
+#define B3000000  00034
+#define B3500000  00035
+#define B4000000  00036
 
 #define CSIZE	00001400
 #define   CS5	00000000
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/a.out.h linux/include/asm-arm/a.out.h
--- v2.2.0-pre5/linux/include/asm-arm/a.out.h	Tue Apr 14 14:29:24 1998
+++ linux/include/asm-arm/a.out.h	Thu Jan  7 15:51:33 1999
@@ -27,4 +27,9 @@
 #define M_ARM 103
 
 #include <asm/arch/a.out.h>
+
+#ifndef LIBRARY_START_TEXT
+#define LIBRARY_START_TEXT	(0x00c00000)
+#endif
+
 #endif /* __A_OUT_GNU_H__ */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-arc/a.out.h linux/include/asm-arm/arch-arc/a.out.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-arc/a.out.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/a.out.h	Thu Jan  7 15:51:33 1999
@@ -10,7 +10,6 @@
 
 #ifdef __KERNEL__
 #define STACK_TOP		(0x01a00000)
-#define LIBRARY_START_TEXT	(0x00c00000)
 #endif
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-arc/dma.h linux/include/asm-arm/arch-arc/dma.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-arc/dma.h	Tue Dec 22 14:16:57 1998
+++ linux/include/asm-arm/arch-arc/dma.h	Thu Jan  7 15:51:33 1999
@@ -16,14 +16,6 @@
 
 #define MAX_DMA_ADDRESS		0x03000000
 
-/*
- * DMA modes - we have two, IN and OUT
- */
-typedef enum {
-	DMA_MODE_READ,
-	DMA_MODE_WRITE
-} dmamode_t;
-
 #ifdef CONFIG_ARCH_ARC
 #define MAX_DMA_CHANNELS	3
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-arc/hardware.h linux/include/asm-arm/arch-arc/hardware.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-arc/hardware.h	Tue Dec 22 14:16:57 1998
+++ linux/include/asm-arm/arch-arc/hardware.h	Thu Jan  7 15:51:33 1999
@@ -20,7 +20,9 @@
  * source.
  */
 #define HAS_IOC
+#include <asm/ioc.h>
 #define HAS_MEMC
+#include <asm/memc.h>
 #define HAS_MEMC1A
 #define HAS_VIDC
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-arc/io.h linux/include/asm-arm/arch-arc/io.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-arc/io.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-arc/io.h	Thu Jan  7 15:51:33 1999
@@ -35,7 +35,7 @@
 	"tst	%2, #0x80000000\n\t"
 	"mov	%0, %4\n\t"
 	"addeq	%0, %0, %3\n\t"
-	"strb	%1, [%0, %2, lsl #2]"
+	"strb	%1, [%0, %2, lsl #2]	@ outb"
 	: "=&r" (temp)
 	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
 	: "cc");
@@ -48,7 +48,7 @@
 	"tst	%2, #0x80000000\n\t"
 	"mov	%0, %4\n\t"
 	"addeq	%0, %0, %3\n\t"
-	"str	%1, [%0, %2, lsl #2]"
+	"str	%1, [%0, %2, lsl #2]	@ outw"
 	: "=&r" (temp)
 	: "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
 	: "cc");
@@ -61,7 +61,7 @@
 	"tst	%2, #0x80000000\n\t"
 	"mov	%0, %4\n\t"
 	"addeq	%0, %0, %3\n\t"
-	"str	%1, [%0, %2, lsl #2]"
+	"str	%1, [%0, %2, lsl #2]	@ outl"
 	: "=&r" (temp)
 	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
 	: "cc");
@@ -75,7 +75,7 @@
 	"tst	%2, #0x80000000\n\t"						\
 	"mov	%0, %4\n\t"							\
 	"addeq	%0, %0, %3\n\t"							\
-	"ldr" ##instr## "	%1, [%0, %2, lsl #2]"				\
+	"ldr" ##instr## "	%1, [%0, %2, lsl #2]	@ in"###fnsuffix	\
 	: "=&r" (temp), "=r" (value)						\
 	: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)		\
 	: "cc");								\
@@ -110,11 +110,11 @@
 ({										\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"strb	%0, [%1, %2]"						\
+		"strb	%0, [%1, %2]	@ outbc"				\
 		: : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"strb	%0, [%1, %2]"						\
+		"strb	%0, [%1, %2]	@ outbc"				\
 		: : "r" (value), "r" (IO_BASE), "r" ((port) << 2));		\
 })
 
@@ -123,11 +123,11 @@
 	unsigned char result;							\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"ldrb	%0, [%1, %2]"						\
+		"ldrb	%0, [%1, %2]	@ inbc"					\
 		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"ldrb	%0, [%1, %2]"						\
+		"ldrb	%0, [%1, %2]	@ inbc"					\
 		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
 	result;									\
 })
@@ -137,11 +137,11 @@
 	unsigned long v = value;						\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]"						\
+		"str	%0, [%1, %2]	@ outwc"				\
 		: : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));	\
 	else									\
 		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]"						\
+		"str	%0, [%1, %2]	@ outwc"				\
 		: : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2));		\
 })
 
@@ -150,11 +150,11 @@
 	unsigned short result;							\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]"						\
+		"ldr	%0, [%1, %2]	@ inwc"					\
 		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]"						\
+		"ldr	%0, [%1, %2]	@ inwc"					\
 		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
 	result & 0xffff;							\
 })
@@ -164,11 +164,11 @@
 	unsigned long v = value;						\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]"						\
+		"str	%0, [%1, %2]	@ outlc"				\
 		: : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]"						\
+		"str	%0, [%1, %2]	@ outlc"				\
 		: : "r" (v), "r" (IO_BASE), "r" ((port) << 2));			\
 })
 
@@ -177,11 +177,11 @@
 	unsigned long result;							\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]"						\
+		"ldr	%0, [%1, %2]	@ inlc"					\
 		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]"						\
+		"ldr	%0, [%1, %2]	@ inlc"					\
 		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
 	result;									\
 })
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-arc/processor.h linux/include/asm-arm/arch-arc/processor.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-arc/processor.h	Tue Dec 22 14:16:57 1998
+++ linux/include/asm-arm/arch-arc/processor.h	Thu Jan  7 15:51:33 1999
@@ -27,7 +27,6 @@
  * space during mmap's.
  */
 #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-arc/system.h linux/include/asm-arm/arch-arc/system.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-arc/system.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/system.h	Thu Jan  7 15:51:33 1999
@@ -23,25 +23,25 @@
 
 #endif
 
-extern __inline__ void arch_hard_reset (void)
+extern __inline__ void arch_reset(char mode)
 {
-	extern void ecard_reset (int card);
+	extern void ecard_reset(int card);
+
+	/*
+	 * Do any cleanups that the processor may require
+	 */
+	processor._proc_fin();
 
 	/*
 	 * Reset all expansion cards.
 	 */
-	ecard_reset (-1);
+	ecard_reset(-1);
 
 	/*
 	 * copy branch instruction to reset location and call it
 	 */
 	*(unsigned long *)0 = *(unsigned long *)0x03800000;
 	((void(*)(void))0)();
-
-	/*
-	 * If that didn't work, loop endlessly
-	 */
-	while (1);
 }
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/a.out.h linux/include/asm-arm/arch-ebsa110/a.out.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/a.out.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa110/a.out.h	Thu Jan  7 15:51:33 1999
@@ -9,7 +9,6 @@
 
 #ifdef __KERNEL__
 #define STACK_TOP		((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#define LIBRARY_START_TEXT	(0x00c00000)
 #endif
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/dma.h linux/include/asm-arm/arch-ebsa110/dma.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/dma.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa110/dma.h	Thu Jan  7 15:51:33 1999
@@ -14,15 +14,6 @@
  * bytes of RAM.
  */
 #define MAX_DMA_ADDRESS		0xd0000000
-
-/*
- * DMA modes - we have two, IN and OUT
- */
-typedef enum {
-	DMA_MODE_READ,
-	DMA_MODE_WRITE
-} dmamode_t;
-
 #define MAX_DMA_CHANNELS	8
 
 #endif /* _ASM_ARCH_DMA_H */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/hardware.h linux/include/asm-arm/arch-ebsa110/hardware.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/hardware.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-ebsa110/hardware.h	Thu Jan  7 15:51:33 1999
@@ -38,7 +38,7 @@
 #define MAPTOPHYS(a)		((unsigned long)(a) - PAGE_OFFSET)
 #define KERNTOPHYS(a)		((unsigned long)(&a))
 #define KERNEL_BASE		(0xc0008000)
-#define SAFE_ADDR		0x40000000
+#define FLUSH_BASE_PHYS		0x40000000
 
 #else
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/io.h linux/include/asm-arm/arch-ebsa110/io.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/io.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa110/io.h	Thu Jan  7 15:51:33 1999
@@ -36,7 +36,7 @@
 	"tst	%2, #0x80000000\n\t"						\
 	"mov	%0, %4\n\t"							\
 	"addeq	%0, %0, %3\n\t"							\
-	"str" ##instr## "	%1, [%0, %2, lsl #2]"				\
+	"str" ##instr## "	%1, [%0, %2, lsl #2]	@ out"###fnsuffix	\
 	: "=&r" (temp)								\
 	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)	\
 	: "cc");								\
@@ -50,7 +50,7 @@
 	"tst	%2, #0x80000000\n\t"						\
 	"mov	%0, %4\n\t"							\
 	"addeq	%0, %0, %3\n\t"							\
-	"ldr" ##instr## "	%1, [%0, %2, lsl #2]"				\
+	"ldr" ##instr## "	%1, [%0, %2, lsl #2]	@ in"###fnsuffix	\
 	: "=&r" (temp), "=r" (value)						\
 	: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)		\
 	: "cc");								\
@@ -87,11 +87,11 @@
 ({										\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"strb	%0, [%1, %2]"						\
+		"strb	%0, [%1, %2]		@ outbc"			\
 		: : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"strb	%0, [%1, %2]"						\
+		"strb	%0, [%1, %2]		@ outbc"			\
 		: : "r" (value), "r" (IO_BASE), "r" ((port) << 2));		\
 })
 
@@ -100,11 +100,11 @@
 	unsigned char result;							\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"ldrb	%0, [%1, %2]"						\
+		"ldrb	%0, [%1, %2]		@ inbc"				\
 		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"ldrb	%0, [%1, %2]"						\
+		"ldrb	%0, [%1, %2]		@ inbc"				\
 		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
 	result;									\
 })
@@ -114,11 +114,11 @@
 	unsigned long v = value;						\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]"						\
+		"str	%0, [%1, %2]		@ outwc"			\
 		: : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));	\
 	else									\
 		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]"						\
+		"str	%0, [%1, %2]		@ outwc"			\
 		: : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2));		\
 })
 
@@ -127,11 +127,11 @@
 	unsigned short result;							\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]"						\
+		"ldr	%0, [%1, %2]		@ inwc"				\
 		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]"						\
+		"ldr	%0, [%1, %2]		@ inwc"				\
 		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
 	result & 0xffff;							\
 })
@@ -141,11 +141,11 @@
 	unsigned long v = value;						\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]"						\
+		"str	%0, [%1, %2]		@ outlc"			\
 		: : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]"						\
+		"str	%0, [%1, %2]		@ outlc"			\
 		: : "r" (v), "r" (IO_BASE), "r" ((port) << 2));			\
 })
 
@@ -154,11 +154,11 @@
 	unsigned long result;							\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]"						\
+		"ldr	%0, [%1, %2]		@ inlc"				\
 		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]"						\
+		"ldr	%0, [%1, %2]		@ inlc"				\
 		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
 	result;									\
 })
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/processor.h linux/include/asm-arm/arch-ebsa110/processor.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/processor.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-ebsa110/processor.h	Thu Jan  7 15:51:33 1999
@@ -24,7 +24,6 @@
  * space during mmap's.
  */
 #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/system.h linux/include/asm-arm/arch-ebsa110/system.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/system.h	Wed Sep  9 14:51:10 1998
+++ linux/include/asm-arm/arch-ebsa110/system.h	Thu Jan  7 15:51:33 1999
@@ -6,13 +6,12 @@
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H
 
-extern __inline__ void arch_hard_reset (void)
+extern __inline__ void arch_reset(char mode)
 {
 	/*
 	 * loop endlessly
 	 */
 	cli();
-	while (1);
 }
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/time.h linux/include/asm-arm/arch-ebsa110/time.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa110/time.h	Wed Sep  9 14:51:11 1998
+++ linux/include/asm-arm/arch-ebsa110/time.h	Thu Jan  7 15:51:33 1999
@@ -9,8 +9,10 @@
  *  10-Oct-1996	RMK	Created
  *  04-Dec-1997	RMK	Updated for new arch/arm/kernel/time.c
  *  07-Aug-1998	RMK	Updated for arch/arm/kernel/leds.c
+ *  28-Dec-1998	APH	Made leds code optional
  */
 
+#include <linux/config.h>
 #include <asm/leds.h>
 
 #define IRQ_TIMER IRQ_EBSA110_TIMER0
@@ -47,15 +49,19 @@
 extern __inline__ int reset_timer (void)
 {
 	static unsigned int divisor;
+#ifdef CONFIG_LEDS	
 	static int count = 50;
+#endif
 
 	*PIT_T1 = (PIT1_COUNT) & 0xff;
 	*PIT_T1 = (PIT1_COUNT) >> 8;
 
+#ifdef CONFIG_LEDS
 	if (--count == 0) {
 		count = 50;
 		leds_event(led_timer);
 	}
+#endif
 
 	if (divisor == 0) {
 		divisor = DIVISOR - 1;
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/a.out.h linux/include/asm-arm/arch-ebsa285/a.out.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/a.out.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa285/a.out.h	Thu Jan  7 15:51:33 1999
@@ -9,7 +9,6 @@
 
 #ifdef __KERNEL__
 #define STACK_TOP		((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#define LIBRARY_START_TEXT	(0x00c00000)
 #endif
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/dma.h linux/include/asm-arm/arch-ebsa285/dma.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/dma.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/arch-ebsa285/dma.h	Thu Jan  7 15:51:33 1999
@@ -15,20 +15,11 @@
 #define MAX_DMA_ADDRESS		0xffffffff
 
 /*
- * DMA modes - we have two, IN and OUT
- */
-
-typedef int dmamode_t;
-#define DMA_MODE_READ		0x44
-#define DMA_MODE_WRITE		0x48
-
-/*
  * The 21285 has two internal DMA channels; we call these 0 and 1.
  * On CATS hardware we have an additional eight ISA dma channels
  * numbered 2..9.
  */
 #define MAX_DMA_CHANNELS	10
-
 #define DMA_ISA_BASE		2
 #define DMA_FLOPPY		(DMA_ISA_BASE + 2)
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/hardware.h linux/include/asm-arm/arch-ebsa285/hardware.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/hardware.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-ebsa285/hardware.h	Thu Jan  7 15:51:33 1999
@@ -19,10 +19,12 @@
  * 0xf8000000	0x7b010000	PCI Config type 0
  * 
  */
+
+#include <asm/dec21285.h>
  
 #define IO_BASE			0xe0000000
 #define PCIO_BASE		0xffe00000
- 
+#define PCI_IACK		0xfc000000 
 
 #define XBUS_LEDS		((volatile unsigned char *)0xfff12000)
 #define XBUS_LED_AMBER		(1 << 0)
@@ -36,68 +38,10 @@
 #define XBUS_SWITCH_J17_11	((*XBUS_SWITCH) & (1 << 5))
 #define XBUS_SWITCH_J17_9	((*XBUS_SWITCH) & (1 << 6))
 
-#define CSR_SA110_CNTL		((volatile unsigned long *)0xfe00013c)
-#define CSR_PCIADDR_EXTN	((volatile unsigned long *)0xfe000140)
-#define CSR_PREFETCHMEMRANGE	((volatile unsigned long *)0xfe000144)
-#define CSR_XBUS_CYCLE		((volatile unsigned long *)0xfe000148)
-#define CSR_XBUS_IOSTROBE	((volatile unsigned long *)0xfe00014c)
-#define CSR_DOORBELL_PCI	((volatile unsigned long *)0xfe000150)
-#define CSR_DOORBELL_SA110	((volatile unsigned long *)0xfe000154)
-
-
-#define CSR_UARTDR		((volatile unsigned long *)0xfe000160)
-#define CSR_RXSTAT		((volatile unsigned long *)0xfe000164)
-#define CSR_H_UBRLCR		((volatile unsigned long *)0xfe000168)
-#define CSR_M_UBRLCR		((volatile unsigned long *)0xfe00016c)
-#define CSR_L_UBRLCR		((volatile unsigned long *)0xfe000170)
-#define CSR_UARTCON		((volatile unsigned long *)0xfe000174)
-#define CSR_UARTFLG		((volatile unsigned long *)0xfe000178)
-
-#define CSR_IRQ_STATUS		((volatile unsigned long *)0xfe000180)
-#define CSR_IRQ_RAWSTATUS	((volatile unsigned long *)0xfe000184)
-#define CSR_IRQ_ENABLE		((volatile unsigned long *)0xfe000188)
-#define CSR_IRQ_DISABLE		((volatile unsigned long *)0xfe00018c)
-#define CSR_IRQ_SOFT		((volatile unsigned long *)0xfe000190)
-
-#define CSR_FIQ_STATUS		((volatile unsigned long *)0xfe000280)
-#define CSR_FIQ_RAWSTATUS	((volatile unsigned long *)0xfe000284)
-#define CSR_FIQ_ENABLE		((volatile unsigned long *)0xfe000288)
-#define CSR_FIQ_DISABLE		((volatile unsigned long *)0xfe00028c)
-#define CSR_FIQ_SOFT		((volatile unsigned long *)0xfe000290)
-
-#define CSR_TIMER1_LOAD		((volatile unsigned long *)0xfe000300)
-#define CSR_TIMER1_VALUE	((volatile unsigned long *)0xfe000304)
-#define CSR_TIMER1_CNTL		((volatile unsigned long *)0xfe000308)
-#define CSR_TIMER1_CLR		((volatile unsigned long *)0xfe00030c)
-
-#define CSR_TIMER2_LOAD		((volatile unsigned long *)0xfe000320)
-#define CSR_TIMER2_VALUE	((volatile unsigned long *)0xfe000324)
-#define CSR_TIMER2_CNTL		((volatile unsigned long *)0xfe000328)
-#define CSR_TIMER2_CLR		((volatile unsigned long *)0xfe00032c)
-
-#define CSR_TIMER3_LOAD		((volatile unsigned long *)0xfe000340)
-#define CSR_TIMER3_VALUE	((volatile unsigned long *)0xfe000344)
-#define CSR_TIMER3_CNTL		((volatile unsigned long *)0xfe000348)
-#define CSR_TIMER3_CLR		((volatile unsigned long *)0xfe00034c)
-
-#define CSR_TIMER4_LOAD		((volatile unsigned long *)0xfe000360)
-#define CSR_TIMER4_VALUE	((volatile unsigned long *)0xfe000364)
-#define CSR_TIMER4_CNTL		((volatile unsigned long *)0xfe000368)
-#define CSR_TIMER4_CLR		((volatile unsigned long *)0xfe00036c)
-
-
-#define TIMER_CNTL_ENABLE	(1 << 7)
-#define TIMER_CNTL_AUTORELOAD	(1 << 6)
-#define TIMER_CNTL_DIV1		(0)
-#define TIMER_CNTL_DIV16	(1 << 2)
-#define TIMER_CNTL_DIV256	(2 << 2)
-#define TIMER_CNTL_CNTEXT	(3 << 2)
-
-
 #define KERNTOPHYS(a)		((unsigned long)(&a))
 
 #define PARAMS_OFFSET		0x0100
 #define PARAMS_BASE		(PAGE_OFFSET + PARAMS_OFFSET)
 
-#define SAFE_ADDR		0x50000000
+#define FLUSH_BASE_PHYS		0x50000000
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/io.h linux/include/asm-arm/arch-ebsa285/io.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/io.h	Tue Jun 23 10:01:25 1998
+++ linux/include/asm-arm/arch-ebsa285/io.h	Thu Jan  7 15:51:33 1999
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-arm/arch-ebsa110/io.h
+ * linux/include/asm-arm/arch-ebsa285/io.h
  *
  * Copyright (C) 1997,1998 Russell King
  *
@@ -9,6 +9,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/dec21285.h>
+
 /*
  * This architecture does not require any delayed IO, and
  * has the constant-optimised IO
@@ -23,7 +25,7 @@
 extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port)	\
 {										\
 	__asm__ __volatile__(							\
-	"str" ##instr## "	%0, [%1, %2]"					\
+	"str%?" ##instr## "	%0, [%1, %2]		@ out"###fnsuffix	\
 	: 									\
 	: "r" (value), "r" (PCIO_BASE), typ (port));				\
 }
@@ -33,7 +35,7 @@
 {										\
 	unsigned long value;							\
 	__asm__ __volatile__(							\
-	"ldr" ##instr## "	%0, [%1, %2]"					\
+	"ldr%?" ##instr## "	%0, [%1, %2]		@ in"###fnsuffix	\
 	: "=&r" (value)								\
 	: "r" (PCIO_BASE), typ (port));						\
 	return (unsigned sz)value;						\
@@ -65,7 +67,7 @@
 #define __outbc(value,port)							\
 ({										\
 	__asm__ __volatile__(							\
-	"strb	%0, [%1, %2]"							\
+	"str%?b	%0, [%1, %2]				@ outbc"		\
 	:									\
 	: "r" (value), "r" (PCIO_BASE), "Jr" (port));				\
 })
@@ -74,7 +76,7 @@
 ({										\
 	unsigned char result;							\
 	__asm__ __volatile__(							\
-	"ldrb	%0, [%1, %2]"							\
+	"ldr%?b	%0, [%1, %2]				@ inbc"			\
 	: "=r" (result)								\
 	: "r" (PCIO_BASE), "Jr" (port));					\
 	result;									\
@@ -83,7 +85,7 @@
 #define __outwc(value,port)							\
 ({										\
 	__asm__ __volatile__(							\
-	"strh	%0, [%1, %2]"							\
+	"str%?h	%0, [%1, %2]				@ outwc"		\
 	:									\
 	: "r" (value), "r" (PCIO_BASE), "r" (port));				\
 })
@@ -92,7 +94,7 @@
 ({										\
 	unsigned short result;							\
 	__asm__ __volatile__(							\
-	"ldrh	%0, [%1, %2]"							\
+	"ldr%?h	%0, [%1, %2]				@ inwc"			\
 	: "=r" (result)								\
 	: "r" (PCIO_BASE), "r" (port));						\
 	result & 0xffff;							\
@@ -101,7 +103,7 @@
 #define __outlc(value,port)							\
 ({										\
 	__asm__ __volatile__(							\
-	"str	%0, [%1, %2]"							\
+	"str%?	%0, [%1, %2]				@ outlc"		\
 	:									\
 	: "r" (value), "r" (PCIO_BASE), "Jr" (port));				\
 })
@@ -110,7 +112,7 @@
 ({										\
 	unsigned long result;							\
 	__asm__ __volatile__(							\
-	"ldr	%0, [%1, %2]"							\
+	"ldr%?	%0, [%1, %2]				@ inlc"			\
 	: "=r" (result)								\
 	: "r" (PCIO_BASE), "Jr" (port));					\
 	result;									\
@@ -141,25 +143,68 @@
 	(*(volatile unsigned long *)(p))
 
 /*
- * This is not sufficient... (and it's a hack anyway)
+ * ioremap support
+ */
+#define valid_ioaddr(iomem,size) ((iomem) < 0x80000000 && (iomem) + (size) <= 0x80000000)
+#define io_to_phys(iomem)	((iomem) + DC21285_PCI_MEM)
+
+/*
+ * Fudge up IO addresses by this much.  Once we're confident that nobody
+ * is using read*() and so on with addresses they didn't get from ioremap
+ * this can go away.
+ */
+#define IO_FUDGE_FACTOR		0xe0000000
+
+extern inline void *ioremap(unsigned long iomem_addr, unsigned long size)
+{
+	unsigned long phys_addr;
+
+	if (!valid_ioaddr(iomem_addr, size))
+		return NULL;
+
+	phys_addr = io_to_phys(iomem_addr & PAGE_MASK);
+
+	return (void *)((unsigned long)__ioremap(phys_addr, size, 0) 
+			- IO_FUDGE_FACTOR);
+}
+
+#define ioremap_nocache(iomem_addr,size) ioremap((iomem_addr),(size))
+
+extern void iounmap(void *addr);
+
+/*
+ * We'd probably be better off with these as macros rather than functions.
+ * Firstly that would be more efficient and secondly we could do with the
+ * ability to stop GCC whinging about type conversions.  --philb
  */
 static inline void writeb(unsigned char b, unsigned int addr)
 {
-	*(volatile unsigned char *)(0xe0000000 + (addr)) = b;
+	*(volatile unsigned char *)(IO_FUDGE_FACTOR + (addr)) = b;
 }
 
 static inline unsigned char readb(unsigned int addr)
 {
-	return *(volatile unsigned char *)(0xe0000000 + (addr));
+	return *(volatile unsigned char *)(IO_FUDGE_FACTOR + (addr));
 }
 
 static inline void writew(unsigned short b, unsigned int addr)
 {
-	*(volatile unsigned short *)(0xe0000000 + (addr)) = b;
+	*(volatile unsigned short *)(IO_FUDGE_FACTOR + (addr)) = b;
 }
 
 static inline unsigned short readw(unsigned int addr)
 {
-	return *(volatile unsigned short *)(0xe0000000 + (addr));
+	return *(volatile unsigned short *)(IO_FUDGE_FACTOR + (addr));
 }
+
+static inline void writel(unsigned long b, unsigned int addr)
+{
+	*(volatile unsigned long *)(IO_FUDGE_FACTOR + (addr)) = b;
+}
+
+static inline unsigned short readl(unsigned int addr)
+{
+	return *(volatile unsigned long *)(IO_FUDGE_FACTOR + (addr));
+}
+
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/irq.h linux/include/asm-arm/arch-ebsa285/irq.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/irq.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-ebsa285/irq.h	Thu Jan  7 15:51:33 1999
@@ -7,7 +7,6 @@
  *   22-08-1998	RMK	Restructured IRQ routines
  *   03-09-1998	PJB	Merged CATS support
  */
-
 #include <linux/config.h>
 
 static void ebsa285_mask_irq(unsigned int irq)
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/mmu.h linux/include/asm-arm/arch-ebsa285/mmu.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/mmu.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-ebsa285/mmu.h	Thu Jan  7 15:51:33 1999
@@ -16,13 +16,13 @@
  * On ebsa285, the dram is contiguous
  */
 #define __virt_to_phys__is_a_macro
-#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
+#define __virt_to_phys(vpage) ((unsigned long)(vpage) - PAGE_OFFSET)
 #define __phys_to_virt__is_a_macro
-#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
+#define __phys_to_virt(ppage) ((unsigned long)(ppage) + PAGE_OFFSET)
 
 #define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x)	(x - 0xe0000000)
+#define __virt_to_bus(x)	((x) - 0xe0000000)
 #define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x)	(x + 0xe0000000)
+#define __bus_to_virt(x)	((x) + 0xe0000000)
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/processor.h linux/include/asm-arm/arch-ebsa285/processor.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/processor.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-ebsa285/processor.h	Thu Jan  7 15:51:33 1999
@@ -24,7 +24,6 @@
  * space during mmap's.
  */
 #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/serial.h linux/include/asm-arm/arch-ebsa285/serial.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/serial.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-ebsa285/serial.h	Thu Jan  7 15:51:33 1999
@@ -11,6 +11,7 @@
 #define __ASM_ARCH_SERIAL_H
 
 #include <linux/config.h>
+
 #include <asm/irq.h>
 
 /*
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/system.h linux/include/asm-arm/arch-ebsa285/system.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/system.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa285/system.h	Thu Jan  7 15:51:33 1999
@@ -6,19 +6,26 @@
 #include <asm/hardware.h>
 #include <asm/leds.h>
 
-/* To reboot, we set up the 21285 watchdog and enable it.
- * We then wait for it to timeout.
- */
-extern __inline__ void arch_hard_reset (void)
+extern __inline__ void arch_reset(char mode)
 {
 	cli();
-	*CSR_TIMER4_LOAD = 0x8000;
-	*CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
-	*CSR_SA110_CNTL |= 1 << 13;
-	while(1);
-}
 
-#define ARCH_IDLE_OK
+	if (mode == 's') {
+		__asm__ volatile (
+		"mov	lr, #0x41000000		@ prepare to jump to ROM
+		 mov	r0, #0x130
+		 mcr	p15, 0, r0, c1, c0	@ MMU off
+		 mcr	p15, 0, ip, c7, c7	@ flush caches
+		 mov	pc, lr");
+	} else {
+		/* To reboot, we set up the 21285 watchdog and enable it.
+		 * We then wait for it to timeout.
+		 */
+		*CSR_TIMER4_LOAD = 0x8000;
+		*CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
+		*CSR_SA110_CNTL |= 1 << 13;
+	}
+}
 
 #define arch_start_idle()	leds_event(led_idle_start)
 #define arch_end_idle()		leds_event(led_idle_end)
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/time.h linux/include/asm-arm/arch-ebsa285/time.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/time.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-ebsa285/time.h	Thu Jan  7 15:51:33 1999
@@ -9,24 +9,29 @@
  * Changelog:
  *  21-Mar-1998	RMK	Created
  *  27-Aug-1998	PJB	CATS support
+ *  28-Dec-1998	APH	Made leds optional
  */
 
 #define RTC_PORT(x)		(0x72+(x))
 #define RTC_ALWAYS_BCD		1
 
+#include <linux/config.h>
 #include <asm/leds.h>
 #include <asm/system.h>
 #include <linux/mc146818rtc.h>
 
 extern __inline__ unsigned long gettimeoffset (void)
 {
-	return 0;
+	unsigned long value = LATCH - *CSR_TIMER1_VALUE;
+
+	return (tick * value) / LATCH;
 }
 
 extern __inline__ int reset_timer (void)
 {
 	*CSR_TIMER1_CLR = 0;
 
+#ifdef CONFIG_LEDS
 	/*
 	 * Do the LEDs thing on EBSA-285 hardware.
 	 */
@@ -47,7 +52,8 @@
 			leds_event(led_timer);
 		}
 	}
-
+#endif
+	
 	return 1;
 }
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/uncompress.h linux/include/asm-arm/arch-ebsa285/uncompress.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-ebsa285/uncompress.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/arch-ebsa285/uncompress.h	Thu Jan  7 15:51:33 1999
@@ -4,27 +4,25 @@
  * Copyright (C) 1996,1997,1998 Russell King
  */
 
+#define BASE 0x42000160
+
+static __inline__ void putc(char c)
+{
+	while (*((volatile unsigned int *)(BASE + 0x18)) & 8);
+	*((volatile unsigned int *)(BASE)) = c;
+}
+
 /*
  * This does not append a newline
  */
 static void puts(const char *s)
 {
-	__asm__ __volatile__("
-	ldrb	%0, [%2], #1
-	teq	%0, #0
-	beq	3f
-1:	strb	%0, [%3]
-2:	ldrb	%1, [%3, #0x14]
-	and	%1, %1, #0x60
-	teq	%1, #0x60
-	bne	2b
-	teq	%0, #'\n'
-	moveq	%0, #'\r'
-	beq	1b
-	ldrb	%0, [%2], #1
-	teq	%0, #0
-	bne	1b
-3:	" : : "r" (0), "r" (0), "r" (s), "r" (0xf0000be0) : "cc");
+	while (*s) {
+		putc(*s);
+		if (*s == '\n')
+			putc('\r');
+		s++;
+	}
 }
 
 /*
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-nexuspci/a.out.h linux/include/asm-arm/arch-nexuspci/a.out.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-nexuspci/a.out.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-nexuspci/a.out.h	Thu Jan  7 15:51:33 1999
@@ -9,7 +9,6 @@
 
 #ifdef __KERNEL__
 #define STACK_TOP		((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#define LIBRARY_START_TEXT	(0x00c00000)
 #endif
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-nexuspci/dma.h linux/include/asm-arm/arch-nexuspci/dma.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-nexuspci/dma.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-nexuspci/dma.h	Thu Jan  7 15:51:33 1999
@@ -7,6 +7,3 @@
  * Copyright (C) 1998 Philip Blundell
  */
 
-/* Need this to keep <asm/dma.h> happy. */
-typedef unsigned int dmamode_t;
-
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-nexuspci/hardware.h linux/include/asm-arm/arch-nexuspci/hardware.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-nexuspci/hardware.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-nexuspci/hardware.h	Thu Jan  7 15:51:33 1999
@@ -34,6 +34,6 @@
  */
 #define RAM_BASE		0x40000000
 #define KERNTOPHYS(a)		((unsigned long)(&a))
-#define SAFE_ADDR		0x40000000
+#define FLUSH_BASE_PHYS		0x40000000
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-nexuspci/processor.h linux/include/asm-arm/arch-nexuspci/processor.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-nexuspci/processor.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-nexuspci/processor.h	Thu Jan  7 15:51:33 1999
@@ -25,7 +25,6 @@
  * space during mmap's.
  */
 #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-nexuspci/system.h linux/include/asm-arm/arch-nexuspci/system.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-nexuspci/system.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-nexuspci/system.h	Thu Jan  7 15:51:33 1999
@@ -6,13 +6,12 @@
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H
 
-extern __inline__ void arch_hard_reset (void)
+extern __inline__ void arch_reset(char mode)
 {
 	/*
 	 * loop endlessly - the watchdog will reset us if it's enabled.
 	 */
 	cli();
-	while (1);
 }
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-rpc/a.out.h linux/include/asm-arm/arch-rpc/a.out.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-rpc/a.out.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-rpc/a.out.h	Thu Jan  7 15:51:33 1999
@@ -9,7 +9,6 @@
 
 #ifdef __KERNEL__
 #define STACK_TOP		((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#define LIBRARY_START_TEXT	(0x00c00000)
 #endif
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-rpc/dma.h linux/include/asm-arm/arch-rpc/dma.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-rpc/dma.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-rpc/dma.h	Thu Jan  7 15:51:33 1999
@@ -7,15 +7,6 @@
  * bytes of RAM.
  */
 #define MAX_DMA_ADDRESS		0xd0000000
-
-/*
- * DMA modes - we have two, IN and OUT
- */
-typedef enum {
-	DMA_MODE_READ,
-	DMA_MODE_WRITE
-} dmamode_t;
-
 #define MAX_DMA_CHANNELS	8
 
 #define DMA_0			0
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-rpc/hardware.h linux/include/asm-arm/arch-rpc/hardware.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-rpc/hardware.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-rpc/hardware.h	Thu Jan  7 15:51:33 1999
@@ -13,6 +13,7 @@
  * What hardware must be present
  */
 #define HAS_IOMD
+#include <asm/iomd.h>
 #define HAS_VIDC20
 
 /* Hardware addresses of major areas.
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-rpc/io.h linux/include/asm-arm/arch-rpc/io.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-rpc/io.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-rpc/io.h	Thu Jan  7 15:51:33 1999
@@ -36,7 +36,7 @@
 	"tst	%2, #0x80000000\n\t"						\
 	"mov	%0, %4\n\t"							\
 	"addeq	%0, %0, %3\n\t"							\
-	"str" ##instr## "	%1, [%0, %2, lsl #2]"				\
+	"str" ##instr## "	%1, [%0, %2, lsl #2]	@ out"###fnsuffix	\
 	: "=&r" (temp)								\
 	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)	\
 	: "cc");								\
@@ -50,7 +50,7 @@
 	"tst	%2, #0x80000000\n\t"						\
 	"mov	%0, %4\n\t"							\
 	"addeq	%0, %0, %3\n\t"							\
-	"ldr" ##instr## "	%1, [%0, %2, lsl #2]"				\
+	"ldr" ##instr## "	%1, [%0, %2, lsl #2]	@ in"###fnsuffix	\
 	: "=&r" (temp), "=r" (value)						\
 	: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)		\
 	: "cc");								\
@@ -87,11 +87,11 @@
 ({										\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"strb	%0, [%1, %2]"						\
+		"strb	%0, [%1, %2]	@ outbc"				\
 		: : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"strb	%0, [%1, %2]"						\
+		"strb	%0, [%1, %2]	@ outbc"				\
 		: : "r" (value), "r" (IO_BASE), "r" ((port) << 2));		\
 })
 
@@ -100,11 +100,11 @@
 	unsigned char result;							\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"ldrb	%0, [%1, %2]"						\
+		"ldrb	%0, [%1, %2]	@ inbc"					\
 		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"ldrb	%0, [%1, %2]"						\
+		"ldrb	%0, [%1, %2]	@ inbc"					\
 		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
 	result;									\
 })
@@ -114,11 +114,11 @@
 	unsigned long v = value;						\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]"						\
+		"str	%0, [%1, %2]	@ outwc"				\
 		: : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));	\
 	else									\
 		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]"						\
+		"str	%0, [%1, %2]	@ outwc"				\
 		: : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2));		\
 })
 
@@ -127,11 +127,11 @@
 	unsigned short result;							\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]"						\
+		"ldr	%0, [%1, %2]	@ inwc"					\
 		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]"						\
+		"ldr	%0, [%1, %2]	@ inwc"					\
 		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
 	result & 0xffff;							\
 })
@@ -141,11 +141,11 @@
 	unsigned long v = value;						\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]"						\
+		"str	%0, [%1, %2]	@ outlc"				\
 		: : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]"						\
+		"str	%0, [%1, %2]	@ outlc"				\
 		: : "r" (v), "r" (IO_BASE), "r" ((port) << 2));			\
 })
 
@@ -154,11 +154,11 @@
 	unsigned long result;							\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]"						\
+		"ldr	%0, [%1, %2]	@ inlc"					\
 		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]"						\
+		"ldr	%0, [%1, %2]	@ inlc"					\
 		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
 	result;									\
 })
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-rpc/processor.h linux/include/asm-arm/arch-rpc/processor.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-rpc/processor.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-rpc/processor.h	Thu Jan  7 15:51:33 1999
@@ -27,7 +27,6 @@
  * space during mmap's.
  */
 #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-rpc/system.h linux/include/asm-arm/arch-rpc/system.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-rpc/system.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-rpc/system.h	Thu Jan  7 15:51:33 1999
@@ -8,10 +8,10 @@
 
 #include <asm/proc-fns.h>
 
-#define arch_hard_reset() {						\
+#define arch_reset(mode) {						\
 	extern void ecard_reset (int card);				\
 	outb (0, IOMD_ROMCR0);						\
-	ecard_reset (-1);						\
+	ecard_reset(-1);						\
 	cli();								\
 	__asm__ __volatile__("msr  spsr, r1;"				\
 			     "mcr  p15, 0, %0, c1, c0, 0;"		\
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-vnc/a.out.h linux/include/asm-arm/arch-vnc/a.out.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-vnc/a.out.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/arch-vnc/a.out.h	Thu Jan  7 15:51:33 1999
@@ -9,7 +9,6 @@
 
 #ifdef __KERNEL__
 #define STACK_TOP		((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#define LIBRARY_START_TEXT	(0x00c00000)
 #endif
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-vnc/dma.h linux/include/asm-arm/arch-vnc/dma.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-vnc/dma.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/arch-vnc/dma.h	Thu Jan  7 15:51:33 1999
@@ -14,15 +14,6 @@
  * bytes of RAM.
  */
 #define MAX_DMA_ADDRESS		0xd0000000
-
-/*
- * DMA modes - we have two, IN and OUT
- */
-typedef enum {
-	DMA_MODE_READ,
-	DMA_MODE_WRITE
-} dmamode_t;
-
 #define MAX_DMA_CHANNELS	8
 
 #endif /* _ASM_ARCH_DMA_H */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-vnc/hardware.h linux/include/asm-arm/arch-vnc/hardware.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-vnc/hardware.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-vnc/hardware.h	Thu Jan  7 15:51:33 1999
@@ -46,4 +46,29 @@
 //#define PARAMS_OFFSET		0x0100
 //#define PARAMS_BASE		(PAGE_OFFSET + PARAMS_OFFSET)
 
-#define SAFE_ADDR		0x50000000
+#define FLUSH_BASE_PHYS		0x50000000
+
+/* GPIO pins */
+#define GPIO_CCLK		0x800
+#define GPIO_DSCLK		0x400
+#define GPIO_E2CLK		0x200
+#define GPIO_IOLOAD		0x100
+#define GPIO_RED_LED		0x080
+#define GPIO_WDTIMER		0x040
+#define GPIO_DATA		0x020
+#define GPIO_IOCLK		0x010
+#define GPIO_DONE		0x008
+#define GPIO_FAN		0x004
+#define GPIO_GREEN_LED		0x002
+#define GPIO_RESET		0x001
+
+/* CPLD pins */
+#define CPLD_DSRESET		8
+#define CPLD_UNMUTE		2
+
+#ifndef __ASSEMBLY__
+extern void gpio_modify_op(int mask, int set);
+extern void gpio_modify_io(int mask, int in);
+extern int  gpio_read(void);
+extern void cpld_modify(int mask, int set);
+#endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-vnc/io.h linux/include/asm-arm/arch-vnc/io.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-vnc/io.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-vnc/io.h	Thu Jan  7 15:51:33 1999
@@ -23,7 +23,7 @@
 extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port)	\
 {										\
 	__asm__ __volatile__(							\
-	"str" ##instr## "	%0, [%1, %2]"					\
+	"str%?" ##instr## "	%0, [%1, %2]		@ out"###fnsuffix	\
 	: 									\
 	: "r" (value), "r" (PCIO_BASE), typ (port));				\
 }
@@ -33,7 +33,7 @@
 {										\
 	unsigned long value;							\
 	__asm__ __volatile__(							\
-	"ldr" ##instr## "	%0, [%1, %2]"					\
+	"ldr%?" ##instr## "	%0, [%1, %2]		@ in"###fnsuffix	\
 	: "=&r" (value)								\
 	: "r" (PCIO_BASE), typ (port));						\
 	return (unsigned sz)value;						\
@@ -65,7 +65,7 @@
 #define __outbc(value,port)							\
 ({										\
 	__asm__ __volatile__(							\
-	"strb	%0, [%1, %2]"							\
+	"strb	%0, [%1, %2]				@ outbc"		\
 	:									\
 	: "r" (value), "r" (PCIO_BASE), "Jr" (port));				\
 })
@@ -74,7 +74,7 @@
 ({										\
 	unsigned char result;							\
 	__asm__ __volatile__(							\
-	"ldrb	%0, [%1, %2]"							\
+	"ldrb	%0, [%1, %2]				@ inbc"			\
 	: "=r" (result)								\
 	: "r" (PCIO_BASE), "Jr" (port));					\
 	result;									\
@@ -83,7 +83,7 @@
 #define __outwc(value,port)							\
 ({										\
 	__asm__ __volatile__(							\
-	"strh	%0, [%1, %2]"							\
+	"strh	%0, [%1, %2]				@ outwc"		\
 	:									\
 	: "r" (value), "r" (PCIO_BASE), "r" (port));				\
 })
@@ -92,7 +92,7 @@
 ({										\
 	unsigned short result;							\
 	__asm__ __volatile__(							\
-	"ldrh	%0, [%1, %2]"							\
+	"ldrh	%0, [%1, %2]				@ inwc"			\
 	: "=r" (result)								\
 	: "r" (PCIO_BASE), "r" (port));						\
 	result & 0xffff;							\
@@ -101,7 +101,7 @@
 #define __outlc(value,port)							\
 ({										\
 	__asm__ __volatile__(							\
-	"str	%0, [%1, %2]"							\
+	"str	%0, [%1, %2]				@ outlc"		\
 	:									\
 	: "r" (value), "r" (PCIO_BASE), "Jr" (port));				\
 })
@@ -110,7 +110,7 @@
 ({										\
 	unsigned long result;							\
 	__asm__ __volatile__(							\
-	"ldr	%0, [%1, %2]"							\
+	"ldr	%0, [%1, %2]				@ inlc"			\
 	: "=r" (result)								\
 	: "r" (PCIO_BASE), "Jr" (port));					\
 	result;									\
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-vnc/irqs.h linux/include/asm-arm/arch-vnc/irqs.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-vnc/irqs.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-vnc/irqs.h	Thu Jan  7 15:51:33 1999
@@ -39,7 +39,7 @@
 #define IRQ_HARDDISK		30	/* from 553.14 */
 
 /* These defines handle the translation from the above FB #defines
- * into physical buts for the FootBridge IRQ registers
+ * into physical bits for the FootBridge IRQ registers
  */
 #define IRQ_MASK_SOFTIRQ	0x00000002
 #define IRQ_MASK_UART_DEBUG	0x0000000C
@@ -52,11 +52,16 @@
 #define IRQ_MASK_VIDCOMP	0x00000400
 #define IRQ_MASK_EXTERN_IRQ	0x00000800
 #define IRQ_MASK_DMA1		0x00030000
-#define IRQ_MASK_PCI_ERR	0xf0000000
+#define IRQ_MASK_PCI_ERR	0xf8800000
 
 /*
  * Now map them to the Linux interrupts
  */
+#undef IRQ_TIMER
 #define IRQ_TIMER		IRQ_TIMER0
+#undef RTC_IRQ
+#define RTC_IRQ			IRQ_RTC_ALARM
+#undef AUX_IRQ
+#define AUX_IRQ			IRQ_MOUSE
 
 #define irq_cannonicalize(i)	(i)
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-vnc/processor.h linux/include/asm-arm/arch-vnc/processor.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-vnc/processor.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-vnc/processor.h	Thu Jan  7 15:51:33 1999
@@ -24,7 +24,6 @@
  * space during mmap's.
  */
 #define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
-#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-vnc/system.h linux/include/asm-arm/arch-vnc/system.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-vnc/system.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-vnc/system.h	Thu Jan  7 15:51:33 1999
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-arm/arch-ebsa285/system.h
+ * linux/include/asm-arm/arch-vnc/system.h
  *
  * Copyright (c) 1996,1997,1998 Russell King.
  * Copyright (c) 1998 Corel Computer Corp.
@@ -9,7 +9,7 @@
 #include <asm/leds.h>
 #include <asm/io.h>
 
-extern __inline__ void arch_hard_reset (void)
+extern __inline__ void arch_reset(char mode)
 {
 	cli();
 
@@ -31,11 +31,7 @@
 	/* set a RED LED and toggle WD_TIMER for rebooting...
 	 */
 	outb(0xC4, 0x338);
-	
-	while(1);
 }
-
-#define ARCH_IDLE_OK
 
 #define arch_start_idle()	leds_event(led_idle_start)
 #define arch_end_idle()		leds_event(led_idle_end)
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/arch-vnc/time.h linux/include/asm-arm/arch-vnc/time.h
--- v2.2.0-pre5/linux/include/asm-arm/arch-vnc/time.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-vnc/time.h	Thu Jan  7 15:51:33 1999
@@ -4,20 +4,80 @@
  * Copyright (c) 1997 Corel Computer Corp.
  * Slight modifications to bring in line with ebsa285 port.
  *  -- Russell King.
+ *  Added LED driver (based on the ebsa285 code) - Alex Holden 28/12/98.
  */
 
+#include <linux/config.h>
 #include <linux/mc146818rtc.h>
 
+#include <asm/leds.h>
+#include <asm/system.h>
+
 #undef IRQ_TIMER
 #define IRQ_TIMER		IRQ_TIMER4
 
+#define mSEC_10_from_14 ((14318180 + 100) / 200)
+
 extern __inline__ unsigned long gettimeoffset (void)
 {
-	return 0;
+	int count;
+
+	static int count_p = (mSEC_10_from_14/6);    /* for the first call after boot */
+	static unsigned long jiffies_p = 0;
+
+	/*
+	 * cache volatile jiffies temporarily; we have IRQs turned off. 
+	 */
+	unsigned long jiffies_t;
+
+	/* timer count may underflow right here */
+	outb_p(0x00, 0x43);	/* latch the count ASAP */
+
+	count = inb_p(0x40);	/* read the latched count */
+
+	/*
+	 * We do this guaranteed double memory access instead of a _p 
+	 * postfix in the previous port access. Wheee, hackady hack
+	 */
+ 	jiffies_t = jiffies;
+
+	count |= inb_p(0x40) << 8;
+
+	/* Detect timer underflows.  If we haven't had a timer tick since 
+	   the last time we were called, and time is apparently going
+	   backwards, the counter must have wrapped during this routine. */
+	if ((jiffies_t == jiffies_p) && (count > count_p))
+		count -= (mSEC_10_from_14/6);
+	else
+		jiffies_p = jiffies_t;
+
+	count_p = count;
+
+	count = (((mSEC_10_from_14/6)-1) - count) * tick;
+	count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
+
+	return count;
 }
 
 extern __inline__ int reset_timer (void)
 {
+#ifdef CONFIG_LEDS
+	static unsigned int count = 50;
+	static int last_pid;
+
+	if (current->pid != last_pid) {
+		last_pid = current->pid;
+		if (last_pid)
+			leds_event(led_idle_end);
+		else
+			leds_event(led_idle_start);
+	}
+
+	if (--count == 0) {
+		count = 50;
+		leds_event(led_timer);
+	}
+#endif
 	return 1;
 }
 
@@ -137,8 +197,6 @@
 		year += 100;
 	return mktime(year, mon, day, hour, min, sec);
 }
-
-#define mSEC_10_from_14 ((14318180 + 100) / 200)
 
 /*
  * Set up timer interrupt, and return the current time in seconds.
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/atomic.h linux/include/asm-arm/atomic.h
--- v2.2.0-pre5/linux/include/asm-arm/atomic.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/atomic.h	Thu Jan  7 15:51:33 1999
@@ -12,16 +12,22 @@
 #ifndef __ASM_ARM_ATOMIC_H
 #define __ASM_ARM_ATOMIC_H
 
+#ifdef __SMP__
+#error SMP not supported
+#endif
+
+#include <linux/config.h>
+
+#ifdef CONFIG_ARCH_CO285
+typedef struct { volatile int counter; } atomic_t;
+#else
 typedef struct { int counter; } atomic_t;
+#endif
 
 #define ATOMIC_INIT(i)	{ (i) }
 
 #ifdef __KERNEL__
 #include <asm/system.h>
-
-#ifdef __SMP__
-#error SMP not supported
-#endif
 
 #define atomic_read(v)	((v)->counter)
 #define atomic_set(v,i)	(((v)->counter) = (i))
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/byteorder.h linux/include/asm-arm/byteorder.h
--- v2.2.0-pre5/linux/include/asm-arm/byteorder.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/byteorder.h	Thu Jan  7 15:51:33 1999
@@ -3,10 +3,14 @@
 
 #include <asm/types.h>
 
-#if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ < 80
+#if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ < 8
 
-/* Recent versions of GCC can do as well or better than this
-   on their own - we shouldn't interfere.  */
+/* Recent versions of GCC can open code the swaps at least as well
+   as we can write them by hand, so the "optimisations" here only 
+   make sense for older compilers.  Worse, some versions of GCC
+   actually go wrong in the presence of the assembler versions.
+   We play it safe and only turn them on for compilers older than
+   GCC 2.8.0.  */
 
 static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
 {
@@ -35,6 +39,11 @@
 #define __arch__swab16(x) ___arch__swab16(x)
 
 #endif /* __GNUC__ */
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#  define __SWAB_64_THRU_32__
+#endif
 
 #include <linux/byteorder/little_endian.h>
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/dec21285.h linux/include/asm-arm/dec21285.h
--- v2.2.0-pre5/linux/include/asm-arm/dec21285.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/dec21285.h	Thu Jan  7 15:51:33 1999
@@ -2,6 +2,8 @@
  * include/asm-arm/dec21285.h
  *
  * Copyright (C) 1998 Russell King
+ *
+ * DC21285 registers
  */
 #define DC21285_PCI_IACK		0x79000000
 #define DC21285_ARMCSR_BASE		0x42000000
@@ -13,109 +15,74 @@
 #define DC21285_PCI_MEM			0x80000000
 
 #ifndef __ASSEMBLY__
-
-/*
- * DEC21285
- */
-#define CSR_SA110_CNTL		((volatile unsigned long *)0xfe00013c)
-#define CSR_PCIADDR_EXTN	((volatile unsigned long *)0xfe000140)
-#define CSR_PREFETCHMEMRANGE	((volatile unsigned long *)0xfe000144)
-#define CSR_XBUS_CYCLE		((volatile unsigned long *)0xfe000148)
-#define CSR_XBUS_IOSTROBE	((volatile unsigned long *)0xfe00014c)
-#define CSR_DOORBELL_PCI	((volatile unsigned long *)0xfe000150)
-#define CSR_DOORBELL_SA110	((volatile unsigned long *)0xfe000154)
-
-#define CSR_UARTDR		((volatile unsigned long *)0xfe000160)
-#define CSR_RXSTAT		((volatile unsigned long *)0xfe000164)
-#define CSR_H_UBRLCR		((volatile unsigned long *)0xfe000168)
-#define CSR_M_UBRLCR		((volatile unsigned long *)0xfe00016c)
-#define CSR_L_UBRLCR		((volatile unsigned long *)0xfe000170)
-#define CSR_UARTCON		((volatile unsigned long *)0xfe000174)
-#define CSR_UARTFLG		((volatile unsigned long *)0xfe000178)
-
-#define CSR_IRQ_STATUS		((volatile unsigned long *)0xfe000180)
-#define CSR_IRQ_RAWSTATUS	((volatile unsigned long *)0xfe000184)
-#define CSR_IRQ_ENABLE		((volatile unsigned long *)0xfe000188)
-#define CSR_IRQ_DISABLE		((volatile unsigned long *)0xfe00018c)
-#define CSR_IRQ_SOFT		((volatile unsigned long *)0xfe000190)
-
-#define CSR_FIQ_STATUS		((volatile unsigned long *)0xfe000280)
-#define CSR_FIQ_RAWSTATUS	((volatile unsigned long *)0xfe000284)
-#define CSR_FIQ_ENABLE		((volatile unsigned long *)0xfe000288)
-#define CSR_FIQ_DISABLE		((volatile unsigned long *)0xfe00028c)
-#define CSR_FIQ_SOFT		((volatile unsigned long *)0xfe000290)
-
-#define CSR_TIMER1_LOAD		((volatile unsigned long *)0xfe000300)
-#define CSR_TIMER1_VALUE	((volatile unsigned long *)0xfe000304)
-#define CSR_TIMER1_CNTL		((volatile unsigned long *)0xfe000308)
-#define CSR_TIMER1_CLR		((volatile unsigned long *)0xfe00030c)
-
-#define CSR_TIMER2_LOAD		((volatile unsigned long *)0xfe000320)
-#define CSR_TIMER2_VALUE	((volatile unsigned long *)0xfe000324)
-#define CSR_TIMER2_CNTL		((volatile unsigned long *)0xfe000328)
-#define CSR_TIMER2_CLR		((volatile unsigned long *)0xfe00032c)
-
-#define CSR_TIMER3_LOAD		((volatile unsigned long *)0xfe000340)
-#define CSR_TIMER3_VALUE	((volatile unsigned long *)0xfe000344)
-#define CSR_TIMER3_CNTL		((volatile unsigned long *)0xfe000348)
-#define CSR_TIMER3_CLR		((volatile unsigned long *)0xfe00034c)
-
-#define CSR_TIMER4_LOAD		((volatile unsigned long *)0xfe000360)
-#define CSR_TIMER4_VALUE	((volatile unsigned long *)0xfe000364)
-#define CSR_TIMER4_CNTL		((volatile unsigned long *)0xfe000368)
-#define CSR_TIMER4_CLR		((volatile unsigned long *)0xfe00036c)
-
+#define DC21285_IO(x)		((volatile unsigned long *)(0xfe000000+(x)))
 #else
-
-#define CSR_SA110_CNTL		0x13c
-#define CSR_PCIADDR_EXTN	0x140
-#define CSR_PREFETCHMEMRANGE	0x144
-#define CSR_XBUS_CYCLE		0x148
-#define CSR_XBUS_IOSTROBE	0x14c
-#define CSR_DOORBELL_PCI	0x150
-#define CSR_DOORBELL_SA110	0x154
-
-#define CSR_UARTDR		0x160
-#define CSR_RXSTAT		0x164
-#define CSR_H_UBRLCR		0x168
-#define CSR_M_UBRLCR		0x16c
-#define CSR_L_UBRLCR		0x170
-#define CSR_UARTCON		0x174
-#define CSR_UARTFLG		0x178
-
-#define CSR_IRQ_STATUS		0x180
-#define CSR_IRQ_RAWSTATUS	0x184
-#define CSR_IRQ_ENABLE		0x188
-#define CSR_IRQ_DISABLE		0x18c
-#define CSR_IRQ_SOFT		0x190
-
-#define CSR_FIQ_STATUS		0x280
-#define CSR_FIQ_RAWSTATUS	0x284
-#define CSR_FIQ_ENABLE		0x288
-#define CSR_FIQ_DISABLE		0x28c
-#define CSR_FIQ_SOFT		0x290
-
-#define CSR_TIMER1_LOAD		0x300
-#define CSR_TIMER1_VALUE	0x304
-#define CSR_TIMER1_CNTL		0x308
-#define CSR_TIMER1_CLR		0x30c
-
-#define CSR_TIMER2_LOAD		0x320
-#define CSR_TIMER2_VALUE	0x324
-#define CSR_TIMER2_CNTL		0x328
-#define CSR_TIMER2_CLR		0x32c
-
-#define CSR_TIMER3_LOAD		0x340
-#define CSR_TIMER3_VALUE	0x344
-#define CSR_TIMER3_CNTL		0x348
-#define CSR_TIMER3_CLR		0x34c
-
-#define CSR_TIMER4_LOAD		0x360
-#define CSR_TIMER4_VALUE	0x364
-#define CSR_TIMER4_CNTL		0x368
-#define CSR_TIMER4_CLR		0x36c
-
+#define DC21285_IO(x)		(x)
 #endif
+
+#define CSR_PCICMD		DC21285_IO(0x0004)
+#define CSR_PCICACHELINESIZE	DC21285_IO(0x000c)
+#define CSR_PCICSRBASE		DC21285_IO(0x0010)
+#define CSR_PCICSRIOBASE	DC21285_IO(0x0014)
+#define CSR_PCISDRAMBASE	DC21285_IO(0x0018)
+#define CSR_PCIROMBASE		DC21285_IO(0x0030)
+#define CSR_CSRBASEMASK		DC21285_IO(0x00f8)
+#define CSR_CSRBASEOFFSET	DC21285_IO(0x00fc)
+#define CSR_SDRAMBASEMASK	DC21285_IO(0x0100)
+#define CSR_SDRAMBASEOFFSET	DC21285_IO(0x0104)
+#define CSR_ROMBASEMASK		DC21285_IO(0x0108)
+#define CSR_SDRAMTIMING		DC21285_IO(0x010c)
+#define CSR_SDRAMADDRSIZE0	DC21285_IO(0x0110)
+#define CSR_SDRAMADDRSIZE1	DC21285_IO(0x0114)
+#define CSR_SDRAMADDRSIZE2	DC21285_IO(0x0118)
+#define CSR_SDRAMADDRSIZE3	DC21285_IO(0x011c)
+#define CSR_I2O_INFREEHEAD	DC21285_IO(0x0120)
+#define CSR_I2O_INPOSTTAIL	DC21285_IO(0x0124)
+#define CSR_I2O_OUTPOSTHEAD	DC21285_IO(0x0128)
+#define CSR_I2O_OUTFREETAIL	DC21285_IO(0x012c)
+#define CSR_I2O_INFREECOUNT	DC21285_IO(0x0130)
+#define CSR_I2O_OUTPOSTCOUNT	DC21285_IO(0x0134)
+#define CSR_I2O_INPOSTCOUNT	DC21285_IO(0x0138)
+#define CSR_SA110_CNTL		DC21285_IO(0x013c)
+#define CSR_PCIADDR_EXTN	DC21285_IO(0x0140)
+#define CSR_PREFETCHMEMRANGE	DC21285_IO(0x0144)
+#define CSR_XBUS_CYCLE		DC21285_IO(0x0148)
+#define CSR_XBUS_IOSTROBE	DC21285_IO(0x014c)
+#define CSR_DOORBELL_PCI	DC21285_IO(0x0150)
+#define CSR_DOORBELL_SA110	DC21285_IO(0x0154)
+#define CSR_UARTDR		DC21285_IO(0x0160)
+#define CSR_RXSTAT		DC21285_IO(0x0164)
+#define CSR_H_UBRLCR		DC21285_IO(0x0168)
+#define CSR_M_UBRLCR		DC21285_IO(0x016c)
+#define CSR_L_UBRLCR		DC21285_IO(0x0170)
+#define CSR_UARTCON		DC21285_IO(0x0174)
+#define CSR_UARTFLG		DC21285_IO(0x0178)
+#define CSR_IRQ_STATUS		DC21285_IO(0x0180)
+#define CSR_IRQ_RAWSTATUS	DC21285_IO(0x0184)
+#define CSR_IRQ_ENABLE		DC21285_IO(0x0188)
+#define CSR_IRQ_DISABLE		DC21285_IO(0x018c)
+#define CSR_IRQ_SOFT		DC21285_IO(0x0190)
+#define CSR_FIQ_STATUS		DC21285_IO(0x0280)
+#define CSR_FIQ_RAWSTATUS	DC21285_IO(0x0284)
+#define CSR_FIQ_ENABLE		DC21285_IO(0x0288)
+#define CSR_FIQ_DISABLE		DC21285_IO(0x028c)
+#define CSR_FIQ_SOFT		DC21285_IO(0x0290)
+#define CSR_TIMER1_LOAD		DC21285_IO(0x0300)
+#define CSR_TIMER1_VALUE	DC21285_IO(0x0304)
+#define CSR_TIMER1_CNTL		DC21285_IO(0x0308)
+#define CSR_TIMER1_CLR		DC21285_IO(0x030c)
+#define CSR_TIMER2_LOAD		DC21285_IO(0x0320)
+#define CSR_TIMER2_VALUE	DC21285_IO(0x0324)
+#define CSR_TIMER2_CNTL		DC21285_IO(0x0328)
+#define CSR_TIMER2_CLR		DC21285_IO(0x032c)
+#define CSR_TIMER3_LOAD		DC21285_IO(0x0340)
+#define CSR_TIMER3_VALUE	DC21285_IO(0x0344)
+#define CSR_TIMER3_CNTL		DC21285_IO(0x0348)
+#define CSR_TIMER3_CLR		DC21285_IO(0x034c)
+#define CSR_TIMER4_LOAD		DC21285_IO(0x0360)
+#define CSR_TIMER4_VALUE	DC21285_IO(0x0364)
+#define CSR_TIMER4_CNTL		DC21285_IO(0x0368)
+#define CSR_TIMER4_CLR		DC21285_IO(0x036c)
 
 #define TIMER_CNTL_ENABLE	(1 << 7)
 #define TIMER_CNTL_AUTORELOAD	(1 << 6)
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/dma.h linux/include/asm-arm/dma.h
--- v2.2.0-pre5/linux/include/asm-arm/dma.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/dma.h	Thu Jan  7 15:51:33 1999
@@ -3,10 +3,24 @@
 
 typedef unsigned int dmach_t;
 
+#include <linux/config.h>
+#include <linux/kernel.h>
 #include <asm/irq.h>
+#include <asm/system.h>
 #include <asm/spinlock.h>
 #include <asm/arch/dma.h>
 
+/*
+ * DMA modes - we have two, IN and OUT
+ */
+typedef unsigned int dmamode_t;
+
+#define DMA_MODE_MASK	1
+
+#define DMA_MODE_READ	0
+#define DMA_MODE_WRITE	1
+#define DMA_AUTOINIT	2
+
 typedef struct {
 	unsigned long address;
 	unsigned long length;
@@ -115,6 +129,12 @@
 
 #ifndef NO_DMA
 #define NO_DMA	255
+#endif
+
+#ifdef CONFIG_PCI_QUIRKS
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy    (0)
 #endif
 
 #endif /* _ARM_DMA_H */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/hardware.h linux/include/asm-arm/hardware.h
--- v2.2.0-pre5/linux/include/asm-arm/hardware.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/hardware.h	Thu Jan  7 15:51:33 1999
@@ -11,257 +11,8 @@
 
 #include <asm/arch/hardware.h>
 
-/*
- * Use these macros to read/write the IOC.  All it does is perform the actual
- * read/write.
- */
-#ifdef HAS_IOC
-#ifndef __ASSEMBLER__
-#define __IOC(offset)	(IOC_BASE + (offset >> 2))
-#else
-#define __IOC(offset)	offset
-#endif
-
-#define IOC_CONTROL	__IOC(0x00)
-#define IOC_KARTTX	__IOC(0x04)
-#define IOC_KARTRX	__IOC(0x04)
-
-#define IOC_IRQSTATA	__IOC(0x10)
-#define IOC_IRQREQA	__IOC(0x14)
-#define IOC_IRQCLRA	__IOC(0x14)
-#define IOC_IRQMASKA	__IOC(0x18)
-
-#define IOC_IRQSTATB	__IOC(0x20)
-#define IOC_IRQREQB	__IOC(0x24)
-#define IOC_IRQMASKB	__IOC(0x28)
-
-#define IOC_FIQSTAT	__IOC(0x30)
-#define IOC_FIQREQ	__IOC(0x34)
-#define IOC_FIQMASK	__IOC(0x38)
-
-#define IOC_T0CNTL	__IOC(0x40)
-#define IOC_T0LTCHL	__IOC(0x40)
-#define IOC_T0CNTH	__IOC(0x44)
-#define IOC_T0LTCHH	__IOC(0x44)
-#define IOC_T0GO	__IOC(0x48)
-#define IOC_T0LATCH	__IOC(0x4c)
-
-#define IOC_T1CNTL	__IOC(0x50)
-#define IOC_T1LTCHL	__IOC(0x50)
-#define IOC_T1CNTH	__IOC(0x54)
-#define IOC_T1LTCHH	__IOC(0x54)
-#define IOC_T1GO	__IOC(0x58)
-#define IOC_T1LATCH	__IOC(0x5c)
-
-#define IOC_T2CNTL	__IOC(0x60)
-#define IOC_T2LTCHL	__IOC(0x60)
-#define IOC_T2CNTH	__IOC(0x64)
-#define IOC_T2LTCHH	__IOC(0x64)
-#define IOC_T2GO	__IOC(0x68)
-#define IOC_T2LATCH	__IOC(0x6c)
-
-#define IOC_T3CNTL	__IOC(0x70)
-#define IOC_T3LTCHL	__IOC(0x70)
-#define IOC_T3CNTH	__IOC(0x74)
-#define IOC_T3LTCHH	__IOC(0x74)
-#define IOC_T3GO	__IOC(0x78)
-#define IOC_T3LATCH	__IOC(0x7c)
-#endif
-
-#ifdef HAS_MEMC
-#define VDMA_ALIGNMENT	PAGE_SIZE
-#define VDMA_XFERSIZE	16
-#define VDMA_INIT	0
-#define VDMA_START	1
-#define VDMA_END	2
-
-#define video_set_dma(start,end,offset)				\
-do {								\
-	memc_write (VDMA_START, (start >> 2));			\
-	memc_write (VDMA_END, (end - VDMA_XFERSIZE) >> 2);	\
-	memc_write (VDMA_INIT, (offset >> 2));			\
-} while (0)
-#endif
-
-#ifdef HAS_IOMD
-#ifndef __ASSEMBLER__
-#define __IOMD(offset)	(IO_IOMD_BASE + (offset >> 2))
-#else
-#define __IOMD(offset)	offset
-#endif
-
-#define IOMD_CONTROL	__IOMD(0x000)
-#define IOMD_KARTTX	__IOMD(0x004)
-#define IOMD_KARTRX	__IOMD(0x004)
-#define IOMD_KCTRL	__IOMD(0x008)
-
-#define IOMD_IRQSTATA	__IOMD(0x010)
-#define IOMD_IRQREQA	__IOMD(0x014)
-#define IOMD_IRQCLRA	__IOMD(0x014)
-#define IOMD_IRQMASKA	__IOMD(0x018)
-
-#define IOMD_IRQSTATB	__IOMD(0x020)
-#define IOMD_IRQREQB	__IOMD(0x024)
-#define IOMD_IRQMASKB	__IOMD(0x028)
-
-#define IOMD_FIQSTAT	__IOMD(0x030)
-#define IOMD_FIQREQ	__IOMD(0x034)
-#define IOMD_FIQMASK	__IOMD(0x038)
-
-#define IOMD_T0CNTL	__IOMD(0x040)
-#define IOMD_T0LTCHL	__IOMD(0x040)
-#define IOMD_T0CNTH	__IOMD(0x044)
-#define IOMD_T0LTCHH	__IOMD(0x044)
-#define IOMD_T0GO	__IOMD(0x048)
-#define IOMD_T0LATCH	__IOMD(0x04c)
-
-#define IOMD_T1CNTL	__IOMD(0x050)
-#define IOMD_T1LTCHL	__IOMD(0x050)
-#define IOMD_T1CNTH	__IOMD(0x054)
-#define IOMD_T1LTCHH	__IOMD(0x054)
-#define IOMD_T1GO	__IOMD(0x058)
-#define IOMD_T1LATCH	__IOMD(0x05c)
-
-#define IOMD_ROMCR0	__IOMD(0x080)
-#define IOMD_ROMCR1	__IOMD(0x084)
-#define IOMD_DRAMCR	__IOMD(0x088)
-#define IOMD_VREFCR	__IOMD(0x08C)
-
-#define IOMD_FSIZE	__IOMD(0x090)
-#define IOMD_ID0	__IOMD(0x094)
-#define IOMD_ID1	__IOMD(0x098)
-#define IOMD_VERSION	__IOMD(0x09C)
-
-#define IOMD_MOUSEX	__IOMD(0x0A0)
-#define IOMD_MOUSEY	__IOMD(0x0A4)
-
-#define IOMD_DMATCR	__IOMD(0x0C0)
-#define IOMD_IOTCR	__IOMD(0x0C4)
-#define IOMD_ECTCR	__IOMD(0x0C8)
-#define IOMD_DMAEXT	__IOMD(0x0CC)
-
-#define DMA_EXT_IO0	1
-#define DMA_EXT_IO1	2
-#define DMA_EXT_IO2	4
-#define DMA_EXT_IO3	8
-
-#define IOMD_IO0CURA	__IOMD(0x100)
-#define IOMD_IO0ENDA	__IOMD(0x104)
-#define IOMD_IO0CURB	__IOMD(0x108)
-#define IOMD_IO0ENDB	__IOMD(0x10C)
-#define IOMD_IO0CR	__IOMD(0x110)
-#define IOMD_IO0ST	__IOMD(0x114)
-
-#define IOMD_IO1CURA	__IOMD(0x120)
-#define IOMD_IO1ENDA	__IOMD(0x124)
-#define IOMD_IO1CURB	__IOMD(0x128)
-#define IOMD_IO1ENDB	__IOMD(0x12C)
-#define IOMD_IO1CR	__IOMD(0x130)
-#define IOMD_IO1ST	__IOMD(0x134)
-
-#define IOMD_IO2CURA	__IOMD(0x140)
-#define IOMD_IO2ENDA	__IOMD(0x144)
-#define IOMD_IO2CURB	__IOMD(0x148)
-#define IOMD_IO2ENDB	__IOMD(0x14C)
-#define IOMD_IO2CR	__IOMD(0x150)
-#define IOMD_IO2ST	__IOMD(0x154)
-
-#define IOMD_IO3CURA	__IOMD(0x160)
-#define IOMD_IO3ENDA	__IOMD(0x164)
-#define IOMD_IO3CURB	__IOMD(0x168)
-#define IOMD_IO3ENDB	__IOMD(0x16C)
-#define IOMD_IO3CR	__IOMD(0x170)
-#define IOMD_IO3ST	__IOMD(0x174)
-
-#define IOMD_SD0CURA	__IOMD(0x180)
-#define IOMD_SD0ENDA	__IOMD(0x184)
-#define IOMD_SD0CURB	__IOMD(0x188)
-#define IOMD_SD0ENDB	__IOMD(0x18C)
-#define IOMD_SD0CR	__IOMD(0x190)
-#define IOMD_SD0ST	__IOMD(0x194)
-
-#define IOMD_SD1CURA	__IOMD(0x1A0)
-#define IOMD_SD1ENDA	__IOMD(0x1A4)
-#define IOMD_SD1CURB	__IOMD(0x1A8)
-#define IOMD_SD1ENDB	__IOMD(0x1AC)
-#define IOMD_SD1CR	__IOMD(0x1B0)
-#define IOMD_SD1ST	__IOMD(0x1B4)
-
-#define IOMD_CURSCUR	__IOMD(0x1C0)
-#define IOMD_CURSINIT	__IOMD(0x1C4)
-
-#define IOMD_VIDCUR	__IOMD(0x1D0)
-#define IOMD_VIDEND	__IOMD(0x1D4)
-#define IOMD_VIDSTART	__IOMD(0x1D8)
-#define IOMD_VIDINIT	__IOMD(0x1DC)
-#define IOMD_VIDCR	__IOMD(0x1E0)
-
-#define IOMD_DMASTAT	__IOMD(0x1F0)
-#define IOMD_DMAREQ	__IOMD(0x1F4)
-#define IOMD_DMAMASK	__IOMD(0x1F8)
-
-#define DMA_END_S	(1 << 31)
-#define DMA_END_L	(1 << 30)
-
-#define DMA_CR_C	0x80
-#define DMA_CR_D	0x40
-#define DMA_CR_E	0x20
-
-#define DMA_ST_OFL	4
-#define DMA_ST_INT	2
-#define DMA_ST_AB	1
-/*
- * IOC compatability
- */
-#define IOC_CONTROL	IOMD_CONTROL
-#define IOC_IRQSTATA	IOMD_IRQSTATA
-#define IOC_IRQREQA	IOMD_IRQREQA
-#define IOC_IRQCLRA	IOMD_IRQCLRA
-#define IOC_IRQMASKA	IOMD_IRQMASKA
-
-#define IOC_IRQSTATB	IOMD_IRQSTATB
-#define IOC_IRQREQB	IOMD_IRQREQB
-#define IOC_IRQMASKB	IOMD_IRQMASKB
-
-#define IOC_FIQSTAT	IOMD_FIQSTAT
-#define IOC_FIQREQ	IOMD_FIQREQ
-#define IOC_FIQMASK	IOMD_FIQMASK
-
-#define IOC_T0CNTL	IOMD_T0CNTL
-#define IOC_T0LTCHL	IOMD_T0LTCHL
-#define IOC_T0CNTH	IOMD_T0CNTH
-#define IOC_T0LTCHH	IOMD_T0LTCHH
-#define IOC_T0GO	IOMD_T0GO
-#define IOC_T0LATCH	IOMD_T0LATCH
-
-#define IOC_T1CNTL	IOMD_T1CNTL
-#define IOC_T1LTCHL	IOMD_T1LTCHL
-#define IOC_T1CNTH	IOMD_T1CNTH
-#define IOC_T1LTCHH	IOMD_T1LTCHH
-#define IOC_T1GO	IOMD_T1GO
-#define IOC_T1LATCH	IOMD_T1LATCH
-
-/*
- * DMA (MEMC) compatability
- */
-#define HALF_SAM	vram_half_sam
-#define VDMA_ALIGNMENT	(HALF_SAM * 2)
-#define VDMA_XFERSIZE	(HALF_SAM)
-#define VDMA_INIT	IOMD_VIDINIT
-#define VDMA_START	IOMD_VIDSTART
-#define VDMA_END	IOMD_VIDEND
-
-#ifndef __ASSEMBLER__
-extern unsigned int vram_half_sam;
-#define video_set_dma(start,end,offset)				\
-do {								\
-	outl (SCREEN_START + start, VDMA_START);		\
-	outl (SCREEN_START + end - VDMA_XFERSIZE, VDMA_END);	\
-	if (offset >= end - VDMA_XFERSIZE)			\
-		offset |= 0x40000000;				\
-	outl (SCREEN_START + offset, VDMA_INIT);		\
-} while (0)
-#endif
+#ifndef FLUSH_BASE
+#define FLUSH_BASE	0xdf000000
 #endif
 
 #ifdef HAS_EXPMASK
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/init.h linux/include/asm-arm/init.h
--- v2.2.0-pre5/linux/include/asm-arm/init.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/init.h	Thu Jan  7 15:51:33 1999
@@ -5,7 +5,7 @@
 
 /* C routines */
 
-#ifdef CONFIG_BINUTILS_NEW
+#ifdef CONFIG_TEXT_INIT_SECTION
 
 #define __init __attribute__ ((__section__ (".text.init")))
 #define __initfunc(__arginit) \
@@ -25,5 +25,8 @@
 #define __INIT		.section	".text.init",@alloc,@execinstr
 #define __INITDATA	.section	".data.init",@alloc,@write
 #define __FINIT	.previous
+
+#define __cacheline_aligned __attribute__ \
+			 ((__aligned__ (L1_CACHE_BYTES)))
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/io.h linux/include/asm-arm/io.h
--- v2.2.0-pre5/linux/include/asm-arm/io.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/io.h	Thu Jan  7 15:51:33 1999
@@ -31,7 +31,7 @@
  *              to an address that the kernel can use.
  */
 #define virt_to_bus(x)	(__virt_to_bus((unsigned long)(x)))
-#define bus_to_virt(x)	((void *)(__bus_to_virt(x)))
+#define bus_to_virt(x)	((void *)(__bus_to_virt((unsigned long)(x))))
 
 /*
  * These macros actually build the multi-value IO function prototypes
@@ -172,6 +172,8 @@
 #undef ARCH_IO_CONSTANT
 
 #ifdef __KERNEL__
+
+extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
 /*
  * String version of IO memory access ops:
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/ioc.h linux/include/asm-arm/ioc.h
--- v2.2.0-pre5/linux/include/asm-arm/ioc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/ioc.h	Thu Jan  7 15:51:33 1999
@@ -0,0 +1,56 @@
+/*
+ * Use these macros to read/write the IOC.  All it does is perform the actual
+ * read/write.
+ */
+
+#ifndef __ASSEMBLER__
+#define __IOC(offset)	(IOC_BASE + (offset >> 2))
+#else
+#define __IOC(offset)	offset
+#endif
+
+#define IOC_CONTROL	__IOC(0x00)
+#define IOC_KARTTX	__IOC(0x04)
+#define IOC_KARTRX	__IOC(0x04)
+
+#define IOC_IRQSTATA	__IOC(0x10)
+#define IOC_IRQREQA	__IOC(0x14)
+#define IOC_IRQCLRA	__IOC(0x14)
+#define IOC_IRQMASKA	__IOC(0x18)
+
+#define IOC_IRQSTATB	__IOC(0x20)
+#define IOC_IRQREQB	__IOC(0x24)
+#define IOC_IRQMASKB	__IOC(0x28)
+
+#define IOC_FIQSTAT	__IOC(0x30)
+#define IOC_FIQREQ	__IOC(0x34)
+#define IOC_FIQMASK	__IOC(0x38)
+
+#define IOC_T0CNTL	__IOC(0x40)
+#define IOC_T0LTCHL	__IOC(0x40)
+#define IOC_T0CNTH	__IOC(0x44)
+#define IOC_T0LTCHH	__IOC(0x44)
+#define IOC_T0GO	__IOC(0x48)
+#define IOC_T0LATCH	__IOC(0x4c)
+
+#define IOC_T1CNTL	__IOC(0x50)
+#define IOC_T1LTCHL	__IOC(0x50)
+#define IOC_T1CNTH	__IOC(0x54)
+#define IOC_T1LTCHH	__IOC(0x54)
+#define IOC_T1GO	__IOC(0x58)
+#define IOC_T1LATCH	__IOC(0x5c)
+
+#define IOC_T2CNTL	__IOC(0x60)
+#define IOC_T2LTCHL	__IOC(0x60)
+#define IOC_T2CNTH	__IOC(0x64)
+#define IOC_T2LTCHH	__IOC(0x64)
+#define IOC_T2GO	__IOC(0x68)
+#define IOC_T2LATCH	__IOC(0x6c)
+
+#define IOC_T3CNTL	__IOC(0x70)
+#define IOC_T3LTCHL	__IOC(0x70)
+#define IOC_T3CNTH	__IOC(0x74)
+#define IOC_T3LTCHH	__IOC(0x74)
+#define IOC_T3GO	__IOC(0x78)
+#define IOC_T3LATCH	__IOC(0x7c)
+
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/iomd.h linux/include/asm-arm/iomd.h
--- v2.2.0-pre5/linux/include/asm-arm/iomd.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/iomd.h	Thu Jan  7 15:51:33 1999
@@ -0,0 +1,180 @@
+
+#ifndef __ASSEMBLER__
+#define __IOMD(offset)	(IO_IOMD_BASE + (offset >> 2))
+#else
+#define __IOMD(offset)	offset
+#endif
+
+#define IOMD_CONTROL	__IOMD(0x000)
+#define IOMD_KARTTX	__IOMD(0x004)
+#define IOMD_KARTRX	__IOMD(0x004)
+#define IOMD_KCTRL	__IOMD(0x008)
+
+#define IOMD_IRQSTATA	__IOMD(0x010)
+#define IOMD_IRQREQA	__IOMD(0x014)
+#define IOMD_IRQCLRA	__IOMD(0x014)
+#define IOMD_IRQMASKA	__IOMD(0x018)
+
+#define IOMD_IRQSTATB	__IOMD(0x020)
+#define IOMD_IRQREQB	__IOMD(0x024)
+#define IOMD_IRQMASKB	__IOMD(0x028)
+
+#define IOMD_FIQSTAT	__IOMD(0x030)
+#define IOMD_FIQREQ	__IOMD(0x034)
+#define IOMD_FIQMASK	__IOMD(0x038)
+
+#define IOMD_T0CNTL	__IOMD(0x040)
+#define IOMD_T0LTCHL	__IOMD(0x040)
+#define IOMD_T0CNTH	__IOMD(0x044)
+#define IOMD_T0LTCHH	__IOMD(0x044)
+#define IOMD_T0GO	__IOMD(0x048)
+#define IOMD_T0LATCH	__IOMD(0x04c)
+
+#define IOMD_T1CNTL	__IOMD(0x050)
+#define IOMD_T1LTCHL	__IOMD(0x050)
+#define IOMD_T1CNTH	__IOMD(0x054)
+#define IOMD_T1LTCHH	__IOMD(0x054)
+#define IOMD_T1GO	__IOMD(0x058)
+#define IOMD_T1LATCH	__IOMD(0x05c)
+
+#define IOMD_ROMCR0	__IOMD(0x080)
+#define IOMD_ROMCR1	__IOMD(0x084)
+#define IOMD_DRAMCR	__IOMD(0x088)
+#define IOMD_VREFCR	__IOMD(0x08C)
+
+#define IOMD_FSIZE	__IOMD(0x090)
+#define IOMD_ID0	__IOMD(0x094)
+#define IOMD_ID1	__IOMD(0x098)
+#define IOMD_VERSION	__IOMD(0x09C)
+
+#define IOMD_MOUSEX	__IOMD(0x0A0)
+#define IOMD_MOUSEY	__IOMD(0x0A4)
+
+#define IOMD_DMATCR	__IOMD(0x0C0)
+#define IOMD_IOTCR	__IOMD(0x0C4)
+#define IOMD_ECTCR	__IOMD(0x0C8)
+#define IOMD_DMAEXT	__IOMD(0x0CC)
+
+#define DMA_EXT_IO0	1
+#define DMA_EXT_IO1	2
+#define DMA_EXT_IO2	4
+#define DMA_EXT_IO3	8
+
+#define IOMD_IO0CURA	__IOMD(0x100)
+#define IOMD_IO0ENDA	__IOMD(0x104)
+#define IOMD_IO0CURB	__IOMD(0x108)
+#define IOMD_IO0ENDB	__IOMD(0x10C)
+#define IOMD_IO0CR	__IOMD(0x110)
+#define IOMD_IO0ST	__IOMD(0x114)
+
+#define IOMD_IO1CURA	__IOMD(0x120)
+#define IOMD_IO1ENDA	__IOMD(0x124)
+#define IOMD_IO1CURB	__IOMD(0x128)
+#define IOMD_IO1ENDB	__IOMD(0x12C)
+#define IOMD_IO1CR	__IOMD(0x130)
+#define IOMD_IO1ST	__IOMD(0x134)
+
+#define IOMD_IO2CURA	__IOMD(0x140)
+#define IOMD_IO2ENDA	__IOMD(0x144)
+#define IOMD_IO2CURB	__IOMD(0x148)
+#define IOMD_IO2ENDB	__IOMD(0x14C)
+#define IOMD_IO2CR	__IOMD(0x150)
+#define IOMD_IO2ST	__IOMD(0x154)
+
+#define IOMD_IO3CURA	__IOMD(0x160)
+#define IOMD_IO3ENDA	__IOMD(0x164)
+#define IOMD_IO3CURB	__IOMD(0x168)
+#define IOMD_IO3ENDB	__IOMD(0x16C)
+#define IOMD_IO3CR	__IOMD(0x170)
+#define IOMD_IO3ST	__IOMD(0x174)
+
+#define IOMD_SD0CURA	__IOMD(0x180)
+#define IOMD_SD0ENDA	__IOMD(0x184)
+#define IOMD_SD0CURB	__IOMD(0x188)
+#define IOMD_SD0ENDB	__IOMD(0x18C)
+#define IOMD_SD0CR	__IOMD(0x190)
+#define IOMD_SD0ST	__IOMD(0x194)
+
+#define IOMD_SD1CURA	__IOMD(0x1A0)
+#define IOMD_SD1ENDA	__IOMD(0x1A4)
+#define IOMD_SD1CURB	__IOMD(0x1A8)
+#define IOMD_SD1ENDB	__IOMD(0x1AC)
+#define IOMD_SD1CR	__IOMD(0x1B0)
+#define IOMD_SD1ST	__IOMD(0x1B4)
+
+#define IOMD_CURSCUR	__IOMD(0x1C0)
+#define IOMD_CURSINIT	__IOMD(0x1C4)
+
+#define IOMD_VIDCUR	__IOMD(0x1D0)
+#define IOMD_VIDEND	__IOMD(0x1D4)
+#define IOMD_VIDSTART	__IOMD(0x1D8)
+#define IOMD_VIDINIT	__IOMD(0x1DC)
+#define IOMD_VIDCR	__IOMD(0x1E0)
+
+#define IOMD_DMASTAT	__IOMD(0x1F0)
+#define IOMD_DMAREQ	__IOMD(0x1F4)
+#define IOMD_DMAMASK	__IOMD(0x1F8)
+
+#define DMA_END_S	(1 << 31)
+#define DMA_END_L	(1 << 30)
+
+#define DMA_CR_C	0x80
+#define DMA_CR_D	0x40
+#define DMA_CR_E	0x20
+
+#define DMA_ST_OFL	4
+#define DMA_ST_INT	2
+#define DMA_ST_AB	1
+/*
+ * IOC compatability
+ */
+#define IOC_CONTROL	IOMD_CONTROL
+#define IOC_IRQSTATA	IOMD_IRQSTATA
+#define IOC_IRQREQA	IOMD_IRQREQA
+#define IOC_IRQCLRA	IOMD_IRQCLRA
+#define IOC_IRQMASKA	IOMD_IRQMASKA
+
+#define IOC_IRQSTATB	IOMD_IRQSTATB
+#define IOC_IRQREQB	IOMD_IRQREQB
+#define IOC_IRQMASKB	IOMD_IRQMASKB
+
+#define IOC_FIQSTAT	IOMD_FIQSTAT
+#define IOC_FIQREQ	IOMD_FIQREQ
+#define IOC_FIQMASK	IOMD_FIQMASK
+
+#define IOC_T0CNTL	IOMD_T0CNTL
+#define IOC_T0LTCHL	IOMD_T0LTCHL
+#define IOC_T0CNTH	IOMD_T0CNTH
+#define IOC_T0LTCHH	IOMD_T0LTCHH
+#define IOC_T0GO	IOMD_T0GO
+#define IOC_T0LATCH	IOMD_T0LATCH
+
+#define IOC_T1CNTL	IOMD_T1CNTL
+#define IOC_T1LTCHL	IOMD_T1LTCHL
+#define IOC_T1CNTH	IOMD_T1CNTH
+#define IOC_T1LTCHH	IOMD_T1LTCHH
+#define IOC_T1GO	IOMD_T1GO
+#define IOC_T1LATCH	IOMD_T1LATCH
+
+/*
+ * DMA (MEMC) compatability
+ */
+#define HALF_SAM	vram_half_sam
+#define VDMA_ALIGNMENT	(HALF_SAM * 2)
+#define VDMA_XFERSIZE	(HALF_SAM)
+#define VDMA_INIT	IOMD_VIDINIT
+#define VDMA_START	IOMD_VIDSTART
+#define VDMA_END	IOMD_VIDEND
+
+#ifndef __ASSEMBLER__
+extern unsigned int vram_half_sam;
+#define video_set_dma(start,end,offset)				\
+do {								\
+	outl (SCREEN_START + start, VDMA_START);		\
+	outl (SCREEN_START + end - VDMA_XFERSIZE, VDMA_END);	\
+	if (offset >= end - VDMA_XFERSIZE)			\
+		offset |= 0x40000000;				\
+	outl (SCREEN_START + offset, VDMA_INIT);		\
+} while (0)
+#endif
+
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/leds.h linux/include/asm-arm/leds.h
--- v2.2.0-pre5/linux/include/asm-arm/leds.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/leds.h	Thu Jan  7 15:51:33 1999
@@ -4,6 +4,8 @@
  * Copyright (C) 1998 Russell King
  *
  * Event-driven interface for LEDs on machines
+ *
+ * Added led_start and led_stop- Alex Holden, 28th Dec 1998.
  */
 #ifndef ASM_ARM_LEDS_H
 #define ASM_ARM_LEDS_H
@@ -11,7 +13,9 @@
 typedef enum {
 	led_idle_start,
 	led_idle_end,
-	led_timer
+	led_timer,
+	led_start,
+	led_stop
 } led_event_t;
 
 /* Use this routine to handle LEDs */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/memc.h linux/include/asm-arm/memc.h
--- v2.2.0-pre5/linux/include/asm-arm/memc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/memc.h	Thu Jan  7 15:51:33 1999
@@ -0,0 +1,13 @@
+#define VDMA_ALIGNMENT	PAGE_SIZE
+#define VDMA_XFERSIZE	16
+#define VDMA_INIT	0
+#define VDMA_START	1
+#define VDMA_END	2
+
+#define video_set_dma(start,end,offset)				\
+do {								\
+	memc_write (VDMA_START, (start >> 2));			\
+	memc_write (VDMA_END, (end - VDMA_XFERSIZE) >> 2);	\
+	memc_write (VDMA_INIT, (offset >> 2));			\
+} while (0)
+
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/proc-armo/pgtable.h linux/include/asm-arm/proc-armo/pgtable.h
--- v2.2.0-pre5/linux/include/asm-arm/proc-armo/pgtable.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/proc-armo/pgtable.h	Thu Jan  7 15:51:33 1999
@@ -94,10 +94,6 @@
 
 #define __flush_entry_to_ram(entry)
 
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified.  Thus, the following
- * hook is made available.
- */
 /* PMD_SHIFT determines the size of the area a second-level page table can map */
 #define PMD_SHIFT       20
 #define PMD_SIZE        (1UL << PMD_SHIFT)
@@ -273,6 +269,10 @@
 	return pte;
 }
 
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
 #define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
 
 extern __inline__ unsigned long pte_page(pte_t pte)
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/proc-armo/system.h linux/include/asm-arm/proc-armo/system.h
--- v2.2.0-pre5/linux/include/asm-arm/proc-armo/system.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/proc-armo/system.h	Thu Jan  7 15:51:33 1999
@@ -40,74 +40,74 @@
 /*
  * Save the current interrupt enable state & disable IRQs
  */
-#define __save_flags_cli(x)		\
-	do {				\
-	  unsigned long temp;		\
-	  __asm__ __volatile__(		\
-"	mov	%0, pc\n"		\
-"	orr	%1, %0, #0x08000000\n"	\
-"	and	%0, %0, #0x0c000000\n"	\
-"	teqp	%1, #0\n"		\
-	  : "=r" (x), "=r" (temp)	\
-	  :				\
-	  : "memory");			\
+#define __save_flags_cli(x)				\
+	do {						\
+	  unsigned long temp;				\
+	  __asm__ __volatile__(				\
+"	mov	%0, pc		@ save_flags_cli\n"	\
+"	orr	%1, %0, #0x08000000\n"			\
+"	and	%0, %0, #0x0c000000\n"			\
+"	teqp	%1, #0\n"				\
+	  : "=r" (x), "=r" (temp)			\
+	  :						\
+	  : "memory");					\
 	} while (0)
 	
 /*
  * Enable IRQs
  */
-#define __sti()				\
-	do {				\
-	  unsigned long temp;		\
-	  __asm__ __volatile__(		\
-"	mov	%0, pc\n"		\
-"	bic	%0, %0, #0x08000000\n"	\
-"	teqp	%0, #0\n"		\
-	  : "=r" (temp)			\
-	  :				\
-	  : "memory");			\
+#define __sti()					\
+	do {					\
+	  unsigned long temp;			\
+	  __asm__ __volatile__(			\
+"	mov	%0, pc		@ sti\n"	\
+"	bic	%0, %0, #0x08000000\n"		\
+"	teqp	%0, #0\n"			\
+	  : "=r" (temp)				\
+	  :					\
+	  : "memory");				\
 	} while(0)
 
 /*
  * Disable IRQs
  */
-#define __cli()				\
-	do {				\
-	  unsigned long temp;		\
-	  __asm__ __volatile__(		\
-"	mov	%0, pc\n"		\
-"	orr	%0, %0, #0x08000000\n"	\
-"	teqp	%0, #0\n"		\
-	  : "=r" (temp)			\
-	  :				\
-	  : "memory");			\
+#define __cli()					\
+	do {					\
+	  unsigned long temp;			\
+	  __asm__ __volatile__(			\
+"	mov	%0, pc		@ cli\n"	\
+"	orr	%0, %0, #0x08000000\n"		\
+"	teqp	%0, #0\n"			\
+	  : "=r" (temp)				\
+	  :					\
+	  : "memory");				\
 	} while(0)
 
 /*
  * save current IRQ & FIQ state
  */
-#define __save_flags(x)			\
-	do {				\
-	  __asm__ __volatile__(		\
-"	mov	%0, pc\n"		\
-"	and	%0, %0, #0x0c000000\n"	\
-	  : "=r" (x));			\
+#define __save_flags(x)				\
+	do {					\
+	  __asm__ __volatile__(			\
+"	mov	%0, pc		@ save_flags\n"	\
+"	and	%0, %0, #0x0c000000\n"		\
+	  : "=r" (x));				\
 	} while (0)
 
 /*
  * restore saved IRQ & FIQ state
  */
-#define __restore_flags(x)		\
-	do {				\
-	  unsigned long temp;		\
-	  __asm__ __volatile__(		\
-"	mov	%0, pc\n"		\
-"	bic	%0, %0, #0x0c000000\n"	\
-"	orr	%0, %0, %1\n"		\
-"	teqp	%0, #0\n"		\
-	  : "=r" (temp)			\
-	  : "r" (x)			\
-	  : "memory");			\
+#define __restore_flags(x)				\
+	do {						\
+	  unsigned long temp;				\
+	  __asm__ __volatile__(				\
+"	mov	%0, pc		@ restore_flags\n"	\
+"	bic	%0, %0, #0x0c000000\n"			\
+"	orr	%0, %0, %1\n"				\
+"	teqp	%0, #0\n"				\
+	  : "=r" (temp)					\
+	  : "r" (x)					\
+	  : "memory");					\
 	} while (0)
 
 #ifdef __SMP__
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/proc-armv/mm-init.h linux/include/asm-arm/proc-armv/mm-init.h
--- v2.2.0-pre5/linux/include/asm-arm/proc-armv/mm-init.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/proc-armv/mm-init.h	Thu Jan  7 15:51:33 1999
@@ -136,7 +136,7 @@
 	/*
 	 * An area to invalidate the cache
 	 */
-	alloc_init_section(&start_mem, 0xdf000000, SAFE_ADDR, DOMAIN_KERNEL,
+	alloc_init_section(&start_mem, FLUSH_BASE, FLUSH_BASE_PHYS, DOMAIN_KERNEL,
 			   PMD_SECT_CACHEABLE | PMD_SECT_AP_READ);
 
 	/*
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/proc-armv/page.h linux/include/asm-arm/proc-armv/page.h
--- v2.2.0-pre5/linux/include/asm-arm/proc-armv/page.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/proc-armv/page.h	Thu Jan  7 15:51:33 1999
@@ -7,6 +7,8 @@
 #ifndef __ASM_PROC_PAGE_H
 #define __ASM_PROC_PAGE_H
 
+#include <asm/hardware.h>
+
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
 #define PAGE_SIZE       (1UL << PAGE_SHIFT)
@@ -60,7 +62,10 @@
 #define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
 /* This handles the memory map.. */
+#ifndef PAGE_OFFSET
 #define PAGE_OFFSET		0xc0000000
+#endif
+
 #define MAP_NR(addr)		(((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT)
 
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/proc-armv/semaphore.h linux/include/asm-arm/proc-armv/semaphore.h
--- v2.2.0-pre5/linux/include/asm-arm/proc-armv/semaphore.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/proc-armv/semaphore.h	Thu Jan  7 15:51:33 1999
@@ -10,20 +10,24 @@
  */
 extern inline void down(struct semaphore * sem)
 {
+	unsigned int cpsr, temp;
+
 	__asm__ __volatile__ ("
 	@ atomic down operation
-	mrs	r0, cpsr
-	orr	r1, r0, #128		@ disable IRQs
-	bic	r0, r0, #0x80000000	@ clear N
-	msr	cpsr, r1
-	ldr	r1, [%0]
-	subs	r1, r1, #1
-	str	r1, [%0]
-	orrmi	r0, r0, #0x80000000	@ set N
-	msr	cpsr, r0
-	movmi	r0, %0
-	blmi	" SYMBOL_NAME_STR(__down)
-		: : "r" (sem) : "r0", "r1", "r2", "r3", "ip", "lr", "cc");
+	mrs	%0, cpsr
+	orr	%1, %0, #128		@ disable IRQs
+	bic	%0, %0, #0x80000000	@ clear N
+	msr	cpsr, %1
+	ldr	%1, [%2]
+	subs	%1, %1, #1
+	orrmi	%0, %0, #0x80000000	@ set N
+	str	%1, [%2]
+	msr	cpsr, %0
+	movmi	r0, %2
+	blmi	" SYMBOL_NAME_STR(__down_failed)
+		: "=&r" (cpsr), "=&r" (temp)
+		: "r" (sem)
+		: "r0", "lr", "cc");
 }
 
 /*
@@ -32,26 +36,28 @@
  */
 extern inline int down_interruptible (struct semaphore * sem)
 {
-	int result;
+	unsigned int cpsr, temp;
+
 	__asm__ __volatile__ ("
-	@ atomic down operation
-	mrs	r0, cpsr
-	orr	r1, r0, #128		@ disable IRQs
-	bic	r0, r0, #0x80000000	@ clear N
-	msr	cpsr, r1
-	ldr	r1, [%1]
-	subs	r1, r1, #1
-	str	r1, [%1]
-	orrmi	r0, r0, #0x80000000	@ set N
-	msr	cpsr, r0
-	movmi	r0, %1
+	@ atomic down interruptible operation
+	mrs	%0, cpsr
+	orr	%1, %0, #128		@ disable IRQs
+	bic	%0, %0, #0x80000000	@ clear N
+	msr	cpsr, %1
+	ldr	%1, [%2]
+	subs	%1, %1, #1
+	orrmi	%0, %0, #0x80000000	@ set N
+	str	%1, [%2]
+	msr	cpsr, %0
+	movmi	r0, %2
 	movpl	r0, #0
-	blmi	" SYMBOL_NAME_STR(__down_interruptible) "
-	mov	%0, r0"
-		: "=r" (result)
+	blmi	" SYMBOL_NAME_STR(__down_interruptible_failed) "
+	mov	%1, r0"
+		: "=&r" (cpsr), "=&r" (temp)
 		: "r" (sem)
-		: "r0", "r1", "r2", "r3", "ip", "lr", "cc");
-	return result;
+		: "r0", "lr", "cc");
+
+	return temp;
 }
 
 /*
@@ -62,20 +68,24 @@
  */
 extern inline void up(struct semaphore * sem)
 {
+	unsigned int cpsr, temp;
+
 	__asm__ __volatile__ ("
 	@ atomic up operation
-	mrs	r0, cpsr
-	orr	r1, r0, #128		@ disable IRQs
-	bic	r0, r0, #0x80000000	@ clear N
-	msr	cpsr, r1
-	ldr	r1, [%0]
-	adds	r1, r1, #1
-	str	r1, [%0]
-	orrls	r0, r0, #0x80000000	@ set N
-	msr	cpsr, r0
-	movmi	r0, %0
-	blmi	" SYMBOL_NAME_STR(__up)
-		: : "r" (sem) : "r0", "r1", "r2", "r3", "ip", "lr", "cc");
+	mrs	%0, cpsr
+	orr	%1, %0, #128		@ disable IRQs
+	bic	%0, %0, #0x80000000	@ clear N
+	msr	cpsr, %1
+	ldr	%1, [%2]
+	adds	%1, %1, #1
+	orrls	%0, %0, #0x80000000	@ set N
+	str	%1, [%2]
+	msr	cpsr, %0
+	movmi	r0, %2
+	blmi	" SYMBOL_NAME_STR(__up_wakeup)
+		: "=&r" (cpsr), "=&r" (temp)
+		: "r" (sem)
+		: "r0", "lr", "cc");
 }
 
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/proc-armv/system.h linux/include/asm-arm/proc-armv/system.h
--- v2.2.0-pre5/linux/include/asm-arm/proc-armv/system.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/proc-armv/system.h	Thu Jan  7 15:51:33 1999
@@ -22,22 +22,24 @@
 	return x;
 }
 
-/*
- * This processor does not need anything special before reset,
- * but RPC may do...
- */
-extern __inline__ void proc_hard_reset(void)
-{
-}
+#define set_cr(x)					\
+	do {						\
+	__asm__ __volatile__(				\
+	"mcr	p15, 0, %0, c1, c0	@ set CR"	\
+	  : : "r" (x));					\
+	} while (0)
+
+extern unsigned long cr_no_alignment;	/* defined in entry-armv.S */
+extern unsigned long cr_alignment;	/* defined in entry-armv.S */
 
 /*
  * We can wait for an interrupt...
  */
-#define proc_idle()			\
-	do {				\
-	__asm__ __volatile__(		\
-"	mcr	p15, 0, %0, c15, c8, 2"	\
-	  : : "r" (0));			\
+#define proc_idle()						\
+	do {							\
+	__asm__ __volatile__(					\
+"	mcr	p15, 0, %0, c15, c8, 2	@ proc_idle"		\
+	  : : "r" (0));						\
 	} while (0)
 
 /*
@@ -47,75 +49,75 @@
 /*
  * Save the current interrupt enable state & disable IRQs
  */
-#define __save_flags_cli(x)		\
-	do {				\
-	  unsigned long temp;		\
-	  __asm__ __volatile__(		\
-	"mrs	%1, cpsr\n"		\
-"	and	%0, %1, #192\n"		\
-"	orr	%1, %1, #128\n"		\
-"	msr	cpsr, %1"		\
-	  : "=r" (x), "=r" (temp)	\
-	  :				\
-	  : "memory");			\
+#define __save_flags_cli(x)					\
+	do {							\
+	  unsigned long temp;					\
+	  __asm__ __volatile__(					\
+	"mrs	%1, cpsr		@ save_flags_cli\n"	\
+"	and	%0, %1, #192\n"					\
+"	orr	%1, %1, #128\n"					\
+"	msr	cpsr, %1"					\
+	  : "=r" (x), "=r" (temp)				\
+	  :							\
+	  : "memory");						\
 	} while (0)
 	
 /*
  * Enable IRQs
  */
-#define __sti()				\
-	do {				\
-	  unsigned long temp;		\
-	  __asm__ __volatile__(		\
-	"mrs	%0, cpsr\n"		\
-"	bic	%0, %0, #128\n"		\
-"	msr	cpsr, %0"		\
-	  : "=r" (temp)			\
-	  :				\
-	  : "memory");			\
+#define __sti()							\
+	do {							\
+	  unsigned long temp;					\
+	  __asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ sti\n"		\
+"	bic	%0, %0, #128\n"					\
+"	msr	cpsr, %0"					\
+	  : "=r" (temp)						\
+	  :							\
+	  : "memory");						\
 	} while(0)
 
 /*
  * Disable IRQs
  */
-#define __cli()				\
-	do {				\
-	  unsigned long temp;		\
-	  __asm__ __volatile__(		\
-	"mrs	%0, cpsr\n"		\
-"	orr	%0, %0, #128\n"		\
-"	msr	cpsr, %0"		\
-	  : "=r" (temp)			\
-	  :				\
-	  : "memory");			\
+#define __cli()							\
+	do {							\
+	  unsigned long temp;					\
+	  __asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ cli\n"		\
+"	orr	%0, %0, #128\n"					\
+"	msr	cpsr, %0"					\
+	  : "=r" (temp)						\
+	  :							\
+	  : "memory");						\
 	} while(0)
 
 /*
  * save current IRQ & FIQ state
  */
-#define __save_flags(x)			\
-	do {				\
-	  __asm__ __volatile__(		\
-	"mrs	%0, cpsr\n"		\
-"	and	%0, %0, #192"		\
-	  : "=r" (x)			\
-	  :				\
-	  : "memory");			\
+#define __save_flags(x)						\
+	do {							\
+	  __asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ save_flags\n"		\
+"	and	%0, %0, #192"					\
+	  : "=r" (x)						\
+	  :							\
+	  : "memory");						\
 	} while (0)
 
 /*
  * restore saved IRQ & FIQ state
  */
-#define __restore_flags(x)		\
-	do {				\
-	  unsigned long temp;		\
-	  __asm__ __volatile__(		\
-	"mrs	%0, cpsr\n"		\
-"	bic	%0, %0, #192\n"		\
-"	orr	%0, %0, %1\n"		\
-"	msr	cpsr, %0"		\
-	  : "=r" (temp)			\
-	  : "r" (x)			\
+#define __restore_flags(x)					\
+	do {							\
+	  unsigned long temp;					\
+	  __asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ restore_flags\n"	\
+"	bic	%0, %0, #192\n"					\
+"	orr	%0, %0, %1\n"					\
+"	msr	cpsr, %0"					\
+	  : "=r" (temp)						\
+	  : "r" (x)						\
 	  : "memory");			\
 	} while (0)
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/proc-armv/uaccess.h linux/include/asm-arm/proc-armv/uaccess.h
--- v2.2.0-pre5/linux/include/asm-arm/proc-armv/uaccess.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/proc-armv/uaccess.h	Thu Jan  7 15:51:33 1999
@@ -55,7 +55,7 @@
 /* We use 33-bit arithmetic here... */
 #define __range_ok(addr,size) ({ \
 	unsigned long flag, sum; \
-	__asm__ __volatile__("adds %1, %2, %3; sbccs %1, %1, %0; movcc %0, #0" \
+	__asm__ __volatile__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \
 		: "=&r" (flag), "=&r" (sum) \
 		: "r" (addr), "Ir" (size), "0" (current->addr_limit) \
 		: "cc"); \
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/semaphore.h linux/include/asm-arm/semaphore.h
--- v2.2.0-pre5/linux/include/asm-arm/semaphore.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/semaphore.h	Thu Jan  7 15:51:33 1999
@@ -18,10 +18,11 @@
 #define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, NULL })
 
 asmlinkage void __down_failed (void /* special register calling convention */);
-asmlinkage int  __down_failed_interruptible (void /* special register calling convention */);
+asmlinkage int  __down_interruptible_failed (void /* special register calling convention */);
 asmlinkage void __up_wakeup (void /* special register calling convention */);
 
 extern void __down(struct semaphore * sem);
+extern int  __down_interruptible(struct semaphore * sem);
 extern void __up(struct semaphore * sem);
 
 #define sema_init(sem, val)	atomic_set(&((sem)->count), (val))
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/signal.h linux/include/asm-arm/signal.h
--- v2.2.0-pre5/linux/include/asm-arm/signal.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/signal.h	Thu Jan  7 15:51:33 1999
@@ -21,7 +21,7 @@
 } sigset_t;
 
 #else
-/* Here we must cater to lics that poke about in kernel headers.  */
+/* Here we must cater to libcs that poke about in kernel headers.  */
 
 #define NSIG		32
 typedef unsigned long sigset_t;
@@ -69,6 +69,8 @@
 #define SIGRTMIN	32
 #define SIGRTMAX	(_NSIG-1)
 
+#define SIGSWI		32
+
 /*
  * SA_FLAGS values:
  *
@@ -96,6 +98,8 @@
 #define SA_INTERRUPT	0x20000000 /* dummy -- ignored */
 
 #define SA_RESTORER	0x04000000
+#define SA_THIRTYTWO	0x02000000 /* deliver signal in 32-bit mode even if
+				      task is running 26 bits. */
 
 /* 
  * sigaltstack controls
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/softirq.h linux/include/asm-arm/softirq.h
--- v2.2.0-pre5/linux/include/asm-arm/softirq.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/softirq.h	Thu Jan  7 15:51:33 1999
@@ -13,7 +13,7 @@
 extern inline void init_bh(int nr, void (*routine)(void))
 {
 	bh_base[nr] = routine;
-	bh_mask_count[nr] = 0;
+	atomic_set(&bh_mask_count[nr], 0);
 	bh_mask |= 1 << nr;
 }
 
@@ -58,13 +58,13 @@
 extern inline void disable_bh(int nr)
 {
 	bh_mask &= ~(1 << nr);
-	bh_mask_count[nr]++;
+	atomic_inc(&bh_mask_count[nr]);
 	synchronize_bh();
 }
 
 extern inline void enable_bh(int nr)
 {
-	if (!--bh_mask_count[nr])
+	if (atomic_dec_and_test(&bh_mask_count[nr]))
 		bh_mask |= 1 << nr;
 }
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/spinlock.h linux/include/asm-arm/spinlock.h
--- v2.2.0-pre5/linux/include/asm-arm/spinlock.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/spinlock.h	Thu Jan  7 15:51:33 1999
@@ -4,11 +4,19 @@
 #ifndef __SMP__
 
 /*
+ * To be safe, we assume the only compiler that can cope with
+ * empty initialisers is EGCS.
+ */
+#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 90))
+#define EMPTY_INIT_OK
+#endif
+
+/*
  * Your basic spinlocks, allowing only a single CPU anywhere
  */
-#if (__GNUC__ > 2) || (__GNUC_MINOR__ >= 8)
+#ifdef EMPTY_INIT_OK
   typedef struct { } spinlock_t;
-# define SPIN_LOCK_UNLOCKED { }
+# define SPIN_LOCK_UNLOCKED (spinlock_t) { }
 #else
   typedef unsigned char spinlock_t;
 # define SPIN_LOCK_UNLOCKED 0
@@ -37,9 +45,9 @@
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
  */
-#if (__GNUC__ > 2) || (__GNUC_MINOR__ >= 8)
+#ifdef EMPTY_INIT_OK
   typedef struct { } rwlock_t;
-# define RW_LOCK_UNLOCKED { }
+# define RW_LOCK_UNLOCKED (rwlock_t) { }
 #else
   typedef unsigned char rwlock_t;
 # define RW_LOCK_UNLOCKED 0
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/termbits.h linux/include/asm-arm/termbits.h
--- v2.2.0-pre5/linux/include/asm-arm/termbits.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/termbits.h	Fri Jan  8 11:11:45 1999
@@ -117,10 +117,21 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
-#define  B57600  0010001
-#define  B115200 0010002
-#define  B230400 0010003
-#define  B460800 0010004
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
 #define CIBAUD	  002003600000	/* input baud rate (not used) */
 #define CMSPAR    010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/timex.h linux/include/asm-arm/timex.h
--- v2.2.0-pre5/linux/include/asm-arm/timex.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/timex.h	Thu Jan  7 15:51:33 1999
@@ -10,4 +10,13 @@
 
 #include <asm/arch/timex.h>
 
+typedef unsigned long cycles_t;
+
+extern cycles_t cacheflush_time;
+
+static inline cycles_t get_cycles (void)
+{
+	return 0;
+}
+
 #endif
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-arm/unistd.h linux/include/asm-arm/unistd.h
--- v2.2.0-pre5/linux/include/asm-arm/unistd.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/unistd.h	Thu Jan  7 15:51:33 1999
@@ -23,7 +23,7 @@
 #define __NR_time			(__NR_SYSCALL_BASE+ 13)
 #define __NR_mknod			(__NR_SYSCALL_BASE+ 14)
 #define __NR_chmod			(__NR_SYSCALL_BASE+ 15)
-#define __NR_chown			(__NR_SYSCALL_BASE+ 16)
+#define __NR_lchown			(__NR_SYSCALL_BASE+ 16)
 #define __NR_break			(__NR_SYSCALL_BASE+ 17)
 #define __NR_oldstat			(__NR_SYSCALL_BASE+ 18)
 #define __NR_lseek			(__NR_SYSCALL_BASE+ 19)
@@ -189,8 +189,12 @@
 #define __NR_rt_sigsuspend		(__NR_SYSCALL_BASE+179)
 #define __NR_pread			(__NR_SYSCALL_BASE+180)
 #define __NR_pwrite			(__NR_SYSCALL_BASE+181)
-#define __NR_xstat			(__NR_SYSCALL_BASE+182)
-#define __NR_xmknod			(__NR_SYSCALL_BASE+183)
+#define __NR_chown			(__NR_SYSCALL_BASE+182)
+#define __NR_getcwd			(__NR_SYSCALL_BASE+183)
+#define __NR_capget			(__NR_SYSCALL_BASE+184)
+#define __NR_capset			(__NR_SYSCALL_BASE+185)
+#define __NR_sigaltstack		(__NR_SYSCALL_BASE+186)
+#define __NR_sendfile			(__NR_SYSCALL_BASE+187)
 
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
@@ -299,41 +303,94 @@
 
 #ifdef __KERNEL_SYSCALLS__
 
-/*
- * we need this inline - forking from kernel space will result
- * in NO COPY ON WRITE (!!!), until an execve is executed. This
- * is no problem, but for the stack. This is handled by not letting
- * main() use the stack at all after fork(). Thus, no function
- * calls - which means inline code for fork too, as otherwise we
- * would use the stack upon exit from 'fork()'.
- *
- * Actually only pause and fork are needed inline, so that there
- * won't be any messing with the stack from main(), but we define
- * some others too.
- */
-#define __NR__exit __NR_exit
-static inline _syscall0(int,idle);
-static inline _syscall0(int,pause);
-static inline _syscall1(int,setup,int,magic);
-static inline _syscall0(int,sync);
-static inline _syscall0(pid_t,setsid);
-static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count);
-static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
-static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count);
-static inline _syscall1(int,dup,int,fd);
-static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp);
-static inline _syscall3(int,open,const char *,file,int,flag,int,mode);
-static inline _syscall1(int,close,int,fd);
-static inline _syscall1(int,_exit,int,exitcode);
-static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options);
-static inline _syscall1(int,delete_module,const char *,name)
+static inline int idle(void)
+{
+	extern int sys_idle(void);
+	return sys_idle();
+}
 
-static inline pid_t wait(int * wait_stat)
+static inline int pause(void)
+{
+	extern int sys_pause(void);
+	return sys_pause();
+}
+
+static inline int sync(void)
+{
+	extern int sys_sync(void);
+	return sys_sync();
+}
+
+static inline pid_t setsid(void)
 {
-	return waitpid(-1,wait_stat,0);
+	extern int sys_setsid(void);
+	return sys_setsid();
 }
 
+static inline int write(int fd, const char *buf, off_t count)
+{
+	extern int sys_write(int, const char *, int);
+	return sys_write(fd, buf, count);
+}
+
+static inline int read(int fd, char *buf, off_t count)
+{
+	extern int sys_read(int, char *, int);
+	return sys_read(fd, buf, count);
+}
+
+static inline off_t lseek(int fd, off_t offset, int count)
+{
+	extern off_t sys_lseek(int, off_t, int);
+	return sys_lseek(fd, offset, count);
+}
+
+static inline int dup(int fd)
+{
+	extern int sys_dup(int);
+	return sys_dup(fd);
+}
 
+static inline int open(const char *file, int flag, int mode)
+{
+	extern int sys_open(const char *, int, int);
+	return sys_open(file, flag, mode);
+}
+
+static inline int close(int fd)
+{
+	return sys_close(fd);
+}
+
+static inline int _exit(int exitcode)
+{
+	extern int sys_exit(int);
+	return sys_exit(exitcode);
+}
+
+static inline pid_t waitpid(pid_t pid, int *wait_stat, int options)
+{
+	extern int sys_wait4(int, int *, int, struct rusage *);
+	return sys_wait4((int)pid, wait_stat, options, NULL);
+}
+
+static inline int delete_module(const char *name)
+{
+	extern int sys_delete_module(const char *name);
+	return sys_delete_module(name);
+}
+
+static inline pid_t wait(int * wait_stat)
+{
+	extern int sys_wait4(int, int *, int, struct rusage *);
+	return sys_wait4(-1, wait_stat, 0, NULL);
+}
+
+/*
+ * The following two can't be eliminated yet - they rely on
+ * specific conditions.
+ */
+static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp);
 
 /*
  * This is the mechanism for creating a new kernel thread.
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-i386/termbits.h linux/include/asm-i386/termbits.h
--- v2.2.0-pre5/linux/include/asm-i386/termbits.h	Fri Jul 31 17:05:52 1998
+++ linux/include/asm-i386/termbits.h	Fri Jan  8 11:11:45 1999
@@ -117,10 +117,21 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
-#define  B57600  0010001
-#define  B115200 0010002
-#define  B230400 0010003
-#define  B460800 0010004
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
 #define CIBAUD	  002003600000	/* input baud rate (not used) */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- v2.2.0-pre5/linux/include/asm-i386/unistd.h	Fri Nov 27 13:09:28 1998
+++ linux/include/asm-i386/unistd.h	Fri Jan  8 14:01:36 1999
@@ -194,6 +194,7 @@
 #define __NR_sendfile		187
 #define __NR_getpmsg		188	/* some people actually want streams */
 #define __NR_putpmsg		189	/* some people actually want streams */
+#define __NR_vfork             190
 
 /* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-m68k/termbits.h linux/include/asm-m68k/termbits.h
--- v2.2.0-pre5/linux/include/asm-m68k/termbits.h	Wed Apr 23 19:01:28 1997
+++ linux/include/asm-m68k/termbits.h	Fri Jan  8 11:11:45 1999
@@ -118,10 +118,21 @@
 #define HUPCL	0002000
 #define CLOCAL	0004000
 #define CBAUDEX 0010000
-#define  B57600  0010001
-#define  B115200 0010002
-#define  B230400 0010003
-#define  B460800 0010004
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
 #define CIBAUD	  002003600000	/* input baud rate (not used) */
 #define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-mips/termbits.h linux/include/asm-mips/termbits.h
--- v2.2.0-pre5/linux/include/asm-mips/termbits.h	Wed Dec 10 10:31:11 1997
+++ linux/include/asm-mips/termbits.h	Fri Jan  8 11:11:45 1999
@@ -153,10 +153,21 @@
 #define CLOCAL	0004000		/* Ignore modem status lines.  */
 #if defined (__USE_BSD) || defined (__KERNEL__)
 #define CBAUDEX 0010000
-#define  B57600  0010001
-#define  B115200 0010002
-#define  B230400 0010003
-#define  B460800 0010004
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
 #define CIBAUD	  002003600000	/* input baud rate (not used) */
 #define CMSPAR    010000000000	/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-ppc/bitops.h linux/include/asm-ppc/bitops.h
--- v2.2.0-pre5/linux/include/asm-ppc/bitops.h	Mon Oct  5 13:13:43 1998
+++ linux/include/asm-ppc/bitops.h	Thu Jan  7 12:06:54 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: bitops.h,v 1.10 1998/08/16 21:56:53 geert Exp $
+ * $Id: bitops.h,v 1.11 1999/01/03 20:16:48 cort Exp $
  * bitops.h: Bit string operations on the ppc
  */
 
@@ -15,6 +15,16 @@
 extern int test_and_set_bit(int nr, volatile void *addr);
 extern int test_and_clear_bit(int nr, volatile void *addr);
 extern int test_and_change_bit(int nr, volatile void *addr);
+
+
+/* Returns the number of 0's to the left of the most significant 1 bit */
+extern __inline__  int cntlzw(int bits)
+{
+	int lz;
+
+	asm ("cntlzw %0,%1" : "=r" (lz) : "r" (bits));
+	return lz;
+}
 
 /*
  * These are if'd out here because using : "cc" as a constraint
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-ppc/dma.h linux/include/asm-ppc/dma.h
--- v2.2.0-pre5/linux/include/asm-ppc/dma.h	Thu Nov 19 09:56:29 1998
+++ linux/include/asm-ppc/dma.h	Thu Jan  7 12:06:54 1999
@@ -204,6 +204,7 @@
 #define DMA2_EXT_REG               0x4D6
 
 #define DMA_MODE_CASCADE 0xC0   /* pass thru DREQ->HRQ, DACK<-HLDA only */
+#define DMA_AUTOINIT	0x10
 
 extern spinlock_t  dma_spin_lock;
 
@@ -392,5 +393,11 @@
 /* These are in kernel/dma.c: */
 extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */
 extern void free_dma(unsigned int dmanr);	/* release it again */
+
+#ifdef CONFIG_PCI_QUIRKS
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy    (0)
+#endif
 
 #endif /* _ASM_DMA_H */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h
--- v2.2.0-pre5/linux/include/asm-ppc/ide.h	Thu Dec 31 10:29:02 1998
+++ linux/include/asm-ppc/ide.h	Thu Jan  7 12:06:54 1999
@@ -80,8 +80,11 @@
 
 static __inline__ int ide_default_irq(ide_ioreg_t base)
 {
-	if ( (_machine == _MACH_Pmac) || (_machine == _MACH_mbx) )
+	if ( _machine == _MACH_Pmac )
 		return 0;
+	else if ( _machine == _MACH_mbx )
+		/* hardcode IRQ 14 on the MBX */
+		return 14+16;		     
         else if ( _machine == _MACH_chrp) {
                 if (chrp_ide_ports_known == 0) 
 			chrp_ide_probe();
@@ -142,7 +145,7 @@
 }
 
 /* Convert the shorts/longs in hd_driveid from little to big endian;
-   chars are endian independant, of course, but strings need to be flipped.
+   chars are endian independent, of course, but strings need to be flipped.
    (Despite what it says in drivers/block/ide.h, they come up as little endian...)
    Changes to linux/hdreg.h may require changes here. */
 static __inline__ void ide_fix_driveid (struct hd_driveid *id) {
@@ -252,14 +255,14 @@
 	}
 }
 
-
 #undef insw
 #define insw(port, buf, ns) 	do {			\
 	if ( _machine == _MACH_chrp)  {\
 		 ide_insw((port)+_IO_BASE, (buf), (ns));  \
 	}\
 	else if ( (_machine == _MACH_Pmac) || (_machine == _MACH_mbx) )			\
-		ide_insw((port), (buf), (ns));		\
+		ide_insw((port)+((_machine==_MACH_mbx)? 0x80000000: 0), \
+			 (buf), (ns));		\
 	else						\
 		/* this must be the same as insw in io.h!! */	\
 		_insw((unsigned short *)((port)+_IO_BASE), (buf), (ns)); \
@@ -270,8 +273,9 @@
 	if ( _machine == _MACH_chrp) {\
 		ide_outsw((port)+_IO_BASE, (buf), (ns)); \
 	}\
-	else if ( (_machine == _MACH_Pmac) || (_machine == _MACH_mbx) )			\
-		ide_outsw((port), (buf), (ns));		\
+	else if ( (_machine == _MACH_Pmac) || (_machine == _MACH_mbx) )	 \
+		ide_outsw((port)+((_machine==_MACH_mbx)? 0x80000000: 0), \
+			   (buf), (ns));		\
 	else						\
 		/* this must be the same as outsw in io.h!! */	\
 		_outsw((unsigned short *)((port)+_IO_BASE), (buf), (ns)); \
@@ -279,13 +283,17 @@
 
 #undef inb
 #define inb(port)	\
-	in_8((unsigned char *)((port) + ((_machine==_MACH_Pmac)? 0: _IO_BASE)))
+	in_8((unsigned char *)((port) + \
+			       ((_machine==_MACH_Pmac)? 0: _IO_BASE) + \
+			       ((_machine==_MACH_mbx)? 0x80000000: 0)) )
 #undef inb_p
 #define inb_p(port)	inb(port)
 
 #undef outb
 #define outb(val, port)	\
-	out_8((unsigned char *)((port) + ((_machine==_MACH_Pmac)? 0: _IO_BASE)), (val))
+	out_8((unsigned char *)((port) + \
+				((_machine==_MACH_Pmac)? 0: _IO_BASE) + \
+				((_machine==_MACH_mbx)? 0x80000000: 0)), (val) )
 #undef outb_p
 #define outb_p(val, port)	outb(val, port)
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h
--- v2.2.0-pre5/linux/include/asm-ppc/pgtable.h	Thu Dec 31 10:29:02 1998
+++ linux/include/asm-ppc/pgtable.h	Thu Jan  7 12:06:54 1999
@@ -226,7 +226,7 @@
  do { \
 	unsigned long __pgdir = (unsigned long)pgdir; \
 	((tsk)->tss.pg_tables = (unsigned long *)(__pgdir)); \
-	asm("mtspr %0,%1 \n\t" :: "i"(M_TWB), "r"(__pa(__pgdir))); \
+	asm("mtspr %0,%1 \n\t" : : "i"(M_TWB), "r"(__pa(__pgdir))); \
  } while (0)
 #endif /* CONFIG_8xx */
      
@@ -637,5 +637,7 @@
 
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
 #define PageSkip(page)		(0)
+#define kern_addr_valid(addr)	(1)
+
 #endif __ASSEMBLY__
 #endif /* _PPC_PGTABLE_H */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/asm-ppc/termbits.h linux/include/asm-ppc/termbits.h
--- v2.2.0-pre5/linux/include/asm-ppc/termbits.h	Sat Aug 16 09:51:09 1997
+++ linux/include/asm-ppc/termbits.h	Fri Jan  8 11:11:45 1999
@@ -126,6 +126,17 @@
 #define  B115200  00021
 #define  B230400  00022
 #define  B460800  00023
+#define  B500000  00024
+#define  B576000  00025
+#define  B921600  00026
+#define B1000000  00027
+#define B1152000  00030
+#define B1500000  00031
+#define B2000000  00032
+#define B2500000  00033
+#define B3000000  00034
+#define B3500000  00035
+#define B4000000  00036
 
 #define CSIZE	00001400
 #define   CS5	00000000
diff -u --recursive --new-file v2.2.0-pre5/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.2.0-pre5/linux/include/linux/mm.h	Thu Jan  7 15:11:40 1999
+++ linux/include/linux/mm.h	Fri Jan  8 15:54:34 1999
@@ -315,14 +315,15 @@
 #define __GFP_LOW	0x02
 #define __GFP_MED	0x04
 #define __GFP_HIGH	0x08
+#define __GFP_IO	0x10
 
 #define __GFP_DMA	0x80
 
 #define GFP_BUFFER	(__GFP_LOW | __GFP_WAIT)
 #define GFP_ATOMIC	(__GFP_HIGH)
-#define GFP_USER	(__GFP_LOW | __GFP_WAIT)
-#define GFP_KERNEL	(__GFP_MED | __GFP_WAIT)
-#define GFP_NFS		(__GFP_HIGH | __GFP_WAIT)
+#define GFP_USER	(__GFP_LOW | __GFP_WAIT | __GFP_IO)
+#define GFP_KERNEL	(__GFP_MED | __GFP_WAIT | __GFP_IO)
+#define GFP_NFS		(__GFP_HIGH | __GFP_WAIT | __GFP_IO)
 
 /* Flag - indicates that the buffer will be suitable for DMA.  Ignored on some
    platforms, used as appropriate on others */
diff -u --recursive --new-file v2.2.0-pre5/linux/include/linux/nls.h linux/include/linux/nls.h
--- v2.2.0-pre5/linux/include/linux/nls.h	Fri Jan 30 11:28:10 1998
+++ linux/include/linux/nls.h	Thu Jan  7 09:25:02 1999
@@ -36,6 +36,7 @@
 extern int init_nls_iso8859_7(void);
 extern int init_nls_iso8859_8(void);
 extern int init_nls_iso8859_9(void);
+extern int init_nls_iso8859_15(void);
 extern int init_nls_cp437(void);
 extern int init_nls_cp737(void);
 extern int init_nls_cp775(void);
diff -u --recursive --new-file v2.2.0-pre5/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.2.0-pre5/linux/include/linux/sched.h	Thu Jan  7 15:11:40 1999
+++ linux/include/linux/sched.h	Fri Jan  8 15:54:34 1999
@@ -257,7 +257,8 @@
 	/* Pointer to task[] array linkage. */
 	struct task_struct **tarray_ptr;
 
-	struct wait_queue *wait_chldexit;	/* for wait4() */
+	struct wait_queue *wait_chldexit, *vfork_sleep;	/* for wait4()/vfork */
+
 	unsigned long policy, rt_priority;
 	unsigned long it_real_value, it_prof_value, it_virt_value;
 	unsigned long it_real_incr, it_prof_incr, it_virt_incr;
@@ -298,6 +299,7 @@
 	struct files_struct *files;
 /* memory management info */
 	struct mm_struct *mm;
+
 /* signal handlers */
 	spinlock_t sigmask_lock;	/* Protects signal and blocked */
 	struct signal_struct *sig;
@@ -348,7 +350,7 @@
 /* proc links*/ &init_task,&init_task,NULL,NULL,NULL, \
 /* pidhash */	NULL, NULL, \
 /* tarray */	&task[0], \
-/* chld wait */	NULL, \
+/* chld wait */	NULL, NULL, \
 /* timeout */	SCHED_OTHER,0,0,0,0,0,0,0, \
 /* timer */	{ NULL, NULL, 0, 0, it_real_fn }, \
 /* utime */	{0,0,0,0},0, \
diff -u --recursive --new-file v2.2.0-pre5/linux/include/linux/sunrpc/stats.h linux/include/linux/sunrpc/stats.h
--- v2.2.0-pre5/linux/include/linux/sunrpc/stats.h	Mon Jan  4 15:08:18 1999
+++ linux/include/linux/sunrpc/stats.h	Fri Jan  8 15:53:15 1999
@@ -9,6 +9,7 @@
 #ifndef _LINUX_SUNRPC_STATS_H
 #define _LINUX_SUNRPC_STATS_H
 
+#include <linux/config.h>
 #include <linux/proc_fs.h>
 
 struct rpc_stat {
diff -u --recursive --new-file v2.2.0-pre5/linux/include/linux/sunrpc/xprt.h linux/include/linux/sunrpc/xprt.h
--- v2.2.0-pre5/linux/include/linux/sunrpc/xprt.h	Thu Aug 20 17:05:19 1998
+++ linux/include/linux/sunrpc/xprt.h	Fri Jan  8 15:52:45 1999
@@ -158,7 +158,7 @@
 	 */
 	union {					/* record marker & XID */
 		u32		header[2];
-		u8 *		data[8];
+		u8 		data[8];
 	}			tcp_recm;
 	struct rpc_rqst *	tcp_rqstp;
 	struct iovec		tcp_iovec[MAX_IOVEC];
diff -u --recursive --new-file v2.2.0-pre5/linux/include/linux/tty.h linux/include/linux/tty.h
--- v2.2.0-pre5/linux/include/linux/tty.h	Thu Nov 19 09:56:29 1998
+++ linux/include/linux/tty.h	Fri Jan  8 15:54:33 1999
@@ -299,6 +299,7 @@
 	int canon_data;
 	unsigned long canon_head;
 	unsigned int canon_column;
+	struct semaphore atomic_read;
 };
 
 /* tty magic number */
@@ -320,6 +321,7 @@
 #define TTY_DO_WRITE_WAKEUP 5
 #define TTY_PUSH 6
 #define TTY_CLOSING 7
+#define TTY_DONT_FLIP 8
 #define TTY_HW_COOK_OUT 14
 #define TTY_HW_COOK_IN 15
 #define TTY_PTY_LOCK 16
diff -u --recursive --new-file v2.2.0-pre5/linux/include/linux/ufs_fs.h linux/include/linux/ufs_fs.h
--- v2.2.0-pre5/linux/include/linux/ufs_fs.h	Fri Oct 23 22:01:27 1998
+++ linux/include/linux/ufs_fs.h	Thu Jan  7 10:31:07 1999
@@ -110,12 +110,12 @@
 #define UFS_MOUNT_ONERROR_UMOUNT	0x00000004
 #define UFS_MOUNT_ONERROR_REPAIR	0x00000008
 
-#define UFS_MOUNT_UFSTYPE		0x000000F0
+#define UFS_MOUNT_UFSTYPE		0x000001F0
 #define UFS_MOUNT_UFSTYPE_OLD		0x00000010
 #define UFS_MOUNT_UFSTYPE_44BSD		0x00000020
 #define UFS_MOUNT_UFSTYPE_SUN		0x00000040
 #define UFS_MOUNT_UFSTYPE_NEXT		0x00000080
-
+#define UFS_MOUNT_UFSTYPE_OPENSTEP	0x00000100
 
 #define ufs_clear_opt(o,opt)	o &= ~UFS_MOUNT_##opt
 #define ufs_set_opt(o,opt)	o |= UFS_MOUNT_##opt
diff -u --recursive --new-file v2.2.0-pre5/linux/include/net/br.h linux/include/net/br.h
--- v2.2.0-pre5/linux/include/net/br.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/br.h	Thu Jan  7 09:25:02 1999
@@ -299,5 +299,5 @@
 /* externs */
 
 extern struct br_stat br_stats;
-
+extern Port_data port_info[];
 
diff -u --recursive --new-file v2.2.0-pre5/linux/include/net/ip_masq.h linux/include/net/ip_masq.h
--- v2.2.0-pre5/linux/include/net/ip_masq.h	Mon Oct  5 13:13:47 1998
+++ linux/include/net/ip_masq.h	Fri Jan  8 15:53:46 1999
@@ -48,7 +48,8 @@
 #define IP_MASQ_F_NO_SADDR	      0x0004	/* no sport set yet */
 #define IP_MASQ_F_NO_SPORT	      0x0008	/* no sport set yet */
 
-#define IP_MASQ_F_NO_REPLY	      0x0010	/* no reply yet from outside */
+#define IP_MASQ_F_DLOOSE	      0x0010	/* loose dest binding */
+#define IP_MASQ_F_NO_REPLY	      0x0080	/* no reply yet from outside */
 
 #define IP_MASQ_F_HASHED	      0x0100 	/* hashed entry */
 #define IP_MASQ_F_OUT_SEQ             0x0200	/* must do output seq adjust */
diff -u --recursive --new-file v2.2.0-pre5/linux/kernel/exit.c linux/kernel/exit.c
--- v2.2.0-pre5/linux/kernel/exit.c	Fri Nov 27 13:09:29 1998
+++ linux/kernel/exit.c	Fri Jan  8 14:03:31 1999
@@ -292,6 +292,7 @@
 		kill_pg(current->pgrp,SIGHUP,1);
 		kill_pg(current->pgrp,SIGCONT,1);
 	}
+
 	/* Let father know we died */
 	notify_parent(current, current->exit_signal);
 
diff -u --recursive --new-file v2.2.0-pre5/linux/kernel/fork.c linux/kernel/fork.c
--- v2.2.0-pre5/linux/kernel/fork.c	Fri Jan  1 12:58:21 1999
+++ linux/kernel/fork.c	Fri Jan  8 14:03:31 1999
@@ -283,6 +283,9 @@
  */
 void mmput(struct mm_struct *mm)
 {
+	/* notify parent sleeping on vfork() */
+	wake_up(&current->p_opptr->vfork_sleep);
+
 	if (atomic_dec_and_test(&mm->count)) {
 		release_segments(mm);
 		exit_mmap(mm);
@@ -521,6 +524,7 @@
 	p->p_pptr = p->p_opptr = current;
 	p->p_cptr = NULL;
 	init_waitqueue(&p->wait_chldexit);
+	init_waitqueue(&p->vfork_sleep);
 
 	p->sigpending = 0;
 	sigemptyset(&p->signal);
diff -u --recursive --new-file v2.2.0-pre5/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.2.0-pre5/linux/mm/page_alloc.c	Thu Jan  7 15:11:41 1999
+++ linux/mm/page_alloc.c	Fri Jan  8 15:34:32 1999
@@ -258,9 +258,6 @@
 		 * a bad memory situation, we're better off trying
 		 * to free things up until things are better.
 		 *
-		 * Normally we shouldn't ever have to do this, with
-		 * kswapd doing this in the background.
-		 *
 		 * Most notably, this puts most of the onus of
 		 * freeing up memory on the processes that _use_
 		 * the most memory, rather than on everybody.
@@ -282,7 +279,7 @@
 		{
 			int freed;
 			current->flags |= PF_MEMALLOC;
-			freed = try_to_free_pages(gfp_mask, SWAP_CLUSTER_MAX);
+			freed = try_to_free_pages(gfp_mask, freepages.high - nr_free_pages);
 			current->flags &= ~PF_MEMALLOC;
 			if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH)))
 				goto nopage;
diff -u --recursive --new-file v2.2.0-pre5/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.2.0-pre5/linux/mm/vmscan.c	Thu Jan  7 15:11:41 1999
+++ linux/mm/vmscan.c	Thu Jan  7 15:09:46 1999
@@ -76,7 +76,6 @@
 		set_pte(page_table, __pte(entry));
 drop_pte:
 		vma->vm_mm->rss--;
-		tsk->nswap++;
 		flush_tlb_page(vma, address);
 		__free_page(page_map);
 		return 0;
@@ -99,6 +98,14 @@
 		pte_clear(page_table);
 		goto drop_pte;
 	}
+
+	/*
+	 * Don't go down into the swap-out stuff if
+	 * we cannot do I/O! Avoid recursing on FS
+	 * locks etc.
+	 */
+	if (!(gfp_mask & __GFP_IO))
+		return 0;
 
 	/*
 	 * Ok, it's really dirty. That means that
diff -u --recursive --new-file v2.2.0-pre5/linux/net/bridge/br.c linux/net/bridge/br.c
--- v2.2.0-pre5/linux/net/bridge/br.c	Thu Jan  7 15:11:41 1999
+++ linux/net/bridge/br.c	Thu Jan  7 09:25:03 1999
@@ -1197,8 +1197,8 @@
  		return NULL;
  	}
   	skb->dev = dev;
- 	skb->mac.raw = skb->h.raw = skb_put(skb,size);
- 	memset(skb->h.raw + 60 - pad_size, 0xa5, pad_size);
+ 	skb->mac.raw = skb->nh.raw = skb_put(skb,size);
+ 	memset(skb->nh.raw + 60 - pad_size, 0xa5, pad_size);
   	eth = skb->mac.ethernet;
   	memcpy(eth->h_dest, bridge_ula, ETH_ALEN);
   	memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
@@ -1221,13 +1221,13 @@
 #endif
 	eth->h_proto = htons(pdu_size + BRIDGE_LLC1_HS);
   
-  	skb->h.raw += skb->dev->hard_header_len;
- 	llc_buffer = skb->h.raw;
+  	skb->nh.raw += skb->dev->hard_header_len;
+ 	llc_buffer = skb->nh.raw;
  	*llc_buffer++ = BRIDGE_LLC1_DSAP;
  	*llc_buffer++ = BRIDGE_LLC1_SSAP;
  	*llc_buffer++ = BRIDGE_LLC1_CTRL;
- 	/* set h.raw to where the bpdu starts */
- 	skb->h.raw += BRIDGE_LLC1_HS;
+ 	/* set nh.raw to where the bpdu starts */
+ 	skb->nh.raw += BRIDGE_LLC1_HS;
   
  	/* mark that we've been here... */
   	skb->pkt_bridged = IS_BRIDGED;
@@ -1248,18 +1248,18 @@
 		return(-1);
 
 	/* copy fields before "flags" */
-	memcpy(skb->h.raw, config_bpdu, BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
+	memcpy(skb->nh.raw, config_bpdu, BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
 
 	/* build the "flags" field */
-	*(skb->h.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) = 0;
+	*(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) = 0;
 	if (config_bpdu->top_change_ack)
-		*(skb->h.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) |= 0x80;
+		*(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) |= 0x80;
 	if (config_bpdu->top_change)
-		*(skb->h.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) |= 0x01;
+		*(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) |= 0x01;
 
 	config_bpdu_hton(config_bpdu);
 	/* copy the rest */
-	memcpy(skb->h.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET+1,
+	memcpy(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET+1,
 		 (char*)&(config_bpdu->root_id),
 		 BRIDGE_BPDU_8021_CONFIG_SIZE-1-BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
 
@@ -1275,7 +1275,7 @@
 	if (skb == NULL)
   		return(-1);
   
-  	memcpy(skb->h.raw, bpdu, sizeof(Tcn_bpdu));
+  	memcpy(skb->nh.raw, bpdu, sizeof(Tcn_bpdu));
   
  	dev_queue_xmit(skb);
   	return(0);
@@ -1376,7 +1376,7 @@
 	if(!port)
 		return 0;
 	
-	skb->h.raw = skb->mac.raw;
+	skb->nh.raw = skb->mac.raw;
 	eth = skb->mac.ethernet;
 	p = &port_info[port];
  
@@ -1480,7 +1480,7 @@
 		return(0);
 	}
 	++br_stats_cnt.port_not_disable;
-	skb->mac.raw = skb->h.raw = skb->data;
+	skb->mac.raw = skb->nh.raw = skb->data;
 	eth = skb->mac.ethernet;
 	port = 0;	/* an impossible port (locally generated) */	
 	if (br_stats.flags & BR_DEBUG)
@@ -1735,7 +1735,7 @@
 			skb->pkt_bridged = IS_BRIDGED;
 			
 			/* reset the skb->ip pointer */	
-			skb->h.raw = skb->data + ETH_HLEN;
+			skb->nh.raw = skb->data + ETH_HLEN;
 
 			/*
 			 *	Send the buffer out.
@@ -1804,7 +1804,7 @@
 			   or have a received valid MAC header */
 			
 /*			printk("Flood to port %d\n",i);*/
-			nskb->h.raw = nskb->data + ETH_HLEN;
+			nskb->nh.raw = nskb->data + ETH_HLEN;
 #if LINUX_VERSION_CODE >= 0x20100
 			nskb->priority = 1;
 			dev_queue_xmit(nskb);
diff -u --recursive --new-file v2.2.0-pre5/linux/net/bridge/br_tree.c linux/net/bridge/br_tree.c
--- v2.2.0-pre5/linux/net/bridge/br_tree.c	Tue Dec 22 14:16:59 1998
+++ linux/net/bridge/br_tree.c	Thu Jan  7 09:25:03 1999
@@ -7,6 +7,7 @@
 #include <linux/string.h>
 #include <linux/malloc.h>
 #include <linux/skbuff.h>
+#include <linux/netdevice.h>
 
 #include <net/br.h>
 #define _DEBUG_AVL
@@ -28,6 +29,10 @@
 static struct fdb **fhpp = &fhp;
 static int fdb_inited = 0;
 
+#ifdef DEBUG_AVL
+static void printk_avl (struct fdb * tree);
+#endif
+
 static int addr_cmp(unsigned char *a1, unsigned char *a2);
 
 /*
@@ -80,7 +85,7 @@
 		addr[4],
 		addr[5]);
 #endif /* DEBUG_AVL */
-	for (tree = &fdb_head ; ; ) {
+	for (tree = fhp ; ; ) {
 		if (tree == avl_br_empty) {
 #if (DEBUG_AVL)
 			printk("search failed, returning node 0x%x\n", (unsigned int)result);
@@ -446,10 +451,10 @@
 		/* don't write the local device */
 		if(tree->port != 0){
 			size = sprintf(*pbuffer,
-				   "%02x:%02x:%02x:%02x:%02x:%02x     eth%d       %d         %d\n",
+				   "%02x:%02x:%02x:%02x:%02x:%02x     %s       %d         %ld\n",
 				   tree->ula[0],tree->ula[1],tree->ula[2],
 				   tree->ula[3],tree->ula[4],tree->ula[5], 
-				   tree->port-1, tree->flags,CURRENT_TIME-tree->timer);
+				   port_info[tree->port].dev->name, tree->flags,CURRENT_TIME-tree->timer);
 
 			(*pos)+=size;
 			(*len)+=size;
diff -u --recursive --new-file v2.2.0-pre5/linux/net/core/dev.c linux/net/core/dev.c
--- v2.2.0-pre5/linux/net/core/dev.c	Tue Dec 22 14:16:59 1998
+++ linux/net/core/dev.c	Thu Jan  7 09:26:41 1999
@@ -1841,7 +1841,11 @@
 extern void dlci_setup(void);
 extern int dmascc_init(void);
 extern int sm_init(void);
-extern int baycom_init(void);
+
+extern int baycom_ser_fdx_init(void);
+extern int baycom_ser_hdx_init(void);
+extern int baycom_par_init(void);
+
 extern int lapbeth_init(void);
 extern void arcnet_init(void);
 extern void ip_auto_config(void);
@@ -1912,8 +1916,14 @@
 #if defined(CONFIG_SDLA)
 	sdla_setup();
 #endif
-#if defined(CONFIG_BAYCOM)
-	baycom_init();
+#if defined(CONFIG_BAYCOM_PAR)
+	baycom_par_init();
+#endif
+#if defined(CONFIG_BAYCOM_SER_FDX)
+	baycom_ser_fdx_init();
+#endif
+#if defined(CONFIG_BAYCOM_SER_HDX)
+	baycom_ser_hdx_init();
 #endif
 #if defined(CONFIG_SOUNDMODEM)
 	sm_init();
diff -u --recursive --new-file v2.2.0-pre5/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- v2.2.0-pre5/linux/net/ipv4/ip_fw.c	Thu Jan  7 15:11:41 1999
+++ linux/net/ipv4/ip_fw.c	Thu Jan  7 09:31:16 1999
@@ -29,6 +29,9 @@
  * 1-May-1998:  Remove caching of device pointer.
  * 12-May-1998: Allow tiny fragment case for TCP/UDP.
  * 15-May-1998: Treat short packets as fragments, don't just block.
+ * 3-Jan-1999:  Fixed serious procfs security hole -- users should never
+ *              be allowed to view the chains!
+ *              Marc Santoro <ultima@snicker.emoti.com>
  */
 
 /*
@@ -509,7 +512,7 @@
 		printk("%s\n",chain->label);
 }
 
-static inline void
+static inline int
 ip_fw_domatch(struct ip_fwkernel *f,
 	      struct iphdr *ip, 
 	      const char *rif,
@@ -550,9 +553,15 @@
 			       len-(sizeof(__u32)*2+IFNAMSIZ));
 			netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_KERNEL);
 		}
-		else duprintf("netlink post failed - alloc_skb failed!\n");
+		else {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ip_fw: packet drop due to "
+				       "netlink failure\n");
+			return 0;
+		}
 	}
 #endif
+	return 1;
 }
 
 /*
@@ -695,9 +704,13 @@
 		for (; f; f = f->next) {
 			if (ip_rule_match(f,rif,ip,
 					  tcpsyn,src_port,dst_port,offset)) {
-				if (!testing)
-					ip_fw_domatch(f, ip, rif, chain->label, skb,
-						      slot, src_port,dst_port);
+				if (!testing
+				    && !ip_fw_domatch(f, ip, rif, chain->label,
+						      skb, slot, 
+						      src_port, dst_port)) {
+					ret = FW_BLOCK;
+					goto out;
+				}
 				break;
 			}
 		}
@@ -759,6 +772,7 @@
 		}
 	} while (ret == FW_SKIP+2);
 
+ out:
 	if (!testing) FWC_READ_UNLOCK(&ip_fw_lock);
 
 	/* Recalculate checksum if not going to reject, and TOS changed. */
@@ -1671,13 +1685,13 @@
 #ifdef CONFIG_PROC_FS		
 static struct proc_dir_entry proc_net_ipfwchains_chain = {
 	PROC_NET_IPFW_CHAINS, sizeof(IP_FW_PROC_CHAINS)-1, 
-	IP_FW_PROC_CHAINS, S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+	IP_FW_PROC_CHAINS, S_IFREG | S_IRUSR | S_IWUSR, 1, 0, 0,
 	0, &proc_net_inode_operations, ip_chain_procinfo
 };
 
 static struct proc_dir_entry proc_net_ipfwchains_chainnames = {
 	PROC_NET_IPFW_CHAIN_NAMES, sizeof(IP_FW_PROC_CHAIN_NAMES)-1, 
-	IP_FW_PROC_CHAIN_NAMES, S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+	IP_FW_PROC_CHAIN_NAMES, S_IFREG | S_IRUSR | S_IWUSR, 1, 0, 0,
 	0, &proc_net_inode_operations, ip_chain_name_procinfo
 };
 
diff -u --recursive --new-file v2.2.0-pre5/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.2.0-pre5/linux/net/ipv4/tcp.c	Thu Dec 31 10:29:03 1998
+++ linux/net/ipv4/tcp.c	Thu Jan  7 09:26:41 1999
@@ -812,7 +812,7 @@
 					 * FIXME: the *_user functions should
 					 *	  return how much data was
 					 *	  copied before the fault
-					 *	  occured and then a partial
+					 *	  occurred and then a partial
 					 *	  packet with this data should
 					 *	  be sent.  Unfortunately
 					 *	  csum_and_copy_from_user doesn't
diff -u --recursive --new-file v2.2.0-pre5/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v2.2.0-pre5/linux/net/netrom/af_netrom.c	Fri Oct 23 22:01:27 1998
+++ linux/net/netrom/af_netrom.c	Thu Jan  7 09:27:47 1999
@@ -892,11 +892,18 @@
 	 */
 	if (frametype != NR_CONNREQ) {
 		/*
+		 * Here it would be nice to be able to send a reset but
+		 * NET/ROM doesn't have one. The following hack would
+		 * have been a way to extend the protocol but apparently
+		 * it kills BPQ boxes... :-(
+		 */
+#if 0
+		/*
 		 * Never reply to a CONNACK/CHOKE.
 		 */
 		if (frametype != NR_CONNACK || flags != NR_CHOKE_FLAG)
 			nr_transmit_refusal(skb, 1);
-
+#endif
 		return 0;
 	}
 
diff -u --recursive --new-file v2.2.0-pre5/linux/net/netsyms.c linux/net/netsyms.c
--- v2.2.0-pre5/linux/net/netsyms.c	Thu Dec 31 10:29:03 1998
+++ linux/net/netsyms.c	Thu Jan  7 09:26:42 1999
@@ -67,7 +67,9 @@
 	defined(CONFIG_E2100)	||	defined(CONFIG_HPLAN_PLUS)	|| \
 	defined(CONFIG_HPLAN)	||	defined(CONFIG_AC3200)		|| \
 	defined(CONFIG_ES3210)	||	defined(CONFIG_ULTRA32)		|| \
-	defined(CONFIG_LNE390)	||	defined(CONFIG_NE3210)
+	defined(CONFIG_LNE390)	||	defined(CONFIG_NE3210)		|| \
+	defined(CONFIG_NE2K_PCI) ||	defined(CONFIG_APNE)		|| \
+	defined(CONFIG_DAYNAPORT)
 #include "../drivers/net/8390.h"
 #endif
 
@@ -392,7 +394,9 @@
 	defined(CONFIG_E2100)	||	defined(CONFIG_HPLAN_PLUS)	|| \
 	defined(CONFIG_HPLAN)	||	defined(CONFIG_AC3200)		|| \
 	defined(CONFIG_ES3210)	||	defined(CONFIG_ULTRA32)		|| \
-	defined(CONFIG_LNE390)	||	defined(CONFIG_NE3210)
+	defined(CONFIG_LNE390)	||	defined(CONFIG_NE3210)		|| \
+	defined(CONFIG_NE2K_PCI) ||	defined(CONFIG_APNE)		|| \
+	defined(CONFIG_DAYNAPORT)
 /* If 8390 NIC support is built in, we will need these. */
 EXPORT_SYMBOL(ei_open);
 EXPORT_SYMBOL(ei_close);
diff -u --recursive --new-file v2.2.0-pre5/linux/net/sched/sch_api.c linux/net/sched/sch_api.c
--- v2.2.0-pre5/linux/net/sched/sch_api.c	Mon Dec 28 15:00:53 1998
+++ linux/net/sched/sch_api.c	Thu Jan  7 09:26:42 1999
@@ -94,7 +94,7 @@
    ---enqueue
 
    enqueue returns number of enqueued packets i.e. this number is 1,
-   if packet was enqueued sucessfully and <1 if something (not
+   if packet was enqueued successfully and <1 if something (not
    necessary THIS packet) was dropped.
 
    Auxiliary routines:
diff -u --recursive --new-file v2.2.0-pre5/linux/net/sched/sch_csz.c linux/net/sched/sch_csz.c
--- v2.2.0-pre5/linux/net/sched/sch_csz.c	Thu May 14 19:47:45 1998
+++ linux/net/sched/sch_csz.c	Thu Jan  7 09:26:42 1999
@@ -704,7 +704,7 @@
 	}
 #ifdef CSZ_PLUS_TBF
 	/* We are about to return no skb.
-	   Schedule watchdog timer, if it occured because of shaping.
+	   Schedule watchdog timer, if it occurred because of shaping.
 	 */
 	if (q->wd_expires) {
 		unsigned long delay = PSCHED_US2JIFFIE(q->wd_expires);
diff -u --recursive --new-file v2.2.0-pre5/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c
--- v2.2.0-pre5/linux/net/sunrpc/sched.c	Mon Jan  4 15:08:18 1999
+++ linux/net/sunrpc/sched.c	Thu Jan  7 09:25:02 1999
@@ -829,6 +829,10 @@
 		}
 		save_flags(oldflags); cli();
 		if (!schedq.task) {
+			/* following two lines added by airlied@linux.ie
+				to make NFS over TCP work 5/1/99 */
+		        dprintk("RPC: rpciod running checking dispatch\n");
+		        rpciod_tcp_dispatcher();
 			dprintk("RPC: rpciod back to sleep\n");
 			interruptible_sleep_on(&rpciod_idle);
 			dprintk("RPC: switch to rpciod\n");
diff -u --recursive --new-file v2.2.0-pre5/linux/net/sunrpc/sysctl.c linux/net/sunrpc/sysctl.c
--- v2.2.0-pre5/linux/net/sunrpc/sysctl.c	Mon Jan  4 15:08:18 1999
+++ linux/net/sunrpc/sysctl.c	Thu Jan  7 09:28:47 1999
@@ -7,6 +7,7 @@
  * impossible at the moment.
  */
 
+#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/types.h>
 #include <linux/linkage.h>
diff -u --recursive --new-file v2.2.0-pre5/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c
--- v2.2.0-pre5/linux/net/sunrpc/xprt.c	Thu Dec 31 10:29:03 1998
+++ linux/net/sunrpc/xprt.c	Thu Jan  7 09:25:02 1999
@@ -821,12 +821,19 @@
 	 */
 	if (!xprt->rx_pending_flag)
 	{
-		dprintk("RPC:     xprt queue\n");
+		int start_queue=0;
+
+		dprintk("RPC:     xprt queue %p\n", rpc_xprt_pending);
 		if(rpc_xprt_pending==NULL)
-			tcp_rpciod_queue();
+			start_queue=1;
 		xprt->rx_pending_flag=1;
 		xprt->rx_pending=rpc_xprt_pending;
 		rpc_xprt_pending=xprt;
+		if (start_queue)
+		  {
+		    tcp_rpciod_queue();
+		    start_queue=0;
+		  }
 	}
 	else
 		dprintk("RPC:     xprt queued already %p\n", xprt);
diff -u --recursive --new-file v2.2.0-pre5/linux/net/wanrouter/patchlevel linux/net/wanrouter/patchlevel
--- v2.2.0-pre5/linux/net/wanrouter/patchlevel	Wed Jul 16 19:22:51 1997
+++ linux/net/wanrouter/patchlevel	Thu Jan  7 09:25:02 1999
@@ -1,2 +1 @@
-1.0.3-modified
-
+2.0.3
diff -u --recursive --new-file v2.2.0-pre5/linux/scripts/header.tk linux/scripts/header.tk
--- v2.2.0-pre5/linux/scripts/header.tk	Mon Jan  4 15:08:18 1999
+++ linux/scripts/header.tk	Thu Jan  7 15:40:02 1999
@@ -207,7 +207,7 @@
 			eval $cmd
 		}
 		if [regexp {([0-9A-Za-z_]+)="([^"]*)"} $line foo var value] {
-			set cmd "global $var; set $var $value"
+			set cmd "global $var; set $var \"$value\""
 			eval $cmd
 		}
 	}
diff -u --recursive --new-file v2.2.0-pre5/linux/scripts/mkdep.c linux/scripts/mkdep.c
--- v2.2.0-pre5/linux/scripts/mkdep.c	Tue Dec 22 14:16:59 1998
+++ linux/scripts/mkdep.c	Fri Jan  8 11:10:11 1999
@@ -208,9 +208,9 @@
 #define GETNEXT { \
 	next_byte(__buf); \
 	if ((unsigned long) next % sizeof(unsigned long) == 0) { \
-		__buf = * (unsigned long *) next; \
-		if (!__buf) \
+		if (next >= end) \
 			break; \
+		__buf = * (unsigned long *) next; \
 	} \
 	next++; \
 }
@@ -249,7 +249,7 @@
  * per memory read.  The MAX6 and MIN6 tests dispose of most
  * input characters with 1 or 2 comparisons.
  */
-void state_machine(const char * map)
+void state_machine(const char * map, const char * end)
 {
 	const char * next = map;
 	const char * map_dot;
@@ -441,7 +441,7 @@
 		return;
 	}
 
-	mapsize = st.st_size + 2*sizeof(unsigned long);
+	mapsize = st.st_size;
 	mapsize = (mapsize+pagesizem1) & ~pagesizem1;
 	map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
 	if ((long) map == -1) {
@@ -457,7 +457,7 @@
 
 	hasdep = 0;
 	clear_config();
-	state_machine(map);
+	state_machine(map, map+st.st_size);
 	if (hasdep)
 		puts(command);
 
diff -u --recursive --new-file v2.2.0-pre5/linux/scripts/tkgen.c linux/scripts/tkgen.c
--- v2.2.0-pre5/linux/scripts/tkgen.c	Thu Jan  7 15:11:42 1999
+++ linux/scripts/tkgen.c	Thu Jan  7 15:40:02 1999
@@ -905,6 +905,7 @@
    * Generate the code to close out the last menu.
    */
   end_proc(menu_num);
+  clear_globalflags(config);
 
   /*
    * The top level menu also needs an update function.  When we exit a
diff -u --recursive --new-file v2.2.0-pre5/linux/scripts/ver_linux linux/scripts/ver_linux
--- v2.2.0-pre5/linux/scripts/ver_linux	Wed Dec 31 16:00:00 1969
+++ linux/scripts/ver_linux	Thu Jan  7 09:27:47 1999
@@ -0,0 +1,29 @@
+#!/bin/sh
+# Before running this script please ensure that your PATH is
+# typical as you use for compilation/istallation. I use
+# /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may
+# differs on your system.
+#
+echo '-- Versions installed: (if some fields are empty or looks'
+echo '-- unusual then possibly you have very old versions)'
+uname -a
+insmod -V 1>/tmp/ver_linux.tmp 2>>/tmp/ver_linux.tmp
+awk 'NR==1{print "Kernel modules        ",$NF}' /tmp/ver_linux.tmp
+rm -f /tmp/ver_linux.tmp
+echo "Gnu C                 " `gcc --version`
+ld -v 2>&1 | awk -F\) '{print $1}' | awk \
+      '/BFD/{print "Binutils              ",$NF}'
+ls -l `ldd /bin/sh | awk '/libc/{print $3}'` | sed -e 's/\.so$//' \
+  | awk -F'[.-]'   '{print "Linux C Library        " $(NF-2)"."$(NF-1)"."$NF}'
+echo -n "Dynamic linker         "
+ldd -v > /dev/null 2>&1 && ldd -v || ldd --version |head -1
+ls -l /usr/lib/lib{g,stdc}++.so  2>/dev/null | awk -F. \
+       '{print "Linux C++ Library      " $4"."$5"."$6}'
+ps --version 2>&1 | awk 'NR==1{print "Procps                ", $NF}'
+mount --version | awk -F\- '{print "Mount                 ", $NF}'
+netstat --version | awk \
+'NR==1{if ($5 != "") { n=split($5,buf,"-"); ver=buf[n]; done=1 }}
+ NR==2{if (done != 1) ver=$3 }
+ END{print "Net-tools             ",ver}'
+loadkeys -h 2>&1 | awk 'NR==1{print "Kbd                   ",$3}'
+expr --v | awk '{print "Sh-utils              ", $NF}'
