diff -u --recursive --new-file v2.1.109/linux/CREDITS linux/CREDITS
--- v2.1.109/linux/CREDITS	Thu Jul 16 18:09:22 1998
+++ linux/CREDITS	Mon Jul 20 17:22:35 1998
@@ -62,10 +62,12 @@
 
 N: Andrea Arcangeli
 E: arcangeli@mbox.queen.it
-W: http://www.cs.unibo.it/~arcangel/
+W: http://e-mind.com/~andrea/
 P: 1024/CB4660B9 CC A0 71 81 F4 A0 63 AC  C0 4B 81 1D 8C 15 C8 E5
-D: Parport sharing hacker.
-D: Various other kernel hacks.
+D: Parport hacker
+D: Implemented a workaround for some interrupt buggy printers
+D: Author of pscan that helps to fix lp/parport bug
+D: Various other kernel hacks
 S: Via Ciaclini 26
 S: Imola 40026
 S: Italy
@@ -715,9 +717,10 @@
 S: Germany
 
 N: Jauder Ho
-E: jauderho@transmeta.com
+E: jauderho@carumba.com
+W: http://www.carumba.com/~jauderho/
 D: bug toaster (A1 sauce makes all the difference)
-D: Transmeta BOFH in my free time
+D: Transmeta BOFH in my copius free time
 
 N: Dirk Hohndel
 E: hohndel@aib.com
@@ -783,6 +786,13 @@
 S: Alleenstrasse 27
 S: D-71679 Asperg
 S: Germany
+
+N: Kenn Humborg
+E: kenn@wombat.ie
+D: Mods to loop device to support sparse backing files
+S: Ballinagard
+S: Roscommon
+S: Ireland
 
 N: Miguel de Icaza Amozurrutia
 E: miguel@nuclecu.unam.mx
diff -u --recursive --new-file v2.1.109/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.109/linux/Documentation/Configure.help	Thu Jul 16 18:09:22 1998
+++ linux/Documentation/Configure.help	Sun Jul 19 14:25:29 1998
@@ -3226,7 +3226,6 @@
   The NCR53C860 and NCR53C875 support FAST-20 transfers. The NCR53C895 
   supports FAST-40 transfers with Ultra2 LVD devices.
   Please read drivers/scsi/README.ncr53c8xx for more information.
-  Linux/i386 and Linux/Alpha are supported by this driver.
 
 synchronous data transfers frequency
 CONFIG_SCSI_NCR53C8XX_SYNC
@@ -3261,17 +3260,17 @@
 
 not allow targets to disconnect
 CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
-  This option is only provided for safety if you suspect some scsi
+  This option is only provided for safety if you suspect some SCSI 
   device of yours to not support properly the target-disconnect
   feature. In that case, you would say Y here. In general however, to
   not allow targets to disconnect is not reasonable if there is more
-  than 1 device on a scsi bus.  The normal answer therefore is N.
+  than 1 device on a SCSI bus.  The normal answer therefore is N.
 
 default tagged command queue depth
 CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
   This option allows you to enable tagged command queuing support at
   linux start-up and to define the default value for the number of 
-  tags per device. If you donnot want tagged command queuing to be 
+  tags per device. If you do not want tagged command queuing to be 
   used by the driver you must enter either 0 or 1 for this option.
   The default value is 8 and should be supported by most hard disks.
   This option has no effect for adapters with NVRAM, since the driver 
@@ -3283,17 +3282,17 @@
   The normal answer therefore is to go with the default 8 and to use 
   a boot command line option for devices that need to use a different 
   command queue depth.
-  There is no safe option other than using good scsi devices.
+  There is no safe option other than using good SCSI devices.
 
 maximum number of queued commands
 CONFIG_SCSI_NCR53C8XX_MAX_TAGS
   This option allows you to specify the maximum number of commands
   that can be queued to any device, when tagged command queuing is
   possible.  The default value is 32. Minimum is 2, maximum is 64.
-  For value less than 32, this option only spares a fiew memory 
-  (8*7*(32-MAXTAGS) bytes), so using less than 32 is'nt worth it.
+  For value less than 32, this option only spares a few memory 
+  (8*7*(32-MAXTAGS) bytes), so using less than 32 isn't worth it.
   For value greater than 32, latency on reselection will be increased 
-  of 1 or 2 micro-seconds. So, the normal answer here is to go with the 
+  by 1 or 2 micro-seconds. So, the normal answer here is to go with the 
   default value 32 unless you are using very large hard disks with 
   large cache (>= 1MB) that are able to get advantage of more than 
   32 tagged commands.
@@ -3312,8 +3311,8 @@
 
 enable profiling statistics gathering
 CONFIG_SCSI_NCR53C8XX_PROFILE
-  This option allows you to enable profiling informations gathering.
-  This statististics are not very accurate due to the low frequency 
+  This option allows you to enable profiling information gathering.
+  These statistics are not very accurate due to the low frequency 
   of the kernel clock (100 Hz on i386) and have performance impact 
   on systems that use very fast devices.
   The normal answer therefore is N.
diff -u --recursive --new-file v2.1.109/linux/Documentation/parport.txt linux/Documentation/parport.txt
--- v2.1.109/linux/Documentation/parport.txt	Tue Apr 14 14:29:19 1998
+++ linux/Documentation/parport.txt	Sun Jul 19 20:40:43 1998
@@ -62,6 +62,8 @@
 (If you are using kmod and have configured parport_probe as a module,
 this will just happen.)
 
+The probe information is available in /proc/parport/?/autoprobe.
+
 
 Parport linked into the kernel statically
 =========================================
@@ -103,6 +105,9 @@
                                 allow you to alter it by writing a new
 				value in (IRQ number or "none").
 
+/proc/parport/0/autoprobe	Any IEEE-1284 device ID information
+				that has been acquired.
+
 
 Device drivers
 ==============
@@ -125,7 +130,7 @@
 that this is different to the way older kernels worked; there used to
 be a static association between the I/O port address and the device
 name, so /dev/lp0 was always the port at 0x3bc.  This is no longer the
-case - if you only have one port, it will always be /dev/lp0,
+case - if you only have one port, it will default to being /dev/lp0,
 regardless of base address.
 
 Also:
diff -u --recursive --new-file v2.1.109/linux/Documentation/sound/OPL3-SA linux/Documentation/sound/OPL3-SA
--- v2.1.109/linux/Documentation/sound/OPL3-SA	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/OPL3-SA	Sat Jul 18 14:11:18 1998
@@ -0,0 +1,76 @@
+OPL3-SA sound driver (opl3sa.o)
+
+The Yamaha OPL3-SAx sound chip is usually found built into motherboards, and
+it's a decent little chip offering a WSS mode, a SB Pro emulation mode, MPU401
+and OPL3 FM Synth capabilities.
+
+You can enable inclusion of the driver via CONFIG_SOUND_OPL3SA1=m, or
+CONFIG_SOUND_OPL3SA1=y through 'make config/xconfig/menuconfig'.
+
+You'll need to know all of the relevant info (irq, dma, and io port) for the
+chip's WSS mode, since that is the mode the kernel sound driver uses, and of
+course you'll also need to know about where the MPU401 and OPL3 ports and
+irq's are if you want to use those.
+
+Here's the skinny on how to load it as a module:
+
+	modprobe opl3sa io=0x530 irq=11 dma=0 dma2=1 mpu_io=0x330 mpu_irq=5
+
+Module options in detail:
+
+	io:	This is the WSS's port base.
+	irq:	This is the WSS's irq.
+	dma:	This is the WSS's dma line. In my BIOS setup screen this was
+		listed as "WSS Play DMA"
+	dma2:	This is the WSS's secondary dma line. My BIOS calls it the
+		"WSS capture DMA"
+	
+	mpu_io:	This is the MPU401's port base.
+	mpu_irq: This is the MPU401's irq.
+
+If you'd like to use the OPL3 FM Synthesizer, make sure you enable
+CONFIG_YM3812 (in 'make config'). That'll build the opl3.o module.
+
+Then a simple 'insmod opl3 io=0x388', and you now have FM Synth.
+
+You can also use the SoftOSS software synthesizer instead of the builtin OPL3.
+Here's how:
+
+Say 'y' or 'm' to "SoftOSS software wave table engine" in make config.
+
+If you said yes, the software synth is availible once you boot your new
+kernel.
+
+If you chose to build it as a module, just insmod the resulting softoss2.o
+
+A 'cat /dev/sndstat' with all the above options should look similar to this:
+
+  OSS/Free:3.8s2++-971130
+  Load type: Driver loaded as a module
+  Kernel: Linux iniquity 2.1.105 #145 Mon Jun 8 11:40:47 MST 1998 i586
+  Config options: 0
+
+  Installed drivers: 
+
+  Card config: 
+
+  Audio devices:
+  0: MSS audio codec (CS4231) (DUPLEX)
+
+  Synth devices:
+  0: Yamaha OPL-3
+  1: SoftOSS
+
+  Midi devices:
+  0: OPL3-SA (MPU401)
+
+  Timers:
+  0: System clock
+  1: MSS audio codec (CS4231)
+
+  Mixers:
+  0: MSS audio codec (CS4231)
+
+Questions? Comments?
+<stiker@northlink.com>
+
diff -u --recursive --new-file v2.1.109/linux/Documentation/sound/Opti linux/Documentation/sound/Opti
--- v2.1.109/linux/Documentation/sound/Opti	Thu Jul 16 18:09:22 1998
+++ linux/Documentation/sound/Opti	Sat Jul 18 14:11:18 1998
@@ -82,6 +82,14 @@
 options opl3 io=0x388
 post-install mad16 /sbin/ad1848_mixer_reroute 14 8 15 3 16 6
 
+If you have an MPU daughtercard or onboard MPU you will want to add to the
+"options mad16" line - eg 
+
+options mad16 irq=5 dma=0 dma16=3 io=0x530 mpu_io=0x330 mpu_irq=9
+
+To set the I/O and IRQ of the MPU.
+
+
 Explain:
 
 alias mixer0 mad16
diff -u --recursive --new-file v2.1.109/linux/Documentation/sound/Tropez+ linux/Documentation/sound/Tropez+
--- v2.1.109/linux/Documentation/sound/Tropez+	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/Tropez+	Sat Jul 18 14:11:18 1998
@@ -0,0 +1,26 @@
+From: Paul Barton-Davis <pbd@op.net>
+
+Here is the configuration I use with a Tropez+ and my modular
+driver:
+
+  alias char-major-14 wavefront
+  alias synth0 wavefront
+  alias mixer0 cs4232
+  alias audio0 cs4232
+  pre-install wavefront modprobe "-k" "cs4232"
+  post-install wavefront modprobe "-k" "opl3"
+  options wavefront io=0x200 irq=9
+  options cs4232 synthirq=9 synthio=0x200 io=0x530 irq=5 dma=1 dma2=0
+  options opl3 io=0x388
+
+Things to note: 
+
+       the wavefront options "io" and "irq" ***MUST*** match the "synthio"
+       and "synthirq" cs4232 options.
+
+       you can do without the opl3 module if you don't
+       want to use the OPL/[34] synth on the soundcard
+
+       the opl3 io parameter is conventionally not adjustable.
+
+Please see drivers/sound/README.wavefront for more details.
diff -u --recursive --new-file v2.1.109/linux/Documentation/sound/Wavefront linux/Documentation/sound/Wavefront
--- v2.1.109/linux/Documentation/sound/Wavefront	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/Wavefront	Sat Jul 18 14:11:18 1998
@@ -0,0 +1,377 @@
+             An OSS/Free Driver for WaveFront soundcards
+               (Turtle Beach Maui, Tropez, Tropez Plus)
+
+                     Paul Barton-Davis, July 1998
+
+Driver Status
+-------------
+
+Requires: Kernel 2.1.106 or later
+        
+As of 7/3/1998, this driver is currently in *BETA* state. This means
+that it compiles and runs, and that I use it on my system (Linux
+2.1.106) with some reasonably demanding applications and uses.  I
+believe the code is approaching an initial "finished" state that
+provides bug-free support for the Tropez Plus.
+
+Please note that to date, the driver has ONLY been tested on a Tropez
+Plus. I would very much like to hear (and help out) people with Tropez
+and Maui cards, since I think the driver can support those cards as
+well.
+
+Finally, the driver has not been tested as a static (non-modular) part
+of the kernel. Alan Cox's good work in modularizing OSS/Free for Linux
+makes this rather unnecessary.
+
+Some Questions
+--------------
+
+**********************************************************************
+0) What does this driver do that the maui driver did not ?
+**********************************************************************
+
+* can fully initialize a WaveFront card from cold boot - no DOS
+          utilities needed
+* working patch/sample/program loading and unloading (the maui
+      driver didn't document how to make this work, and assumed
+      user-level preparation of the patch data for writing
+      to the board. ick.)
+* full user-level access to all WaveFront commands
+* for the Tropez Plus, (primitive) control of the YSS225 FX processor
+* Virtual MIDI mode supported - 2 MIDI devices accessible via the
+          WaveFront's MPU401/UART emulation. One
+          accesses the WaveFront synth, the other accesses the
+          external MIDI connector. Full MIDI read/write semantics
+          for both devices.
+* OSS-compliant /dev/sequencer interface for the WaveFront synth,
+          including native and GUS-format patch downloading.
+* semi-intelligent patch management (prototypical at this point)
+
+
+**********************************************************************
+1) What to do about MIDI interfaces ?
+**********************************************************************
+
+The Tropez Plus (and perhaps other WF cards) can in theory support up
+to 2 physical MIDI interfaces. One of these is connected to the
+ICS2115 chip (the WaveFront synth itself) and is controlled by
+MPU/UART-401 emulation code running as part of the WaveFront OS.  The
+other is controlled by the CS4232 chip present on the board. However,
+physical access to the CS4232 connector is difficult, and it is
+unlikely (though not impossible) that you will want to use it.
+
+An older version of this driver introduced an additional kernel config
+variable which controlled whether or not the CS4232 MIDI interface was
+configured. Because of Alan Cox's work on modularizing the sound
+drivers, and now backporting them to 2.0.34 kernels, there seems to be
+little reason to support "static" configuration variables, and so this
+has been abandoned in favor of *only* module parameters. Specifying
+"mpuio" and "mpuirq" for the cs4232 parameter will result in the
+CS4232 MIDI interface being configured; leaving them unspecified will
+leave it unconfigured (and thus unusable).
+
+BTW, I have heard from one Tropez+ user that the CS4232 interface is
+more reliable than the ICS2115 one. I have had no problems with the
+latter, and I don't have the right cable to test the former one
+out. Reports welcome.
+
+**********************************************************************
+2) Why does line XXX of the code look like this .... ?
+**********************************************************************
+
+Either because its not finished yet, or because you're a better coder
+than I am, or because you don't understand some aspect of how the card
+or the code works.
+
+I absolutely welcome comments, criticisms and suggestions about the
+design and implementation of the driver.
+
+**********************************************************************
+3) What files are included ?
+**********************************************************************
+
+   drivers/sound/README.wavefront       -- this file
+   drivers/sound/wavefront.patch        -- patches for the 2.1.106 sound driver
+s
+                                           needed to make the rest of this work
+   drivers/sound/wavfront.c             -- the driver
+   drivers/sound/ys225.h                -- data declarations for FX config
+   drivers/sound/ys225.c                -- data definitions for FX config
+   drivers/sound/wf_midi.c              -- the "uart401" driver
+                                              to support virtual MIDI mode.
+   include/wavefront.h                  -- the header file
+   Documentation/sound/Tropez+          -- short docs on configuration
+
+**********************************************************************
+4) How do I compile/install/use it ?
+**********************************************************************
+
+PART ONE: install the source code into your sound driver directory
+
+  cd <top-of-your-2.1.106-code-base-e.g.-/usr/src/linux>
+  tar -zxvf <where-you-put/wavefront.tar.gz>
+
+PART TWO: apply the patches
+
+  cd drivers/sound
+  patch < wavefront.patch
+
+PART THREE: configure your kernel
+
+  cd <top of your kernel tree>
+  make xconfig (or whichever config option you use)
+
+         - choose YES for Sound Support
+         - choose MODULE (M) for OSS Sound Modules
+         - choose MODULE(M) to Generic OPL2/OPL3 support
+         - choose MODULE(M) to YM3812/OPL3 support
+         - choose MODULE(M) for WaveFront support
+         - choose MODULE(M) for CS4232 support
+
+         - choose "N" for everything else (unless you have other
+              soundcards you want support for)
+
+
+   make dep
+   make boot
+   .
+   .
+   .
+   <whatever you normally do for a kernel install>
+   make modules
+   .
+   .
+   .
+   make modules_isntall
+
+Here's my autoconf.h SOUND section:
+
+/*
+ * Sound
+ */
+#define CONFIG_SOUND 1
+#undef  CONFIG_SOUND_OSS
+#define CONFIG_SOUND_OSS_MODULE 1
+#undef  CONFIG_SOUND_PAS
+#undef  CONFIG_SOUND_SB
+#undef  CONFIG_SOUND_ADLIB
+#define CONFIG_SOUND_ADLIB_MODULE 1
+#undef  CONFIG_SOUND_GUS
+#undef  CONFIG_SOUND_MPU401
+#undef  CONFIG_SOUND_PSS
+#undef  CONFIG_SOUND_MSS
+#undef  CONFIG_SOUND_SSCAPE
+#undef  CONFIG_SOUND_TRIX
+#undef  CONFIG_SOUND_MAD16
+#undef  CONFIG_SOUND_WAVEFRONT
+#define CONFIG_SOUND_WAVEFRONT_MODULE 1
+#undef  CONFIG_SOUND_CS4232
+#define CONFIG_SOUND_CS4232_MODULE 1
+#undef  CONFIG_SOUND_MAUI
+#undef  CONFIG_SOUND_SGALAXY
+#undef  CONFIG_SOUND_OPL3SA1
+#undef  CONFIG_SOUND_SOFTOSS
+#undef  CONFIG_SOUND_YM3812
+#define CONFIG_SOUND_YM3812_MODULE 1
+#undef  CONFIG_SOUND_VMIDI
+#undef  CONFIG_SOUND_UART6850
+/*
+ * Additional low level sound drivers
+ */
+#undef  CONFIG_LOWLEVEL_SOUND
+
+************************************************************
+6) How do I configure my card ?
+************************************************************
+
+You need to edit /etc/conf.modules. Here's mine (edited to show the
+relevant details):
+
+  # Sound system
+  alias char-major-14 wavefront
+  alias synth0 wavefront
+  alias mixer0 cs4232
+  pre-install wavefront modprobe "-k" "cs4232"
+  post-install wavefront modprobe "-k" "adlib_card"
+  options wavefront io=0x200 irq=9
+  options cs4232 synthirq=9 synthio=0x200 io=0x530 irq=5 dma=1 dma2=0
+  options adlib_card io=0x388
+
+Things to note:
+
+       the wavefront options "io" and "irq" ***MUST*** match the "synthio"
+       and "synthirq" cs4232 options.
+
+       you can do without the adlib_card module if you don't
+       want to use the OPL/[34] synth on the soundcard
+
+       the adlib_card io parameter is conventionally not adjustable.
+       In theory, any not-in-use IO port address would work, but
+       just use 0x388 and stick with the crowd.
+
+**********************************************************************
+7) What about firmware ?
+**********************************************************************
+
+Turtle Beach have not given me permission to distribute their firmware
+for the ICS2115. However, if you have a WaveFront card, then you
+almost certainly have the firmware, and if not, its freely available
+on their website, at:
+
+   http://www.tbeach.com/tbs/downloads/scardsdown.htm#tropezplus
+
+The file is called WFOS2001.MOT (for the Tropez+).
+
+This driver, however, doesn't use the pure firmware as distributed,
+but instead relies on a somewhat processed form of it. You can
+generate this very easily. Following an idea from Andrew Veliath's
+Pinnacle driver, the following flex program will generate the
+processed version:
+
+---- cut here -------------------------
+%option main
+%%
+^S[28].*\r$ printf ("%c%.*s", yyleng-1,yyleng-1,yytext);
+<<EOF>> { fputc ('\0', stdout); return; }
+\n {}
+.  {}
+---- cut here -------------------------
+
+To use it, put the above in file (say, ws.l) compile it like this:
+
+      shell> flex -ows.c ws.l
+      shell> cc -o ws ws.c
+
+and then use it like this:
+
+    ws < my-copy-of-the-oswf.mot-file > /etc/sound/wavefront.os
+
+If you put it somewhere else, you'll always have to use the wf_ospath
+module parameter (see below) or alter the source code.
+
+**********************************************************************
+7) How do I get it working ?
+**********************************************************************
+
+Optionally, you can reboot with the "new" kernel (even though the only
+changes have really been made to a module).
+
+Then, as root do:
+
+     modprobe wavefront
+
+You should get something like this, directly if you're on a console, and in
+/var/log/messages:
+
+    WaveFront: firmware 1.20 already loaded.
+
+or
+
+    WaveFront: no response to firmware probe, assume raw.
+
+then:
+
+    WaveFront: waiting for memory configuration ...
+    WaveFront: hardware version 1.64
+    WaveFront: available DRAM 8191k
+    WaveFront: 332 samples used (266 real, 13 aliases, 53 multi), 180 empty
+    WaveFront: 128 programs slots in use
+    WaveFront: 256 patch slots filled, 142 in use
+
+The whole process takes about 16 seconds, the longest waits being
+after reporting the hardware version (during the firmware download),
+and after reporting program status (during patch status inquiry).  Its
+shorter (about 10 secs) if the firmware is already loaded (i.e. only
+warm reboots since the last firmware load).
+
+The "available DRAM" line will vary depending on how much added RAM
+your card has. Mine has 8MB.
+
+Next, check /dev/sndstat, which on my machine says:
+---------------------------------------------------------------------
+OSS/Free:3.8s2++-971130
+Load type: Driver loaded as a module
+Kernel: Linux bd 2.1.106 #12 SMP Fri Jul 3 00:37:34 EDT 1998 i486
+Config options: 0
+
+Installed drivers:
+
+Card config:
+
+Audio devices:
+0: Crystal audio controller (CS4232) (DUPLEX)
+
+Synth devices:
+0: Turtle Beach WaveFront
+1: Yamaha OPL-3
+
+Midi devices:
+0: WaveFront Internal MIDI
+1: WaveFront External MIDI
+
+Timers:
+0: System clock
+1: Crystal audio controller (CS4232)
+
+Mixers:
+0: Crystal audio controller (CS4232)
+-----------------------------------------------------------
+
+To check basically functionality, use play(1) or splay(1) to send a
+.WAV or other audio file through the audio portion. Then use playmidi
+to play a General MIDI file. Try the "-D 0" to hear the
+difference between sending MIDI to the WaveFront and using the OPL/3,
+which is the default (I think ...). If you have an external synth(s)
+hooked to the soundcard, you can use "-e" to route to the
+external synth(s) (in theory, -D 1 should work as well, but I think
+there is a bug in playmidi which prevents this from doing what it
+should).
+
+**********************************************************************
+8) What are the module parameters ?
+**********************************************************************
+
+Its best to read wavefront.c for this, but here is a summary:
+
+integers:
+          wf_raw  - if set, ignore apparent presence of firmware
+                    loaded onto the ICS2115, reset the whole
+                    board, and initialize it from scratch. (default = 0)
+
+          fx_raw  - if set, always initialize the YSS225 processor
+                    on the Tropez plus. (default = 1)
+
+          < The next 4 are basically for kernel hackers to allow
+            tweaking the driver for testing purposes. >
+
+          wf_short_wait_count - loop counter used when waiting for
+                                status conditions on the board. This
+                                is CPU-specific. After this many
+                                loops, the driver will sleep.
+                                The default is 5000. I have a 66Mhz 486.
+
+          wf_sleep_interval  - the driver sleeps for
+                               HZ/wf_sleep_interval seconds per sleep.
+                               The default is 50.
+
+          wf_sleep_tries  - the number of times the driver will sleep
+                            when waiting for a status condition on the
+                            board. The default is 100 (2 secs, if
+                            wf_sleep_interval is 50).
+
+          wf_debug_default - debugging flags. See sound/wavefront.h
+                             for WF_DEBUG_* values. Default is zero.
+                             Setting this allows you to debug the
+                             driver during module installation.
+strings:
+          wf_ospath - path to get to the pre-processed OS firmware.
+                    (default: /etc/sound/wavefront.os)
+
+**********************************************************************
+9) Who should I contact if I have problems?
+**********************************************************************
+
+Just me: Paul Barton-Davis <pbd@op.net>
+
+
+
diff -u --recursive --new-file v2.1.109/linux/Documentation/tlan.txt linux/Documentation/tlan.txt
--- v2.1.109/linux/Documentation/tlan.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/tlan.txt	Sun Jul 19 20:50:04 1998
@@ -0,0 +1,135 @@
+TLAN driver for Linux, version 1.0
+README
+
+Well, I'm back.  The TLAN driver seems pretty stable, so I'm
+declaring this cycle of development finished, and calling the
+driver 1.0.  I will, of course continue to work on improving
+the driver, and work towards a 2.0 release.
+
+
+
+I.  Supported Devices.
+
+    Only PCI devices will work with this driver.
+
+    Supported:
+    Vendor ID	Device ID	Name
+    0e11	ae32		Compaq Netelligent 10/100 TX PCI UTP
+    0e11	ae34		Compaq Netelligent 10 T PCI UTP
+    0e11	ae35		Compaq Integrated NetFlex 3/P
+    0e11	ae40		Compaq Netelligent Dual 10/100 TX PCI UTP
+    0e11	ae43		Compaq Netelligent Integrated 10/100 TX UTP
+    0e11	b011		Compaq Netelligent 10/100 TX Embedded UTP
+    0e11	b012		Compaq Netelligent 10 T/2 PCI UTP/Coax
+    0e11	b030		Compaq Netelligent 10/100 TX UTP
+    0e11	f130		Compaq NetFlex 3/P
+    0e11	f150		Compaq NetFlex 3/P
+    108d	0012		Olicom OC-2325	
+    108d	0013		Olicom OC-2183
+    108d	0014		Olicom OC-2326	
+
+
+    Caveats:
+    
+    I am not sure if 100BaseTX daughterboards (for those cards which
+    support such things) will work.  I haven't had any solid evidence
+    either way.
+
+    However, if a card supports 100BaseTx without requiring an add
+    on daughterboard, it should work with 100BaseTx.
+
+    The "Netelligent 10 T/2 PCI UTP/Coax" (b012) device is untested,
+    but I do not expect any problems.
+    
+
+II.  Building the Driver.
+
+    The TLAN driver may be compiled into the kernel, or it may be compiled
+    as a module separately, or in the kernel.  A patch is included for
+    2.0.29 (which also works for 2.0.30, 2.0.31, and 2.0.32).
+
+    To compile it as part of the kernel:
+        1. Download and untar the TLAN driver package.
+	2. If your kernel is 2.1.45 or later, you do not need to patch the
+           kernel sources.  Copy the tlan.c and tlan.h to drivers/net in
+           the kernel source tree.
+        3. Otherwise, apply the appropriate patch for your kernel.  For
+	   example:
+
+	       cd /usr/src/linux
+               patch -p1 < kernel.2.0.29
+
+        4. Copy the files tlan.c and tlan.h from the TLAN package to the
+           directory drivers/net in the Linux kernel source tree.
+        5. Configure your kernel for the TLAN driver.  Answer 'Y' when
+           prompted to ask about experimental code (the first question).
+           Then answer 'Y' when prompted if to include TI ThunderLAN
+           support.  If you want the driver compiled as a module, answer 'M'
+           instead of 'Y'.
+        6. Make the kernel and, if necessary, the modules.
+    
+    To compile the TLAN driver independently:
+        1. Download and untar the TLAN driver package.
+        2. Change to the tlan directory.
+        3. If you are NOT using a versioned kernel (ie, want an non-
+           versioned module), edit the Makefile, and comment out the
+           line:
+                 MODVERSIONS = -DMODVERSIONS
+        4. Run 'make'.
+
+
+III.  Driver Options
+	1. You can append debug=x to the end of the insmod line to get
+           debug messages, where x is a bit field where the bits mean
+	   the following:
+	   
+	   0x01		Turn on general debugging messages.
+	   0x02		Turn on receive debugging messages.
+	   0x04		Turn on transmit debugging messages.
+	   0x08		Turn on list debugging messsages.
+
+	2. You can append aui=1 to the end of the insmod line to cause
+           the adapter to use the AUI interface instead of the 10 Base T
+           interface.  This is also what to do if you want to use the BNC
+	   connector on a TLAN based device.  (Setting this option on a
+	   device that does not have an AUI/BNC connector will probably
+	   cause it to not function correctly.)
+
+	4. You can set duplex=1 to force half duplex, and duplex=2 to
+	   force full duplex.
+
+	5. You can set speed=10 to force 10Mbs operation, and speed=100Mbs
+	   to force 100Mbs operation. (I'm not sure what will happen
+	   if a card which only supports 10Mbs is forced into 100Mbs
+	   mode.)
+
+	3. If the driver is built into the kernel, you can use the 3rd
+	   and 4th parameters to set aui and debug respectively.  For
+	   example:
+
+	   ether=0,0,0x1,0x7,eth0
+
+	   This sets aui to 0x1 and debug to 0x7, assuming eth0 is a
+	   supported TLAN device.
+
+	   The bits in the third byte are assigned as follows:
+
+		0x01 = aui
+		0x02 = use SA_INTERRUPT flag when reserving the irq.
+		0x04 = use half duplex
+		0x08 = use full duplex
+		0x10 = use 10BaseT
+		0x20 = use 100BaseTx
+
+
+IV.  Things to try if you have problems.
+	1. Make sure your card's PCI id is among those listed in
+	   section I, above.
+	1. Make sure routing is correct.
+	2. If you are using a 2.1.x kernel, try to duplicate the
+	   problem on a 2.0.x (preferably 2.0.29 or 2.0.30) kernel.
+
+
+There is also a tlan mailing list which you can join by sending "subscribe tlan"
+in the body of an email to majordomo@vuser.vu.union.edu.
+
diff -u --recursive --new-file v2.1.109/linux/MAINTAINERS linux/MAINTAINERS
--- v2.1.109/linux/MAINTAINERS	Thu Jul 16 18:09:22 1998
+++ linux/MAINTAINERS	Sun Jul 19 20:50:04 1998
@@ -439,13 +439,15 @@
 L:	linux-kernel@vger.rutgers.edu
 S:	Maintained
 
-PARALLEL PORT SHARING SUPPORT
+PARALLEL PORT SUPPORT
 P:	Phil Blundell
 M:	Philip.Blundell@pobox.com
 P:	Tim Waugh
 M:	tim@cyberelk.demon.co.uk
 P:	David Campbell
-M:	campbell@tirian.che.curtin.edu.au
+M:	campbell@torque.net
+P:	Andrea Arcangeli
+M:	arcangeli@mbox.queen.it
 L:	linux-parport@torque.net
 L:	pnp-list@redhat.com
 W:	http://www.cyberelk.demon.co.uk/parport.html
@@ -587,9 +589,9 @@
 
 TLAN NETWORK DRIVER
 P:	James Banks
-M:	james.banks@caldera.com
-L:	linux-net@vger.rutgers.edu
-S:	Supported
+M:	james@sovereign.org
+L:	tlan@vuser.vu.union.edu
+S:	Maintained
 
 TOKEN-RING NETWORK DRIVER
 P:	Paul Norton
diff -u --recursive --new-file v2.1.109/linux/Makefile linux/Makefile
--- v2.1.109/linux/Makefile	Thu Jul 16 18:09:22 1998
+++ linux/Makefile	Mon Jul 20 10:05:15 1998
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 109
+SUBLEVEL = 110
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
@@ -24,7 +24,7 @@
 FINDHPATH	= $(HPATH)/asm $(HPATH)/linux $(HPATH)/scsi $(HPATH)/net
 
 HOSTCC  	=gcc
-HOSTCFLAGS	=-O2 -fomit-frame-pointer
+HOSTCFLAGS	=-Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
 
 CROSS_COMPILE 	=
 
@@ -159,21 +159,10 @@
 
 include arch/$(ARCH)/Makefile
 
-ifdef SMP
-
 .S.s:
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -E -o $*.s $<
 .S.o:
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $<
-
-else
-
-.S.s:
-	$(CC) -D__ASSEMBLY__ -traditional -E -o $*.s $<
-.S.o:
-	$(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
-
-endif
 
 Version: dummy
 	@rm -f include/linux/compile.h
diff -u --recursive --new-file v2.1.109/linux/arch/alpha/Makefile linux/arch/alpha/Makefile
--- v2.1.109/linux/arch/alpha/Makefile	Tue Jun  9 11:57:28 1998
+++ linux/arch/alpha/Makefile	Sun Jul 19 20:44:33 1998
@@ -29,11 +29,16 @@
 # determine if we can use the BWX instructions with GAS
 OLD_GAS := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi)
 
-# if PYXIS, then enable use of BWIO space
+# If PYXIS, then enable use of BWIO space
 ifneq ($(OLD_GAS),y)
  ifeq ($(CONFIG_ALPHA_PYXIS),y)
   CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED
  endif
+endif
+
+# If EV6, turn on the proper optimizations.
+ifeq ($(CONFIG_ALPHA_EV6),y)
+ CFLAGS := -mcpu=ev6 $(CFLAGS)
 endif
 
 HEAD := arch/alpha/kernel/head.o
diff -u --recursive --new-file v2.1.109/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.1.109/linux/arch/alpha/defconfig	Wed Apr  1 20:11:47 1998
+++ linux/arch/alpha/defconfig	Sun Jul 19 20:44:33 1998
@@ -47,10 +47,11 @@
 CONFIG_ALPHA_CIA=y
 CONFIG_ALPHA_SRM=y
 CONFIG_ALPHA_EISA=y
-CONFIG_TGA_CONSOLE=y
+# CONFIG_PCI_QUIRKS is not set
 CONFIG_PCI_OLD_PROC=y
 CONFIG_NET=y
 CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
@@ -64,7 +65,7 @@
 # CONFIG_PNP is not set
 
 #
-# Floppy, IDE, and other block devices
+# Block devices
 #
 CONFIG_BLK_DEV_FD=y
 # CONFIG_BLK_DEV_IDE is not set
@@ -78,6 +79,7 @@
 # Additional Block Devices
 #
 # CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_XD is not set
@@ -98,8 +100,6 @@
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
 # CONFIG_IP_PNP is not set
-# CONFIG_IP_ACCT is not set
-# CONFIG_IP_MASQUERADE is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
@@ -195,6 +195,7 @@
 # CONFIG_DEC_ELCP is not set
 # CONFIG_DGRS is not set
 # CONFIG_EEXPRESS_PRO100 is not set
+# CONFIG_NE2K_PCI is not set
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
 # CONFIG_DLCI is not set
@@ -281,6 +282,12 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
+
+#
+# Console drivers
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_FB is not set
 
 #
 # Sound
diff -u --recursive --new-file v2.1.109/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
--- v2.1.109/linux/arch/alpha/kernel/bios32.c	Wed Jun 24 22:54:02 1998
+++ linux/arch/alpha/kernel/bios32.c	Sun Jul 19 20:44:33 1998
@@ -29,6 +29,8 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
 #include <asm/dma.h>
 
 #if 0
@@ -39,24 +41,11 @@
 
 #ifndef CONFIG_PCI
 
-int pcibios_present(void)
-{
-	return 0;
-}
-
-asmlinkage int sys_pciconfig_read()
-{
-	return -ENOSYS;
-}
-
-asmlinkage int sys_pciconfig_write()
-{
-	return -ENOSYS;
-}
+asmlinkage int sys_pciconfig_read() { return -ENOSYS; }
+asmlinkage int sys_pciconfig_write() { return -ENOSYS; }
 
 #else /* CONFIG_PCI */
 
-#include <linux/pci.h>
 #include <linux/malloc.h>
 #include <linux/mm.h>
 
@@ -82,17 +71,19 @@
 #define ALIGN(val,align)	(((val) + ((align) - 1)) & ~((align) - 1))
 
 
-#if defined(CONFIG_ALPHA_MCPCIA) || defined(CONFIG_ALPHA_TSUNAMI)
-/* multiple PCI bus machines */
-/* make handle from bus number */
+/*
+ * On multiple PCI bus machines, create a handle from the bus number.
+ */
+#if defined(CONFIG_ALPHA_MCPCIA) /* || defined(CONFIG_ALPHA_TSUNAMI) */
 extern struct linux_hose_info *bus2hose[256];
 #define HANDLE(b) (((unsigned long)(bus2hose[(b)]->pci_hose_index)&3)<<32)
 #define DEV_IS_ON_PRIMARY(dev) \
 	(bus2hose[(dev)->bus->number]->pci_first_busno == (dev)->bus->number)
-#else /* MCPCIA || TSUNAMI */
+#else
 #define HANDLE(b) (0)
 #define DEV_IS_ON_PRIMARY(dev) ((dev)->bus->number == 0)
-#endif /* MCPCIA || TSUNAMI */
+#endif
+
 /*
  * PCI_MODIFY
  *
@@ -1946,8 +1937,8 @@
 }
 
 
-void __init
-pcibios_fixup(void)
+__initfunc(void
+pcibios_fixup(void))
 {
 	  struct pci_bus *cur;
 
@@ -2022,6 +2013,12 @@
 }
 
 
+__initfunc(void
+pcibios_fixup_bus(struct pci_bus *bus))
+{
+}
+
+
 asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn,
 				  unsigned long off, unsigned long len,
 				  unsigned char *buf)
@@ -2193,7 +2190,6 @@
 #ifdef CONFIG_ALPHA_SRM_SETUP
 void reset_for_srm(void)
 {
-	extern void scrreset(void);
 	struct pci_dev *dev;
 	int i;
 
@@ -2224,9 +2220,7 @@
 		   io_to_reset[i]);
 #endif
 }
-
-	/* reset the visible screen to the top of display memory */
-	scrreset();
+	/* FIXME: reset the video origin.  */
 }
 #endif /* CONFIG_ALPHA_SRM_SETUP */
 
diff -u --recursive --new-file v2.1.109/linux/arch/alpha/kernel/lca.c linux/arch/alpha/kernel/lca.c
--- v2.1.109/linux/arch/alpha/kernel/lca.c	Wed Jun 24 22:54:02 1998
+++ linux/arch/alpha/kernel/lca.c	Mon Jul 20 14:06:55 1998
@@ -13,6 +13,7 @@
 #include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/smp.h>
 
 /*
  * BIOS32-style PCI interface:
diff -u --recursive --new-file v2.1.109/linux/arch/alpha/kernel/mcpcia.c linux/arch/alpha/kernel/mcpcia.c
--- v2.1.109/linux/arch/alpha/kernel/mcpcia.c	Wed Jun 24 22:54:02 1998
+++ linux/arch/alpha/kernel/mcpcia.c	Sun Jul 19 20:44:33 1998
@@ -9,13 +9,13 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/hwrpb.h>
 #include <asm/ptrace.h>
 #include <asm/mmu_context.h>
-#include <asm/delay.h>
 
 /*
  * NOTE: Herein lie back-to-back mb instructions.  They are magic. 
@@ -921,8 +921,7 @@
 	} while (nbus-- > 0);
 }
 
-static void mcpcia_probe(struct linux_hose_info *hose,
-			 unsigned long *mem_start)
+static void mcpcia_probe(struct linux_hose_info *hose)
 {
 	static struct pci_bus *pchain = NULL;
 	struct pci_bus *pbus = &hose->pci_bus;
@@ -939,7 +938,7 @@
 
 	mcpcia_fixup_busno(hose, busno);
 
-	pbus->subordinate = pci_scan_bus(pbus, mem_start); /* the original! */
+	pbus->subordinate = pci_scan_bus(pbus); /* the original! */
 
 	/*
 	 * Set the maximum subordinate bus of this hose.
@@ -970,8 +969,7 @@
 	pci_probe_enabled = 1;
 
 	/* for each hose, probe and setup the devices on the hose */
-	for (hose = mcpcia_root; hose; hose = hose->next) {
-		mcpcia_probe(hose, &memory_start);
-	}
+	for (hose = mcpcia_root; hose; hose = hose->next)
+		mcpcia_probe(hose);
 }
 #endif /* CONFIG_ALPHA_MCPCIA */
diff -u --recursive --new-file v2.1.109/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.1.109/linux/arch/alpha/kernel/osf_sys.c	Wed Jun 24 22:54:03 1998
+++ linux/arch/alpha/kernel/osf_sys.c	Sun Jul 19 20:44:33 1998
@@ -761,7 +761,7 @@
 	}
 
 	if (uss) {
-		unsigned long ss_sp;
+		void *ss_sp;
 
 		error = -EFAULT;
 		if (get_user(ss_sp, &uss->ss_sp))
@@ -776,7 +776,7 @@
 		/* Since we don't know the extent of the stack, and we don't
 		   track onstack-ness, but rather calculate it, we must 
 		   presume a size.  Ho hum this interface is lossy.  */
-		current->sas_ss_sp = ss_sp - SIGSTKSZ;
+		current->sas_ss_sp = (unsigned long)ss_sp - SIGSTKSZ;
 		current->sas_ss_size = SIGSTKSZ;
 	}
 
diff -u --recursive --new-file v2.1.109/linux/arch/alpha/kernel/smc37c669.c linux/arch/alpha/kernel/smc37c669.c
--- v2.1.109/linux/arch/alpha/kernel/smc37c669.c	Wed Jun 24 22:54:03 1998
+++ linux/arch/alpha/kernel/smc37c669.c	Sat Jul 18 14:05:25 1998
@@ -6,6 +6,7 @@
 #include <linux/malloc.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 
 #include <asm/hwrpb.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.1.109/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- v2.1.109/linux/arch/alpha/kernel/smp.c	Wed Jun 24 22:54:03 1998
+++ linux/arch/alpha/kernel/smp.c	Sun Jul 19 20:44:41 1998
@@ -9,12 +9,12 @@
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 
 #include <asm/hwrpb.h>
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
 
-#include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
diff -u --recursive --new-file v2.1.109/linux/arch/alpha/lib/io.c linux/arch/alpha/lib/io.c
--- v2.1.109/linux/arch/alpha/lib/io.c	Tue Aug 20 06:57:15 1996
+++ linux/arch/alpha/lib/io.c	Sun Jul 19 20:44:41 1998
@@ -3,7 +3,7 @@
  * files..
  */
 #include <linux/kernel.h>
-
+#include <linux/types.h>
 #include <asm/io.h>
 
 /* 
@@ -70,6 +70,10 @@
 	return __readl(addr);
 }
 
+unsigned long _readq(unsigned long addr)
+{
+	return __readq(addr);
+}
 
 void _writeb(unsigned char b, unsigned long addr)
 {
@@ -86,6 +90,11 @@
 	__writel(b, addr);
 }
 
+void _writeq(unsigned long b, unsigned long addr)
+{
+	__writeq(b, addr);
+}
+
 /*
  * Read COUNT 8-bit bytes from port PORT into memory starting at
  * SRC.
@@ -363,12 +372,48 @@
  * Copy data from IO memory space to "real" memory space.
  * This needs to be optimized.
  */
-void _memcpy_fromio(void * to, unsigned long from, unsigned long count)
+void _memcpy_fromio(void * to, unsigned long from, long count)
 {
-	while (count) {
+	/* Optimize co-aligned transfers.  Everything else gets handled
+	   a byte at a time. */
+
+	if (count >= 8 && ((long)to & 7) == (from & 7)) {
+		count -= 8;
+		do {
+			*(u64 *)to = readq(from);
+			count -= 8;
+			to += 8;
+			from += 8;
+		} while (count >= 0);
+		count += 8;
+	}
+
+	if (count >= 4 && ((long)to & 3) == (from & 3)) {
+		count -= 4;
+		do {
+			*(u32 *)to = readl(from);
+			count -= 4;
+			to += 4;
+			from += 4;
+		} while (count >= 0);
+		count += 4;
+	}
+		
+	if (count >= 2 && ((long)to & 1) == (from & 1)) {
+		count -= 2;
+		do {
+			*(u16 *)to = readw(from);
+			count -= 2;
+			to += 2;
+			from += 2;
+		} while (count >= 0);
+		count += 2;
+	}
+
+	while (count > 0) {
+		*(u8 *) to = readb(from);
 		count--;
-		*(char *) to = readb(from);
-		((char *) to)++;
+		to++;
 		from++;
 	}
 }
@@ -377,13 +422,49 @@
  * Copy data from "real" memory space to IO memory space.
  * This needs to be optimized.
  */
-void _memcpy_toio(unsigned long to, void * from, unsigned long count)
+void _memcpy_toio(unsigned long to, void * from, long count)
 {
-	while (count) {
+	/* Optimize co-aligned transfers.  Everything else gets handled
+	   a byte at a time. */
+
+	if (count >= 8 && (to & 7) == ((long)from & 7)) {
+		count -= 8;
+		do {
+			writeq(*(u64 *)from, to);
+			count -= 8;
+			to += 8;
+			from += 8;
+		} while (count >= 0);
+		count += 8;
+	}
+
+	if (count >= 4 && (to & 3) == ((long)from & 3)) {
+		count -= 4;
+		do {
+			writel(*(u32 *)from, to);
+			count -= 4;
+			to += 4;
+			from += 4;
+		} while (count >= 0);
+		count += 4;
+	}
+		
+	if (count >= 2 && (to & 1) == ((long)from & 1)) {
+		count -= 2;
+		do {
+			writew(*(u16 *)from, to);
+			count -= 2;
+			to += 2;
+			from += 2;
+		} while (count >= 0);
+		count += 2;
+	}
+
+	while (count > 0) {
+		writeb(*(u8 *) from, to);
 		count--;
-		writeb(*(char *) from, to);
-		((char *) from)++;
 		to++;
+		from++;
 	}
 }
 
@@ -391,11 +472,45 @@
  * "memset" on IO memory space.
  * This needs to be optimized.
  */
-void _memset_io(unsigned long dst, int c, unsigned long count)
+void _memset_c_io(unsigned long to, unsigned long c, long count)
 {
-	while (count) {
+	if (count > 0 && (to & 1)) {
+		writeb(c, to);
+		to++;
 		count--;
-		writeb(c, dst);
-		dst++;
+	}
+	if (count >= 2 && (to & 2)) {
+		writew(c, to);
+		to += 2;
+		count -= 2;
+	}
+	if (count >= 4 && (to & 4)) {
+		writel(c, to);
+		to += 4;
+		count -= 4;
+	}
+	if ((to & 7) == 0) {
+		count -= 8;
+		while (count >= 0) {
+			writeq(c, to);
+			to += 8;
+			count -= 8;
+		}
+		count += 8;
+	}
+	if (count >= 4 && (to & 4)) {
+		writel(c, to);
+		to += 4;
+		count -= 4;
+	}
+	if (count >= 2 && (to & 2)) {
+		writew(c, to);
+		to += 2;
+		count -= 2;
+	}
+	while (count > 0) {
+		writeb(c, to);
+		count--;
+		to++;
 	}
 }
diff -u --recursive --new-file v2.1.109/linux/arch/alpha/lib/memset.S linux/arch/alpha/lib/memset.S
--- v2.1.109/linux/arch/alpha/lib/memset.S	Sun Aug  4 03:37:59 1996
+++ linux/arch/alpha/lib/memset.S	Sun Jul 19 20:44:41 1998
@@ -18,6 +18,7 @@
 	.set noreorder
 .text
 	.globl __memset
+	.globl __memsetw
 	.globl __constant_c_memset
 	.ent __memset
 .align 5
@@ -25,8 +26,8 @@
 	.frame $30,0,$26,0
 	.prologue 0
 
-	zapnot $17,1,$17	/* E0 */
-	sll $17,8,$1		/* E1 (p-c latency, next cycle) */
+	and $17,255,$1		/* E1 */
+	insbl $17,1,$17		/* .. E0 */
 	bis $17,$1,$17		/* E0 (p-c latency, next cycle) */
 	sll $17,16,$1		/* E1 (p-c latency, next cycle) */
 
@@ -52,9 +53,9 @@
 	insql $17,$16,$2	/* E0 */
 	subq $3,8,$3		/* .. E1 */
 
-	addq $18,$3,$18		/* E0		$18 is new count ($3 is negative) */
+	addq $18,$3,$18		/* E0	$18 is new count ($3 is negative) */
 	mskql $4,$16,$4		/* .. E1 (and possible load stall) */
-	subq $16,$3,$16		/* E0 		$16 is new aligned destination */
+	subq $16,$3,$16		/* E0 	$16 is new aligned destination */
 	bis $2,$4,$1		/* .. E1 */
 
 	bis $31,$31,$31		/* E0 */
@@ -102,6 +103,22 @@
 end:
 	ret $31,($26),1		/* E1 */
 	.end __memset
+
+	.align 5
+	.ent __memsetw
+__memsetw:
+	.prologue 0
+
+	inswl $17,0,$1		/* E0 */
+	inswl $17,2,$2		/* E0 */
+	inswl $17,4,$3		/* E0 */
+	or $1,$2,$1		/* .. E1 */
+	inswl $17,6,$4		/* E0 */
+	or $1,$3,$1		/* .. E1 */
+	or $1,$4,$17		/* E0 */
+	br __constant_c_memset	/* .. E1 */
+
+	.end __memsetw
 
 #ifdef __ELF__
  .weak memset; memset = __memset
diff -u --recursive --new-file v2.1.109/linux/arch/alpha/math-emu/fp-emul.c linux/arch/alpha/math-emu/fp-emul.c
--- v2.1.109/linux/arch/alpha/math-emu/fp-emul.c	Tue Feb 17 13:12:44 1998
+++ linux/arch/alpha/math-emu/fp-emul.c	Sun Jul 19 20:44:41 1998
@@ -76,6 +76,7 @@
 	alpha_fp_emul_imprecise = save_emul;
 }
 
+#undef alpha_fp_emul_imprecise
 #define alpha_fp_emul_imprecise  do_alpha_fp_emul_imprecise
 
 #endif /* MODULE */
diff -u --recursive --new-file v2.1.109/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- v2.1.109/linux/arch/arm/Makefile	Fri May  8 23:14:41 1998
+++ linux/arch/arm/Makefile	Sat Jul 18 11:55:22 1998
@@ -21,6 +21,9 @@
 
 ifeq ($(CONFIG_CPU_26),y)
   PROCESSOR		 = armo
+  TEXTADDR		 = 0x02080000
+  ZTEXTADDR		 = 0x01800000
+  ZRELADDR		 = 0x02080000
   ifeq ($(CONFIG_BINUTILS_NEW),y)
     CFLAGS_PROC		+= -mapcs-26 -mshort-load-bytes
     ifeq ($(CONFIG_CPU_ARM2),y)
@@ -45,6 +48,7 @@
 
 ifeq ($(CONFIG_CPU_32),y)
   PROCESSOR		 = armv
+  TEXTADDR		 = 0xC0008000
   ifeq ($(CONFIG_BINUTILS_NEW),y)
     CFLAGS_PROC		+= -mapcs-32 -mshort-load-bytes
     ifeq ($(CONFIG_CPU_ARM6),y)
@@ -72,12 +76,6 @@
 
 COMPRESSED_HEAD	 = head.o
 
-ifeq ($(PROCESSOR),armo)
-TEXTADDR	 = 0x02080000
-ZTEXTADDR	 = 0x01800000
-ZRELADDR	 = 0x02080000
-endif
-
 ifeq ($(CONFIG_ARCH_A5K),y)
 MACHINE		 = a5k
 ARCHDIR		 = arc
@@ -90,9 +88,6 @@
 COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr.o
 endif
 
-ifeq ($(PROCESSOR),armv)
-TEXTADDR	 = 0xC0008000
-
 ifeq ($(CONFIG_ARCH_RPC),y)
 MACHINE		 = rpc
 ARCHDIR		 = rpc
@@ -118,12 +113,22 @@
 ifeq ($(CONFIG_ARCH_NEXUSPCI),y)
 MACHINE		 = nexuspci
 ARCHDIR		 = nexuspci
-TEXTADDR	 = 0xc0000000
 ZTEXTADDR	 = 0x40200000
-ZRELADDR	 = 0x40000000
+ZRELADDR	 = 0x40008000
 COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr_scc.o
 COMPRESSED_HEAD	 = head-nexuspci.o
 endif
+
+ifeq ($(CONFIG_ARCH_VNC),y)
+MACHINE		 = vnc
+ARCHDIR		 = vnc
+endif
+
+ifeq ($(CONFIG_ARCH_TBOX),y)
+MACHINE		 = tbox
+ARCHDIR		 = tbox
+ZTEXTADDR	 = 0x80008000
+ZRELDIR		 = 0x80008000
 endif
 
 PERL		 = perl
@@ -144,23 +149,28 @@
 endif
 CFLAGS		:= $(CFLAGS_PROC) $(CFLAGS) -pipe
 ASFLAGS		:= $(ASFLAGS_PROC) $(ASFLAGS)
-LINKFLAGS	 = -T $(TOPDIR)/arch/arm/vmlinux.lds -e stext -Ttext $(TEXTADDR)
+LINKFLAGS	 = -T $(TOPDIR)/arch/arm/vmlinux-$(PROCESSOR).lds -e stext -Ttext $(TEXTADDR)
 ZLINKFLAGS	 = -Ttext $(ZTEXTADDR)
 
-SUBDIRS		:= $(SUBDIRS:drivers=) arch/arm/lib arch/arm/kernel arch/arm/mm arch/arm/drivers
+SUBDIRS		:= $(SUBDIRS:drivers=arch/arm/drivers) arch/arm/lib arch/arm/kernel arch/arm/mm
 HEAD		:= arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.o
 CORE_FILES	:= arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
 LIBS		:= arch/arm/lib/lib.a $(LIBS) $(GCCLIB)
 
 BLOCK_DRIVERS	:= arch/arm/drivers/block/block.a
 CDROM_DRIVERS	:= drivers/cdrom/cdrom.a
+ifeq ($(CONFIG_FB),y)
+CHAR_DRIVERS	:= arch/arm/drivers/char1/char.a
+else
 CHAR_DRIVERS	:= arch/arm/drivers/char/char.a
+endif
 MISC_DRIVERS	:= drivers/misc/misc.a
 NET_DRIVERS	:= drivers/net/net.a
 PARIDE_DRIVERS	:= drivers/block/paride/paride.a
 PCI_DRIVERS	:= drivers/pci/pci.a
 SCSI_DRIVERS	:= drivers/scsi/scsi.a
 SOUND_DRIVERS	:= drivers/sound/sound.a
+VIDEO_DRIVERS	:= drivers/video/video.a
 
 ifeq ($(CONFIG_ARCH_ACORN),y)
 BLOCK_DRIVERS	+= drivers/acorn/block/acorn-block.a
@@ -171,6 +181,9 @@
 
 DRIVERS		:= $(BLOCK_DRIVERS) $(CHAR_DRIVERS) $(MISC_DRIVERS) $(NET_DRIVERS)
 
+ifeq ($(CONFIG_FB),y)
+DRIVERS		:= $(DRIVERS) $(VIDEO_DRIVERS)
+endif
 ifeq ($(CONFIG_SCSI),y)
 DRIVERS		:= $(DRIVERS) $(SCSI_DRIVERS)
 endif
@@ -192,7 +205,7 @@
 	(cd include/asm-arm; ln -sf arch-$(ARCHDIR) arch; ln -sf proc-$(PROCESSOR) proc)
 
 # Once we've finished integrating the sources, the @$(MAKE) will disappear
-mrproper::
+archmrproper:
 	rm -f include/asm-arm/arch include/asm-arm/proc
 	@$(MAKE) -C arch/$(ARCH)/drivers mrproper
 
@@ -202,6 +215,9 @@
 arch/arm/mm: dummy
 	$(MAKE) linuxsubdirs SUBDIRS=arch/arm/mm
 
+arch/arm/lib: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=arch/arm/lib
+
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
 zImage: vmlinux
@@ -225,8 +241,6 @@
 archclean:
 	@$(MAKEBOOT) clean
 	$(RM) arch/arm/lib/constants.h
-
-archmrproper:
 
 archdep:
 	@$(MAKEBOOT) dep
diff -u --recursive --new-file v2.1.109/linux/arch/arm/boot/compressed/Makefile.debug linux/arch/arm/boot/compressed/Makefile.debug
--- v2.1.109/linux/arch/arm/boot/compressed/Makefile.debug	Tue Jan 20 16:39:41 1998
+++ linux/arch/arm/boot/compressed/Makefile.debug	Sat Jul 18 11:55:22 1998
@@ -5,12 +5,19 @@
 #
 
 COMPRESSED_EXTRA=../../lib/ll_char_wr.o
-OBJECTS=misc-debug.o $(COMPRESSED_EXTRA)
+OBJECTS=misc-debug.o ll_char_wr.aout.o
 
 CFLAGS=-D__KERNEL__ -O2 -DSTDC_HEADERS -DSTANDALONE_DEBUG -Wall -I../../../../include -c
 
-test-gzip: piggy.o $(OBJECTS)
-	$(CC) -o $@ $(OBJECTS) piggy.o
+test-gzip: piggy.aout.o $(OBJECTS)
+	$(CC) -o $@ $(OBJECTS) piggy.aout.o
 
 misc-debug.o: misc.c
 	$(CC) $(CFLAGS) -o $@ misc.c
+
+piggy.aout.o: piggy.o
+	arm-linuxelf-objcopy --change-leading-char -I elf32-arm -O arm-aout32-linux piggy.o piggy.aout.o
+
+ll_char_wr.aout.o: $(COMPRESSED_EXTRA)
+	arm-linuxelf-objcopy --change-leading-char -I elf32-arm -O arm-aout32-linux $(COMPRESSED_EXTRA) ll_char_wr.aout.o
+
diff -u --recursive --new-file v2.1.109/linux/arch/arm/boot/compressed/head-nexuspci.S linux/arch/arm/boot/compressed/head-nexuspci.S
--- v2.1.109/linux/arch/arm/boot/compressed/head-nexuspci.S	Tue Jan 20 16:39:41 1998
+++ linux/arch/arm/boot/compressed/head-nexuspci.S	Sat Jul 18 11:55:22 1998
@@ -1,35 +1,32 @@
 /*
  * linux/arch/arm/boot/compressed/head-nexuspci.S
  *
- * Copyright (C) 1996 Philip Blundell
+ * Copyright (C) 1996, 1997, 1998 Philip Blundell
+ *
+ * NexusPCI is unusual because we don't have a bootloader -- the kernel is
+ * run directly out of ROM at the moment.  Maybe this will change one day and
+ * then this file can go away.
+ *
  */
 
-#define ARM_CP			p15
-#define ARM610_REG_CONTROL	cr1
-#define ARM_REG_ZERO		cr0
-
 		.text
 
-start:		b	skip1
-		b	go_uncompress
-		b	go_uncompress
-		b	go_uncompress
-		b	go_uncompress
-		b	go_uncompress
+.globl	_start
+_start:		b	reset
+		b	undefined
+		b	undefined
+		b	undefined
+		b	undefined
+		b	undefined
+		b	undefined
+		b	undefined
 		b	go_uncompress
-		b	go_uncompress
-		b	go_uncompress
-		b	go_uncompress
-skip1:		mov	sp, #0x40000000
-		add	sp, sp, #0x200000
-		mov	r2, #0x20000000
+	
+reset:		mov	r2, #0x20000000			@ LED off
 		mov	r1, #0x1a
 		str	r1, [r2]
 
-		MOV	r0, #0x30
-		MCR	ARM_CP, 0, r0, ARM610_REG_CONTROL, ARM_REG_ZERO
-		
-		mov	r2, #0x10000000
+		mov	r2, #0x10000000			@ SCC init
 
 		mov	r1, #42
 		strb	r1, [r2, #8]
@@ -57,37 +54,46 @@
 		mov	r1, #5
 		strb	r1, [r2, #0x8]
 
-		mov	r0, #0x50
+		ldr	r2, =_start
+		ldr	r3, =_edata
+		mov	r8, r2
+		mov	r0, #0
+1:
+		ldmia	r0!, {r4, r5, r6, r7}
+		stmia	r2!, {r4, r5, r6, r7}
+		cmp	r2, r3
+		ble	1b
+
+		ldr	r3, =_edata
+		ldr	r1, =_end
+		mov	r2, #0
+1:
+		strb	r2, [r3]
+		cmp	r3, r1
+		beq	2f
+		add	r3, r3, #1
+		b	1b
+2:	
+		add	pc, r8, #0x20
+
+undefined:	ldr	r4, =undef_msg
+1:		ldrb	r0, [r4], #1
+		movs	r0, r0
+2:		beq	2b
 		bl	_ll_write_char
+		b	1b
 
-		mov	r4, #0x40000000
-		mov	r1, #0x00200000
-		add	r4, r4, r1
-copylp:
-		ldr	r3, [r1]
-		str	r3, [r4, r1]
-		subs	r1, r1, #4
-		bne	copylp
-
-		add	pc, r4, #0x28
-
+undef_msg:	.ascii	"Undefined instruction (or other problem)\000"
+		.align	4
 
 /*
  * Uncompress the kernel
  */
 go_uncompress:
-		mov	r0,   #0x40000000
-		add	r0, r0, #0x300000
-		bl	_decompress_kernel
-
-		mov	r0,   #0x40000000
-		add	r1, r0, #0x300000
-		mov	r2, #0x100000
-
-clp2:		ldr	r3, [r1, r2]
-		str	r3, [r0, r2]
-		subs	r2, r2, #4
-		bne	clp2
+		mov	r0, #0x40000000
+		ldr	sp, =user_stack
+		add	sp, sp, #4096
+		bl	decompress_kernel
 
 		mov	r2, #0x40000000
 		mov	r0, #0
diff -u --recursive --new-file v2.1.109/linux/arch/arm/boot/compressed/head.S linux/arch/arm/boot/compressed/head.S
--- v2.1.109/linux/arch/arm/boot/compressed/head.S	Tue Jan 20 16:39:41 1998
+++ linux/arch/arm/boot/compressed/head.S	Sat Jul 18 11:55:22 1998
@@ -20,7 +20,10 @@
 		mov	r0, r0
 		mov	r0, r0
 		mov	r0, r0
-		teq	r0, #0
+		b	1f
+		.word	0x016f2818			@ Magic numbers to help the loader
+		.word	_start	
+1:		teq	r0, #0
 		beq	2f
 		mov	r4, #0x02000000
 		add	r4, r4, #0x7C000
@@ -59,11 +62,13 @@
  * Uncompress the kernel
  */
 		mov	r1, #0x8000
-		add	r2, r2, r1, lsl #1	@ Add 64k for malloc
+		add	r3, r2, r1, lsl #1	@ Add 64k for malloc
 		sub	r1, r1, #1
-		add	r2, r2, r1
-		bic	r5, r2, r1		@ decompress kernel to after end of the compressed
+		add	r3, r3, r1
+		bic	r5, r3, r1		@ decompress kernel to after end of the compressed
 		mov	r0, r5
+		mov	r1, r2
+		mov	r2, r0
 		bl	SYMBOL_NAME(decompress_kernel)
 		add	r0, r0, #7
 		bic	r2, r0, #7
diff -u --recursive --new-file v2.1.109/linux/arch/arm/boot/compressed/misc.c linux/arch/arm/boot/compressed/misc.c
--- v2.1.109/linux/arch/arm/boot/compressed/misc.c	Tue Jan 20 16:39:41 1998
+++ linux/arch/arm/boot/compressed/misc.c	Sat Jul 18 11:55:22 1998
@@ -274,10 +274,10 @@
 
 #ifndef STANDALONE_DEBUG
 
-ulg decompress_kernel(ulg output_start)
+ulg decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p)
 {
-	free_mem_ptr = (ulg)&end;
-	free_mem_ptr_end = output_start;
+	free_mem_ptr = free_mem_ptr_p;
+	free_mem_ptr_end = free_mem_ptr_end_p;
 
 	proc_decomp_setup ();
 	arch_decomp_setup ();
diff -u --recursive --new-file v2.1.109/linux/arch/arm/defconfig linux/arch/arm/defconfig
--- v2.1.109/linux/arch/arm/defconfig	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/defconfig	Sat Jul 18 11:55:22 1998
@@ -172,7 +172,6 @@
 CONFIG_ETHER1=m
 CONFIG_ETHER3=m
 CONFIG_ETHERH=m
-CONFIG_CDROM=y
 
 #
 # Filesystems
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c
--- v2.1.109/linux/arch/arm/kernel/armksyms.c	Fri May  8 23:14:41 1998
+++ linux/arch/arm/kernel/armksyms.c	Sat Jul 18 11:55:23 1998
@@ -5,10 +5,11 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 
 #include <asm/ecard.h>
+#include <asm/elf.h>
 #include <asm/io.h>
-#include <asm/delay.h>
 #include <asm/dma.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -73,6 +74,9 @@
 EXPORT_SYMBOL(ecard_address);
 #endif
 
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+
 /* processor dependencies */
 EXPORT_SYMBOL(processor);
 
@@ -100,26 +104,23 @@
 EXPORT_SYMBOL(__bad_pmd);
 EXPORT_SYMBOL(__bad_pmd_kernel);
 
+#define EXPORT_VERS0(sym,orig) \
+ const char __kstrtab_##sym##[] __attribute__((section(".kstrtab"))) = \
+    __MODULE_STRING(##sym##_R00000000); \
+ const struct module_symbol __ksymtab_##sym __attribute__((section("__ksymtab"))) = \
+    { (unsigned long)&##orig, __kstrtab_##sym };
 /*
  * floating point math emulator support.
  * These symbols will never change their calling convention...
  */
-EXPORT_SYMBOL_NOVERS(fpreturn);
-EXPORT_SYMBOL_NOVERS(fpundefinstr);
-EXPORT_SYMBOL_NOVERS(fp_enter);
-EXPORT_SYMBOL_NOVERS(fp_save);
-EXPORT_SYMBOL_NOVERS(fp_restore);
-EXPORT_SYMBOL_NOVERS(fp_setup);
-
-const char __kstrtab_fp_printk[] __attribute__((section(".kstrtab"))) = __MODULE_STRING(fp_printk);
-const struct module_symbol __ksymtab_fp_printk __attribute__((section("__ksymtab"))) =
-{ (unsigned long)&printk, __kstrtab_fp_printk };
-
-const char __kstrtab_fp_send_sig[] __attribute__((section(".kstrtab"))) = __MODULE_STRING(fp_send_sig);
-const struct module_symbol __ksymtab_fp_send_sig __attribute__((section("__ksymtab"))) =
-{ (unsigned long)&send_sig, __kstrtab_fp_send_sig };
-
-//EXPORT_SYMBOL_NOVERS(fp_current);
+EXPORT_VERS0(fpreturn,fpreturn);
+EXPORT_VERS0(fpundefinstr,fpundefinstr);
+EXPORT_VERS0(fp_enter,fp_enter);
+EXPORT_VERS0(fp_save,fp_save);
+EXPORT_VERS0(fp_restore,fp_restore);
+EXPORT_VERS0(fp_setup,fp_setup);
+EXPORT_VERS0(fp_printk,printk);
+EXPORT_VERS0(fp_send_sig,send_sig);
 
 	/*
 	 * string / mem functions
@@ -183,3 +184,8 @@
 EXPORT_SYMBOL(test_and_change_bit);
 EXPORT_SYMBOL(find_first_zero_bit);
 EXPORT_SYMBOL(find_next_zero_bit);
+
+	/* elf */
+EXPORT_SYMBOL(armidlist);
+EXPORT_SYMBOL(armidindex);
+EXPORT_SYMBOL(elf_platform);
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S
--- v2.1.109/linux/arch/arm/kernel/calls.S	Fri May  8 23:14:42 1998
+++ linux/arch/arm/kernel/calls.S	Sat Jul 18 11:55:23 1998
@@ -1,11 +1,12 @@
 /*
  * linux/arch/arm/lib/calls.h
  *
- * Copyright (C) 1995, 1996 Russell King
+ * Copyright (C) 1995-1998 Russell King
+ *
+ * This file is included twice in entry-common.S
  */
-#ifndef NR_SYSCALLS
+#ifndef NR_syscalls
 #define NR_syscalls 256
-#define NR_SYSCALLS 184
 #else
 
 /* 0 */		.long	SYMBOL_NAME(sys_setup)
@@ -24,7 +25,7 @@
 		.long	SYMBOL_NAME(sys_time)
 		.long	SYMBOL_NAME(sys_mknod)
 /* 15 */	.long	SYMBOL_NAME(sys_chmod)
-		.long	SYMBOL_NAME(sys_chown)
+		.long	SYMBOL_NAME(sys_lchown)
 		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_break */
 		.long	SYMBOL_NAME(sys_stat)
 		.long	SYMBOL_NAME(sys_lseek)
@@ -190,11 +191,13 @@
 		.long	SYMBOL_NAME(sys_rt_sigsuspend_wrapper)
 /* 180 */	.long	SYMBOL_NAME(sys_pread)
 		.long	SYMBOL_NAME(sys_pwrite)
-#if 0
-		.long	SYMBOL_NAME(sys_xstat)
-		.long	SYMBOL_NAME(sys_xmknod)
-#else
-		.space	8
-#endif
-		.space	(NR_syscalls - 184) * 4
+		.long	SYMBOL_NAME(sys_chown)
+		.long	SYMBOL_NAME(sys_getcwd)
+		.long	SYMBOL_NAME(sys_capget)
+/* 185 */	.long	SYMBOL_NAME(sys_capset)
+		.long	SYMBOL_NAME(sys_sigaltstack_wrapper)
+
+		.rept	NR_syscalls-186
+			.long	SYMBOL_NAME(sys_ni_syscall)
+		.endr
 #endif
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/dec21285.c linux/arch/arm/kernel/dec21285.c
--- v2.1.109/linux/arch/arm/kernel/dec21285.c	Thu May 14 19:47:37 1998
+++ linux/arch/arm/kernel/dec21285.c	Sat Jul 18 14:02:10 1998
@@ -109,6 +109,7 @@
 {
 	struct pci_dev *dev;
 	unsigned char pin;
+	unsigned int cmd;
 
 	for (dev = pci_devices; dev; dev = dev->next) {
 		pcibios_read_config_byte(dev->bus->number,
@@ -127,6 +128,10 @@
 			dev->bus->number, dev->devfn,
 			dev->vendor, dev->device,
 			pin, dev->irq);
+
+		/* Turn on bus mastering - boot loader doesn't - perhaps it should! */
+		pcibios_read_config_byte(dev->bus->number, dev->devfn, PCI_COMMAND, &cmd);
+		pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
 	}
 }
 
@@ -136,6 +141,10 @@
 
 	rev = *(unsigned char *)0xfe000008;
 	printk("DEC21285 PCI revision %02X\n", rev);
+}
+
+__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+{
 }
 
 __initfunc(char *pcibios_setup(char *str))
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/dma-a5k.c linux/arch/arm/kernel/dma-a5k.c
--- v2.1.109/linux/arch/arm/kernel/dma-a5k.c	Fri May  8 23:14:42 1998
+++ linux/arch/arm/kernel/dma-a5k.c	Sat Jul 18 11:55:23 1998
@@ -9,12 +9,15 @@
 #include <linux/init.h>
 
 #include <asm/dma.h>
+#include <asm/fiq.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/pgtable.h>
 
 #include "dma.h"
 
+static struct fiq_handler fh = { "floppydma", NULL };
+
 int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id)
 {
 	if (channel == DMA_VIRTUAL_FLOPPY)
@@ -26,13 +29,13 @@
 void arch_free_dma(dmach_t channel, dma_t *dma)
 {
 	if (channel != DMA_VIRTUAL_FLOPPY)
-		printk ("arch_free_dma: invalid channel %d\n", channel);
+		printk("arch_free_dma: invalid channel %d\n", channel);
 }
 
 int arch_get_dma_residue(dmach_t channel, dma_t *dma)
 {
 	if (channel != DMA_VIRTUAL_FLOPPY)
-		printk ("arch_dma_count: invalid channel %d\n", channel);
+		printk("arch_dma_count: invalid channel %d\n", channel);
 	else {
 		extern int floppy_fiqresidual(void);
 		return floppy_fiqresidual();
@@ -43,11 +46,11 @@
 void arch_enable_dma(dmach_t channel, dma_t *dma)
 {
 	if (channel != DMA_VIRTUAL_FLOPPY)
-		printk ("arch_enable_dma: invalid channel %d\n", channel);
+		printk("arch_enable_dma: invalid channel %d\n", channel);
 	else {
 		void *fiqhandler_start;
 		unsigned int fiqhandler_length;
-		extern void floppy_fiqsetup (unsigned long len, unsigned long addr,
+		extern void floppy_fiqsetup(unsigned long len, unsigned long addr,
 					     unsigned long port);
 
 		if (dma->dma_mode == DMA_MODE_READ) {
@@ -59,19 +62,25 @@
 			fiqhandler_start = &floppy_fiqout_start;
 			fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
 		}
-		memcpy ((void *)0x1c, fiqhandler_start, fiqhandler_length);
+		if (claim_fiq(&fh)) {
+			printk("floppydma: couldn't claim FIQ.\n");
+			return;
+		}
+		memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length);
 		flush_page_to_ram(0);
-		floppy_fiqsetup (dma->buf.length, __bus_to_virt(dma->buf.address), (int)PCIO_FLOPPYDMABASE);
-		enable_irq (dma->dma_irq);
+		floppy_fiqsetup(dma->buf.length, __bus_to_virt(dma->buf.address), (int)PCIO_FLOPPYDMABASE);
+		enable_irq(dma->dma_irq);
 	}
 }
 
 void arch_disable_dma(dmach_t channel, dma_t *dma)
 {
 	if (channel != DMA_VIRTUAL_FLOPPY)
-		printk ("arch_disable_dma: invalid channel %d\n", channel);
-	else
-		disable_irq (dma->dma_irq);
+		printk("arch_disable_dma: invalid channel %d\n", channel);
+	else {
+		disable_irq(dma->dma_irq);
+		release_fiq(&fh);
+	}
 }
 
 __initfunc(void arch_dma_init(dma_t *dma))
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/dma-rpc.c linux/arch/arm/kernel/dma-rpc.c
--- v2.1.109/linux/arch/arm/kernel/dma-rpc.c	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/dma-rpc.c	Sat Jul 18 11:55:23 1998
@@ -13,12 +13,15 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/dma.h>
+#include <asm/fiq.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/uaccess.h>
 
 #include "dma.h"
 
+static struct fiq_handler fh = { "floppydma", NULL };
+
 #if 0
 typedef enum {
 	dma_size_8	= 1,
@@ -269,6 +272,10 @@
 			extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
 			fiqhandler_start = &floppy_fiqout_start;
 			fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
+		}
+		if (claim_fiq(&fh)) {
+			printk("floppydma: couldn't claim FIQ.\n");
+			return;
 		}
 		/* Allow access to page 0 via domains */
 		__asm__ __volatile__("mcr	p15, 0, %0, c3, c0" :
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S
--- v2.1.109/linux/arch/arm/kernel/entry-armv.S	Wed May 20 19:10:37 1998
+++ linux/arch/arm/kernel/entry-armv.S	Sat Jul 18 11:55:23 1998
@@ -9,12 +9,13 @@
  * Note:  there is a StrongARM bug in the STMIA rn, {regs}^ instruction that causes
  * it to save wrong values...  Be aware!
  */
-#include <linux/config.h> /* for CONFIG_ARCH_EBSA110 */
+#include <linux/config.h> /* for CONFIG_ARCH_xxxx */
 #include <linux/linkage.h>
 
 #include <asm/assembler.h>
 #include <asm/errno.h>
 #include <asm/hardware.h>
+#include <asm/arch/irqs.h>
 
 #include "../lib/constants.h"
 
@@ -89,7 +90,7 @@
 		adreq	\base, irq_prio_l
 
 		teq	\irqstat, #0
-		ldrneb	\irqnr, [r5, \irqstat]		@ get IRQ number
+		ldrneb	\irqnr, [\base, \irqstat]	@ get IRQ number
 		.endm
 
 /*
@@ -159,7 +160,7 @@
 		adr	\base, irq_prio_ebsa110
 
 		teq	\irqstat, #0
-		ldrneb	\irqnr, [r5, \irqstat]		@ get IRQ number
+		ldrneb	\irqnr, [\base, \irqstat]	@ get IRQ number
 		.endm
 
 		.macro	irq_prio_table
@@ -225,6 +226,65 @@
 		.macro	irq_prio_table
 		.endm
 
+#elif defined(CONFIG_ARCH_VNC)
+
+		.macro	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base
+		mov	r4, #IO_BASE_ARM_CSR
+		ldr	\irqstat, [r4, #IRQ_STATUS]	@ just show us the unmasked ones
+
+		@ run through hard priorities
+		@ timer
+		tst	\irqstat, #IRQ_MASK_TIMER0
+		movne	\irqnr, #IRQ_TIMER0
+		bne	1f
+
+		@ ether10
+		tst	\irqstat, #IRQ_MASK_ETHER10
+		movne	\irqnr, #IRQ_ETHER10
+		bne	1f
+
+		@ ether100
+		tst	\irqstat, #IRQ_MASK_ETHER100
+		movne	\irqnr, #IRQ_ETHER100
+		bne	1f
+
+		@ video compressor
+		tst	\irqstat, #IRQ_VIDCOMP_MASK
+		movne	\irqnr, #IRQ_VIDCOMP
+		bne	1f
+
+		@ now try all the PIC sources
+		@ determine whether we have an irq
+		tst	\irqstat, #IRQ_MASK_EXTERN_IRQ
+		beq	3f
+		mov	r4, #(IO_BASE_PCI_IACK & 0xff000000)
+		orr	r4, r4, #(IO_BASE_PCI_IACK & 0x00ff0000)
+		ldrb	\irqnr, [r4]			@ get the IACK byte
+		b	1f
+
+3:		@ PCI errors
+		tst	\irqstat, #IRQ_MASK_PCI_ERR
+		movne	\irqnr, #IRQ_PCI_ERR
+		bne	1f
+
+		@ softint
+		tst	\irqstat, #IRQ_MASK_SOFT_IRQ
+		movne	\irqnr, #IRQ_SOFT_IRQ
+		bne	1f
+
+		@ debug uart
+		tst	\irqstat, #IRQ_MASK_UART_DEBUG
+		movne	\irqnr, #IRQ_UART_DEBUG
+		bne	1f
+
+		@ watchdog
+		tst	\irqstat, #IRQ_WATCHDOG_MASK
+		movne	\irqnr, #IRQ_WATCHDOG
+
+1:		@ If Z is set, then we will not enter an interrupt
 #else
 #error Unknown architecture
 #endif
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S
--- v2.1.109/linux/arch/arm/kernel/entry-common.S	Thu May 14 19:47:37 1998
+++ linux/arch/arm/kernel/entry-common.S	Sat Jul 18 11:55:23 1998
@@ -73,7 +73,7 @@
 		
 		bic	r6, r6, #0xff000000	@ mask off SWI op-code
 		eor	r6, r6, #OS_NUMBER<<20	@ check OS number
-		cmp	r6, #NR_SYSCALLS	@ check upper syscall limit
+		cmp	r6, #NR_syscalls	@ check upper syscall limit
 		bcs	2f
 
 		get_current_task r5
@@ -133,7 +133,7 @@
 SYMBOL_NAME(sys_syscall):
 		mov	r6, r0
 		eor	r6, r6, #OS_NUMBER << 20
-		cmp	r6, #NR_SYSCALLS		@ check range
+		cmp	r6, #NR_syscalls		@ check range
 		movgt	r0, #-ENOSYS
 		movgt	pc, lr
 		add	sp, sp, #4			@ take of the save of our r4
@@ -192,6 +192,10 @@
 sys_rt_sigreturn_wrapper:
 		add	r0, sp, #4
 		b	SYMBOL_NAME(sys_rt_sigreturn)
+
+sys_sigaltstack_wrapper:
+		ldr	r2, [sp, #4 + S_SP]
+		b	do_sigaltstack
 
 /*
  *=============================================================================
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/head-armv.S linux/arch/arm/kernel/head-armv.S
--- v2.1.109/linux/arch/arm/kernel/head-armv.S	Fri May  8 23:14:42 1998
+++ linux/arch/arm/kernel/head-armv.S	Sat Jul 18 11:55:23 1998
@@ -22,18 +22,20 @@
  * MMU off.  Note! These should be unique!!! Please read Documentation/ARM-README
  * for more information.
  *
- *  r1 = 0 -> ebsa110  (Ram @ 0x00000000)
- *  r1 = 1 -> RPC      (Ram @ 0x10000000)
- *  r1 = 2 -> ebsit    (???)
+ *  r1 = 0 -> ebsa110
+ *  r1 = 1 -> RPC
+ *  r1 = 2 -> ebsit
  *  r1 = 3 -> nexuspci
- *  r1 = 4 -> ebsa285  (Ram @ 0x00000000)
+ *  r1 = 4 -> ebsa285
+ *  r1 = 5 -> vnc
+ *  r1 = 6 -> CATS
  */
 ENTRY(stext)
 ENTRY(_stext)
 __entry:
 		teq	r0, #0					@ check for illegal entry...
 		bne	.Lerror					@ loop indefinitely
-		cmp	r1, #5					@ Unknown machine architecture
+		cmp	r1, #7					@ Unknown machine architecture
 		bge	.Lerror
 @
 @ First thing to do is to get the page tables set up so that we can call the kernel
@@ -119,7 +121,8 @@
 								@ we lose this page!
 		mov	pc, lr
 
-.Lerror:	mov	r0, #0x02000000
+.Lerror:
+1:		mov	r0, #0x02000000
 		mov	r1, #0x11
 		orr	r1, r1, r1, lsl #8
 		orr	r1, r1, r1, lsl #16
@@ -127,7 +130,7 @@
 		str	r1, [r0], #4
 		str	r1, [r0], #4
 		str	r1, [r0], #4
-		b	.Lerror
+		b	1b
 
 .Lbranch:	.long	.Lalready_done_mmap			@ Real address of routine
 
@@ -156,12 +159,22 @@
 		.long	0
 
 		@ EBSA285
-		.long	SYMBOL_NAME(swapper_pg_dir) - 0xc0000000	@ Address of page tables (physical)
+		.long	SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 @ Address of page tables (physical)
 		.long	0					@ Address of RAM
 		.long	0x24000000				@ I/O base address (0x42000000 -> 0xFE000000)
 		.long	0
 
+		@ Corel VNC
+		.long	SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 @ Address of page tables (physical)
+		.long	0					@ Address of RAM
+		.long	0x24000000				@ I/O base address (0x42000000 -> 0xfe000000)
+		.long	0
 
+		@ CATS
+		.long	SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 @ Address of page tables (physical)
+		.long	0					@ Address of RAM
+		.long	0x24000000				@ I/O base address (0x42000000 -> 0xfe000000)
+		.long	0
 
 .LCProcTypes:	@ ARM6 / 610
 		.long	0x41560600
@@ -170,13 +183,20 @@
 		b	.Larmv3_flush_early			@ arm v3 flush & ctrl early setup
 		mov	pc, lr
 
-		@ ARM7 / 710
+		@ ARM7
 		.long	0x41007000
 		.long	0xfffff000
 		.long	0x00000c12
 		b	.Larmv3_flush_late			@ arm v3 flush & ctrl late setup
 		mov	pc, lr
 
+		@ ARM710
+		.long	0x41007000
+		.long	0xfff8f000				@ arm710 processors are weird
+		.long	0x00000c12
+		b	.Larmv3_flush_late			@ arm v3 flush & ctrl late setup
+		mov	pc, lr
+
 		@ StrongARM
 		.long	0x4401a100
 		.long	0xfffffff0
@@ -267,6 +287,7 @@
 		.macro	busyuart,rd,rx
 1002:		ldrb	\rd, [\rx, #0x14]
 		and	\rd, \rd, #0x60
+		teq	\rd, #0x60
 		bne	1002b
 		.endm
 
@@ -289,6 +310,7 @@
 		.macro	busyuart,rd,rx
 1002:		ldrb	\rd, [\rx, #0x14]
 		and	\rd, \rd, #0x60
+		teq	\rd, #0x60
 		bne	1002b
 		.endm
 
@@ -298,7 +320,7 @@
 		beq	1001b
 		.endm
 
-#elif defined(CONFIG_ARCH_EBSA285)
+#elif defined(CONFIG_ARCH_EBSA285) || defined(CONFIG_ARCH_VNC)
 		.macro	addruart,rx
 		mov	\rx, #0xfe000000
 		.endm
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/iic.c linux/arch/arm/kernel/iic.c
--- v2.1.109/linux/arch/arm/kernel/iic.c	Tue Jan 20 16:39:41 1998
+++ linux/arch/arm/kernel/iic.c	Sat Jul 18 11:55:23 1998
@@ -6,8 +6,9 @@
  * IIC is used to get the current time from the CMOS rtc.
  */
 
+#include <linux/delay.h>
+
 #include <asm/system.h>
-#include <asm/delay.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
 
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/irq.c linux/arch/arm/kernel/irq.c
--- v2.1.109/linux/arch/arm/kernel/irq.c	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/irq.c	Sat Jul 18 11:55:23 1998
@@ -2,7 +2,8 @@
  *  linux/arch/arm/kernel/irq.c
  *
  *  Copyright (C) 1992 Linus Torvalds
- *  Modifications for ARM processor Copyright (C) 1995, 1996 Russell King.
+ *  Modifications for ARM processor Copyright (C) 1995-1998 Russell King.
+ *  FIQ support written by Philip Blundell <philb@gnu.org>, 1998.
  *
  * This file contains the code used by various IRQ handling routines:
  * asking for different IRQ's should be done through these routines
@@ -30,14 +31,20 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 
+#include <asm/fiq.h>
+#include <asm/hardware.h>
 #include <asm/io.h>
+#include <asm/pgtable.h>
 #include <asm/system.h>
-#include <asm/hardware.h>
 #include <asm/arch/irq.h>
 
 unsigned int local_bh_count[NR_CPUS];
 unsigned int local_irq_count[NR_CPUS];
 spinlock_t irq_controller_lock;
+static struct fiq_handler *current_fiq;
+static unsigned long no_fiq_insn;
+
+#define FIQ_VECTOR ((unsigned long *)0x1c)
 
 #ifndef SMP
 #define irq_enter(cpu, irq)	(++local_irq_count[cpu])
@@ -46,6 +53,20 @@
 #error SMP not supported
 #endif
 
+#ifdef CONFIG_ARCH_ACORN
+/* Bitmask indicating valid interrupt numbers
+ * (to be moved to include/asm-arm/arch-*)
+ */
+unsigned long validirqs[NR_IRQS / 32] = {
+	0x003ffe7f,	0x000001ff,	0x000000ff,	0x00000000
+};
+
+#define valid_irq(x) ((x) < NR_IRQS && validirqs[(x) >> 5] & (1 << ((x) & 31)))
+#else
+
+#define valid_irq(x) ((x) < NR_IRQS)
+#endif
+
 void disable_irq(unsigned int irq_nr)
 {
 	unsigned long flags;
@@ -74,21 +95,6 @@
 
 struct irqaction *irq_action[NR_IRQS];
 
-#ifdef CONFIG_ARCH_ACORN
-/* Bitmask indicating valid interrupt numbers
- * (to be moved to include/asm-arm/arch-*)
- */
-unsigned long validirqs[NR_IRQS / 32] = {
-	0x003ffe7f,	0x000001ff,	0x000000ff,	0x00000000
-};
-
-#define valid_irq(x) ((x) < NR_IRQS && validirqs[(x) >> 5] & (1 << ((x) & 31)))
-#else
-
-#define valid_irq(x) ((x) < NR_IRQS)
-
-#endif
-
 int get_irq_list(char *buf)
 {
 	int i;
@@ -106,6 +112,8 @@
 		}
 		*p++ = '\n';
 	}
+	p += sprintf(p, "FIQ:              %s\n",
+		     current_fiq?current_fiq->name:"unused");
 	return p - buf;
 }
 
@@ -186,7 +194,7 @@
 	}
 }
 
-#if defined(HAS_IOMD) || defined(HAS_IOC)
+#if defined(CONFIG_ARCH_ACORN)
 void do_ecard_IRQ(int irq, struct pt_regs *regs)
 {
 	struct irqaction * action;
@@ -336,9 +344,41 @@
 	return i;
 }
 
+int claim_fiq(struct fiq_handler *f)
+{
+	if (current_fiq) {
+		if (current_fiq->callback == NULL || (*current_fiq->callback)())
+			return -EBUSY;
+	}
+	current_fiq = f;
+	return 0;
+}
+
+void release_fiq(struct fiq_handler *f)
+{
+	if (current_fiq != f) {
+		printk(KERN_ERR "%s tried to release FIQ when not owner!\n",
+		       f->name);
+#ifdef CONFIG_DEBUG_ERRORS
+		__backtrace();
+#endif
+		return;
+	}
+	current_fiq = NULL;
+
+	*FIQ_VECTOR = no_fiq_insn;
+	__flush_entry_to_ram(FIQ_VECTOR);
+}
+
 __initfunc(void init_IRQ(void))
 {
 	extern void init_dma(void);
+
 	irq_init_irq();
+
+	current_fiq = NULL;
+	no_fiq_insn = *FIQ_VECTOR;
+
 	init_dma();
 }
+
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c
--- v2.1.109/linux/arch/arm/kernel/process.c	Fri May  8 23:14:42 1998
+++ linux/arch/arm/kernel/process.c	Sat Jul 18 11:55:23 1998
@@ -38,6 +38,8 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
+struct task_struct *last_task_used_math;
+
 extern void fpe_save(struct fp_soft_struct *);
 extern char *processor_modes[];
 
@@ -171,15 +173,7 @@
 	current->flags &= ~PF_USEDFPU;
 }
 
-void release_segments(struct mm_struct *mm)
-{
-}
-
 void release_thread(struct task_struct *dead_task)
-{
-}
-
-void copy_segments(int nr, struct task_struct *p, struct mm_struct *new_mm)
 {
 }
 
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/setup-ebsa110.c linux/arch/arm/kernel/setup-ebsa110.c
--- v2.1.109/linux/arch/arm/kernel/setup-ebsa110.c	Fri May  8 23:14:42 1998
+++ linux/arch/arm/kernel/setup-ebsa110.c	Sat Jul 18 11:55:23 1998
@@ -26,6 +26,7 @@
 #include <linux/major.h>
 #include <linux/utsname.h>
 #include <linux/init.h>
+#include <linux/console.h>
 
 #include <asm/hardware.h>
 #include <asm/pgtable.h>
@@ -58,7 +59,7 @@
 extern int root_mountflags;
 extern int _etext, _edata, _end;
 
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
+static char command_line[COMMAND_LINE_SIZE] __initdata = { 0, };
        char saved_command_line[COMMAND_LINE_SIZE];
 
 #ifdef CONFIG_BLK_DEV_RAM
@@ -164,6 +165,10 @@
 	*memory_start_p = memory_start;
 	*memory_end_p = memory_end;
 	strcpy (system_utsname.machine, "sa110");
+
+#ifdef CONFIG_FB
+	conswitchp = &fb_con;
+#endif
 }
 
 int get_cpuinfo(char * buffer)
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c
--- v2.1.109/linux/arch/arm/kernel/setup.c	Fri May  8 23:14:42 1998
+++ linux/arch/arm/kernel/setup.c	Sat Jul 18 11:55:23 1998
@@ -27,7 +27,9 @@
 #include <linux/utsname.h>
 #include <linux/blk.h>
 #include <linux/init.h>
+#include <linux/console.h>
 
+#include <asm/elf.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
@@ -38,7 +40,9 @@
 #include <asm/arch/mmu.h>
 
 struct drive_info_struct { char dummy[32]; } drive_info;
-struct screen_info screen_info;
+struct screen_info screen_info = {
+  0, 0,  0,  0, 0, 0,  0,  0,  0,  0, 1, 8
+};
 struct processor processor;
 unsigned char aux_device_present;
 
@@ -49,27 +53,39 @@
 extern const struct processor arm7_processor_functions;
 extern const struct processor sa110_processor_functions;
 
-struct armversions armidlist[] = {
+char elf_platform[ELF_PLATFORM_SIZE];
+
+const struct armversions armidlist[] = {
+  /*-- Match -- --- Mask -- -- Manu --  Processor  uname -m   --- ELF STUFF ---
+	--- processor asm funcs --- */
 #if defined(CONFIG_CPU_26)
-	{ 0x41560200, 0xfffffff0, F_MEMC	, "ARM/VLSI",	"arm2"		, &arm2_processor_functions   , "arm2"},
-	{ 0x41560250, 0xfffffff0, F_MEMC	, "ARM/VLSI",	"arm250"	, &arm250_processor_functions , "arm3"},
-	{ 0x41560300, 0xfffffff0, F_MEMC|F_CACHE, "ARM/VLSI",	"arm3"		, &arm3_processor_functions   , "arm3"},
+  { 0x41560200, 0xfffffff0, "ARM/VLSI",	"arm2"	 , "armv1"  , "v1", 0,
+	&arm2_processor_functions   },
+  { 0x41560250, 0xfffffff0, "ARM/VLSI",	"arm250" , "armv2"  , "v2", HWCAP_SWP,
+	&arm250_processor_functions },
+  { 0x41560300, 0xfffffff0, "ARM/VLSI",	"arm3"	 , "armv2"  , "v2", HWCAP_SWP,
+	&arm3_processor_functions   },
 #elif defined(CONFIG_CPU_32)
-	{ 0x41560600, 0xfffffff0, F_MMU|F_32BIT	, "ARM/VLSI",	"arm6"		, &arm6_processor_functions   , "arm6"},
-	{ 0x41560610, 0xfffffff0, F_MMU|F_32BIT	, "ARM/VLSI",	"arm610"	, &arm6_processor_functions   , "arm6"},
-	{ 0x41007000, 0xffffff00, F_MMU|F_32BIT , "ARM/VLSI",   "arm7"		, &arm7_processor_functions   , "arm6"},
-	{ 0x41007100, 0xffffff00, F_MMU|F_32BIT , "ARM/VLSI",   "arm710"	, &arm7_processor_functions   , "arm6"},
-	{ 0x4401a100, 0xfffffff0, F_MMU|F_32BIT	, "DEC",	"sa110"		, &sa110_processor_functions  , "sa1x"},
+  { 0x41560600, 0xfffffff0, "ARM/VLSI",	"arm6"	 , "armv3"  , "v3", HWCAP_SWP,
+	&arm6_processor_functions   },
+  { 0x41560610, 0xfffffff0, "ARM/VLSI",	"arm610" , "armv3"  , "v3", HWCAP_SWP,
+	&arm6_processor_functions   },
+  { 0x41007000, 0xffffff00, "ARM/VLSI",	"arm7"	 , "armv3"  , "v3", HWCAP_SWP,
+	&arm7_processor_functions   },
+  /* ARM710 IDs are non-standard */
+  { 0x41007100, 0xfff8ff00, "ARM/VLSI",	"arm710" , "armv3"  , "v3", HWCAP_SWP,
+	&arm7_processor_functions   },
+  { 0x4401a100, 0xfffffff0, "DEC",	"sa110"	 , "armv4"  , "v3", HWCAP_SWP|HWCAP_HALF,
+	&sa110_processor_functions  },
 #endif
-	{ 0x00000000, 0x00000000, 0		, "***",	"*unknown*"	, NULL			      , NULL  }
+  { 0x00000000, 0x00000000, "***", "unknown", "unknown", "**", 0, NULL }
 };
 
-static struct param_struct *params = (struct param_struct *)PARAMS_BASE;
+static const struct param_struct *params = (struct param_struct *)PARAMS_BASE;
 
 unsigned long arm_id;
 unsigned int vram_half_sam;
 int armidindex;
-int ioebpresent;
 int memc_ctrl_reg;
 int number_ide_drives;
 int number_mfm_drives;
@@ -91,9 +107,11 @@
  */
 #ifdef CONFIG_ARCH_RPC
 
-extern void init_dram_banks(struct param_struct *params);
+extern void
+init_dram_banks(const struct param_struct *params);
 
-static void setup_rpc (struct param_struct *params)
+static void
+setup_rpc(const struct param_struct *params)
 {
 	init_dram_banks(params);
 
@@ -123,11 +141,12 @@
 extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
 extern int rd_image_start;	/* starting block # of image */
 
-static void setup_ramdisk (struct param_struct *params)
+static void
+setup_ramdisk(const struct param_struct *params)
 {
-    rd_image_start	= params->u1.s.rd_start;
-    rd_prompt		= (params->u1.s.flags & FLAG_RDPROMPT) == 0;
-    rd_doload		= (params->u1.s.flags & FLAG_RDLOAD) == 0;
+	rd_image_start	= params->u1.s.rd_start;
+	rd_prompt	= (params->u1.s.flags & FLAG_RDPROMPT) == 0;
+	rd_doload	= (params->u1.s.flags & FLAG_RDLOAD) == 0;
 }
 #else
 #define setup_ramdisk(p)
@@ -137,33 +156,30 @@
  * initial ram disk
  */
 #ifdef CONFIG_BLK_DEV_INITRD
-static void setup_initrd (struct param_struct *params, unsigned long memory_end)
+static void
+setup_initrd(const struct param_struct *params, unsigned long memory_end)
 {
-    initrd_start = params->u1.s.initrd_start;
-    initrd_end   = params->u1.s.initrd_start + params->u1.s.initrd_size;
+	if (params->u1.s.initrd_start) {
+		initrd_start = params->u1.s.initrd_start;
+		initrd_end   = initrd_start + params->u1.s.initrd_size;
+	} else {
+		initrd_start = 0;
+		initrd_end   = 0;
+	}
 
-    if (initrd_end > memory_end) {
-	printk ("initrd extends beyond end of memory "
-		"(0x%08lx > 0x%08lx) - disabling initrd\n",
-		initrd_end, memory_end);
-	initrd_start = 0;
-    }
+	if (initrd_end > memory_end) {
+		printk ("initrd extends beyond end of memory "
+			"(0x%08lx > 0x%08lx) - disabling initrd\n",
+			initrd_end, memory_end);
+		initrd_start = 0;
+	}
 }
 #else
 #define setup_initrd(p,m)
 #endif
 
-#ifdef IOEB_BASE
-static inline void check_ioeb_present(void)
-{
-	if (((*IOEB_BASE) & 15) == 5)
-		armidlist[armidindex].features |= F_IOEB;
-}
-#else
-#define check_ioeb_present()
-#endif
-
-static inline void get_processor_type (void)
+static inline void
+get_processor_type(void)
 {
 	for (armidindex = 0; ; armidindex ++)
 		if (!((armidlist[armidindex].id ^ arm_id) &
@@ -186,7 +202,7 @@
 /* Can this be initdata?  --pb
  *  command_line can be, saved_command_line can't though
  */
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
+static char command_line[COMMAND_LINE_SIZE] __initdata = { 0, };
        char saved_command_line[COMMAND_LINE_SIZE];
 
 __initfunc(void setup_arch(char **cmdline_p,
@@ -194,7 +210,8 @@
 {
 	static unsigned char smptrap;
 	unsigned long memory_start, memory_end;
-	char c = ' ', *to = command_line, *from;
+	char endian = 'l', c = ' ', *to = command_line;
+	char *from;
 	int len = 0;
 
 	if (smptrap == 1)
@@ -202,12 +219,13 @@
 	smptrap = 1;
 
 	get_processor_type ();
-	check_ioeb_present ();
 	processor._proc_init ();
 
+#ifndef CONFIG_FB
 	bytes_per_char_h  = params->u1.s.bytes_per_char_h;
 	bytes_per_char_v  = params->u1.s.bytes_per_char_v;
-	from		  = params->commandline;
+#endif
+	from		  = (char *)params->commandline;
 	ROOT_DEV	  = to_kdev_t (params->u1.s.rootdev);
 	ORIG_X		  = params->u1.s.video_x;
 	ORIG_Y		  = params->u1.s.video_y;
@@ -217,8 +235,8 @@
 	number_ide_drives = (params->u1.s.adfsdrives >> 6) & 3;
 	number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3;
 
-	setup_rpc (params);
-	setup_ramdisk (params);
+	setup_rpc(params);
+	setup_ramdisk(params);
 
 	if (!(params->u1.s.flags & FLAG_READONLY))
 		root_mountflags &= ~MS_RDONLY;
@@ -264,36 +282,73 @@
 	*memory_start_p = memory_start;
 	*memory_end_p = memory_end;
 
-	setup_initrd (params, memory_end);
+	setup_initrd(params, memory_end);
+
+	sprintf(system_utsname.machine, "%s%c", armidlist[armidindex].arch_vsn, endian);
+	sprintf(elf_platform, "%s%c", armidlist[armidindex].elf_vsn, endian);
 
-	strcpy (system_utsname.machine, armidlist[armidindex].name);
+#ifdef CONFIG_FB
+	conswitchp = &fb_con;
+#endif
 }
 
-#define ISSET(bit) (armidlist[armidindex].features & bit)
+#if defined(CONFIG_ARCH_ARC)
+#define HARDWARE "Acorn-Archimedes"
+#define IO_BUS	 "Acorn"
+#elif defined(CONFIG_ARCH_A5K)
+#define HARDWARE "Acorn-A5000"
+#define IO_BUS	 "Acorn"
+#elif defined(CONFIG_ARCH_RPC)
+#define HARDWARE "Acorn-RiscPC"
+#define IO_BUS	 "Acorn"
+#elif defined(CONFIG_ARCH_EBSA110)
+#define HARDWARE "DEC-EBSA110"
+#define IO_BUS	 "DEC"
+#elif defined(CONFIG_ARCH_EBSA285)
+#define HARDWARE "DEC-EBSA285"
+#define IO_BUS   "PCI"
+#elif defined(CONFIG_ARCH_NEXUSPCI)
+#define HARDWARE "Nexus-NexusPCI"
+#define IO_BUS   "PCI"
+#elif defined(CONFIG_ARCH_VNC)
+#define HARDWARE "Corel-VNC"
+#define IO_BUS   "PCI"
+#else
+#define HARDWARE "unknown"
+#define IO_BUS   "unknown"
+#endif
+
+#if defined(CONFIG_CPU_ARM2)
+#define OPTIMISATION "ARM2"
+#elif defined(CONFIG_CPU_ARM3)
+#define OPTIMISATION "ARM3"
+#elif defined(CONFIG_CPU_ARM6)
+#define OPTIMISATION "ARM6"
+#elif defined(CONFIG_CPU_ARM7)
+#define OPTIMISATION "ARM7"
+#elif defined(CONFIG_CPU_SA110)
+#define OPTIMISATION "StrongARM"
+#else
+#define OPTIMISATION "unknown"
+#endif
 
 int get_cpuinfo(char * buffer)
 {
 	int len;
 
-	len = sprintf (buffer,  "CPU:\n"
-				"Type\t\t: %s\n"
-				"Revision\t: %d\n"
-				"Manufacturer\t: %s\n"
-				"32bit modes\t: %s\n"
-				"BogoMips\t: %lu.%02lu\n",
-				armidlist[armidindex].name,
-				(int)arm_id & 15,
-				armidlist[armidindex].manu,
-				ISSET (F_32BIT) ? "yes" : "no",
-				(loops_per_sec+2500) / 500000,
-				((loops_per_sec+2500) / 5000) % 100);
-	len += sprintf (buffer + len,
-				"\nHardware:\n"
-				"Mem System\t: %s\n"
-				"IOEB\t\t: %s\n",
-				ISSET(F_MEMC)  ? "MEMC" : 
-				ISSET(F_MMU)   ? "MMU"  : "*unknown*",
-				ISSET(F_IOEB)  ? "present" : "absent"
-				);
+	len = sprintf(buffer,
+		"Processor\t: %s %s rev %d\n"
+		"BogoMips\t: %lu.%02lu\n"
+		"Hardware\t: %s\n"
+		"Optimisation\t: %s\n"
+		"IO Bus\t: %s\n",
+		armidlist[armidindex].manu,
+		armidlist[armidindex].name,
+		(int)arm_id & 15,
+		(loops_per_sec+2500) / 500000,
+		((loops_per_sec+2500) / 5000) % 100,
+		HARDWARE,
+		OPTIMISATION,
+		IO_BUS);
 	return len;
 }
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/signal.c linux/arch/arm/kernel/signal.c
--- v2.1.109/linux/arch/arm/kernel/signal.c	Fri May  8 23:14:42 1998
+++ linux/arch/arm/kernel/signal.c	Sat Jul 18 11:55:23 1998
@@ -4,7 +4,7 @@
  *  Copyright (C) 1995, 1996 Russell King
  */
 
-#include <linux/config.h> /* for CONFIG_CPU_ARM6 and CONFIG_CPU_SA110 */
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -37,7 +37,6 @@
  */
 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs)
 {
-
 	sigset_t saveset;
 
 	mask &= _BLOCKABLE;
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c
--- v2.1.109/linux/arch/arm/kernel/sys_arm.c	Tue Jun 23 10:01:19 1998
+++ linux/arch/arm/kernel/sys_arm.c	Sat Jul 18 11:55:23 1998
@@ -239,7 +239,6 @@
 	lock_kernel();
 	if (!newsp)
 		newsp = regs->ARM_sp;
-
 	ret = do_fork(clone_flags, newsp, regs);
 	unlock_kernel();
 	return ret;
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c
--- v2.1.109/linux/arch/arm/kernel/time.c	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/time.c	Sat Jul 18 11:55:23 1998
@@ -24,11 +24,11 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/delay.h>
 
 #include <linux/timex.h>
 #include <asm/hardware.h>
diff -u --recursive --new-file v2.1.109/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- v2.1.109/linux/arch/arm/kernel/traps.c	Fri May  8 23:14:42 1998
+++ linux/arch/arm/kernel/traps.c	Sat Jul 18 11:55:23 1998
@@ -24,6 +24,7 @@
 #include <asm/atomic.h>
 #include <asm/pgtable.h>
 
+extern struct task_struct *last_task_used_math;
 extern void fpe_save(struct fp_soft_struct *);
 extern void fpe_restore(struct fp_soft_struct *);
 extern void die_if_kernel(char *str, struct pt_regs *regs, int err, int ret);
@@ -306,7 +307,7 @@
 
 asmlinkage void deferred(int n, struct pt_regs *regs)
 {
-	dump_state("old system call", regs, 0);
+	dump_state("old system call", regs, n);
 	force_sig (SIGILL, current);
 }
 
diff -u --recursive --new-file v2.1.109/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile
--- v2.1.109/linux/arch/arm/lib/Makefile	Fri May  8 23:14:42 1998
+++ linux/arch/arm/lib/Makefile	Sat Jul 18 11:55:23 1998
@@ -6,7 +6,7 @@
 
 L_TARGET := lib.a
 L_OBJS   := backtrace.o bitops.o checksum.o delay.o fp_support.o \
-	    loaders.o memcpy.o system.o string.o uaccess.o
+	    loaders.o memcpy.o system.o string.o uaccess.o io.o
 
 ifeq ($(PROCESSOR),armo)
   L_OBJS += uaccess-armo.o
diff -u --recursive --new-file v2.1.109/linux/arch/arm/lib/extractconstants.pl linux/arch/arm/lib/extractconstants.pl
--- v2.1.109/linux/arch/arm/lib/extractconstants.pl	Fri May  8 23:14:42 1998
+++ linux/arch/arm/lib/extractconstants.pl	Sat Jul 18 11:55:23 1998
@@ -24,7 +24,7 @@
 	/elf32/ && ( $elf = 1 );
 	/a.out/ && ( $aout = 1 );
 	next if ($aout && ! / 07 /);
-	next if ($elf && ! (/^00...... g/ && /.data/));
+	next if ($elf && ! (/^0*0...... g/ && /.data/));
 	next if (!$aout && !$elf);
 
 	if ($aout) {
@@ -33,7 +33,7 @@
 	}
 	if ($elf) {
 		chomp;
-		$addr = substr ($_, 0, 8);
+		$addr = substr ($_, 0, index($_, " "));
 		$name = substr ($_, rindex($_, " ") + 1);
 		$nam[hex($addr)] = $name;
 	}
diff -u --recursive --new-file v2.1.109/linux/arch/arm/lib/getconstants.c linux/arch/arm/lib/getconstants.c
--- v2.1.109/linux/arch/arm/lib/getconstants.c	Fri May  8 23:14:42 1998
+++ linux/arch/arm/lib/getconstants.c	Wed Dec 31 16:00:00 1969
@@ -1,74 +0,0 @@
-/*
- * linux/arch/arm/lib/getconstants.c
- *
- * Copyright (C) 1995, 1996 Russell King
- */
-
-#include <linux/mm.h>
-#include <asm/pgtable.h>
-#include <stdio.h>
-#include <linux/unistd.h>
-
-void printdef(char *def, int no)
-{
-	printf("#define %s\t%d\n", def, no);
-}
-
-#include "getconstants.h"
-
-int main()
-{
-	printf("/*\n *  contants.h generated by getconstants\n * DO NOT EDIT!\n */\n");
-
-	printf("#define _current\t_%s\n", "current_set");
-
-#ifdef _PAGE_PRESENT
-	printdef("PAGE_PRESENT",	_PAGE_PRESENT);
-#endif
-#ifdef _PAGE_RW
-	printdef("PAGE_RW",		_PAGE_RW);
-#endif
-#ifdef _PAGE_USER
-	printdef("PAGE_USER",		_PAGE_USER);
-#endif
-#ifdef _PAGE_ACCESSED
-	printdef("PAGE_ACCESSED",	_PAGE_ACCESSED);
-#endif
-#ifdef _PAGE_DIRTY
-	printdef("PAGE_DIRTY",		_PAGE_DIRTY);
-#endif
-#ifdef _PAGE_READONLY
-	printdef("PAGE_READONLY",	_PAGE_READONLY);
-#endif
-#ifdef _PAGE_NOT_USER
-	printdef("PAGE_NOT_USER",	_PAGE_NOT_USER);
-#endif
-#ifdef _PAGE_OLD
-	printdef("PAGE_OLD",		_PAGE_OLD);
-#endif
-#ifdef _PAGE_CLEAN
-	printdef("PAGE_CLEAN",		_PAGE_CLEAN);
-#endif
-	printdef("TSS_MEMMAP",		(int)tss_memmap);
-	printdef("TSS_SAVE",		(int)tss_save);
-#ifdef __HAS_tss_memcmap
-	printdef("TSS_MEMCMAP",		(int)tss_memcmap);
-#endif
-#ifdef __HAS_addr_limit
-	printdef("ADDR_LIMIT",		(int)addr_limit);
-#endif
-#ifdef __HAS_kernel_domain
-	printdef("KERNEL_DOMAIN",	kernel_domain);
-#endif
-#ifdef __HAS_user_domain
-	printdef("USER_DOMAIN",		user_domain);
-#endif
-	printdef("TSS_FPESAVE",		(int)tss_fpesave);
-	printdef("MM",			(int)mm);
-	printdef("PGD",			(int)pgd);
-
-	printf("#define KSWI_BASE	0x900000\n");
-	printf("#define KSWI_SYS_BASE	0x9F0000\n");
-	printf("#define SYS_ERROR0	0x9F0000\n");
-	return 0;
-}
diff -u --recursive --new-file v2.1.109/linux/arch/arm/lib/getconstants.h linux/arch/arm/lib/getconstants.h
--- v2.1.109/linux/arch/arm/lib/getconstants.h	Fri May  8 23:14:42 1998
+++ linux/arch/arm/lib/getconstants.h	Wed Dec 31 16:00:00 1969
@@ -1,17 +0,0 @@
-/*
- * *** THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT! ***
- */
-unsigned long addr_limit = 56;
-#define __HAS_addr_limit
-unsigned long tss_memmap = 640;
-#define __HAS_tss_memmap
-unsigned long mm = 1676;
-#define __HAS_mm
-unsigned long pgd = 8;
-#define __HAS_pgd
-unsigned long tss_save = 636;
-#define __HAS_tss_save
-unsigned long tss_fpesave = 492;
-#define __HAS_tss_fpesave
-unsigned long tss_memcmap = 644;
-#define __HAS_tss_memcmap
diff -u --recursive --new-file v2.1.109/linux/arch/arm/lib/io-ebsa285.S linux/arch/arm/lib/io-ebsa285.S
--- v2.1.109/linux/arch/arm/lib/io-ebsa285.S	Fri May  8 23:14:42 1998
+++ linux/arch/arm/lib/io-ebsa285.S	Sat Jul 18 11:55:23 1998
@@ -97,12 +97,50 @@
 		bne	4b
 		mov	pc, lr
 
+		/* Nobody could say these are optimal, but not to worry. */
 
-ENTRY(outsw)
 ENTRY(outswb)
+		mov	r2, r2, lsr #1
+ENTRY(outsw)
+		add	r0, r0, #0xff000000
+		add	r0, r0, #0x00e00000
+1:		teq	r2, #0
+		ldrneh	r3, [r1], #2
+		strneh	r3, [r0]
+		subne	r2, r2, #1
+		bne	1b
 		mov	pc, lr
 
-ENTRY(insw)
 ENTRY(inswb)
+		mov	r2, r2, lsr #1
+ENTRY(insw)
+		add	r0, r0, #0xff000000
+		add	r0, r0, #0x00e00000
+1:		teq	r2, #0
+		ldrneh	r3, [r0]
+		strneh	r3, [r1], #2
+		subne	r2, r2, #1
+		bne	1b
 		mov	pc, lr
 
+
+ENTRY(insb)
+		add	r0, r0, #0xff000000
+		add	r0, r0, #0x00e00000
+1:		teq	r2, #0
+		ldrneb	r3, [r0]
+		strneb	r3, [r1], #1
+		subne	r2, r2, #1
+		bne	1b
+		mov	pc, lr
+
+
+ENTRY(outsb)
+		add	r0, r0, #0xff000000
+		add	r0, r0, #0x00e00000
+1:		teq	r2, #0
+		ldrneb	r3, [r1], #1
+		strneb	r3, [r0]
+		subne	r2, r2, #1
+		bne	1b
+		mov	pc, lr
diff -u --recursive --new-file v2.1.109/linux/arch/arm/lib/io.c linux/arch/arm/lib/io.c
--- v2.1.109/linux/arch/arm/lib/io.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/io.c	Sat Jul 18 11:55:23 1998
@@ -0,0 +1,43 @@
+#include <asm/io.h>
+
+/*
+ * Copy data from IO memory space to "real" memory space.
+ * This needs to be optimized.
+ */
+void _memcpy_fromio(void * to, unsigned long from, unsigned long count)
+{
+	while (count) {
+		count--;
+		*(char *) to = readb(from);
+		((char *) to)++;
+		from++;
+	}
+}
+
+/*
+ * Copy data from "real" memory space to IO memory space.
+ * This needs to be optimized.
+ */
+void _memcpy_toio(unsigned long to, void * from, unsigned long count)
+{
+	while (count) {
+		count--;
+		writeb(*(char *) from, to);
+		((char *) from)++;
+		to++;
+	}
+}
+
+/*
+ * "memset" on IO memory space.
+ * This needs to be optimized.
+ */
+void _memset_io(unsigned long dst, int c, unsigned long count)
+{
+	while (count) {
+		count--;
+		writeb(c, dst);
+		dst++;
+	}
+}
+
diff -u --recursive --new-file v2.1.109/linux/arch/arm/mm/fault-armo.c linux/arch/arm/mm/fault-armo.c
--- v2.1.109/linux/arch/arm/mm/fault-armo.c	Thu May 14 19:47:38 1998
+++ linux/arch/arm/mm/fault-armo.c	Sat Jul 18 11:55:23 1998
@@ -28,8 +28,6 @@
 #define FAULT_CODE_WRITE	0x02
 #define FAULT_CODE_USER		0x01
 
-#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
-
 struct pgtable_cache_struct quicklists;
 
 void __bad_pmd(pmd_t *pmd)
diff -u --recursive --new-file v2.1.109/linux/arch/arm/mm/mm-a5k.c linux/arch/arm/mm/mm-a5k.c
--- v2.1.109/linux/arch/arm/mm/mm-a5k.c	Fri May  8 23:14:42 1998
+++ linux/arch/arm/mm/mm-a5k.c	Wed Dec 31 16:00:00 1969
@@ -1,7 +0,0 @@
-/*
- * arch/arm/mm/mm-a5k.c
- *
- * Extra MM routines for the Archimedes architecture
- *
- * Copyright (C) 1998 Russell King
- */
diff -u --recursive --new-file v2.1.109/linux/arch/arm/mm/mm-arc.c linux/arch/arm/mm/mm-arc.c
--- v2.1.109/linux/arch/arm/mm/mm-arc.c	Fri May  8 23:14:42 1998
+++ linux/arch/arm/mm/mm-arc.c	Sat Jul 18 11:55:23 1998
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 1998 Russell King
  */
+#include <linux/init.h>
 #include <asm/hardware.h>
 #include <asm/pgtable.h>
 
@@ -13,7 +14,7 @@
 /*
  * This routine needs more work to make it dynamically release/allocate mem!
  */
-unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update)
+__initfunc(unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update))
 {
 	static int updated = 0;
 
@@ -75,8 +76,7 @@
 
 		phys_screen_end = offset;
 		flush_tlb_all ();
-		update_mm_cache_all ();
+		update_memc_all ();
 	}
 	return kmem;
 }
-
diff -u --recursive --new-file v2.1.109/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c
--- v2.1.109/linux/arch/arm/mm/mm-armv.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mm/mm-armv.c	Sat Jul 18 11:55:23 1998
@@ -0,0 +1,71 @@
+/*
+ * arch/arm/mm/mm-armv.c
+ *
+ * Common routines for ARM v3 and v4 architectures.
+ *
+ * Copyright (C) 1998 Russell King
+ *
+ * Do not compile this file directly!
+ */
+
+#ifndef MAPPING
+#error MAPPING not defined - do not compile this file individually
+#endif
+
+static const struct mapping {
+	unsigned long virtual;
+	unsigned long physical;
+	unsigned long length;
+	int domain:4,
+	    prot_read:1,
+	    prot_write:1;
+} mapping[] __initdata = {
+	MAPPING
+};
+
+#define SIZEOFMAP (sizeof(mapping) / sizeof(mapping[0]))
+
+__initfunc(unsigned long setup_io_pagetables(unsigned long start_mem))
+{
+	const struct mapping *mp;
+	int i;
+
+	for (i = 0, mp = mapping; i < SIZEOFMAP; i++, mp++) {
+		unsigned long virtual, physical, length;
+		int prot;
+
+		virtual = mp->virtual;
+		physical = mp->physical;
+		length = mp->length;
+		prot = (mp->prot_read ? PTE_AP_READ : 0) | (mp->prot_write ? PTE_AP_WRITE : 0);
+
+		while ((virtual & 1048575 || physical & 1048575) && length >= PAGE_SIZE) {
+			alloc_init_page(&start_mem, virtual, physical, mp->domain, prot);
+			length -= PAGE_SIZE;
+			virtual += PAGE_SIZE;
+			physical += PAGE_SIZE;
+		}
+
+		prot = (mp->prot_read ? PMD_SECT_AP_READ : 0) |
+		       (mp->prot_write ? PMD_SECT_AP_WRITE : 0);
+
+		while (length >= 1048576) {
+			alloc_init_section(&start_mem, virtual, physical, mp->domain, prot);
+			length -= 1048576;
+			virtual += 1048576;
+			physical += 1048576;
+		}
+
+		prot = (mp->prot_read ? PTE_AP_READ : 0) | (mp->prot_write ? PTE_AP_WRITE : 0);
+
+		while (length >= PAGE_SIZE) {
+			alloc_init_page(&start_mem, virtual, physical, mp->domain, prot);
+			length -= PAGE_SIZE;
+			virtual += PAGE_SIZE;
+			physical += PAGE_SIZE;
+		}
+	}
+
+	return start_mem;
+}
+
diff -u --recursive --new-file v2.1.109/linux/arch/arm/mm/mm-ebsa110.c linux/arch/arm/mm/mm-ebsa110.c
--- v2.1.109/linux/arch/arm/mm/mm-ebsa110.c	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/mm/mm-ebsa110.c	Sat Jul 18 11:55:23 1998
@@ -1,26 +1,15 @@
 /*
  * arch/arm/mm/mm-ebsa110.c
  *
- * Extra MM routines for the Archimedes architecture
+ * Extra MM routines for the EBSA-110 architecture
  *
  * Copyright (C) 1998 Russell King
  */
-
+#include <linux/init.h>
 #include <asm/io.h>
  
-/* map in IO */
-void setup_io_pagetables(void)
-{
-	unsigned long address = IO_START;
-	int spi = IO_BASE >> PGDIR_SHIFT;
-
-	pgd_val(swapper_pg_dir[spi-1]) = 0xc0000000 | PMD_TYPE_SECT |
-					 PMD_DOMAIN(DOMAIN_KERNEL) | PMD_SECT_AP_WRITE;
+#define MAPPING \
+	{ IO_BASE - PGDIR_SIZE	, 0xc0000000	, PGDIR_SIZE	, DOMAIN_IO, 0, 1 }, \
+	{ IO_BASE		, IO_START	, IO_SIZE	, DOMAIN_IO, 0, 1 }
 
-	while (address < IO_START + IO_SIZE && address) {
-		pgd_val(swapper_pg_dir[spi++]) = address | PMD_TYPE_SECT |
-						PMD_DOMAIN(DOMAIN_IO) |
-						PMD_SECT_AP_WRITE;
-		address += PGDIR_SIZE;
-	}
-}
+#include "mm-armv.c"
diff -u --recursive --new-file v2.1.109/linux/arch/arm/mm/mm-ebsa285.c linux/arch/arm/mm/mm-ebsa285.c
--- v2.1.109/linux/arch/arm/mm/mm-ebsa285.c	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/mm/mm-ebsa285.c	Sun Jul 19 20:45:45 1998
@@ -3,16 +3,48 @@
  *
  * Extra MM routines for the EBSA285 architecture
  *
- * Copyright (C) 1998 Russell King
+ * Copyright (C) 1998 Russell King, Dave Gilbert.
  */
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/init.h>
  
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/io.h>
 #include <asm/proc/mm-init.h>
- 
+
+/*
+ * These two functions convert PCI bus addresses to virtual addresses
+ * and back again.
+ */ 
+unsigned long __virt_to_bus(unsigned long res)
+{
+	if (res < PAGE_OFFSET || res >= 0xD0000000) {
+		printk("__virt_to_bus: invalid address 0x%08lx\n", res);
+#ifdef CONFIG_DEBUG_ERRORS
+		__backtrace();
+#endif
+	} else
+		res = (res - PAGE_OFFSET) + 0x10000000;
+
+	return res;
+}
+
+unsigned long __bus_to_virt(unsigned long res)
+{
+	if (res < 0x10000000 || res >= 0x20000000) {
+		printk("__bus_to_virt: invalid address 0x%08lx\n", res);
+#ifdef CONFIG_DEBUG_ERRORS
+		__backtrace();
+#endif
+	} else
+		res = (res - 0x10000000) + PAGE_OFFSET;
+
+	return res;
+}
+
 /*    Logical    Physical
  * 0xfff00000	0x40000000	X-Bus
  * 0xffe00000	0x7c000000	PCI I/O space
@@ -23,75 +55,25 @@
  * 0xf8000000	0x7b000000	PCI Config type 0
  */
 
-static struct mapping {
-	unsigned long virtual;
-	unsigned long physical;
-	unsigned long length;
-} io_mapping[] = {
-	/*
-	 * This is to allow us to fiddle with the EEPROM
-	 *  This entry will go away in time
-	 */
-	{ 0xd8000000, 0x41000000, 0x00400000 },
-
-	/*
-	 * These ones are so that we can fiddle
-	 *  with the various cards (eg VGA)
-	 *  until we're happy with them...
-	 */
-	{ 0xdc000000, 0x7c000000, 0x00100000 },
-	{ 0xe0000000, 0x80000000, 0x10000000 },
-
-	{ 0xf8000000, 0x7b000000, 0x01000000 },	/* Type 0 Config */
-
-	{ 0xf9000000, 0x7a000000, 0x01000000 },	/* Type 1 Config */
-
-	{ 0xfc000000, 0x79000000, 0x01000000 },	/* PCI IACK	 */
-	{ 0xfd000000, 0x78000000, 0x01000000 },	/* Outbound wflsh*/
-	{ 0xfe000000, 0x42000000, 0x01000000 },	/* CSR		 */
-	{ 0xffe00000, 0x7c000000, 0x00100000 },	/* PCI I/O	 */
-	{ 0xfff00000, 0x40000000, 0x00100000 },	/* X-Bus	 */
-};
-
-#define SIZEOFIO (sizeof(io_mapping) / sizeof(io_mapping[0]))
-
-/* map in IO */
-unsigned long setup_io_pagetables(unsigned long start_mem)
-{
-	struct mapping *mp;
-	int i;
-
-	for (i = 0, mp = io_mapping; i < SIZEOFIO; i++, mp++) {
-		while ((mp->virtual & 1048575 || mp->physical & 1048575) && mp->length >= PAGE_SIZE) {
-			alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
-					PTE_AP_WRITE);
-
-			mp->length -= PAGE_SIZE;
-			mp->virtual += PAGE_SIZE;
-			mp->physical += PAGE_SIZE;
-		}
-
-		while (mp->length >= 1048576) {
-if (mp->virtual > 0xf0000000)
-			alloc_init_section(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
-					   PMD_SECT_AP_WRITE);
-else
-alloc_init_section(&start_mem, mp->virtual, mp->physical, DOMAIN_USER, PMD_SECT_AP_WRITE | PMD_SECT_AP_READ);
-
-			mp->length -= 1048576;
-			mp->virtual += 1048576;
-			mp->physical += 1048576;
-		}
-
-		while (mp->length >= PAGE_SIZE) {
-			alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
-					PTE_AP_WRITE);
-
-			mp->length -= PAGE_SIZE;
-			mp->virtual += PAGE_SIZE;
-			mp->physical += PAGE_SIZE;
-		}
-	}
-	return start_mem;
-}
+/*
+ * This is to allow us to fiddle with the EEPROM
+ *  This entry will go away in time, once the fmu
+ *  can mmap() the flash.
+ *
+ * These ones are so that we can fiddle
+ *  with the various cards (eg VGA)
+ *  until we're happy with them...
+ */
+#define MAPPING \
+	{ 0xd8000000, 0x41000000, 0x00400000, DOMAIN_USER, 1, 1 },	/* EEPROM */	    \
+	{ 0xdc000000, 0x7c000000, 0x00100000, DOMAIN_USER, 1, 1 },	/* VGA */	    \
+	{ 0xe0000000, 0x80000000, 0x10000000, DOMAIN_USER, 1, 1 },	/* VGA */	    \
+	{ 0xf8000000, 0x7b000000, 0x01000000, DOMAIN_IO  , 0, 1 },	/* Type 0 Config */ \
+	{ 0xf9000000, 0x7a000000, 0x01000000, DOMAIN_IO  , 0, 1 },	/* Type 1 Config */ \
+	{ 0xfc000000, 0x79000000, 0x01000000, DOMAIN_IO  , 0, 1 },	/* PCI IACK	 */ \
+	{ 0xfd000000, 0x78000000, 0x01000000, DOMAIN_IO  , 0, 1 },	/* Outbound wflsh*/ \
+	{ 0xfe000000, 0x42000000, 0x01000000, DOMAIN_IO  , 0, 1 },	/* CSR		 */ \
+	{ 0xffe00000, 0x7c000000, 0x00100000, DOMAIN_IO  , 0, 1 },	/* PCI I/O	 */ \
+	{ 0xfff00000, 0x40000000, 0x00100000, DOMAIN_IO  , 0, 1 },	/* X-Bus	 */
 
+#include "mm-armv.c"
diff -u --recursive --new-file v2.1.109/linux/arch/arm/mm/mm-nexuspci.c linux/arch/arm/mm/mm-nexuspci.c
--- v2.1.109/linux/arch/arm/mm/mm-nexuspci.c	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/mm/mm-nexuspci.c	Sat Jul 18 11:55:23 1998
@@ -4,25 +4,24 @@
  *
  * Extra MM routines for the NexusPCI architecture
  *
+ * Copyright (C) 1998 Phil Blundell
  * Copyright (C) 1998 Russell King
  */
 
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+ 
+#include <asm/pgtable.h>
+#include <asm/page.h>
 #include <asm/io.h>
+#include <asm/proc/mm-init.h>
  
-/* map in IO */
-void setup_io_pagetables(void)
-{
-	unsigned long address = IO_START;
-	int spi = IO_BASE >> PGDIR_SHIFT;
-
-	pgd_val(swapper_pg_dir[spi-1]) = 0xc0000000 | PMD_TYPE_SECT |
-					 PMD_DOMAIN(DOMAIN_KERNEL) | PMD_SECT_AP_WRITE;
-
-	while (address < IO_START + IO_SIZE && address) {
-		pgd_val(swapper_pg_dir[spi++]) = address | PMD_TYPE_SECT |
-						PMD_DOMAIN(DOMAIN_IO) |
-						PMD_SECT_AP_WRITE;
-		address += PGDIR_SIZE;
-	}
-}
+#define MAPPING								\
+ 	{ 0xfff00000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffe00000, 0x20000000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffc00000, 0x60000000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xfe000000, 0x80000000, 0x00100000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xfd000000, 0x88000000, 0x00100000, DOMAIN_IO, 0, 1 }
 
+#include "mm-armv.c"
diff -u --recursive --new-file v2.1.109/linux/arch/arm/mm/mm-rpc.c linux/arch/arm/mm/mm-rpc.c
--- v2.1.109/linux/arch/arm/mm/mm-rpc.c	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/mm/mm-rpc.c	Sat Jul 18 11:55:23 1998
@@ -5,9 +5,9 @@
  *
  * Copyright (C) 1998 Russell King
  */
-
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/init.h>
 
 #include <asm/pgtable.h>
 #include <asm/setup.h>
@@ -88,50 +88,10 @@
 	current->tss.memmap = __virt_to_phys((unsigned long)swapper_pg_dir);
 }
 
-static struct mapping {
-	unsigned long virtual;
-	unsigned long physical;
-	unsigned long length;
-} io_mapping[] = {
-	{ SCREEN2_BASE,	SCREEN_START,	2*1048576	},	/* VRAM		*/
-	{ IO_BASE,	IO_START,	IO_SIZE		}	/* IO space	*/
-};
-
-#define SIZEOFIO (sizeof(io_mapping) / sizeof(io_mapping[0]))
-
-/* map in IO */
-unsigned long setup_io_pagetables(unsigned long start_mem)
-{
-	struct mapping *mp;
-	int i;
-
-	for (i = 0, mp = io_mapping; i < SIZEOFIO; i++, mp++) {
-		while ((mp->virtual & 1048575 || mp->physical & 1048575) && mp->length >= PAGE_SIZE) {
-			alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
-					PTE_AP_WRITE);
-
-			mp->length -= PAGE_SIZE;
-			mp->virtual += PAGE_SIZE;
-			mp->physical += PAGE_SIZE;
-		}
-
-		while (mp->length >= 1048576) {
-			alloc_init_section(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
-					   PMD_SECT_AP_WRITE);
-			mp->length -= 1048576;
-			mp->virtual += 1048576;
-			mp->physical += 1048576;
-		}
-
-		while (mp->length >= PAGE_SIZE) {
-			alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
-					PTE_AP_WRITE);
-
-			mp->length -= PAGE_SIZE;
-			mp->virtual += PAGE_SIZE;
-			mp->physical += PAGE_SIZE;
-		}
-	}
-
-	return start_mem;
-}
+#define MAPPING \
+	{ SCREEN2_BASE,	SCREEN_START,	2*1048576, DOMAIN_IO, 0, 1 },	/* VRAM		*/ \
+	{ IO_BASE,	IO_START,	IO_SIZE	 , DOMAIN_IO, 0, 1 }	/* IO space	*/
+/*
+ * Include common routine to set up page tables
+ */
+#include "mm-armv.c"
diff -u --recursive --new-file v2.1.109/linux/arch/arm/mm/mm-tbox.c linux/arch/arm/mm/mm-tbox.c
--- v2.1.109/linux/arch/arm/mm/mm-tbox.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mm/mm-tbox.c	Sat Jul 18 11:55:23 1998
@@ -0,0 +1,56 @@
+/*
+ * arch/arm/mm/mm-tbox.c
+ *  from arch/arm/mm/mm-ebsa110.c
+ *
+ * Extra MM routines for the Tbox architecture
+ *
+ * Copyright (C) 1998 Phil Blundell
+ * Copyright (C) 1998 Russell King
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/proc/mm-init.h>
+ 
+ 
+/*    Logical    Physical
+ * 0xffff1000	0x00100000	DMA registers
+ * 0xffff2000	0x00200000	MPEG
+ * 0xffff3000	0x00300000	FPGA1 local control
+ * 0xffff4000	0x00400000	External serial
+ * 0xffff5000	0x00500000	Internal serial
+ * 0xffff6000	0x00600000	Parallel
+ * 0xffff7000	0x00700000	Interrupt control
+ * 0xffff8000	0x00800000	Computer video
+ * 0xffff9000	0x00900000	Control register 0
+ * 0xffffs000	0x00a00000	Control register 1
+ * 0xffffb000	0x00b00000	Control register 2
+ * 0xffffc000	0x00c00000	FPGA2 local control
+ * 0xffffd000	0x00d00000	Interrupt reset
+ * 0xffffe000	0x00e00000	MPEG DMA throttle
+ */
+ 
+#define MAPPING								\
+  	{ 0xffff0000, 0x01000000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffff1000, 0x00100000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffff2000, 0x00200000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffff3000, 0x00300000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffff4000, 0x00400000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xfe000000, 0x00400000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffff5000, 0x00500000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffff6000, 0x00600000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffff7000, 0x00700000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffff8000, 0x00800000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffff9000, 0x00900000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffffa000, 0x00a00000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffffb000, 0x00b00000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffffc000, 0x00c00000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffffd000, 0x00d00000, 0x00001000, DOMAIN_IO, 0, 1 },	\
+ 	{ 0xffffe000, 0x00e00000, 0x00001000, DOMAIN_IO, 0, 1 }
+
+#include "mm-armv.c"
diff -u --recursive --new-file v2.1.109/linux/arch/arm/mm/mm-vnc.c linux/arch/arm/mm/mm-vnc.c
--- v2.1.109/linux/arch/arm/mm/mm-vnc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mm/mm-vnc.c	Sat Jul 18 11:55:23 1998
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mm/mm-vnc.c
+ *
+ * Extra MM routines for the Corel VNC architecture
+ *
+ * Copyright (C) 1998 Russell King
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+ 
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/proc/mm-init.h>
+
+/* Table describing the MMU translation mapping
+ * mainly used to set up the I/O mappings.
+ */ 
+#define MAPPING \
+  { 0xe0000000, DC21285_PCI_IO,		      0x00100000, DOMAIN_IO, 0, 1 }, /* PCI I/O		*/ \
+  { 0xe0100000, DC21285_PCI_TYPE_0_CONFIG,    0x00f00000, DOMAIN_IO, 0, 1 }, /* Type 0 Config	*/ \
+  { 0xe1000000, DC21285_ARMCSR_BASE,	      0x00100000, DOMAIN_IO, 0, 1 }, /* ARM CSR		*/ \
+  { 0xe1100000, DC21285_PCI_IACK,	      0x00100000, DOMAIN_IO, 0, 1 }, /* PCI IACK	*/ \
+  { 0xe1300000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh	*/ \
+  { 0xe1400000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh	*/ \
+  { 0xe1500000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh	*/ \
+  { 0xe1600000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh	*/ \
+  { 0xe1700000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh	*/ \
+  { 0xe1800000, DC21285_FLASH,                0x00800000, DOMAIN_IO, 0, 1 }  /* Flash		*/
+
+#include "mm-armv.c"
diff -u --recursive --new-file v2.1.109/linux/arch/arm/mm/proc-arm6,7.S linux/arch/arm/mm/proc-arm6,7.S
--- v2.1.109/linux/arch/arm/mm/proc-arm6,7.S	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/mm/proc-arm6,7.S	Sat Jul 18 11:55:23 1998
@@ -347,12 +347,11 @@
  *
  * Purpose : Set a PMD and flush it out of any WB cache
  */
-_arm6_set_pmd:	and	r2, r1, #3
-		teq	r2, #2
-		andeq	r2, r1, #8
-		orreq	r1, r1, r2, lsl #1		@ Updatable = Cachable
+_arm6_set_pmd:	and	r2, r1, #11
 		teq	r2, #1
-		orreq	r1, r1, #16			@ Updatable = 1 if Page table
+		teqne	r2, #9
+		teqne	r2, #10
+		orreq	r1, r1, #16			@ Updatable = 1 if Page table/Cacheable section
 		str	r1, [r0]
 		mov	pc, lr
 
@@ -364,7 +363,8 @@
  *
  * Purpose : Set a PMD and flush it out of any WB cache
  */
-_arm7_set_pmd:	orr	r1, r1, #16			@ Updatable bit is always set on ARM7
+_arm7_set_pmd:	tst	r1, #3
+		orrne	r1, r1, #16			@ Updatable bit is always set on ARM7
 		str	r1, [r0]
 		mov	pc, lr
 
diff -u --recursive --new-file v2.1.109/linux/arch/arm/vmlinux-armo.lds linux/arch/arm/vmlinux-armo.lds
--- v2.1.109/linux/arch/arm/vmlinux-armo.lds	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/vmlinux-armo.lds	Sat Jul 18 11:55:23 1998
@@ -0,0 +1,63 @@
+/* ld script to make ARM Linux kernel
+ * taken from the i386 version
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+  _text = .;			/* Text and read-only data */
+  .text : {
+	*(.text)
+	*(.fixup)
+	*(.gnu.warning)
+	} = 0x9090
+  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
+  .rodata : { *(.rodata) }
+  .kstrtab : { *(.kstrtab) }
+
+  . = ALIGN(16);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  __start___ksymtab = .;	/* Kernel symbol table */
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+
+  _etext = .;			/* End of text section */
+
+  .data : {			/* Data */
+	*(.data)
+	CONSTRUCTORS
+	}
+
+  _edata = .;			/* End of data section */
+
+  /* This has to be aligned to a page boundary to do us any good.  This
+     alignment is overkill for ARM6 up but needed for ARM3.  Since all this
+     data will be thrown away I don't think the extra padding will hurt.
+       -- pb */
+  . = ALIGN(32768);		/* Init code and data */
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(32768);
+  __init_end = .;
+
+  __bss_start = .;		/* BSS */
+  .bss : {
+	*(.bss)
+	}
+  _end = . ;
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
diff -u --recursive --new-file v2.1.109/linux/arch/arm/vmlinux-armv.lds linux/arch/arm/vmlinux-armv.lds
--- v2.1.109/linux/arch/arm/vmlinux-armv.lds	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/vmlinux-armv.lds	Sat Jul 18 11:55:23 1998
@@ -0,0 +1,63 @@
+/* ld script to make ARM Linux kernel
+ * taken from the i386 version
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+  _text = .;			/* Text and read-only data */
+  .text : {
+	*(.text)
+	*(.fixup)
+	*(.gnu.warning)
+	} = 0x9090
+  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
+  .rodata : { *(.rodata) }
+  .kstrtab : { *(.kstrtab) }
+
+  . = ALIGN(16);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  __start___ksymtab = .;	/* Kernel symbol table */
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+
+  _etext = .;			/* End of text section */
+
+  .data : {			/* Data */
+	*(.data)
+	CONSTRUCTORS
+	}
+
+  _edata = .;			/* End of data section */
+
+  /* This has to be aligned to a page boundary to do us any good.  This
+     alignment is overkill for ARM6 up but needed for ARM3.  Since all this
+     data will be thrown away I don't think the extra padding will hurt.
+       -- pb */
+  . = ALIGN(4096);		/* Init code and data */
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);
+  __init_end = .;
+
+  __bss_start = .;		/* BSS */
+  .bss : {
+	*(.bss)
+	}
+  _end = . ;
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
diff -u --recursive --new-file v2.1.109/linux/arch/arm/vmlinux.lds linux/arch/arm/vmlinux.lds
--- v2.1.109/linux/arch/arm/vmlinux.lds	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/vmlinux.lds	Wed Dec 31 16:00:00 1969
@@ -1,63 +0,0 @@
-/* ld script to make ARM Linux kernel
- * taken from the i386 version
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
- */
-OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")
-OUTPUT_ARCH(arm)
-ENTRY(_start)
-SECTIONS
-{
-  _text = .;			/* Text and read-only data */
-  .text : {
-	*(.text)
-	*(.fixup)
-	*(.gnu.warning)
-	} = 0x9090
-  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
-  .rodata : { *(.rodata) }
-  .kstrtab : { *(.kstrtab) }
-
-  . = ALIGN(16);		/* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
-  __start___ksymtab = .;	/* Kernel symbol table */
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
-
-  _etext = .;			/* End of text section */
-
-  .data : {			/* Data */
-	*(.data)
-	CONSTRUCTORS
-	}
-
-  _edata = .;			/* End of data section */
-
-  /* This has to be aligned to a page boundary to do us any good.  This
-     alignment is overkill for ARM6 up but needed for ARM3.  Since all this
-     data will be thrown away I don't think the extra padding will hurt.
-       -- pb */
-  . = ALIGN(32768);		/* Init code and data */
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(32768);
-  __init_end = .;
-
-  __bss_start = .;		/* BSS */
-  .bss : {
-	*(.bss)
-	}
-  _end = . ;
-
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
-}
diff -u --recursive --new-file v2.1.109/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v2.1.109/linux/arch/i386/Makefile	Fri May  8 23:14:42 1998
+++ linux/arch/i386/Makefile	Mon Jul 20 10:05:15 1998
@@ -13,10 +13,6 @@
 # Copyright (C) 1994 by Linus Torvalds
 #
 
-AS86    =$(CROSS_COMPILE)as86 -0 -a
-AS386   =$(CROSS_COMPILE)as86 -3
-LD86    =$(CROSS_COMPILE)ld86 -0
-
 LD=$(CROSS_COMPILE)ld -m elf_i386
 CPP=$(CC) -E
 OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
@@ -41,10 +37,6 @@
 
 ifdef CONFIG_M686
 CFLAGS := $(CFLAGS) -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=686
-endif
-
-ifdef SMP
-CFLAGS := $(CFLAGS) -D__SMP__
 endif
 
 HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o
diff -u --recursive --new-file v2.1.109/linux/arch/i386/boot/Makefile linux/arch/i386/boot/Makefile
--- v2.1.109/linux/arch/i386/boot/Makefile	Wed Apr 23 19:01:14 1997
+++ linux/arch/i386/boot/Makefile	Mon Jul 20 10:05:15 1998
@@ -8,9 +8,8 @@
 # Copyright (C) 1994 by Linus Torvalds
 #
 
-ifdef SMP
-HOSTCFLAGS := $(HOSTCFLAGS) -D__SMP__
-endif
+AS86	=$(CROSS_COMPILE)as86 -0 -a
+LD86	=$(CROSS_COMPILE)ld86 -0
 
 BOOT_INCL =	$(TOPDIR)/include/linux/config.h \
 		$(TOPDIR)/include/linux/autoconf.h \
diff -u --recursive --new-file v2.1.109/linux/arch/i386/boot/compressed/Makefile linux/arch/i386/boot/compressed/Makefile
--- v2.1.109/linux/arch/i386/boot/compressed/Makefile	Sun Dec 21 17:27:17 1997
+++ linux/arch/i386/boot/compressed/Makefile	Mon Jul 20 10:05:15 1998
@@ -22,10 +22,6 @@
 ZLINKFLAGS = -Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS)
 BZLINKFLAGS = -Ttext $(BZIMAGE_OFFSET) $(ZLDFLAGS)
 
-ifdef SMP
-CFLAGS := $(CFLAGS) -D__SMP__
-endif
-
 all: vmlinux
 
 vmlinux: piggy.o $(OBJECTS)
@@ -34,18 +30,8 @@
 bvmlinux: piggy.o $(OBJECTS)
 	$(LD) $(BZLINKFLAGS) -o bvmlinux $(OBJECTS) piggy.o
 
-ifdef SMP
-
 head.o: head.S $(TOPDIR)/include/linux/tasks.h
-	$(CC) -D__SMP__ -traditional -c head.S
-
-else
-
-head.o: head.S $(TOPDIR)/include/linux/tasks.h
-	$(CC) -traditional -c head.S
-
-endif
-
+	$(CC) $(AFLAGS) -traditional -c head.S
 
 piggy.o:	$(SYSTEM)
 	tmppiggy=_tmp_$$$$piggy; \
diff -u --recursive --new-file v2.1.109/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.1.109/linux/arch/i386/defconfig	Thu Jul 16 18:09:23 1998
+++ linux/arch/i386/defconfig	Sat Jul 18 14:26:45 1998
@@ -269,7 +269,6 @@
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_NVRAM is not set
 # CONFIG_JOYSTICK is not set
-# CONFIG_MISC_RADIO is not set
 
 #
 # Ftape, the floppy tape device driver
diff -u --recursive --new-file v2.1.109/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
--- v2.1.109/linux/arch/i386/kernel/Makefile	Sat May  2 14:19:52 1998
+++ linux/arch/i386/kernel/Makefile	Mon Jul 20 10:05:15 1998
@@ -7,13 +7,8 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-ifdef SMP
 .S.o:
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
-else
-.S.o:
-	$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
-endif
 
 all: kernel.o head.o init_task.o
 
@@ -39,19 +34,11 @@
   endif
 endif
 
-
 ifdef SMP
-
 O_OBJS += io_apic.o smp.o trampoline.o
+endif
 
 head.o: head.S $(TOPDIR)/include/linux/tasks.h
-	$(CC) -D__ASSEMBLY__ -D__SMP__ -traditional -c $*.S -o $*.o
-
-else
-
-head.o: head.S $(TOPDIR)/include/linux/tasks.h
-	$(CC) -D__ASSEMBLY__ -traditional -c $*.S -o $*.o
-
-endif
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.109/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- v2.1.109/linux/arch/i386/kernel/bios32.c	Wed Jul  1 19:38:52 1998
+++ linux/arch/i386/kernel/bios32.c	Mon Jul 20 13:18:54 1998
@@ -1,7 +1,7 @@
 /*
  * bios32.c - Low-Level PCI Access
  *
- * $Id: bios32.c,v 1.37 1998/06/19 17:11:37 mj Exp $
+ * $Id: bios32.c,v 1.40 1998/07/16 21:16:03 mj Exp $
  *
  * Copyright 1993, 1994 Drew Eckhardt
  *      Visionary Computing
@@ -80,13 +80,13 @@
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/smp.h>
 #include <asm/spinlock.h>
 
 #include "irq.h"
 
 #undef DEBUG
+#define DEBUG
 
 #ifdef DEBUG
 #define DBG(x...) printk(x)
@@ -795,7 +795,7 @@
 				break;
 			}
 		}
-		if (!idx) {
+		if (e == dev) {
 			printk("PCI: Device %02x:%02x not found by BIOS\n",
 				dev->bus->number, dev->devfn);
 			d = dev;
@@ -870,6 +870,46 @@
 }
 
 /*
+ * Several buggy motherboards address only 16 devices and mirror
+ * them to next 16 IDs. We try to detect this `feature' on all
+ * primary busses (those containing host bridges as they are
+ * expected to be unique) and remove the ghost devices.
+ */
+
+__initfunc(void pcibios_fixup_ghosts(struct pci_bus *b))
+{
+	struct pci_dev *d, *e, **z;
+	int mirror = PCI_DEVFN(16,0);
+	int seen_host_bridge = 0;
+
+	DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
+	for(d=b->devices; d && d->devfn < mirror; d=d->sibling) {
+		if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+			seen_host_bridge++;
+		for(e=d->next; e; e=e->sibling)
+			if (e->devfn == d->devfn + mirror &&
+			    e->vendor == d->vendor &&
+			    e->device == d->device &&
+			    e->class == d->class &&
+			    !memcmp(e->base_address, d->base_address, sizeof(e->base_address)))
+				break;
+		if (!e)
+			return;
+	}
+	if (!seen_host_bridge)
+		return;
+	printk("PCI: Ignoring ghost devices on bus %d\n", b->number);
+	for(e=b->devices; e->sibling != d; e=e->sibling);
+	e->sibling = NULL;
+	for(z=&pci_devices; (d=*z);)
+		if (d->bus == b && d->devfn >= mirror) {
+			*z = d->next;
+			kfree_s(d, sizeof(*d));
+		} else
+			z = &d->next;
+}
+
+/*
  * In case there are peer host bridges, scan bus behind each of them.
  * Although several sources claim that the host bridges should have
  * header type 1 and be assigned a bus number as for PCI2PCI bridges,
@@ -928,18 +968,24 @@
 			} else if (a & PCI_BASE_ADDRESS_MEM_MASK)
 				has_mem = 1;
 		}
-		pci_read_config_word(dev, PCI_COMMAND, &cmd);
-		if (has_io && !(cmd & PCI_COMMAND_IO)) {
-			printk("PCI: Enabling I/O for device %02x:%02x\n",
-				dev->bus->number, dev->devfn);
-			cmd |= PCI_COMMAND_IO;
-			pci_write_config_word(dev, PCI_COMMAND, cmd);
-		}
-		if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
-			printk("PCI: Enabling memory for device %02x:%02x\n",
-				dev->bus->number, dev->devfn);
-			cmd |= PCI_COMMAND_MEMORY;
-			pci_write_config_word(dev, PCI_COMMAND, cmd);
+		/*
+		 * Don't enable VGA-compatible cards since they have
+		 * fixed I/O and memory space.
+		 */
+		if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
+			pci_read_config_word(dev, PCI_COMMAND, &cmd);
+			if (has_io && !(cmd & PCI_COMMAND_IO)) {
+				printk("PCI: Enabling I/O for device %02x:%02x\n",
+					dev->bus->number, dev->devfn);
+				cmd |= PCI_COMMAND_IO;
+				pci_write_config_word(dev, PCI_COMMAND, cmd);
+			}
+			if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
+				printk("PCI: Enabling memory for device %02x:%02x\n",
+					dev->bus->number, dev->devfn);
+				cmd |= PCI_COMMAND_MEMORY;
+				pci_write_config_word(dev, PCI_COMMAND, cmd);
+			}
 		}
 #ifdef __SMP__
 		/*
@@ -962,7 +1008,7 @@
 		}
 #endif
 		/*
-		 * Fix out-of-range IRQ numbers and report bogus IRQ.
+		 * Fix out-of-range IRQ numbers
 		 */
 		if (dev->irq >= NR_IRQS)
 			dev->irq = 0;
@@ -982,6 +1028,11 @@
 	if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
 		pcibios_sort();
 #endif
+}
+
+__initfunc(void pcibios_fixup_bus(struct pci_bus *b))
+{
+	pcibios_fixup_ghosts(b);
 }
 
 /*
diff -u --recursive --new-file v2.1.109/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.1.109/linux/arch/i386/kernel/entry.S	Thu Jul 16 18:09:23 1998
+++ linux/arch/i386/kernel/entry.S	Mon Jul 20 14:00:11 1998
@@ -75,6 +75,7 @@
 sigpending	=  8
 addr_limit	= 12
 exec_domain	= 16
+need_resched	= 20
 
 ENOSYS = 38
 
@@ -178,7 +179,7 @@
 	andl SYMBOL_NAME(bh_active),%eax
 	jne handle_bottom_half
 ret_with_reschedule:
-	cmpl $0,SYMBOL_NAME(need_resched)
+	cmpl $0,need_resched(%ebx)
 	jne reschedule
 	cmpl $0,sigpending(%ebx)
 	jne signal_return
diff -u --recursive --new-file v2.1.109/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.1.109/linux/arch/i386/kernel/io_apic.c	Wed Jun 24 22:54:03 1998
+++ linux/arch/i386/kernel/io_apic.c	Mon Jul 20 14:00:07 1998
@@ -32,7 +32,7 @@
  * volatile is justified in this case, it might change
  * spontaneously, GCC should not cache it
  */
-#define IO_APIC_BASE ((volatile int *)0xfec00000)
+#define IO_APIC_BASE ((volatile int *)fix_to_virt(FIX_IO_APIC_BASE))
 
 enum mp_irq_source_types {
     mp_INT = 0,
@@ -525,6 +525,22 @@
 	return 0;
 }
 
+__initfunc(static int assign_irq_vector(int irq))
+{
+	static int current_vector = IRQ0_TRAP_VECTOR, offset = 0;
+	if (IO_APIC_VECTOR(irq) > 0)
+		return IO_APIC_VECTOR(irq);
+	current_vector += 8;
+	if (current_vector > 0xFE) {
+		offset++;
+		current_vector = IRQ0_TRAP_VECTOR + offset;
+		printk("WARNING: ASSIGN_IRQ_VECTOR wrapped back to %02X\n",
+		       current_vector);
+	}
+	IO_APIC_VECTOR(irq) = current_vector;
+	return current_vector;
+}
+
 __initfunc(void setup_IO_APIC_irqs (void))
 {
 	struct IO_APIC_route_entry entry;
@@ -563,7 +579,7 @@
 		if (!IO_APIC_IRQ(irq))
 			continue;
 
-		entry.vector = IO_APIC_VECTOR(irq);
+		entry.vector = assign_irq_vector(irq);
 
 		bus = mp_irqs[idx].mpc_srcbus;
 
@@ -592,7 +608,7 @@
 	entry.mask = 0;					/* unmask IRQ now */
 	entry.dest.logical.logical_dest = 0xff;		/* all CPUs */
 
-	entry.vector = IO_APIC_VECTOR(irq);
+	entry.vector = assign_irq_vector(irq);
 
 	entry.polarity=0;
 	entry.trigger=0;
@@ -618,7 +634,7 @@
 	entry.mask = 0;					/* unmask IRQ now */
 	entry.dest.logical.logical_dest = 0x01;		/* all CPUs */
 
-	entry.vector = IO_APIC_VECTOR(pin);		/* it's ignored */
+	entry.vector = 0;				/* it's ignored */
 
 	entry.polarity=0;
 	entry.trigger=0;
@@ -1109,8 +1125,7 @@
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
 	for (i = 0; i < NR_IRQS ; i++) {
-		if ((IO_APIC_VECTOR(i) <= 0xfe)  /* HACK */ &&
-		    (IO_APIC_IRQ(i))) {
+		if (IO_APIC_IRQ(i)) {
 			if (IO_APIC_irq_trigger(i))
 				irq_desc[i].handler = &ioapic_level_irq_type;
 			else
@@ -1217,6 +1232,7 @@
 	 * mptable:
 	 */
 	setup_IO_APIC_irqs ();
+	init_IRQ_SMP();
 	check_timer();
  
 	print_IO_APIC();
diff -u --recursive --new-file v2.1.109/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.1.109/linux/arch/i386/kernel/irq.c	Wed Jun 24 22:54:03 1998
+++ linux/arch/i386/kernel/irq.c	Thu Jul 16 18:11:35 1998
@@ -61,7 +61,11 @@
  *
  * (0x0000ffff for NR_IRQS==16, 0x00ffffff for NR_IRQS=24)
  */
-unsigned int cached_irq_mask = (1<<NR_IRQS)-1;
+#if NR_IRQS == 64
+unsigned long long cached_irq_mask = -1;
+#else
+unsigned long long cached_irq_mask = (((unsigned long long) 1)<<NR_IRQS)-1;
+#endif
 
 #define cached_21	((cached_irq_mask | io_apic_irqs) & 0xff)
 #define cached_A1	(((cached_irq_mask | io_apic_irqs) >> 8) & 0xff)
@@ -84,7 +88,7 @@
  * To get IO-APIC interrupts we turn some of them into IO-APIC
  * interrupts during boot.
  */
-unsigned int io_apic_irqs = 0;
+unsigned long long io_apic_irqs = 0;
 
 static void do_8259A_IRQ (unsigned int irq, int cpu, struct pt_regs * regs);
 static void enable_8259A_irq (unsigned int irq);
@@ -113,9 +117,11 @@
 
 irq_desc_t irq_desc[NR_IRQS] = {
 	[0 ... 15] = { 0, 0, 0, &i8259A_irq_type, },	/* default to standard ISA IRQs */
-	[16 ... 23] = { 0, 0, 0, &no_irq_type, },	/* 'high' PCI IRQs filled in on demand */
+	[16 ... 63] = { 0, 0, 0, &no_irq_type, },	/* 'high' PCI IRQs filled in on demand */
 };
 
+int irq_vector[NR_IRQS] = { IRQ0_TRAP_VECTOR , 0 };
+
 
 /*
  * These have to be protected by the irq controller spinlock
@@ -207,6 +213,16 @@
  */
 BUILD_IRQ(23)
 
+BUILD_IRQ(24)
+BUILD_IRQ(25) BUILD_IRQ(26) BUILD_IRQ(27) BUILD_IRQ(28) BUILD_IRQ(29)
+BUILD_IRQ(30) BUILD_IRQ(31) BUILD_IRQ(32) BUILD_IRQ(33) BUILD_IRQ(34)
+BUILD_IRQ(35) BUILD_IRQ(36) BUILD_IRQ(37) BUILD_IRQ(38) BUILD_IRQ(39)
+BUILD_IRQ(40) BUILD_IRQ(41) BUILD_IRQ(42) BUILD_IRQ(43) BUILD_IRQ(44)
+BUILD_IRQ(45) BUILD_IRQ(46) BUILD_IRQ(47) BUILD_IRQ(48) BUILD_IRQ(49)
+BUILD_IRQ(50) BUILD_IRQ(51) BUILD_IRQ(52) BUILD_IRQ(53) BUILD_IRQ(54)
+BUILD_IRQ(55) BUILD_IRQ(56) BUILD_IRQ(57) BUILD_IRQ(58) BUILD_IRQ(59)
+BUILD_IRQ(60) BUILD_IRQ(61) BUILD_IRQ(62) BUILD_IRQ(63)
+
 /*
  * The following vectors are part of the Linux architecture, there
  * is no hardware IRQ pin equivalent for them, they are triggered
@@ -236,7 +252,19 @@
 	IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt
 #ifdef __SMP__
 	,IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt,
-	IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt
+	IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt,
+	IRQ24_interrupt, IRQ25_interrupt, IRQ26_interrupt, IRQ27_interrupt,
+	IRQ28_interrupt, IRQ29_interrupt,
+	IRQ30_interrupt, IRQ31_interrupt, IRQ32_interrupt, IRQ33_interrupt,
+	IRQ34_interrupt, IRQ35_interrupt, IRQ36_interrupt, IRQ37_interrupt,
+	IRQ38_interrupt, IRQ39_interrupt,
+	IRQ40_interrupt, IRQ41_interrupt, IRQ42_interrupt, IRQ43_interrupt,
+	IRQ44_interrupt, IRQ45_interrupt, IRQ46_interrupt, IRQ47_interrupt,
+	IRQ48_interrupt, IRQ49_interrupt,
+	IRQ50_interrupt, IRQ51_interrupt, IRQ52_interrupt, IRQ53_interrupt,
+	IRQ54_interrupt, IRQ55_interrupt, IRQ56_interrupt, IRQ57_interrupt,
+	IRQ58_interrupt, IRQ59_interrupt,
+	IRQ60_interrupt, IRQ61_interrupt, IRQ62_interrupt, IRQ63_interrupt
 #endif
 };
 
@@ -817,12 +845,6 @@
 	if (!shared) {
 #ifdef __SMP__
 		if (IO_APIC_IRQ(irq)) {
-			if (IO_APIC_VECTOR(irq) > 0xfe)
-				/*
-				 * break visibly for now, FIXME
-				 */
-				panic("ayiee, tell mingo");
-
 			/*
 			 * First disable it in the 8259A:
 			 */
@@ -991,9 +1013,11 @@
 
 #ifdef __SMP__	
 
-	for (i = 0; i < NR_IRQS ; i++)
-		if (IO_APIC_VECTOR(i) <= 0xfe)  /* hack -- mingo */
-			set_intr_gate(IO_APIC_VECTOR(i),interrupt[i]);
+	/*
+	  IRQ0 must be given a fixed assignment and initialized
+	  before init_IRQ_SMP.
+	*/
+	set_intr_gate(IRQ0_TRAP_VECTOR, interrupt[0]);
 
 	/*
 	 * The reschedule interrupt slowly changes it's functionality,
@@ -1029,3 +1053,14 @@
 	setup_x86_irq(13, &irq13);
 } 
 
+#ifdef __SMP__	
+
+__initfunc(void init_IRQ_SMP(void))
+{
+	int i;
+	for (i = 0; i < NR_IRQS ; i++)
+		if (IO_APIC_VECTOR(i) > 0)
+			set_intr_gate(IO_APIC_VECTOR(i), interrupt[i]);
+}
+
+#endif
diff -u --recursive --new-file v2.1.109/linux/arch/i386/kernel/irq.h linux/arch/i386/kernel/irq.h
--- v2.1.109/linux/arch/i386/kernel/irq.h	Sun Jun  7 11:16:27 1998
+++ linux/arch/i386/kernel/irq.h	Thu Jul 16 18:11:35 1998
@@ -39,8 +39,12 @@
 	unsigned int unused[3];
 } irq_desc_t;
 
+#define IRQ0_TRAP_VECTOR 0x51
+
 extern irq_desc_t irq_desc[NR_IRQS];
+extern int irq_vector[NR_IRQS];
 
+extern void init_IRQ_SMP(void);
 extern int handle_IRQ_event(unsigned int, struct pt_regs *);
 
 /*
@@ -68,10 +72,10 @@
 void init_pic_mode (void);
 void print_IO_APIC (void);
 
-extern unsigned int io_apic_irqs;
-extern unsigned int cached_irq_mask;
+extern unsigned long long io_apic_irqs;
+extern unsigned long long cached_irq_mask;
 
-#define IO_APIC_VECTOR(irq)	(0x51+((irq)<<3))
+#define IO_APIC_VECTOR(irq)	irq_vector[irq]
 
 #define MAX_IRQ_SOURCES 128
 #define MAX_MP_BUSSES 32
diff -u --recursive --new-file v2.1.109/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.1.109/linux/arch/i386/kernel/mtrr.c	Thu Jul 16 18:09:23 1998
+++ linux/arch/i386/kernel/mtrr.c	Mon Jul 20 17:22:35 1998
@@ -114,6 +114,9 @@
 	       Only manipulate interrupt enable flag on local CPU.
 	       Allow enclosed uncachable regions.
   v1.21
+    19980611   Richard Gooch <rgooch@atnf.csiro.au>
+	       Always define <main_lock>.
+  v1.22
 */
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -147,7 +150,7 @@
 #include <asm/atomic.h>
 #include <linux/smp.h>
 
-#define MTRR_VERSION            "1.21 (19980521)"
+#define MTRR_VERSION            "1.22 (19980611)"
 
 #define TRUE  1
 #define FALSE 0
@@ -199,9 +202,7 @@
 static unsigned int ascii_buf_bytes = 0;
 #endif
 static unsigned int *usage_table = NULL;
-#ifdef __SMP__
 static spinlock_t main_lock = SPIN_LOCK_UNLOCKED;
-#endif
 
 /*  Private functions  */
 #ifdef CONFIG_PROC_FS
diff -u --recursive --new-file v2.1.109/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.1.109/linux/arch/i386/kernel/process.c	Thu Jul 16 18:09:23 1998
+++ linux/arch/i386/kernel/process.c	Mon Jul 20 17:22:35 1998
@@ -77,7 +77,7 @@
 
 static void hard_idle(void)
 {
-	while (!need_resched) {
+	while (!current->need_resched) {
 		if (boot_cpu_data.hlt_works_ok && !hlt_counter) {
 #ifdef CONFIG_APM
 				/* If the APM BIOS is not enabled, or there
@@ -86,14 +86,14 @@
 				 need_resched again because an interrupt
 				 may have occurred in apm_do_idle(). */
 			start_bh_atomic();
-			if (!apm_do_idle() && !need_resched)
+			if (!apm_do_idle() && !current->need_resched)
 				__asm__("hlt");
 			end_bh_atomic();
 #else
 			__asm__("hlt");
 #endif
 	        }
- 		if (need_resched) 
+ 		if (current->need_resched) 
  			break;
 		schedule();
 	}
@@ -130,11 +130,11 @@
 		if (jiffies - start_idle > HARD_IDLE_TIMEOUT) 
 			hard_idle();
 		else  {
-			if (boot_cpu_data.hlt_works_ok && !hlt_counter && !need_resched)
+			if (boot_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched)
 		        	__asm__("hlt");
 		}
 		run_task_queue(&tq_scheduler);
-		if (need_resched) 
+		if (current->need_resched) 
 			start_idle = 0;
 		schedule();
 	}
@@ -156,7 +156,7 @@
 	while(1)
 	{
 		if(current_cpu_data.hlt_works_ok &&
-		 		!hlt_counter && !need_resched)
+		 		!hlt_counter && !current->need_resched)
 			__asm("hlt");
 		check_pgt_cache();
 		/*
@@ -410,6 +410,8 @@
 
 void show_regs(struct pt_regs * regs)
 {
+	long cr0 = 0L, cr2 = 0L, cr3 = 0L;
+
 	printk("\n");
 	printk("EIP: %04x:[<%08lx>]",0xffff & regs->xcs,regs->eip);
 	if (regs->xcs & 3)
@@ -421,6 +423,10 @@
 		regs->esi, regs->edi, regs->ebp);
 	printk(" DS: %04x ES: %04x\n",
 		0xffff & regs->xds,0xffff & regs->xes);
+	__asm__("movl %%cr0, %0": "=r" (cr0));
+	__asm__("movl %%cr2, %0": "=r" (cr2));
+	__asm__("movl %%cr3, %0": "=r" (cr3));
+	printk("CR0: %08lx CR2: %08lx CR3: %08lx\n", cr0, cr2, cr3);
 }
 
 /*
@@ -506,7 +512,7 @@
 	int i;
 
 	for (i=0 ; i<8 ; i++)
-		current->debugreg[i] = 0;
+		current->tss.debugreg[i] = 0;
 
 	/*
 	 * Forget coprocessor state..
@@ -655,7 +661,7 @@
 	dump->u_dsize -= dump->u_tsize;
 	dump->u_ssize = 0;
 	for (i = 0; i < 8; i++)
-		dump->u_debugreg[i] = current->debugreg[i];  
+		dump->u_debugreg[i] = current->tss.debugreg[i];  
 
 	if (dump->start_stack < TASK_SIZE)
 		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
@@ -687,7 +693,7 @@
 #define loaddebug(tsk,register) \
 		__asm__("movl %0,%%db" #register  \
 			: /* no output */ \
-			:"r" (tsk->debugreg[register]))
+			:"r" (tsk->tss.debugreg[register]))
 
 
 /*
@@ -755,7 +761,7 @@
 	/*
 	 * Now maybe reload the debug registers
 	 */
-	if (next->debugreg[7]){
+	if (next->tss.debugreg[7]){
 		loaddebug(next,0);
 		loaddebug(next,1);
 		loaddebug(next,2);
diff -u --recursive --new-file v2.1.109/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v2.1.109/linux/arch/i386/kernel/ptrace.c	Thu Jul 16 18:09:23 1998
+++ linux/arch/i386/kernel/ptrace.c	Mon Jul 20 16:59:59 1998
@@ -443,7 +443,7 @@
 			   addr <= (long) &dummy->u_debugreg[7]){
 				addr -= (long) &dummy->u_debugreg[0];
 				addr = addr >> 2;
-				tmp = child->debugreg[addr];
+				tmp = child->tss.debugreg[addr];
 			};
 			ret = put_user(tmp,(unsigned long *) data);
 			goto out;
@@ -489,7 +489,7 @@
 
 			  addr -= (long) &dummy->u_debugreg;
 			  addr = addr >> 2;
-			  child->debugreg[addr] = data;
+			  child->tss.debugreg[addr] = data;
 			  ret = 0;
 			  goto out;
 		  };
diff -u --recursive --new-file v2.1.109/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.1.109/linux/arch/i386/kernel/setup.c	Thu Jul 16 18:09:23 1998
+++ linux/arch/i386/kernel/setup.c	Sat Jul 18 13:43:05 1998
@@ -147,6 +147,13 @@
 			memory_end = memory_alt_end;
 	}
 #endif
+
+#define VMALLOC_RESERVE	(64 << 20)	/* 64MB for vmalloc */
+#define MAXMEM	((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
+
+	if (memory_end > MAXMEM)
+		memory_end = MAXMEM;
+
 	memory_end &= PAGE_MASK;
 #ifdef CONFIG_BLK_DEV_RAM
 	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
@@ -436,8 +443,9 @@
 	    NULL, "Pentium II (Deschutes)", NULL, NULL, NULL, NULL, NULL, NULL,
 	    NULL, NULL, NULL, NULL }},
 	{ X86_VENDOR_AMD,	4,
-	  { NULL, NULL, NULL, "DX/2", NULL, NULL, NULL, "DX/2-WB", "DX/4",
-	    "DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT", "Am5x86-WB" }},
+	  { NULL, NULL, NULL, "486 DX/2", NULL, NULL, NULL, "486 DX/2-WB",
+	    "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT",
+	    "Am5x86-WB" }},
 	{ X86_VENDOR_AMD,	5,
 	  { "K5/SSA5 (PR75, PR90, PR100)", "K5 (PR120, PR133)",
 	    "K5 (PR166)", "K5 (PR200)", NULL, NULL,
diff -u --recursive --new-file v2.1.109/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.1.109/linux/arch/i386/kernel/smp.c	Wed Jun 24 22:54:03 1998
+++ linux/arch/i386/kernel/smp.c	Mon Jul 20 23:34:41 1998
@@ -126,7 +126,7 @@
 volatile unsigned long kstack_ptr;			/* Stack vector for booting CPUs			*/
 struct cpuinfo_x86 cpu_data[NR_CPUS];			/* Per CPU bogomips and other parameters 		*/
 static unsigned int num_processors = 1;			/* Internal processor count				*/
-static unsigned long io_apic_addr = 0xFEC00000;		/* Address of the I/O apic (not yet used) 		*/
+unsigned long mp_ioapic_addr = 0xFEC00000;		/* Address of the I/O apic (not yet used) 		*/
 unsigned char boot_cpu_id = 0;				/* Processor that is doing the boot up 			*/
 static int smp_activated = 0;				/* Tripped once we need to start cross invalidating 	*/
 int apic_version[NR_CPUS];				/* APIC version number					*/
@@ -363,7 +363,7 @@
 					printk("I/O APIC #%d Version %d at 0x%lX.\n",
 						m->mpc_apicid,m->mpc_apicver,
 						m->mpc_apicaddr);
-					io_apic_addr = m->mpc_apicaddr;
+					mp_ioapic_addr = m->mpc_apicaddr;
 				}
 				mpt+=sizeof(*m);
 				count+=sizeof(*m);
@@ -649,6 +649,35 @@
 	udelay(100);
 }
 
+__initfunc(unsigned long init_smp_mappings(unsigned long memory_start))
+{
+	unsigned long apic_phys, ioapic_phys;
+
+	if (smp_found_config) {
+		apic_phys = mp_lapic_addr;
+		ioapic_phys = mp_ioapic_addr;
+	} else {
+		/*
+		 * set up a fake all zeroes page to simulate the
+		 * local APIC and another one for the IO-APIC. We
+		 * could use the real zero-page, but it's safer
+		 * this way if some buggy code writes to this page ...
+		 */
+		apic_phys = __pa(memory_start);
+		ioapic_phys = __pa(memory_start+PAGE_SIZE);
+		memset((void *)memory_start, 0, 2*PAGE_SIZE);
+		memory_start += 2*PAGE_SIZE;
+	}
+
+	set_fixmap(FIX_APIC_BASE,apic_phys);
+	set_fixmap(FIX_IO_APIC_BASE,ioapic_phys);
+
+	printk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
+	printk("mapped IOAPIC to %08lx (%08lx)\n", fix_to_virt(FIX_IO_APIC_BASE), ioapic_phys);
+
+	return memory_start;
+}
+
 __initfunc(void smp_callin(void))
 {
 	extern void calibrate_delay(void);
@@ -684,7 +713,7 @@
 	set_bit(cpuid, (unsigned long *)&cpu_callin_map[0]);
 }
 
-static int cpucount = 0;
+int cpucount = 0;
 
 extern int cpu_idle(void * unused);
 
@@ -1125,10 +1154,6 @@
 	setup_IO_APIC();
 
 smp_done:
-#ifdef CONFIG_MTRR
-	/*  Must be done after other processors booted  */
-	mtrr_init ();
-#endif
 }
 
 
@@ -1174,6 +1199,18 @@
  * enabled in a civilised fashion. That will also boost performance.
  */
 
+unsigned int TIME64 (void)
+{
+        unsigned int dummy,low;
+
+        __asm__("rdtsc"
+                :"=a" (low),
+                 "=d" (dummy));
+        return low;
+}
+
+int ipi_timestamp;
+
 void smp_message_pass(int target, int msg, unsigned long data, int wait)
 {
 	unsigned long cfg;
@@ -1277,7 +1314,11 @@
 		cpu_callin_map[0]=0;
 	}
 	else
-		panic("huh?");
+	{
+		dest=0;
+		target_map=(1<<target);
+		cpu_callin_map[0]=0;
+	}
 
 	/*
 	 * Program the APIC to deliver the IPI
@@ -1376,6 +1417,17 @@
 /*	printk("SMID\n");*/
 }
 
+
+void smp_send_reschedule(int cpu)
+{
+	unsigned long flags;
+
+	__save_flags(flags);
+	__cli();
+	smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 2);
+	__restore_flags(flags);
+}
+
 /*
  * Local timer interrupt handler. It does both profiling and
  * process statistics/rescheduling.
@@ -1422,7 +1474,7 @@
 			p->counter -= 1;
 			if (p->counter < 0) {
 				p->counter = 0;
-				need_resched = 1;
+				p->need_resched = 1;
 			}
 			if (p->priority < DEF_PRIORITY) {
 				kstat.cpu_nice += user;
@@ -1476,21 +1528,11 @@
 }
 
 /*
- * Reschedule call back (not used currently)
+ * Reschedule call back
  */
-
 asmlinkage void smp_reschedule_interrupt(void)
 {
-	int cpu = smp_processor_id();
-
 	ack_APIC_irq();
-	/*
-	 * This looks silly, but we actually do need to wait
-	 * for the global interrupt lock.
-	 */
-	irq_enter(cpu, 0);
-	need_resched = 1;
-	irq_exit(cpu, 0);
 }
 
 /*
diff -u --recursive --new-file v2.1.109/linux/arch/i386/lib/Makefile linux/arch/i386/lib/Makefile
--- v2.1.109/linux/arch/i386/lib/Makefile	Sat Jan 10 14:51:20 1998
+++ linux/arch/i386/lib/Makefile	Mon Jul 20 10:05:15 1998
@@ -2,13 +2,8 @@
 # Makefile for i386-specific library files..
 #
 
-ifdef SMP
 .S.o:
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
-else
-.S.o:
-	$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
-endif
 
 L_TARGET = lib.a
 L_OBJS  = checksum.o semaphore.o locks.o delay.o usercopy.o getuser.o putuser.o
diff -u --recursive --new-file v2.1.109/linux/arch/i386/math-emu/fpu_entry.c linux/arch/i386/math-emu/fpu_entry.c
--- v2.1.109/linux/arch/i386/math-emu/fpu_entry.c	Tue Jun 23 10:01:20 1998
+++ linux/arch/i386/math-emu/fpu_entry.c	Mon Jul 20 14:00:11 1998
@@ -558,7 +558,7 @@
   RE_ENTRANT_CHECK_ON;
 #endif DEBUG
 
-  if (FPU_lookahead && !need_resched)
+  if (FPU_lookahead && !current->need_resched)
     {
       FPU_ORIG_EIP = FPU_EIP - code_base;
       if ( valid_prefix(&byte1, (u_char **)&FPU_EIP,
diff -u --recursive --new-file v2.1.109/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.1.109/linux/arch/i386/mm/init.c	Thu Jul 16 18:09:23 1998
+++ linux/arch/i386/mm/init.c	Mon Jul 20 14:00:07 1998
@@ -27,8 +27,10 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/dma.h>
+#include <asm/fixmap.h>
 
 extern void show_net_buffers(void);
+extern unsigned long init_smp_mappings(unsigned long);
 
 void __bad_pte_kernel(pmd_t *pmd)
 {
@@ -191,6 +193,50 @@
 }
 
 /*
+ * allocate page table(s) for compile-time fixed mappings
+ */
+static unsigned long fixmap_init (unsigned long start_mem)
+{
+	pgd_t * pg_dir;
+	unsigned int idx;
+	unsigned long address;
+
+	start_mem &= PAGE_MASK;
+
+	for (idx=1; idx < __end_of_fixed_addresses; idx += PTRS_PER_PTE)
+	{
+		address = fix_to_virt(__end_of_fixed_addresses-idx);
+		pg_dir = swapper_pg_dir + (address >> PGDIR_SHIFT);
+		memset((void *)start_mem, 0, PAGE_SIZE);
+		pgd_val(*pg_dir) = _PAGE_TABLE | __pa(start_mem);
+		start_mem += PAGE_SIZE;
+	}
+
+	return start_mem;
+}
+
+static void set_pte_phys (unsigned long vaddr, unsigned long phys)
+{
+	pgprot_t prot;
+	pte_t * pte;
+
+	pte = pte_offset(pmd_offset(pgd_offset_k(vaddr), vaddr), vaddr);
+	prot = PAGE_KERNEL;
+	if (boot_cpu_data.x86_capability & X86_FEATURE_PGE)
+		pgprot_val(prot) |= _PAGE_GLOBAL;
+	set_pte(pte, mk_pte_phys(phys, prot));
+
+	local_flush_tlb();
+}
+
+void set_fixmap (enum fixed_addresses idx, unsigned long phys)
+{
+	unsigned long address = fix_to_virt(idx);
+
+	set_pte_phys (address,phys);
+}
+
+/*
  * paging_init() sets up the page tables - note that the first 4MB are
  * already mapped by head.S.
  *
@@ -293,59 +339,9 @@
 			address += PAGE_SIZE;
 		}
 	}
+	start_mem = fixmap_init(start_mem);
 #ifdef __SMP__
-{
-	extern unsigned long mp_lapic_addr;
-	pte_t pte;
-	unsigned long apic_area = (unsigned long)APIC_BASE;
-
-	pg_dir = swapper_pg_dir + ((apic_area) >> PGDIR_SHIFT);
-	memset((void *)start_mem, 0, PAGE_SIZE);
-	pgd_val(*pg_dir) = _PAGE_TABLE | __pa(start_mem);
-	start_mem += PAGE_SIZE;
-
-	if (smp_found_config) {
-		/*
-		 * Map the local APIC to FEE00000. (it's only the default
-		 * value, thanks to Steve Hsieh for finding this out. We
-		 * now save the real local-APIC physical address in smp_scan(),
-		 * and use it here)
-		 */
-		pg_table = pte_offset((pmd_t *)pg_dir, apic_area);
-		pte = mk_pte_phys(mp_lapic_addr, PAGE_KERNEL);
-		set_pte(pg_table, pte);
-
-		/*
-		 * Map the IO-APIC to FEC00000.
-		 */
-		apic_area = 0xFEC00000; /*(unsigned long)IO_APIC_BASE;*/
-		pg_table = pte_offset((pmd_t *)pg_dir, apic_area);
-		pte = mk_pte_phys(apic_area, PAGE_KERNEL);
-		set_pte(pg_table, pte);
-	} else {
-		/*
-		 * No local APIC but we are compiled SMP ... set up a
-		 * fake all zeroes page to simulate the local APIC.
-		 */
-		pg_table = pte_offset((pmd_t *)pg_dir, apic_area);
-		pte = mk_pte(start_mem, PAGE_KERNEL);
-		memset((void *)start_mem, 0, PAGE_SIZE);
-		start_mem += PAGE_SIZE;
-		set_pte(pg_table, pte);
-
-		/*
-		 * Do the same for the IO-APIC
-		 */
-		apic_area = 0xFEC00000;
-		pg_table = pte_offset((pmd_t *)pg_dir, apic_area);
-		pte = mk_pte(start_mem, PAGE_KERNEL);
-		memset((void *)start_mem, 0, PAGE_SIZE);
-		start_mem += PAGE_SIZE;
-		set_pte(pg_table, pte);		
-	}
-
-	local_flush_tlb();
-}
+	start_mem = init_smp_mappings(start_mem);
 #endif
 	local_flush_tlb();
 
diff -u --recursive --new-file v2.1.109/linux/arch/m68k/kernel/bios32.c linux/arch/m68k/kernel/bios32.c
--- v2.1.109/linux/arch/m68k/kernel/bios32.c	Tue Jun 23 10:01:20 1998
+++ linux/arch/m68k/kernel/bios32.c	Sat Jul 18 14:02:10 1998
@@ -587,6 +587,10 @@
 	hades_fixup();
 }
 
+__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+{
+}
+
 __initfunc(char *pcibios_setup(char *str))
 {
 	return str;
diff -u --recursive --new-file v2.1.109/linux/arch/mips/kernel/pci.c linux/arch/mips/kernel/pci.c
--- v2.1.109/linux/arch/mips/kernel/pci.c	Fri May  8 23:14:43 1998
+++ linux/arch/mips/kernel/pci.c	Sat Jul 18 14:02:10 1998
@@ -129,4 +129,13 @@
 	return pci_ops->pcibios_write_config_dword(bus, dev_fn, where, val);
 }
 
+__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+{
+}
+
+__initfunc(char *pcibios_setup(char *str))
+{
+	return str;
+}
+
 #endif /* defined(CONFIG_PCI) */
diff -u --recursive --new-file v2.1.109/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v2.1.109/linux/arch/ppc/kernel/pci.c	Fri May  8 23:14:45 1998
+++ linux/arch/ppc/kernel/pci.c	Sat Jul 18 14:02:10 1998
@@ -245,6 +245,10 @@
 	}
 }
 
+__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+{
+}
+
 __initfunc(char *pcibios_setup(char *str))
 {
 	return str;
diff -u --recursive --new-file v2.1.109/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile
--- v2.1.109/linux/arch/sparc/kernel/Makefile	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/kernel/Makefile	Mon Jul 20 10:05:15 1998
@@ -7,24 +7,12 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-ifdef SMP
-
 .S.s:
 	$(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s
 
 .S.o:
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o
 
-else
-
-.S.s:
-	$(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s
-
-.S.o:
-	$(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
-
-endif
-
 all: kernel.o head.o init_task.o
 
 O_TARGET := kernel.o
@@ -46,17 +34,8 @@
 O_OBJS += auxio.o
 endif
 
-ifdef SMP
-
 head.o: head.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $*.S -o $*.o
-
-else
-
-head.o: head.S
-	$(CC) -D__ASSEMBLY__ -ansi -c $*.S -o $*.o
-
-endif
 
 check_asm: dummy
 	@echo "/* Automatically generated. Do not edit. */" > asm_offsets.h
diff -u --recursive --new-file v2.1.109/linux/arch/sparc/lib/Makefile linux/arch/sparc/lib/Makefile
--- v2.1.109/linux/arch/sparc/lib/Makefile	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/lib/Makefile	Mon Jul 20 10:05:15 1998
@@ -45,8 +45,6 @@
 memset.o: memset.S
 	$(CC) -D__ASSEMBLY__ -ansi -c -o memset.o memset.S
 
-ifdef SMP
-
 locks.o: locks.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o locks.o locks.S
 
@@ -56,20 +54,9 @@
 bitops.o: bitops.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o bitops.o bitops.S
 
+ifdef SMP
 irqlock.o: irqlock.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o irqlock.o irqlock.S
-
-else
-
-locks.o: locks.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o locks.o locks.S
-
-atomic.o: atomic.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o atomic.o atomic.S
-
-bitops.o: bitops.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o bitops.o bitops.S
-
 endif
 
 strlen.o: strlen.S
diff -u --recursive --new-file v2.1.109/linux/arch/sparc/mm/Makefile linux/arch/sparc/mm/Makefile
--- v2.1.109/linux/arch/sparc/mm/Makefile	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/mm/Makefile	Mon Jul 20 10:05:15 1998
@@ -22,8 +22,6 @@
 
 include $(TOPDIR)/Rules.make
 
-ifdef SMP
-
 hypersparc.o: hypersparc.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o hypersparc.o hypersparc.S
 
@@ -35,19 +33,3 @@
 
 tsunami.o: tsunami.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o tsunami.o tsunami.S
-
-else
-
-hypersparc.o: hypersparc.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o hypersparc.o hypersparc.S
-
-turbosparc.o: turbosparc.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o turbosparc.o turbosparc.S
-
-viking.o: viking.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o viking.o viking.S
-
-tsunami.o: tsunami.S
-	$(CC) -D__ASSEMBLY__ -ansi -c -o tsunami.o tsunami.S
-
-endif
diff -u --recursive --new-file v2.1.109/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile
--- v2.1.109/linux/arch/sparc64/kernel/Makefile	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc64/kernel/Makefile	Mon Jul 20 10:05:15 1998
@@ -7,23 +7,11 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-ifdef SMP
-
 .S.s:
 	$(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s
 
 .S.o:
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o
-
-else
-
-.S.s:
-	$(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s
-
-.S.o:
-	$(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
-
-endif
 
 all: kernel.o head.o init_task.o
 
diff -u --recursive --new-file v2.1.109/linux/arch/sparc64/kernel/psycho.c linux/arch/sparc64/kernel/psycho.c
--- v2.1.109/linux/arch/sparc64/kernel/psycho.c	Fri May  8 23:14:46 1998
+++ linux/arch/sparc64/kernel/psycho.c	Sat Jul 18 14:02:10 1998
@@ -2381,6 +2381,10 @@
 	return err;
 }
 
+__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+{
+}
+
 __initfunc(char *pcibios_setup(char *str))
 {
 	return str;
diff -u --recursive --new-file v2.1.109/linux/arch/sparc64/mm/Makefile linux/arch/sparc64/mm/Makefile
--- v2.1.109/linux/arch/sparc64/mm/Makefile	Thu Jul 31 13:09:17 1997
+++ linux/arch/sparc64/mm/Makefile	Mon Jul 20 10:05:16 1998
@@ -7,23 +7,11 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
-ifdef SMP
-
 .S.s:
 	$(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s
 
 .S.o:
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o
-
-else
-
-.S.s:
-	$(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s
-
-.S.o:
-	$(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
-
-endif
 
 O_TARGET := mm.o
 O_OBJS   := ultra.o fault.o init.o generic.o asyncd.o extable.o modutil.o
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/block/mfmhd.c linux/drivers/acorn/block/mfmhd.c
--- v2.1.109/linux/drivers/acorn/block/mfmhd.c	Sun Jun  7 11:16:28 1998
+++ linux/drivers/acorn/block/mfmhd.c	Sat Jul 18 11:55:23 1998
@@ -87,6 +87,8 @@
  * 17/1/97:RMK:	Upgraded to 2.1 kernels.
  *
  *  4/3/98:RMK:	Changed major number to 21.
+ *
+ * 27/6/98:RMK:	Changed asm/delay.h to linux/delay.h for mdelay().
  */
 
 /*
@@ -109,15 +111,15 @@
 #include <linux/genhd.h>
 #include <linux/major.h>
 #include <linux/ioport.h>
+#include <linux/delay.h>
 
 #define MAJOR_NR	MFM_ACORN_MAJOR
 #include <linux/blk.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/irq-no.h>
+#include <asm/irq.h>
 #include <asm/uaccess.h>
-#include <asm/delay.h>
 #include <asm/dma.h>
 #include <asm/hardware.h>
 #include <asm/ecard.h>
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/char/serial-card.c linux/drivers/acorn/char/serial-card.c
--- v2.1.109/linux/drivers/acorn/char/serial-card.c	Fri May  8 23:14:46 1998
+++ linux/drivers/acorn/char/serial-card.c	Sat Jul 18 11:55:24 1998
@@ -52,6 +52,7 @@
     req.baud_base = MY_BAUD_BASE;
     req.irq = irq;
     req.port = port;
+    req.flags = 0;
 
     return register_serial(&req);
 }
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/char/serial-dualsp.c linux/drivers/acorn/char/serial-dualsp.c
--- v2.1.109/linux/drivers/acorn/char/serial-dualsp.c	Fri May  8 23:14:46 1998
+++ linux/drivers/acorn/char/serial-dualsp.c	Sat Jul 18 11:55:24 1998
@@ -15,4 +15,3 @@
 #define MY_PORT_ADDRESS(port,cardaddress) \
 	((cardaddress) + (port) * 8)
 #include "serial-card.c"
-
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c
--- v2.1.109/linux/drivers/acorn/net/ether3.c	Fri May  8 23:14:46 1998
+++ linux/drivers/acorn/net/ether3.c	Sat Jul 18 11:55:24 1998
@@ -27,13 +27,18 @@
  * 1.10	RMK	15/07/1997	Fixed autoprobing of NQ8004.
  * 1.11	RMK	16/11/1997	Fixed autoprobing of NQ8005A.
  * 1.12	RMK	31/12/1997	Removed reference to dev_tint for Linux 2.1.
- *
+ *      RMK	27/06/1998	Changed asm/delay.h to linux/delay.h.
+ * 1.13	RMK	29/06/1998	Fixed problem with transmission of packets.
+ *				Chip seems to have a bug in, whereby if the
+ *				packet starts two bytes from the end of the
+ *				buffer, it corrupts the receiver chain, and
+ *				never updates the transmit status correctly.
  * TODO:
  *  When we detect a fatal error on the interface, we should restart it.
  *  Reap transmit packets after some time even if the buffer never filled.
  */
 
-static char *version = "ether3 ethernet driver (c) 1995-1998 R.M.King v1.12\n";
+static char *version = "ether3 ethernet driver (c) 1995-1998 R.M.King v1.13\n";
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -51,20 +56,16 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/ecard.h>
-#include <asm/delay.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
 #include "ether3.h"
 
-#ifndef MODULE
-#define CLAIM_IRQ_AT_OPEN
-#endif
-
 static unsigned int net_debug = NET_DEBUG;
 static const card_ids ether3_cids[] = {
 	{ MANU_ANT2, PROD_ANT_ETHER3 },
@@ -135,7 +136,7 @@
 #define ether3_writelong(dev,data)	{			\
 	unsigned long reg_bufwin = REG_BUFWIN;			\
 	outw((data), reg_bufwin);				\
-	outw((data) >> 16, reg_bufwin);			\
+	outw((data) >> 16, reg_bufwin);				\
 }
 
 /*
@@ -263,6 +264,7 @@
 	priv->regs.config1 = CFG1_RECVCOMPSTAT0|CFG1_DMABURST8;
 	priv->regs.config2 = CFG2_CTRLO|CFG2_RECVCRC|CFG2_ERRENCRC;
 	priv->regs.command = 0;
+
 	/*
 	 * Set up our hardware address
 	 */
@@ -311,6 +313,10 @@
 
 	memset(&priv->stats, 0, sizeof(struct enet_statistics));
 
+	/* Reset the chip */
+	outw(CFG2_RESET, REG_CONFIG2);
+	udelay(4);
+
 	priv->regs.command = 0;
 	outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND);
 	while (inw(REG_STATUS) & (STAT_RXON|STAT_TXON));
@@ -425,12 +431,8 @@
 
 		/* Fill in the fields of the device structure with ethernet values. */
 		ether_setup(dev);
-#ifndef CLAIM_IRQ_AT_OPEN
-		if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev))
-			error = EAGAIN;
-		else
-#endif
-			return 0;
+
+		return 0;
 	}
 
 failed:
@@ -475,20 +477,19 @@
 static int
 ether3_open(struct device *dev)
 {
-	ether3_init_for_open(dev);
-
 	MOD_INC_USE_COUNT;
 
-#ifdef CLAIM_IRQ_AT_OPEN
 	if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev)) {
 	    	MOD_DEC_USE_COUNT;
 		return -EAGAIN;
 	}
-#endif
 
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
+
+	ether3_init_for_open(dev);
+
 	return 0;
 }
 
@@ -511,10 +512,7 @@
 	outb(0x80, REG_CONFIG2 + 1);
 	outw(0, REG_COMMAND);
 
-	enable_irq(dev->irq);
-#ifdef CLAIM_IRQ_AT_OPEN
 	free_irq(dev->irq, dev);
-#endif
 
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -545,8 +543,7 @@
 	if (dev->flags & IFF_PROMISC) {
 		/* promiscuous mode */
 		priv->regs.config1 |= CFG1_RECVPROMISC;
-	} else
-	if (dev->flags & IFF_ALLMULTI) {
+	} else if (dev->flags & IFF_ALLMULTI) {
 		priv->regs.config1 |= CFG1_RECVSPECBRMULTI;
 	} else
 		priv->regs.config1 |= CFG1_RECVSPECBROAD;
@@ -571,7 +568,7 @@
 			unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 			unsigned int ptr, nextptr;
 
-			length = (length + 1) & ~1;
+			length = (length + 3) & ~3;
 
 			if (priv->broken) {
 				dev_kfree_skb(skb);
@@ -589,32 +586,42 @@
 			priv->tx_head = nextptr;
 
 			save_flags_cli(flags);
+
+#define TXHDR_FLAGS (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE|TXHDR_DATAFOLLOWS|TXHDR_ENSUCCESS)
+
 			ether3_setbuffer(dev, buffer_write, nextptr);
 			ether3_writelong(dev, 0);
+
 			ether3_setbuffer(dev, buffer_write, ptr + 4);
 			ether3_writebuffer(dev, skb->data, length);
 			ether3_writeword(dev, htons(nextptr));
 			ether3_writeword(dev, (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE) >> 16);
+
 			ether3_setbuffer(dev, buffer_write, ptr);
-#define TXHDR_FLAGS (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE|TXHDR_DATAFOLLOWS|TXHDR_ENSUCCESS)
 			ether3_writeword(dev, htons(ptr + length + 4));
-			ether3_writeword(dev, (TXHDR_FLAGS >> 16));
+			ether3_writeword(dev, TXHDR_FLAGS >> 16);
 			ether3_ledon(dev, priv);
+
 			priv->tx_used ++;
-			if (priv->tx_used < MAX_TX_BUFFERED)
-				dev->tbusy = 0;
 			if (priv->tx_used >= (MAX_TX_BUFFERED * 3 / 4)) {
 				priv->regs.command |= CMD_ENINTTX;
 				outw(priv->regs.command, REG_COMMAND);
 			}
-			restore_flags(flags);
 
-			dev->trans_start = jiffies;
-			dev_kfree_skb(skb);
 			if (!(inw(REG_STATUS) & STAT_TXON)) {
 				outw(ptr, REG_TRANSMITPTR);
 				outw(priv->regs.command | CMD_TXON, REG_COMMAND);
 			}
+
+			if (priv->tx_used < MAX_TX_BUFFERED)
+				dev->tbusy = 0;
+
+			dev->trans_start = jiffies;
+
+			restore_flags(flags);
+
+			dev_kfree_skb(skb);
+
 			return 0;
 		} else {
 			printk("%s: transmitter access conflict.\n", dev->name);
@@ -625,12 +632,27 @@
 		 * There should really be a "kick me" function call instead.
 		 */
 		int tickssofar = jiffies - dev->trans_start;
+		unsigned long flags;
+
 		if (tickssofar < 5)
 			return 1;
 		del_timer(&priv->timer);
-		printk("%s: transmit timed out, network cable problem?\n", dev->name);
+
+		save_flags_cli(flags);
+		printk(KERN_ERR "%s: transmit timed out, network cable problem?\n", dev->name);
+		printk(KERN_ERR "%s: state: { status=%04X cfg1=%04X cfg2=%04X }\n", dev->name,
+			inw(REG_STATUS), inw(REG_CONFIG1), inw(REG_CONFIG2));
+		printk(KERN_ERR "%s: { rpr=%04X rea=%04X tpr=%04X }\n", dev->name,
+			inw(REG_RECVPTR), inw(REG_RECVEND), inw(REG_TRANSMITPTR));
+		printk(KERN_ERR "%s: tx head=%04X tx tail=%04X\n", dev->name,
+			priv->tx_head, priv->tx_tail);
+		ether3_setbuffer(dev, buffer_read, priv->tx_tail);
+		printk(KERN_ERR "%s: packet status = %08X\n", dev->name, ether3_readlong(dev));
+		restore_flags(flags);
+
 		dev->tbusy = 0;
 		priv->regs.config2 |= CFG2_CTRLO;
+		priv->stats.tx_errors += 1;
 		outw(priv->regs.config2 , REG_CONFIG2);
 		dev->trans_start = jiffies;
 		goto retry;
@@ -709,7 +731,8 @@
 			ether3_setbuffer(dev, buffer_read, next_ptr);
 			temp_ptr = ether3_readword(dev);
 			status = ether3_readword(dev);
-			if (!(status & RXSTAT_DONE) || !temp_ptr)
+			if ((status & (RXSTAT_DONE | RXHDR_CHAINCONTINUE | RXHDR_RECEIVE)) !=
+				(RXSTAT_DONE | RXHDR_CHAINCONTINUE) || !temp_ptr)
 				break;
 
 			this_ptr = next_ptr + 4;
@@ -754,7 +777,7 @@
 		} else {
 			struct enet_statistics *stats = &priv->stats;
 			outw(next_ptr >> 8, REG_RECVEND);
-			if (status & RXSTAT_OVERSIZE)	  stats->rx_length_errors ++;
+			if (status & RXSTAT_OVERSIZE)	  stats->rx_over_errors ++;
 			if (status & RXSTAT_CRCERROR)	  stats->rx_crc_errors ++;
 			if (status & RXSTAT_DRIBBLEERROR) stats->rx_fifo_errors ++;
 			if (status & RXSTAT_SHORTPACKET)  stats->rx_length_errors ++;
@@ -804,6 +827,7 @@
 
 	do {
 	    	unsigned long status;
+
     		/*
 	    	 * Read the packet header
     		 */
@@ -813,7 +837,8 @@
 		/*
 		 * Check to see if this packet has been transmitted
 		 */
-		if (!(status & TXSTAT_DONE) || !(status & TXHDR_TRANSMIT))
+		if ((status & (TXSTAT_DONE | TXHDR_TRANSMIT)) !=
+		    (TXSTAT_DONE | TXHDR_TRANSMIT))
 			break;
 
 		/*
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/net/etherh.c linux/drivers/acorn/net/etherh.c
--- v2.1.109/linux/drivers/acorn/net/etherh.c	Sun Jun  7 11:16:28 1998
+++ linux/drivers/acorn/net/etherh.c	Sat Jul 18 11:55:24 1998
@@ -36,11 +36,11 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/ecard.h>
-#include <asm/delay.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
@@ -525,8 +525,8 @@
 static struct device *my_ethers[MAX_ETHERH_CARDS];
 static struct expansion_card *ec[MAX_ETHERH_CARDS];
 
-int
-init_module(void)
+static int
+init_all_cards(void)
 {
 	struct device *dev = NULL;
 	struct expansion_card *boguscards[MAX_ETHERH_CARDS];
@@ -550,6 +550,7 @@
 		if (!io[i]) {
 			if ((ec[i] = ecard_find (0, etherh_cids)) == NULL)
 				continue;
+
 			if (!dev)
 				return -ENOMEM;
 
@@ -567,7 +568,7 @@
 
 		my_ethers[i] = dev;
 
-		if (register_netdev (my_ethers[i]) != 0) {
+		if (register_netdev(dev) != 0) {
 			printk (KERN_WARNING "No etherh card found at %08lX\n", dev->base_addr);
 			if (ec[i]) {
 				boguscards[i] = ec[i];
@@ -578,16 +579,36 @@
 		found ++;
 		dev = NULL;
 	}
+
 	if (dev)
 		kfree (dev);
+
 	for (i = 0; i < MAX_ETHERH_CARDS; i++)
 		if (boguscards[i]) {
 			boguscards[i]->ops = NULL;
 			ecard_release (boguscards[i]);
 		}
-	if (!found)
-		return -ENODEV;
-	return 0;
+
+	return found ? 0 : -ENODEV;
+}
+
+int
+init_module(void)
+{
+	int ret;
+
+	if (load_8390_module(__FILE__))
+		return -ENOSYS;
+
+	lock_8390_module();
+
+	ret = init_all_cards();
+
+	if (ret) {
+		unlock_8390_module();
+	}
+
+	return ret;
 }
 
 void
@@ -607,5 +628,6 @@
 			ec[i] = NULL;
 		}
 	}
+	unlock_8390_module();
 }
 #endif /* MODULE */
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/acornscsi.c linux/drivers/acorn/scsi/acornscsi.c
--- v2.1.109/linux/drivers/acorn/scsi/acornscsi.c	Fri May  8 23:14:46 1998
+++ linux/drivers/acorn/scsi/acornscsi.c	Sat Jul 18 11:55:24 1998
@@ -20,6 +20,7 @@
  *			reconnect race condition causing a warning message.
  *  12-Oct-1997	RMK	Added catch for re-entering interrupt routine.
  *  15-Oct-1997	RMK	Improved handling of commands.
+ *  27-Jun-1998	RMK	Changed asm/delay.h to linux/delay.h.
  */
 #define DEBUG_NO_WRITE	1
 #define DEBUG_QUEUES	2
@@ -136,8 +137,9 @@
 #include <linux/stat.h>
 #include <linux/ioport.h>
 #include <linux/blk.h>
+#include <linux/delay.h>
+
 #include <asm/bitops.h>
-#include <asm/delay.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/ecard.h>
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/cumana_1.c linux/drivers/acorn/scsi/cumana_1.c
--- v2.1.109/linux/drivers/acorn/scsi/cumana_1.c	Fri May  8 23:14:46 1998
+++ linux/drivers/acorn/scsi/cumana_1.c	Sat Jul 18 11:55:24 1998
@@ -128,7 +128,7 @@
         outb(0x00, instance->io_port - 577);
 
 	if (instance->irq != IRQ_NONE)
-	    if (request_irq(instance->irq, cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
+	    if (request_irq(instance->irq, do_cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
 		printk("scsi%d: IRQ%d not free, interrupts disabled\n",
 		    instance->host_no, instance->irq);
 		instance->irq = IRQ_NONE;
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/cumana_1.h linux/drivers/acorn/scsi/cumana_1.h
--- v2.1.109/linux/drivers/acorn/scsi/cumana_1.h	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/scsi/cumana_1.h	Sat Jul 18 11:55:24 1998
@@ -90,7 +90,7 @@
 #define NCR5380_read(reg) cumanascsi_read(_instance, reg)
 #define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
 
-#define NCR5380_intr cumanascsi_intr
+#define do_NCR5380_intr do_cumanascsi_intr
 #define NCR5380_queue_command cumanascsi_queue_command
 #define NCR5380_abort cumanascsi_abort
 #define NCR5380_reset cumanascsi_reset
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/cumana_2.c linux/drivers/acorn/scsi/cumana_2.c
--- v2.1.109/linux/drivers/acorn/scsi/cumana_2.c	Fri May  8 23:14:46 1998
+++ linux/drivers/acorn/scsi/cumana_2.c	Sat Jul 18 11:55:24 1998
@@ -8,6 +8,7 @@
  *  22-01-1998	RMK	0.0.1	Updated to 2.1.80
  *  15-04-1998	RMK	0.0.1	Only do PIO if FAS216 will allow it.
  *  02-05-1998	RMK	0.0.2	Updated & added DMA support
+ *  27-06-1998	RMK		Changed asm/delay.h to linux/delay.h
  */
 
 #include <linux/module.h>
@@ -19,8 +20,8 @@
 #include <linux/proc_fs.h>
 #include <linux/unistd.h>
 #include <linux/stat.h>
+#include <linux/delay.h>
 
-#include <asm/delay.h>
 #include <asm/dma.h>
 #include <asm/ecard.h>
 #include <asm/io.h>
@@ -72,6 +73,11 @@
 
 static struct expansion_card *ecs[MAX_ECARDS];
 
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("Cumana SCSI II driver");
+MODULE_PARM(term, "1-8i");
+MODULE_PARM_DESC(term, "SCSI bus termination");
+
 /*
  * Use term=0,1,0,0,0 to turn terminators on/off
  */
@@ -250,7 +256,7 @@
 			if (!(status & STATUS_DRQ))
 				continue;
 
-			word = *addr | (*addr + 1) << 8;
+			word = *addr | *(addr + 1) << 8;
 			outw (info->dmaarea);
 			addr += 2;
 			length -= 2;
@@ -361,6 +367,7 @@
 		info->info.ifcfg.asyncperiod	= CUMANASCSI2_ASYNC_PERIOD;
 		info->info.ifcfg.sync_max_depth	= CUMANASCSI2_SYNC_DEPTH;
 		info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
+		info->info.ifcfg.disconnect_ok	= 1;
 		info->info.dma.setup		= cumanascsi_2_dma_setup;
 		info->info.dma.pseudo		= cumanascsi_2_dma_pseudo;
 		info->info.dma.stop		= cumanascsi_2_dma_stop;
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/ecoscsi.c linux/drivers/acorn/scsi/ecoscsi.c
--- v2.1.109/linux/drivers/acorn/scsi/ecoscsi.c	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/scsi/ecoscsi.c	Sat Jul 18 11:55:24 1998
@@ -131,7 +131,7 @@
     request_region (instance->io_port, instance->n_io_port, "ecoscsi");
 
     if (instance->irq != IRQ_NONE)
-	if (request_irq(instance->irq, ecoscsi_intr, SA_INTERRUPT, "ecoscsi", NULL)) {
+	if (request_irq(instance->irq, do_ecoscsi_intr, SA_INTERRUPT, "ecoscsi", NULL)) {
 	    printk("scsi%d: IRQ%d not free, interrupts disabled\n",
 	    instance->host_no, instance->irq);
 	    instance->irq = IRQ_NONE;
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/ecoscsi.h linux/drivers/acorn/scsi/ecoscsi.h
--- v2.1.109/linux/drivers/acorn/scsi/ecoscsi.h	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/scsi/ecoscsi.h	Sat Jul 18 11:55:24 1998
@@ -81,7 +81,7 @@
 #define NCR5380_read(reg) ecoscsi_read(_instance, reg)
 #define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value)
 
-#define NCR5380_intr ecoscsi_intr
+#define do_NCR5380_intr do_ecoscsi_intr
 #define NCR5380_queue_command ecoscsi_queue_command
 #define NCR5380_abort ecoscsi_abort
 #define NCR5380_reset ecoscsi_reset
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/eesox.c linux/drivers/acorn/scsi/eesox.c
--- v2.1.109/linux/drivers/acorn/scsi/eesox.c	Fri May  8 23:14:46 1998
+++ linux/drivers/acorn/scsi/eesox.c	Sat Jul 18 11:55:24 1998
@@ -14,6 +14,7 @@
  *  14-03-1998	RMK	Updated DMA support
  *			Added terminator control
  *  15-04-1998	RMK	Only do PIO if FAS216 will allow it.
+ *  27-06-1998	RMK	Changed asm/delay.h to linux/delay.h
  */
 
 #include <linux/module.h>
@@ -25,8 +26,8 @@
 #include <linux/proc_fs.h>
 #include <linux/unistd.h>
 #include <linux/stat.h>
+#include <linux/delay.h>
 
-#include <asm/delay.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
@@ -73,6 +74,11 @@
 
 static struct expansion_card *ecs[MAX_ECARDS];
 
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("EESOX SCSI driver");
+MODULE_PARM(term, "1-8i");
+MODULE_PARM_DESC(term, "SCSI bus termination");
+
 /*
  * Use term=0,1,0,0,0 to turn terminators on/off
  */
@@ -377,6 +383,7 @@
 		info->info.ifcfg.asyncperiod	= EESOX_ASYNC_PERIOD;
 		info->info.ifcfg.sync_max_depth	= EESOX_SYNC_DEPTH;
 		info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
+		info->info.ifcfg.disconnect_ok	= 1;
 		info->info.dma.setup		= eesoxscsi_dma_setup;
 		info->info.dma.pseudo		= eesoxscsi_dma_pseudo;
 		info->info.dma.stop		= eesoxscsi_dma_stop;
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/fas216.c linux/drivers/acorn/scsi/fas216.c
--- v2.1.109/linux/drivers/acorn/scsi/fas216.c	Fri May  8 23:14:47 1998
+++ linux/drivers/acorn/scsi/fas216.c	Sat Jul 18 11:55:24 1998
@@ -22,6 +22,8 @@
  *  06-04-1998	RMK	Tightened conditions for printing incomplete
  *			transfers
  *  02-05-1998	RMK	Added extra checks in fas216_reset
+ *  24-05-1998	RMK	Fixed synchronous transfers with period >= 200ns
+ *  27-06-1998	RMK	Changed asm/delay.h to linux/delay.h
  *
  * Todo:
  *  - tighten up the MESSAGE_REJECT support.
@@ -37,8 +39,8 @@
 #include <linux/proc_fs.h>
 #include <linux/unistd.h>
 #include <linux/stat.h>
+#include <linux/delay.h>
 
-#include <asm/delay.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -50,9 +52,12 @@
 #include "../../scsi/hosts.h"
 #include "fas216.h"
 
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver");
+
 #define VER_MAJOR	0
 #define VER_MINOR	0
-#define VER_PATCH	3
+#define VER_PATCH	4
 
 #define SCSI2_TAG
 
@@ -81,7 +86,6 @@
  */
 #define SCSI2_SYNC
 
-#undef NO_DISCONNECTS
 #undef DEBUG_CONNECT
 #undef DEBUG_BUSSERVICE
 #undef DEBUG_FUNCTIONDONE
@@ -94,8 +98,7 @@
 
 static void fas216_dumpstate(FAS216_Info *info)
 {
-	printk("FAS216 registers:\n");
-	printk("    CTCL=%02X CTCM=%02X CMD=%02X STAT=%02X"
+	printk("FAS216: CTCL=%02X CTCM=%02X CMD=%02X STAT=%02X"
 	       " INST=%02X IS=%02X CFIS=%02X",
 		inb(REG_CTCL(info)), inb(REG_CTCM(info)),
 		inb(REG_CMD(info)),  inb(REG_STAT(info)),
@@ -114,7 +117,7 @@
 	if (used++)
 		return;
 
-	printk("FAS216_Info = \n");
+	printk("FAS216_Info=\n");
 	printk("  { magic_start=%lX host=%p SCpnt=%p origSCpnt=%p\n",
 		info->magic_start, info->host, info->SCpnt,
 		info->origSCpnt);
@@ -122,17 +125,18 @@
 		info->scsi.io_port, info->scsi.io_shift, info->scsi.irq,
 		info->scsi.cfg[0], info->scsi.cfg[1], info->scsi.cfg[2],
 		info->scsi.cfg[3]);
-	printk("           type=%p phase=%X reconnected = { target=%d lun=%d tag=%d }\n",
+	printk("           type=%p phase=%X reconnected={ target=%d lun=%d tag=%d }\n",
 		info->scsi.type, info->scsi.phase,
 		info->scsi.reconnected.target,
 		info->scsi.reconnected.lun, info->scsi.reconnected.tag);
-	printk("           SCp = { ptr=%p this_residual=%X buffer=%p buffers_residual=%X }\n",
+	printk("           SCp={ ptr=%p this_residual=%X buffer=%p buffers_residual=%X }\n",
 		info->scsi.SCp.ptr, info->scsi.SCp.this_residual,
 		info->scsi.SCp.buffer, info->scsi.SCp.buffers_residual);
 	printk("      msgs async_stp=%X last_message=%X disconnectable=%d aborting=%d }\n",
 		info->scsi.async_stp, info->scsi.last_message,
 		info->scsi.disconnectable, info->scsi.aborting);
-	printk("    stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X disconnects=%X aborts=%X resets=%X }\n",
+	printk("    stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X\n"
+	       "            disconnects=%X aborts=%X resets=%X }\n",
 		info->stats.queues, info->stats.removes, info->stats.fins,
 		info->stats.reads, info->stats.writes, info->stats.miscs,
 		info->stats.disconnects, info->stats.aborts, info->stats.resets);
@@ -148,7 +152,7 @@
 	printk("    dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n",
 		info->dma.transfer_type, info->dma.setup,
 		info->dma.pseudo, info->dma.stop);
-	printk("    internal_done=%X magic_end=%lX\n",
+	printk("    internal_done=%X magic_end=%lX }\n",
 		info->internal_done, info->magic_end);
 }
 
@@ -228,9 +232,9 @@
 
 	i = ptr;
 
-	printk(KERN_ERR "SCSI state trail: ");
+	printk(KERN_ERR "SCSI IRQ trail: ");
 	do {
-		printk("%02X:%02X:%02X:%02X ",
+		printk("%02X:%02X:%02X:%1X ",
 			list[i].stat, list[i].ssr,
 			list[i].isr, list[i].ph);
 		i = (i + 1) & 7;
@@ -265,7 +269,8 @@
  *         : ns   - period in ns (between subsequent bytes)
  * Returns : Value suitable for REG_STP
  */
-static int fas216_syncperiod(FAS216_Info *info, int ns)
+static int
+fas216_syncperiod(FAS216_Info *info, int ns)
 {
 	int value = (info->ifcfg.clockrate * ns) / 1000;
 
@@ -279,6 +284,25 @@
 	return value & 31;
 }
 
+/* Function: void fas216_set_sync(FAS216_Info *info, int target)
+ * Purpose : Correctly setup FAS216 chip for specified transfer period.
+ * Params  : info   - state structure for interface
+ *         : target - target
+ * Notes   : we need to switch the chip out of FASTSCSI mode if we have
+ *           a transfer period >= 200ns - otherwise the chip will violate
+ *           the SCSI timings.
+ */
+static void
+fas216_set_sync(FAS216_Info *info, int target)
+{
+	outb(info->device[target].sof, REG_SOF(info));
+	outb(info->device[target].stp, REG_STP(info));
+	if (info->device[target].period >= (200 / 4))
+		outb(info->scsi.cfg[2] & ~CNTL3_FASTSCSI, REG_CNTL3(info));
+	else
+		outb(info->scsi.cfg[2], REG_CNTL3(info));
+}
+
 /* Function: void fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
  * Purpose : update data pointers after transfer suspended/paused
  * Params  : info              - interface's local pointer to update
@@ -504,6 +528,8 @@
 		fas216_updateptrs(info, total - residual);
 		info->dma.transfer_type = fasdma_none;
 	}
+	if (info->scsi.phase == PHASE_DATAOUT)
+		outb(CMD_FLUSHFIFO, REG_CMD(info));
 }
 
 /* Function: void fas216_disconnected_intr(FAS216_Info *info)
@@ -857,13 +883,13 @@
 				info->scsi.phase = PHASE_MSGOUT;
 			case syncneg_sent:
 				info->device[info->SCpnt->target].negstate = syncneg_complete;
+				info->device[info->SCpnt->target].period = message[3];
 				info->device[info->SCpnt->target].sof = message[4];
 				info->device[info->SCpnt->target].stp =
 					fas216_syncperiod(info, message[3] * 4);
 				printk(KERN_NOTICE "scsi%d.%c: using synchronous transfer, offset %d, %d ns\n",
 					info->host->host_no, fas216_target(info), message[4], message[3] * 4);
-				outb(info->device[info->SCpnt->target].sof, REG_SOF(info));
-				outb(info->device[info->SCpnt->target].stp, REG_STP(info));
+				fas216_set_sync(info, info->SCpnt->target);
 				break;
 			}
 			break;
@@ -1416,8 +1442,7 @@
 	outb(info->ifcfg.select_timeout, REG_STIM(info));
 
 	/* synchronous transfers */
-	outb(info->device[SCpnt->target].sof, REG_SOF(info));
-	outb(info->device[SCpnt->target].stp, REG_STP(info));
+	fas216_set_sync(info, SCpnt->target);
 
 	msglen = msgqueue_msglength(&info->scsi.msgs);
 
@@ -1742,8 +1767,8 @@
 	info->stats.aborts += 1;
 
 	print_debug_list();
-	fas216_dumpinfo(info);
 	fas216_dumpstate(info);
+	fas216_dumpinfo(info);
 	printk(KERN_WARNING "scsi%d: fas216_abort: ", info->host->host_no);
 
 	do {
@@ -1823,12 +1848,9 @@
 #endif
 
 	for (i = 0; i < 8; i++) {
-#ifndef NO_DISCONNECTS
-		info->device[i].disconnect_ok = 1;
-#else
-		info->device[i].disconnect_ok = 0;
-#endif
+		info->device[i].disconnect_ok = info->ifcfg.disconnect_ok;
 		info->device[i].negstate = negstate;
+		info->device[i].period = info->ifcfg.asyncperiod / 4;
 		info->device[i].stp = info->scsi.async_stp;
 		info->device[i].sof = 0;
 	}
@@ -1979,6 +2001,8 @@
 		queue_free(&info->queues.issue);
 		return 1;
 	}
+
+	outb(CMD_RESETCHIP, REG_CMD(info));
 
 	outb(0, REG_CNTL3(info));
 	outb(CNTL2_S2FE, REG_CNTL2(info));
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/fas216.h linux/drivers/acorn/scsi/fas216.h
--- v2.1.109/linux/drivers/acorn/scsi/fas216.h	Fri May  8 23:14:47 1998
+++ linux/drivers/acorn/scsi/fas216.h	Sat Jul 18 11:55:24 1998
@@ -257,6 +257,7 @@
 		unsigned char	sync_max_depth;		/* Synchronous xfer max fifo depth	*/
 		unsigned char	cntl3;			/* Control Reg 3			*/
 		unsigned int	asyncperiod;		/* Async transfer period (ns)		*/
+		unsigned int	disconnect_ok:1;	/* Disconnects allowed?			*/
 	} ifcfg;
 
 	/* queue handling */
@@ -268,6 +269,7 @@
 	/* per-device info */
 	struct {
 		unsigned char	disconnect_ok:1;	/* device can disconnect		*/
+		unsigned int	period;			/* sync xfer period (*4ns)		*/
 		unsigned char	stp;			/* synchronous transfer period		*/
 		unsigned char	sof;			/* synchronous offset register		*/
 		syncneg_t	negstate;		/* synchronous transfer mode		*/
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/msgqueue.c linux/drivers/acorn/scsi/msgqueue.c
--- v2.1.109/linux/drivers/acorn/scsi/msgqueue.c	Fri May  8 23:14:47 1998
+++ linux/drivers/acorn/scsi/msgqueue.c	Sat Jul 18 11:55:24 1998
@@ -1,7 +1,7 @@
 /*
  * drivers/acorn/scsi/msgqueue.c: message queue handling
  *
- * Copyright (C) 1997,8 Russell King
+ * Copyright (C) 1997-1998 Russell King
  */
 
 #include <linux/module.h>
@@ -9,6 +9,9 @@
 #include <linux/stddef.h>
 
 #include "msgqueue.h"
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("SCSI message queue handling");
 
 /*
  * Function: struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq)
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/oak.c linux/drivers/acorn/scsi/oak.c
--- v2.1.109/linux/drivers/acorn/scsi/oak.c	Fri May  8 23:14:47 1998
+++ linux/drivers/acorn/scsi/oak.c	Sat Jul 18 11:55:24 1998
@@ -116,7 +116,7 @@
 	request_region (instance->io_port, instance->n_io_port, "Oak SCSI");
 
 	if (instance->irq != IRQ_NONE)
-	    if (request_irq(instance->irq, oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
+	    if (request_irq(instance->irq, do_oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
 		printk("scsi%d: IRQ%d not free, interrupts disabled\n",
 		    instance->host_no, instance->irq);
 		instance->irq = IRQ_NONE;
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/oak.h linux/drivers/acorn/scsi/oak.h
--- v2.1.109/linux/drivers/acorn/scsi/oak.h	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/scsi/oak.h	Sat Jul 18 11:55:24 1998
@@ -85,7 +85,7 @@
 
 #define NCR5380_read(reg)		oakscsi_read(_instance, reg)
 #define NCR5380_write(reg, value)	oakscsi_write(_instance, reg, value)
-#define NCR5380_intr			oakscsi_intr
+#define do_NCR5380_intr			do_oakscsi_intr
 #define NCR5380_queue_command		oakscsi_queue_command
 #define NCR5380_abort			oakscsi_abort
 #define NCR5380_reset			oakscsi_reset
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/powertec.c linux/drivers/acorn/scsi/powertec.c
--- v2.1.109/linux/drivers/acorn/scsi/powertec.c	Fri May  8 23:14:47 1998
+++ linux/drivers/acorn/scsi/powertec.c	Sat Jul 18 11:55:24 1998
@@ -12,6 +12,7 @@
  *  15-02-1998	RMK	Added DMA support and hardware definitions.
  *  15-04-1998	RMK	Only do PIO if FAS216 will allow it.
  *  02-05-1998	RMK	Moved DMA sg list into per-interface structure.
+ *  27-06-1998	RMK	Changed asm/delay.h to linux/delay.h
  */
 
 #include <linux/module.h>
@@ -23,8 +24,8 @@
 #include <linux/proc_fs.h>
 #include <linux/unistd.h>
 #include <linux/stat.h>
+#include <linux/delay.h>
 
-#include <asm/delay.h>
 #include <asm/dma.h>
 #include <asm/ecard.h>
 #include <asm/io.h>
@@ -68,6 +69,11 @@
 #define VER_MINOR	0
 #define VER_PATCH	2
 
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("Powertec SCSI driver");
+MODULE_PARM(term, "1-8i");
+MODULE_PARM_DESC(term, "SCSI bus termination");
+
 static struct expansion_card *ecs[MAX_ECARDS];
 
 /*
@@ -271,6 +277,7 @@
 		info->info.ifcfg.asyncperiod	= POWERTEC_ASYNC_PERIOD;
 		info->info.ifcfg.sync_max_depth	= POWERTEC_SYNC_DEPTH;
 		info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
+		info->info.ifcfg.disconnect_ok	= 1;
 		info->info.dma.setup		= powertecscsi_dma_setup;
 		info->info.dma.pseudo		= NULL;
 		info->info.dma.stop		= powertecscsi_dma_stop;
diff -u --recursive --new-file v2.1.109/linux/drivers/acorn/scsi/queue.c linux/drivers/acorn/scsi/queue.c
--- v2.1.109/linux/drivers/acorn/scsi/queue.c	Fri May  8 23:14:47 1998
+++ linux/drivers/acorn/scsi/queue.c	Sat Jul 18 11:55:25 1998
@@ -20,6 +20,9 @@
 
 #include "../../scsi/scsi.h"
 
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("SCSI command queueing");
+
 typedef struct queue_entry {
 	struct queue_entry *next;
 	struct queue_entry *prev;
diff -u --recursive --new-file v2.1.109/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.1.109/linux/drivers/block/loop.c	Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/loop.c	Mon Jul 20 17:22:35 1998
@@ -14,6 +14,8 @@
  * Adapted for 1.3.59 kernel - Andries Brouwer, 1 Feb 1996
  *
  * Fixed do_loop_request() re-entrancy - <Vincent.Renardias@waw.com> Mar 20, 1997
+ *
+ * Handle sparse backing files correctly - Kenn Humborg, Jun 28, 1998
  */
 
 #include <linux/module.h>
@@ -55,6 +57,14 @@
 static int loop_sizes[MAX_LOOP];
 static int loop_blksizes[MAX_LOOP];
 
+#define FALSE 0
+#define TRUE (!FALSE)
+
+/* Forward declaration of function to create missing blocks in the 
+   backing file (can happen if the backing file is sparse) */
+static int create_missing_block(struct loop_device *lo, int block, int blksize);
+
+
 /*
  * Transfer functions
  */
@@ -187,6 +197,7 @@
 	struct loop_device *lo;
 	struct buffer_head *bh;
 	struct request *current_request;
+	int	block_present;
 
 repeat:
 	INIT_REQUEST;
@@ -226,50 +237,70 @@
 		if (lo->lo_flags & LO_FLAGS_READ_ONLY)
 			goto error_out;
 	} else if (current_request->cmd != READ) {
-		printk("unknown loop device command (%d)?!?", current_request->cmd);
+		printk(KERN_ERR "unknown loop device command (%d)?!?", current_request->cmd);
 		goto error_out;
 	}
 	spin_unlock_irq(&io_request_lock);
 	while (len > 0) {
+
+		size = blksize - offset;
+		if (size > len)
+			size = len;
+
 		real_block = block;
+		block_present = TRUE;
+
 		if (lo->lo_flags & LO_FLAGS_DO_BMAP) {
 			real_block = bmap(lo->lo_dentry->d_inode, block);
 			if (!real_block) {
-				printk("loop: block %d not present\n", block);
-				goto error_out_lock;
+
+				/* The backing file is a sparse file and this block
+				   doesn't exist.  If reading, return zeros.  If
+				   writing, force the underlying FS to create
+				   the block */
+				if (current_request->cmd == READ) {
+					memset(dest_addr, 0, size);
+					block_present = FALSE;
+				} else {
+					if (!create_missing_block(lo, block, blksize)) {
+						goto error_out_lock;
+					}
+				}
+
 			}
 		}
-		bh = getblk(lo->lo_device, real_block, blksize);
-		if (!bh) {
-			printk("loop: device %s: getblk(-, %d, %d) returned NULL",
-			       kdevname(lo->lo_device),
-			       block, blksize);
-			goto error_out_lock;
-		}
-		if (!buffer_uptodate(bh) && ((current_request->cmd == READ) ||
-					(offset || (len < blksize)))) {
-			ll_rw_block(READ, 1, &bh);
-			wait_on_buffer(bh);
-			if (!buffer_uptodate(bh)) {
+
+		if (block_present) {
+			bh = getblk(lo->lo_device, real_block, blksize);
+			if (!bh) {
+				printk(KERN_ERR "loop: device %s: getblk(-, %d, %d) returned NULL",
+					kdevname(lo->lo_device),
+					block, blksize);
+				goto error_out_lock;
+			}
+			if (!buffer_uptodate(bh) && ((current_request->cmd == READ) ||
+						(offset || (len < blksize)))) {
+				ll_rw_block(READ, 1, &bh);
+				wait_on_buffer(bh);
+				if (!buffer_uptodate(bh)) {
+					brelse(bh);
+					goto error_out_lock;
+				}
+			}
+
+			if ((lo->transfer)(lo, current_request->cmd, bh->b_data + offset,
+					dest_addr, size)) {
+				printk(KERN_ERR "loop: transfer error block %d\n", block);
 				brelse(bh);
 				goto error_out_lock;
 			}
-		}
-		size = blksize - offset;
-		if (size > len)
-			size = len;
-			   
-		if ((lo->transfer)(lo, current_request->cmd, bh->b_data + offset,
-				   dest_addr, size)) {
-			printk("loop: transfer error block %d\n", block);
+
+			if (current_request->cmd == WRITE) {
+				mark_buffer_uptodate(bh, 1);
+				mark_buffer_dirty(bh, 1);
+			}
 			brelse(bh);
-			goto error_out_lock;
 		}
-		if (current_request->cmd == WRITE) {
-			mark_buffer_uptodate(bh, 1);
-			mark_buffer_dirty(bh, 1);
-		}
-		brelse(bh);
 		dest_addr += size;
 		len -= size;
 		offset = 0;
@@ -289,6 +320,57 @@
 	goto repeat;
 }
 
+static int create_missing_block(struct loop_device *lo, int block, int blksize)
+{
+	struct file     *file;
+	loff_t          new_offset;
+	char            zero_buf[1] = { 0 };
+	ssize_t         retval;
+	mm_segment_t	old_fs;
+
+	file = lo->lo_backing_file;
+	if (file == NULL) {
+		printk(KERN_WARNING "loop: cannot create block - no backing file\n");
+		return FALSE;
+	}
+
+	if (file->f_op == NULL) {
+		printk(KERN_WARNING "loop: cannot create block - no file ops\n");
+		return FALSE;
+	}
+
+	new_offset = block * blksize;
+
+	if (file->f_op->llseek != NULL) {
+		file->f_op->llseek(file, new_offset, 0);
+	} else {
+		/* Do what the default llseek() code would have done */
+		file->f_pos = new_offset;
+		file->f_reada = 0;
+		file->f_version = ++event;
+	}
+
+	if (file->f_op->write == NULL) {
+		printk(KERN_WARNING "loop: cannot create block - no write file op\n");
+		return FALSE;
+	}
+
+	old_fs = get_fs();
+	set_fs(get_ds());
+
+	retval = file->f_op->write(file, zero_buf, 1, &file->f_pos);
+
+	set_fs(old_fs);
+
+	if (retval < 0) {
+		printk(KERN_WARNING "loop: cannot create block - FS write failed: code %d\n", 
+									retval);
+		return FALSE;
+	} else {
+		return TRUE;
+	}
+}
+
 static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
 {
 	struct file	*file;
@@ -309,7 +391,7 @@
 	error = -EINVAL;
 	inode = file->f_dentry->d_inode;
 	if (!inode) {
-		printk("loop_set_fd: NULL inode?!?\n");
+		printk(KERN_ERR "loop_set_fd: NULL inode?!?\n");
 		goto out_putf;
 	}
 
@@ -317,10 +399,36 @@
 		error = blkdev_open(inode, file);
 		lo->lo_device = inode->i_rdev;
 		lo->lo_flags = 0;
+
+		/* Backed by a block device - don't need to hold onto
+		   a file structure */
+		lo->lo_backing_file = NULL;
 	} else if (S_ISREG(inode->i_mode)) {
+
+		/* Backed by a regular file - we need to hold onto
+		   a file structure for this file.  We'll use it to
+		   write to blocks that are not already present in 
+		   a sparse file.  We create a new file structure
+		   based on the one passed to us via 'arg'.  This is
+		   to avoid changing the file structure that the
+		   caller is using */
+
 		lo->lo_device = inode->i_dev;
 		lo->lo_flags = LO_FLAGS_DO_BMAP;
-		error = 0;
+
+		error = -ENFILE;
+		lo->lo_backing_file = get_empty_filp();
+		if (lo->lo_backing_file) {
+			lo->lo_backing_file->f_mode = file->f_mode;
+			lo->lo_backing_file->f_pos = file->f_pos;
+			lo->lo_backing_file->f_flags = file->f_flags;
+			lo->lo_backing_file->f_owner = file->f_owner;
+			lo->lo_backing_file->f_dentry = file->f_dentry;
+			lo->lo_backing_file->f_op = file->f_op;
+			lo->lo_backing_file->private_data = file->private_data;
+
+			error = 0;
+		}
 	}
 	if (error)
 		goto out_putf;
@@ -358,7 +466,14 @@
 	if (S_ISBLK(dentry->d_inode->i_mode))
 		blkdev_release (dentry->d_inode);
 	lo->lo_dentry = NULL;
-	dput(dentry);
+
+	if (lo->lo_backing_file != NULL) {
+		fput(lo->lo_backing_file);
+		lo->lo_backing_file = NULL;
+	} else {
+		dput(dentry);
+	}
+
 	lo->lo_device = 0;
 	lo->lo_encrypt_type = 0;
 	lo->lo_offset = 0;
@@ -470,7 +585,7 @@
 	if (!inode)
 		return -EINVAL;
 	if (MAJOR(inode->i_rdev) != MAJOR_NR) {
-		printk("lo_ioctl: pseudo-major != %d\n", MAJOR_NR);
+		printk(KERN_WARNING "lo_ioctl: pseudo-major != %d\n", MAJOR_NR);
 		return -ENODEV;
 	}
 	dev = MINOR(inode->i_rdev);
@@ -506,7 +621,7 @@
 	if (!inode)
 		return -EINVAL;
 	if (MAJOR(inode->i_rdev) != MAJOR_NR) {
-		printk("lo_open: pseudo-major != %d\n", MAJOR_NR);
+		printk(KERN_WARNING "lo_open: pseudo-major != %d\n", MAJOR_NR);
 		return -ENODEV;
 	}
 	dev = MINOR(inode->i_rdev);
@@ -526,7 +641,7 @@
 	if (!inode)
 		return 0;
 	if (MAJOR(inode->i_rdev) != MAJOR_NR) {
-		printk("lo_release: pseudo-major != %d\n", MAJOR_NR);
+		printk(KERN_WARNING "lo_release: pseudo-major != %d\n", MAJOR_NR);
 		return 0;
 	}
 	dev = MINOR(inode->i_rdev);
@@ -535,7 +650,7 @@
 	fsync_dev(inode->i_rdev);
 	lo = &loop_dev[dev];
 	if (lo->lo_refcnt <= 0)
-		printk("lo_release: refcount(%d) <= 0\n", lo->lo_refcnt);
+		printk(KERN_ERR "lo_release: refcount(%d) <= 0\n", lo->lo_refcnt);
 	else  {
 		lo->lo_refcnt--;
 		MOD_DEC_USE_COUNT;
@@ -567,17 +682,17 @@
 	int	i;
 
 	if (register_blkdev(MAJOR_NR, "loop", &lo_fops)) {
-		printk("Unable to get major number %d for loop device\n",
+		printk(KERN_WARNING "Unable to get major number %d for loop device\n",
 		       MAJOR_NR);
 		return -EIO;
 	}
 #ifndef MODULE
-	printk("loop: registered device at major %d\n", MAJOR_NR);
+	printk(KERN_INFO "loop: registered device at major %d\n", MAJOR_NR);
 #ifdef DES_AVAILABLE
-	printk("loop: DES encryption available\n");
+	printk(KERN_INFO "loop: DES encryption available\n");
 #endif
 #ifdef IDEA_AVAILABLE
-	printk("loop: IDEA encryption available\n");
+	printk(KERN_INFO "loop: IDEA encryption available\n");
 #endif
 #endif
 
@@ -598,6 +713,6 @@
 void
 cleanup_module( void ) {
   if (unregister_blkdev(MAJOR_NR, "loop") != 0)
-    printk("loop: cleanup_module failed\n");
+    printk(KERN_WARNING "loop: cleanup_module failed\n");
 }
 #endif
diff -u --recursive --new-file v2.1.109/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.1.109/linux/drivers/char/Config.in	Tue Jun  9 11:57:28 1998
+++ linux/drivers/char/Config.in	Sat Jul 18 14:14:17 1998
@@ -132,16 +132,13 @@
   if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then
     hex '  SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284
   fi
+  dep_tristate 'Zoltrix Radio' CONFIG_RADIO_ZOLTRIX $CONFIG_VIDEO_DEV
+  if [ "$CONFIG_RADIO_ZOLTRIX" != "n" ]; then
+    hex '  ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c
+  fi
 fi
 tristate '/dev/nvram support' CONFIG_NVRAM
 tristate 'PC joystick support' CONFIG_JOYSTICK
-bool 'Radio Device Support' CONFIG_MISC_RADIO
-if [ "$CONFIG_MISC_RADIO" != "n" ]; then
-  bool '  AIMSlab RadioTrack (aka RadioReveal) support' CONFIG_RADIO_RTRACK
-  if [ "$CONFIG_RADIO_RTRACK" != "n" ]; then
-    hex '    RadioTrack i/o port (0x20f or 0x30f)' CONFIG_RADIO_RTRACK_PORT 20f
-  fi
-fi
 
 mainmenu_option next_comment
 comment 'Ftape, the floppy tape device driver'
diff -u --recursive --new-file v2.1.109/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.1.109/linux/drivers/char/Makefile	Thu Jul 16 18:09:24 1998
+++ linux/drivers/char/Makefile	Mon Jul 20 10:05:16 1998
@@ -451,7 +451,7 @@
 fastdep:
 
 conmakehash: conmakehash.c
-	$(HOSTCC) -o conmakehash conmakehash.c
+	$(HOSTCC) $(HOSTCFLAGS) -o conmakehash conmakehash.c
 
 consolemap_deftbl.c: $(FONTMAPFILE) conmakehash
 	./conmakehash $(FONTMAPFILE) > consolemap_deftbl.c
diff -u --recursive --new-file v2.1.109/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.1.109/linux/drivers/char/bttv.c	Tue Jun 23 10:01:22 1998
+++ linux/drivers/char/bttv.c	Sat Jul 18 14:14:17 1998
@@ -36,13 +36,13 @@
 */
 
 #include <linux/module.h>
-#include <linux/bios32.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/malloc.h>
+#include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
 #include <linux/signal.h>
@@ -352,9 +352,9 @@
 			break;
         	case I2C_DRIVERID_TUNER:
 			btv->have_tuner = 1;
-			if (btv->type == BTTV_MIRO) 
+			if (btv->tuner_type != -1) 
 			{
-				tunertype=((btread(BT848_GPIO_DATA)>>10)-1)&7;
+				tunertype=btv->tuner_type;
 				i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER,
 					TUNER_SET_TYPE,&tunertype);
 			}
@@ -436,17 +436,6 @@
  *	Tuner, Radio, internal, external and mute 
  */
  
-static unsigned char audiomuxs[][5] = 
-{
-	{ 0x00, 0x00, 0x00, 0x00, 0x00}, /* unknown */
-	{ 0x02, 0x00, 0x00, 0x00, 0x0a}, /* MIRO */
-	{ 0x00, 0x01, 0x02, 0x03, 0x04}, /* Hauppauge */
-	{ 0x04, 0x00, 0x02, 0x03, 0x01}, /* STB */
-	{ 0x00, 0x01, 0x02, 0x03, 0x04}, /* Intel??? */
-	{ 0x00, 0x01, 0x00, 0x01, 0x03}, /* Diamond DTV2000 */
-	{ 0x0c, 0x00, 0x0b, 0x0b, 0x00}, /* AVerMedia TVPhone */
-};
-
 static void audio(struct bttv *btv, int mode)
 {
 	btaor(tvcards[btv->type].gpiomask, ~tvcards[btv->type].gpiomask,
@@ -803,150 +792,6 @@
 	*x+=dx;
 }
 
-static void make_clip_tab(struct bttv *btv, struct cliprec *cr, int count)
-{
-        int i,ncr;
-	int yy, y, x, dx;
-	struct cliprec first, *cur, *cur2, *nx, first2, *prev, *nx2;
-	int bpp, bpl, width, height, inter;
-	unsigned int **rp,*ro,*re;
-	unsigned long adr;
-	int cx,cx2,cy,cy2;
-
-	inter=(btv->win.interlace&1)^1;
-	bpp=btv->win.bpp;
-	bpl=btv->win.bpl;
-	ncr=btv->ncr;
-	ro=btv->risc_odd;
-	re=btv->risc_even;
-	width=btv->win.width;
-	height=btv->win.height;
-	adr=btv->win.vidadr+btv->win.x*bpp+btv->win.y*bpl;
-
-	/* clip clipping rects against viewing window AND screen 
-	   so we do not have to rely on the user program
-	 */
-	cx=(btv->win.x<0) ? (-btv->win.x) : 0;
-	cy=(btv->win.y<0) ? (-btv->win.y) : 0;
-	cx2=(btv->win.x+width>btv->win.swidth) ? 
-	        (btv->win.swidth-btv->win.x) : width;
-	cy2=(btv->win.y+height>btv->win.sheight) ? 
-	        (btv->win.sheight-btv->win.y) : height;
-	first.next=NULL;
-	for (i=0; i<ncr; i++)
-	{
-                if (cr[i].y<cy)
-		{
-		        if (cr[i].y2<cy)
-			        continue;
-			cr[i].y=cy;
-		} 
-		if (cr[i].y2>=cy2) 
-		{
-		        if (cr[i].y>=cy2)
-			        continue;
-			cr[i].y2=cy2-1;
-		}
-                if (cr[i].x<cx)
-		{
-		        if (cr[i].x2<cx)
-			        continue;
-			cr[i].x=cx;
-		} 
-		if (cr[i].x2>=cx2) 
-		{
-		        if (cr[i].x>=cx2)
-			        continue;
-			cr[i].x2=cx2-1;
-		}
-	        cur=&first;
-		while ((nx=cur->next) && (cr[i].y > cur->next->y))
-		        cur=nx; 
-		cur->next=&(cr[i]);
-		cr[i].next=nx;
-	}
-	first2.next=NULL;
-	
-	*(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;
-	*(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0;
-	
-	/* loop through all lines */
-	for (yy=0; yy<(height<<inter); yy++) 
-	{
-		y=yy>>inter;
-		rp= (yy&1) ? &re : &ro;
-	  
-		/* remove rects with y2 > y */
-		if ((cur=first2.next))
-		{
-			prev=&first2;
-			do
-                	{
-				if (cur->y2 < y) 
-					prev->next=cur->next;
-				else
-					prev=cur;
-			} 
-                	while ((cur=cur->next));
-		}
-
-		/* add rect to second (x-sorted) list if rect.y == y  */
-		if ((cur=first.next))
-		{
-		 	while ((cur) && (cur->y == y))
-			{ 
-			        first.next=cur->next;
-				cur2=&first2;
-				while ((nx2=cur2->next) && (cur->x > cur2->next->x)) 
-				        cur2=nx2; 
-				cur2->next=cur;
-				cur->next=nx2;
-				cur=first.next;
-			}
-		}
-        	x=0;
-		if ((btv->win.y+y<=0)||(btv->win.y+y>=btv->win.sheight))
-			write_risc_segment(rp, adr, BT848_RISC_SKIP, &x,
- 					width, bpp, width);
-		else 
-		{
-			dx=cx;
-			for (cur2=first2.next; cur2; cur2=cur2->next)
-	       	        {
-				if (x+dx < cur2->x)
-				{
-					write_risc_segment(rp, adr, BT848_RISC_SKIP,
-						&x, dx, bpp, width);
-					dx=cur2->x-x;
-					write_risc_segment(rp, adr, BT848_RISC_WRITEC,
-						&x, dx, bpp, width);
-					dx=cur2->x2-x+1;
-				}
-				else if (x+dx < cur2->x2) 
-					dx=cur2->x2-x+1; 
-			}
-			if (cx2<width)
-			{
-				write_risc_segment(rp, adr, BT848_RISC_SKIP,
-					&x, dx, bpp, width);
-				write_risc_segment(rp, adr, BT848_RISC_WRITEC,
-					&x, cx2-x, bpp, width);
-				dx=width-x;
-			}
-			write_risc_segment(rp, adr, BT848_RISC_SKIP,
-				&x, dx, bpp, width);
-			write_risc_segment(rp, adr, BT848_RISC_WRITEC,
-				&x, width-x, bpp, width);
-		}
-		if ((!inter)||(yy&1))
-			adr+=bpl;
-	}
-	
-	*(ro++)=BT848_RISC_JUMP;
-	*(ro++)=btv->bus_vbi_even;
-	*(re++)=BT848_RISC_JUMP;
-	*(re++)=btv->bus_vbi_odd;
-}
 
 /*
  *	Set the registers for the size we have specified. Don't bother
@@ -1092,28 +937,15 @@
 static void bt848_set_winsize(struct bttv *btv)
 {
         unsigned short format;
-	int bpp;
 
         btv->win.color_fmt=format= (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 :
 		bpp2fmt[(btv->win.bpp-1)&3];
-#if 0
-	bpp=fmtbppx2[btv->win.color_fmt&0x0f]/2;
-	if (btv->win.bpp == 0) 
-	{
-	        btv->win.bpp=bpp;
-		format=btv->win.color_fmt;
-	}
-	else if (btv->win.bpp!=bpp)
-		btv->win.color_fmt=format=bpp2fmt[(btv->win.bpp-1)&3];
-	else
-                format=btv->win.color_fmt;
-#endif
                 	
 	/*	RGB8 seems to be a 9x5x5 GRB color cube starting at
 	 *	color 16. Why the h... can't they even mention this in the
-	 *	datasheet???  [AC - because its a standard format so I guess
-	 *	it never occured them]
-	 *	Enable dithering in this mode
+	 *	data sheet?  [AC - because it's a standard format so I guess
+	 *	it never occurred to them]
+	 *	Enable dithering in this mode.
 	 */
 #if 0	 
 	if (format==BT848_COLOR_FMT_RGB8)
@@ -1727,7 +1559,7 @@
 			strcpy(v.name, "Television");
 			v.rangelow=0;
 			v.rangehigh=0xFFFFFFFF;
-			v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC;
+			v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
 			v.mode = btv->win.norm;
 			if(copy_to_user(arg,&v,sizeof(v)))
 				return -EFAULT;
@@ -1913,13 +1745,7 @@
 				return -EFAULT;
 			if(v.depth!=8 && v.depth!=15 && v.depth!=16 && v.depth!=24 && v.depth!=32)
 				return -EINVAL;
-			if (v.base) {
-			        /* also handle virtual base addresses */
-			        if ((unsigned int)v.base>=0xe0000000UL)
-			                btv->win.vidadr=(uint)v.base;
-				else 
-				  btv->win.vidadr= __va(uvirt_to_bus((uint)v.base));
-			}
+	                btv->win.vidadr=(unsigned long)v.base;
 			btv->win.sheight=v.height;
 			btv->win.swidth=v.width;
 			btv->win.bpp=((v.depth+1)&0x38)/8;
@@ -2315,6 +2141,8 @@
 		"Matrox Millennium", PCI_BASE_ADDRESS_1},
 	{ PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2,
 		"Matrox Millennium II", PCI_BASE_ADDRESS_0},
+	{ PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP,
+		"Matrox Millennium II AGP", PCI_BASE_ADDRESS_0},
 	{ PCI_VENDOR_ID_MATROX, 0x051a, "Matrox Mystique", PCI_BASE_ADDRESS_1},
 	{ PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128, 
 		"Number Nine Imagine 128", PCI_BASE_ADDRESS_0},
@@ -2339,48 +2167,41 @@
 
 static int find_vga(void)
 {
-	unsigned int devfn, class, vendev;
-	unsigned short vendor, device, badr;
-	int found=0, bus=0, i, tga_type;
+	unsigned short badr;
+	int found = 0, i, tga_type;
 	unsigned int vidadr=0;
+	struct pci_dev *dev;
 
 
-	for (devfn = 0; devfn < 0xff; devfn++) 
+	for (dev = pci_devices; dev != NULL; dev = dev->next) 
 	{
-		if (PCI_FUNC(devfn) != 0)
+		if (dev->class != PCI_CLASS_NOT_DEFINED_VGA &&
+			(dev->class) >> 8 != PCI_BASE_CLASS_DISPLAY) 
+		{
 			continue;
-		pcibios_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendev);
-		if (vendev == 0xffffffff || vendev == 0x00000000) 
+		}
+		if (PCI_FUNC(dev->devfn) != 0)
 			continue;
-		pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor);
-		pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &device);
-		pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class);
-		class = class >> 16;
-/*		if (class == PCI_CLASS_DISPLAY_VGA) {*/
-		if ((class>>8) == PCI_BASE_CLASS_DISPLAY ||
-			/* Number 9 GXE64Pro needs this */
-			class == PCI_CLASS_NOT_DEFINED_VGA) 
-		{
-			badr=0;
-			printk(KERN_INFO "bttv: PCI display adapter: ");
-			for (i=0; i<NR_CARDS; i++) 
-			{
-				if (vendor==vbs[i].vendor) 
-				{
-					if (vbs[i].device) 
-						if (vbs[i].device!=device)
-							continue;
-					printk("%s.\n", vbs[i].name);
-					badr=vbs[i].badr;
-					break;
-				}
+
+		badr=0;
+		printk(KERN_INFO "bttv: PCI display adapter: ");
+		for (i=0; i<NR_CARDS; i++) 
+		{
+			if (dev->vendor == vbs[i].vendor) 
+			{
+				if (vbs[i].device) 
+					if (vbs[i].device!=dev->device)
+						continue;
+				printk("%s.\n", vbs[i].name);
+				badr=vbs[i].badr;
+				break;
 			}
 			if (!badr) 
 			{
 				printk(KERN_ERR "bttv: Unknown video memory base address.\n");
 				continue;
 			}
-			pcibios_read_config_dword(bus, devfn, badr, &vidadr);
+			pci_read_config_dword(dev, badr, &vidadr);
 			if (vidadr & PCI_BASE_ADDRESS_SPACE_IO) 
 			{
 				printk(KERN_ERR "bttv: Memory seems to be I/O memory.\n");
@@ -2394,8 +2215,8 @@
 				continue;
 			}
       
-			if (vendor==PCI_VENDOR_ID_DEC)
-				if (device==PCI_DEVICE_ID_DEC_TGA) 
+			if (dev->vendor == PCI_VENDOR_ID_DEC &&
+				dev->device == PCI_DEVICE_ID_DEC_TGA) 
 			{
 				tga_type = (readl((unsigned long)vidadr) >> 12) & 0x0f;
 				if (tga_type != 0 && tga_type != 1 && tga_type != 3) 
@@ -2405,9 +2226,8 @@
 				}
 				vidadr+=dec_offsets[tga_type];
 			}
-
 			DEBUG(printk(KERN_DEBUG "bttv: memory @ 0x%08x, ", vidadr));
-			DEBUG(printk(KERN_DEBUG "devfn: 0x%04x.\n", devfn));
+			DEBUG(printk(KERN_DEBUG "devfn: 0x%04x.\n", dev->devfn));
 			found++;
 		}
 	}
@@ -2434,76 +2254,65 @@
   
 static void handle_chipset(void)
 {
-	int index;
+	struct pci_dev *dev = NULL;
   
 	/*	Just in case some nut set this to something dangerous */
 	if (triton1)
 		triton1=BT848_INT_ETBF;
 	
-	for (index = 0; index < 8; index++)
+	while ((dev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, dev))) 
 	{
-		unsigned char bus, devfn;
-		unsigned char b;
-    
 		/* Beware the SiS 85C496 my friend - rev 49 don't work with a bttv */
-		
-		if (!pcibios_find_device(PCI_VENDOR_ID_SI, 
-					 PCI_DEVICE_ID_SI_496, 
-					 index, &bus, &devfn))
-		{
-			printk(KERN_WARNING "BT848 and SIS 85C496 chipset don't always work together.\n");
-		}			
+		printk(KERN_WARNING "BT848 and SIS 85C496 chipset don't always work together.\n");
+	}			
 
-		if (!pcibios_find_device(PCI_VENDOR_ID_INTEL, 
-					 PCI_DEVICE_ID_INTEL_82441,
-					 index, &bus, &devfn)) 
-		{
-			pcibios_read_config_byte(bus, devfn, 0x53, &b);
-			DEBUG(printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "));
-			DEBUG(printk("bufcon=0x%02x\n",b));
-		}
+	/* dev == NULL */
 
-		if (!pcibios_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437,
-			    index, &bus, &devfn)) 
-		{
-			printk(KERN_INFO "bttv: Host bridge 82437FX Triton PIIX\n");
-			triton1=BT848_INT_ETBF;
+	while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, dev))) 
+	{
+		unsigned char b;
+		pci_read_config_byte(dev, 0x53, &b);
+		DEBUG(printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "));
+		DEBUG(printk("bufcon=0x%02x\n",b));
+	}
+
+	while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, dev))) 
+	{
+/*		unsigned char b;
+		unsigned char bo;*/
+
+		printk(KERN_INFO "bttv: Host bridge 82437FX Triton PIIX\n");
+		triton1=BT848_INT_ETBF;
 			
 #if 0			
-			/* The ETBF bit SHOULD make all this unnecessary */
-			/* 430FX (Triton I) freezes with bus concurrency on -> switch it off */
-			{   
-			        unsigned char bo;
-
-				pcibios_read_config_byte(bus, devfn, TRITON_PCON, &b);
-				bo=b;
-				DEBUG(printk(KERN_DEBUG "bttv: 82437FX: PCON: 0x%x\n",b));
-
-				if(!(b & TRITON_BUS_CONCURRENCY)) 
-				{
-					printk(KERN_WARNING "bttv: 82437FX: disabling bus concurrency\n");
-					b |= TRITON_BUS_CONCURRENCY;
-				}
+		/* The ETBF bit SHOULD make all this unnecessary */
+		/* 430FX (Triton I) freezes with bus concurrency on -> switch it off */
 
-				if(b & TRITON_PEER_CONCURRENCY) 
-				{
-					printk(KERN_WARNING "bttv: 82437FX: disabling peer concurrency\n");
-					b &= ~TRITON_PEER_CONCURRENCY;
-				}
-				if(!(b & TRITON_STREAMING)) 
-				{
-					printk(KERN_WARNING "bttv: 82437FX: disabling streaming\n");
-					b |=  TRITON_STREAMING;
-				}
+		pci_read_config_byte(dev, TRITON_PCON, &b);
+		bo=b;
+		DEBUG(printk(KERN_DEBUG "bttv: 82437FX: PCON: 0x%x\n",b));
+		if(!(b & TRITON_BUS_CONCURRENCY)) 
+		{
+			printk(KERN_WARNING "bttv: 82437FX: disabling bus concurrency\n");
+			b |= TRITON_BUS_CONCURRENCY;
+		}
+		if(b & TRITON_PEER_CONCURRENCY) 
+		{
+			printk(KERN_WARNING "bttv: 82437FX: disabling peer concurrency\n");
+			b &= ~TRITON_PEER_CONCURRENCY;
+		}
+		if(!(b & TRITON_STREAMING)) 
+		{
+			printk(KERN_WARNING "bttv: 82437FX: disabling streaming\n");
+			b |=  TRITON_STREAMING;
+		}
 
-				if (b!=bo) 
-				{
-					pcibios_write_config_byte(bus, devfn, TRITON_PCON, b); 
-					printk(KERN_DEBUG "bttv: 82437FX: PCON changed to: 0x%x\n",b);
-				}
-			}
-#endif
+		if (b!=bo) 
+		{
+			pci_write_config_byte(dev, TRITON_PCON, b); 
+			printk(KERN_DEBUG "bttv: 82437FX: PCON changed to: 0x%x\n",b);
 		}
+#endif
 	}
 }
 
@@ -2534,13 +2343,13 @@
 
 static void idcard(struct bttv *btv)
 {
-	int tunertype;
 	btwrite(0, BT848_GPIO_OUT_EN);
 	DEBUG(printk(KERN_DEBUG "bttv: GPIO: 0x%08x\n", btread(BT848_GPIO_DATA)));
 
 	/* Default the card to the user-selected one. */
 	btv->type=card;
- 
+        btv->tuner_type=-1; /* use default tuner type */
+
 	/* If we were asked to auto-detect, then do so! 
 	   Right now this will only recognize Miro, Hauppauge or STB
 	   */
@@ -2553,6 +2362,11 @@
 		else
 		        if (I2CRead(&(btv->i2c), I2C_STBEE)>=0)
 			        btv->type=BTTV_STB;
+
+                if (btv->type == BTTV_MIRO) {
+                        /* auto detect tuner for MIRO cards */
+                        btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7;
+                }
 	}
 
         if (I2CRead(&(btv->i2c), I2C_TDA9850) >=0)
@@ -2583,13 +2397,6 @@
 	{
 		case BTTV_MIRO:
 			printk("MIRO\n");
-			if (btv->have_tuner) 
-			{
-				tunertype=((btread(BT848_GPIO_DATA)>>10)-1)&7;
-				i2c_control_device(&(btv->i2c),
-						   I2C_DRIVERID_TUNER,
-						   TUNER_SET_TYPE,&tunertype);
-			}
 			strcpy(btv->video_dev.name,"BT848(Miro)");
 			break;
 		case BTTV_HAUPPAUGE:
@@ -2666,7 +2473,7 @@
 	btv->risc_jmp[12]=BT848_RISC_JUMP;
 	btv->risc_jmp[13]=virt_to_bus(btv->risc_jmp);
 
-	/* enable cpaturing and DMA */
+	/* enable capturing and DMA */
 	btaor(flags, ~0x0f, BT848_CAP_CTL);
 	if (flags&0x0f)
 		bt848_dma(btv, 3);
@@ -2973,30 +2780,29 @@
  
 static int find_bt848(void)
 {
-	short pci_index;    
 	unsigned char command, latency;
 	int result;
-	unsigned char bus, devfn;
 	struct bttv *btv;
+	struct pci_dev *dev;
 
 	bttv_num=0;
 
 	if (!pcibios_present()) 
 	{
-		DEBUG(printk(KERN_DEBUG "bttv: PCI-BIOS not present or not accessable!\n"));
+		DEBUG(printk(KERN_DEBUG "bttv: PCI-BIOS not present or not accessible!\n"));
 		return 0;
 	}
-
-	for (pci_index = 0;
-                !pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849,
-				     pci_index, &bus, &devfn)
-	      ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848,
- 				    pci_index, &bus, &devfn);
-		++pci_index) 
+	for (dev = pci_devices; dev != NULL; dev = dev->next) 
 	{
+		if (dev->vendor != PCI_VENDOR_ID_BROOKTREE)
+			continue;
+		if (dev->device != PCI_DEVICE_ID_BT849 &&
+			dev->device != PCI_DEVICE_ID_BT848)
+			continue;
+
+		/* Ok, Bt848 or Bt849 found! */
 		btv=&bttvs[bttv_num];
-		btv->bus=bus;
-		btv->devfn=devfn;
+		btv->dev=dev;
 		btv->bt848_mem=NULL;
 		btv->vbibuf=NULL;
 		btv->risc_jmp=NULL;
@@ -3009,12 +2815,10 @@
 
 		btv->vbip=VBIBUF_SIZE;
 
-		pcibios_read_config_word(btv->bus, btv->devfn, PCI_DEVICE_ID,
-					 &btv->id);
-		pcibios_read_config_byte(btv->bus, btv->devfn,
-			PCI_INTERRUPT_LINE, &btv->irq);
-		pcibios_read_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
-			&btv->bt848_adr);
+		pci_read_config_word (btv->dev, PCI_DEVICE_ID,      &btv->id);
+
+		/* pci_read_config_dword(btv->dev, PCI_BASE_ADDRESS_0, &btv->bt848_adr); */
+		btv->bt848_adr = btv->dev->base_address[0];
     
 		if (remap&&(!bttv_num))
 		{ 
@@ -3022,20 +2826,19 @@
 			remap&=PCI_BASE_ADDRESS_MEM_MASK;
 			printk(KERN_INFO "Remapping to : 0x%08x.\n", remap);
 			remap|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK);
-			pcibios_write_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
-				 remap);
-			pcibios_read_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
-				&btv->bt848_adr);
+			pci_write_config_dword(btv->dev, PCI_BASE_ADDRESS_0, remap);
+			pci_read_config_dword(btv->dev,  PCI_BASE_ADDRESS_0, &btv->bt848_adr);
+			btv->dev->base_address[0] = btv->bt848_adr;
 		}					
     
 		btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK;
-		pcibios_read_config_byte(btv->bus, btv->devfn, PCI_CLASS_REVISION,
+		pci_read_config_byte(btv->dev, PCI_CLASS_REVISION,
 			     &btv->revision);
 		printk(KERN_INFO "bttv: Brooktree Bt%d (rev %d) ",
 			btv->id, btv->revision);
 		printk("bus: %d, devfn: %d, ",
-			btv->bus, btv->devfn);
-		printk("irq: %d, ",btv->irq);
+			btv->dev->bus->number, btv->dev->devfn);
+		printk("irq: %d, ",btv->dev->irq);
 		printk("memory: 0x%08x.\n", btv->bt848_adr);
     
     		btv->pll = 0;
@@ -3049,7 +2852,7 @@
                 
 		btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
 
-		result = request_irq(btv->irq, bttv_irq,
+		result = request_irq(btv->dev->irq, bttv_irq,
 			SA_SHIRQ | SA_INTERRUPT,"bttv",(void *)btv);
 		if (result==-EINVAL) 
 		{
@@ -3058,29 +2861,27 @@
 		}
 		if (result==-EBUSY)
 		{
-			printk(KERN_ERR "bttv: IRQ %d busy, change your PnP config in BIOS\n",btv->irq);
+			printk(KERN_ERR "bttv: IRQ %d busy, change your PnP config in BIOS\n",btv->dev->irq);
 			return result;
 		}
 		if (result < 0) 
 			return result;
 
 		/* Enable bus-mastering */
-		pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
+		pci_read_config_byte(btv->dev, PCI_COMMAND, &command);
 		command|=PCI_COMMAND_MASTER;
-		pcibios_write_config_byte(btv->bus, btv->devfn, PCI_COMMAND, command);
-		pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
+		pci_write_config_byte(btv->dev, PCI_COMMAND, command);
+		pci_read_config_byte(btv->dev, PCI_COMMAND, &command);
 		if (!(command&PCI_COMMAND_MASTER)) 
 		{
 			printk(KERN_ERR "bttv: PCI bus-mastering could not be enabled\n");
 			return -1;
 		}
-		pcibios_read_config_byte(btv->bus, btv->devfn, PCI_LATENCY_TIMER,
-			&latency);
+		pci_read_config_byte(btv->dev, PCI_LATENCY_TIMER, &latency);
 		if (!latency) 
 		{
 			latency=32;
-			pcibios_write_config_byte(btv->bus, btv->devfn,
-						  PCI_LATENCY_TIMER, latency);
+			pci_write_config_byte(btv->dev, PCI_LATENCY_TIMER, latency);
 		}
 		DEBUG(printk(KERN_DEBUG "bttv: latency: %02x\n", latency));
 		bttv_num++;
@@ -3114,9 +2915,10 @@
 		i2c_unregister_bus((&btv->i2c));
 
 		/* disable PCI bus-mastering */
-		pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
-		command|=PCI_COMMAND_MASTER;
-		pcibios_write_config_byte(btv->bus, btv->devfn, PCI_COMMAND, command);
+		pci_read_config_byte(btv->dev, PCI_COMMAND, &command);
+		/* Should this be &=~ ?? */
+ 		command|=PCI_COMMAND_MASTER;
+		pci_write_config_byte(btv->dev, PCI_COMMAND, command);
     
 		/* unmap and free memory */
 		if (btv->grisc)
@@ -3137,7 +2939,7 @@
 			vfree((void *) btv->vbibuf);
 
 
-		free_irq(btv->irq,btv);
+		free_irq(btv->dev->irq,btv);
 		DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%08x.\n", btv->bt848_mem));
 		if (btv->bt848_mem)
 			iounmap(btv->bt848_mem);
diff -u --recursive --new-file v2.1.109/linux/drivers/char/bttv.h linux/drivers/char/bttv.h
--- v2.1.109/linux/drivers/char/bttv.h	Tue Jun  9 11:57:29 1998
+++ linux/drivers/char/bttv.h	Sat Jul 18 14:14:17 1998
@@ -54,7 +54,7 @@
 	ushort swidth, sheight;
 	short cropx, cropy;
 	ushort cropwidth, cropheight;
-	unsigned int vidadr;
+	unsigned long vidadr;
 	ushort freq;
 	int norm;
 	int interlace;
@@ -74,12 +74,11 @@
 	struct i2c_bus i2c;
 	int have_msp3400;
 	int have_tuner;
+        int tuner_type;
 
 	unsigned short id;
-	unsigned char bus;          /* PCI bus the Bt848 is on */
-	unsigned char devfn;
+	struct pci_dev *dev;
 	unsigned char revision;
-	unsigned char irq;          /* IRQ used by Bt848 card */
 	unsigned int bt848_adr;      /* bus address of IO mem returned by PCI BIOS */
 	unsigned char *bt848_mem;   /* pointer to mapped IO memory */
 	unsigned long busriscmem; 
diff -u --recursive --new-file v2.1.109/linux/drivers/char/c-qcam.c linux/drivers/char/c-qcam.c
--- v2.1.109/linux/drivers/char/c-qcam.c	Sun Jun  7 11:16:29 1998
+++ linux/drivers/char/c-qcam.c	Mon Jul 20 17:44:40 1998
@@ -356,7 +356,7 @@
 		wantlen -= t;
 		if (t < s) 
 			break;
-		if (need_resched)
+		if (current->need_resched)
 			schedule();
 	}
 
@@ -377,7 +377,7 @@
 		int l;
 		do {
 			l = qcam_read_bytes(q, tmpbuf, 3);
-			if (need_resched)
+			if (current->need_resched)
 				schedule();
 		} while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
 		if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
@@ -407,7 +407,7 @@
 		int l;
 		do {
 			l = qcam_read_bytes(q, tmpbuf, 1);
-			if (need_resched)
+			if (current->need_resched)
 				schedule();
 		} while (l && tmpbuf[0] == 0x7e);
 		l = qcam_read_bytes(q, tmpbuf+1, 2);
diff -u --recursive --new-file v2.1.109/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.1.109/linux/drivers/char/console.c	Thu Jul 16 18:09:24 1998
+++ linux/drivers/char/console.c	Sat Jul 18 13:55:47 1998
@@ -165,15 +165,24 @@
 int kmsg_redirect = 0;
 
 /*
+ * For each existing display, we have a pointer to console currently visible
+ * on that display, allowing consoles other than fg_console to be refreshed
+ * appropriately. Unless the low-level driver supplies its own display_fg
+ * variable, we use this one for the "master display".
+ */
+static struct vc_data *master_display_fg = NULL;
+
+/*
  *	Low-Level Functions
  */
 
 #define IS_FG (currcons == fg_console)
+#define IS_VISIBLE (*display_fg == vc_cons[currcons].d)
 
 #ifdef VT_BUF_VRAM_ONLY
 #define DO_UPDATE 0
 #else
-#define DO_UPDATE IS_FG
+#define DO_UPDATE IS_VISIBLE
 #endif
 
 static inline unsigned short *screenpos(int currcons, int offset, int viewed)
@@ -205,7 +214,7 @@
 		nr = b - t - 1;
 	if (b > video_num_lines || t >= b || nr < 1)
 		return;
-	if (IS_FG && sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr))
+	if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr))
 		return;
 	d = (unsigned short *) (origin+video_size_row*t);
 	s = (unsigned short *) (origin+video_size_row*(t+nr));
@@ -224,7 +233,7 @@
 		nr = b - t - 1;
 	if (b > video_num_lines || t >= b || nr < 1)
 		return;
-	if (IS_FG && sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr))
+	if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr))
 		return;
 	s = (unsigned short *) (origin+video_size_row*(b-nr-1));
 	step = video_num_columns * nr;
@@ -401,7 +410,6 @@
 	}
 }
 
-/* FIXME: Does it make sense to hide cursor on non-fg consoles? */
 static inline void hide_cursor(int currcons)
 {
     sw->con_cursor(vc_cons[currcons].d,CM_ERASE);
@@ -419,7 +427,7 @@
 
 static void set_origin(int currcons)
 {
-	if (!IS_FG ||
+	if (!IS_VISIBLE ||
 	    !sw->con_set_origin ||
 	    !sw->con_set_origin(vc_cons[currcons].d))
 		origin = (unsigned long) screenbuf;
@@ -442,9 +450,11 @@
 void update_screen(int new_console)
 {
 	int currcons = fg_console;
-	int xx, yy, startx, attrib;
+	int redraw = 1;
+	int xx, yy, startx, attrib, old_console;
 	unsigned short *p, *q;
 	static int lock = 0;
+	struct vc_data **display;
 
 	if (lock)
 		return;
@@ -457,31 +467,42 @@
 
 	clear_selection();
 
-	fg_console = new_console;
-	set_origin(currcons);
-	currcons = new_console;
-	sw->con_cursor (vc_cons[currcons].d, CM_ERASE);
-	set_origin(currcons);
-	if (sw->con_switch (vc_cons[currcons].d)) {
-		/* Update the screen contents */
-		p = (unsigned short *)origin;
-		attrib = scr_readw(p) & 0xff00;
-		for (yy = 0; yy < video_num_lines; yy++) {
-			q = p;
-			for (startx = xx = 0; xx < video_num_columns; xx++) {
-				if (attrib != (scr_readw(p) & 0xff00)) {
-					if (p > q)
-						sw->con_putcs (vc_cons[currcons].d, q,
-							       p - q, yy, startx);
-					startx = xx;
-					q = p;
-					attrib = (scr_readw(p) & 0xff00);
+	hide_cursor(currcons);
+	if (fg_console != new_console) {
+		display = vc_cons[new_console].d->vc_display_fg;
+		old_console = (*display) ? (*display)->vc_num : fg_console;
+		*display = vc_cons[new_console].d;
+		fg_console = new_console;
+		currcons = old_console;
+		if (!IS_VISIBLE)
+			set_origin(currcons);
+		currcons = new_console;
+		if (old_console == new_console)
+			redraw = 0;
+	}
+	if (redraw) {
+		set_origin(currcons);
+		if (sw->con_switch (vc_cons[currcons].d)) {
+			/* Update the screen contents */
+			p = (unsigned short *)origin;
+			attrib = scr_readw(p) & 0xff00;
+			for (yy = 0; yy < video_num_lines; yy++) {
+				q = p;
+				for (startx = xx = 0; xx < video_num_columns; xx++) {
+					if (attrib != (scr_readw(p) & 0xff00)) {
+						if (p > q)
+							sw->con_putcs (vc_cons[currcons].d, q,
+								       p - q, yy, startx);
+						startx = xx;
+						q = p;
+						attrib = (scr_readw(p) & 0xff00);
+					}
+					p++;
 				}
-				p++;
+				if (p > q)
+					sw->con_putcs (vc_cons[currcons].d, q,
+						       p - q, yy, startx);
 			}
-			if (p > q)
-				sw->con_putcs (vc_cons[currcons].d, q,
-					       p - q, yy, startx);
 		}
 	}
 	set_cursor (currcons);
@@ -504,6 +525,7 @@
     /* ++Geert: sw->con_init determines console size */
     sw = conswitchp;
     cons_num = currcons;
+    display_fg = &master_display_fg;
     sw->con_init(vc_cons[currcons].d, 1);
     video_size_row = video_num_columns<<1;
     video_screen_size = video_num_lines*video_size_row;
@@ -1155,6 +1177,7 @@
 				update_screen(par[1]-1);
 			break;
 		case 13: /* unblank the screen */
+			/* FIXME: call poke_blanked_console? */
 			unblank_screen();
 			break;
 		case 14: /* set vesa powerdown interval */
@@ -1692,6 +1715,12 @@
 	    return 0;
 	}
 
+	if (from_user) {
+		/* just to make sure that noone lurks at places he shouldn't see. */
+		if (verify_area(VERIFY_READ, buf, count))
+			return 0; /* ?? are error codes legal here ?? */
+	}
+
 	/* undraw cursor first */
 	if (DO_UPDATE)
 		hide_cursor(currcons);
@@ -1700,12 +1729,6 @@
 	if (currcons == sel_cons)
 		clear_selection();
 
-	if (from_user) {
-		/* just to make sure that noone lurks at places he shouldn't see. */
-		if (verify_area(VERIFY_READ, buf, count))
-			return 0; /* ?? are error codes legal here ?? */
-	}
-
 	disable_bh(CONSOLE_BH);
 	while (count) {
 		enable_bh(CONSOLE_BH);
@@ -1816,7 +1839,6 @@
 			}
 			continue;
 		}
-		/* FIXME: Handle tabs in a special way and use putcs for them as well */
 		FLUSH
 		do_con_trol(tty, currcons, c);
 	}
@@ -1839,6 +1861,7 @@
 {
 	if (want_console >= 0) {
 		if (want_console != fg_console) {
+			clear_selection();
 			save_screen();
 			change_console(want_console);
 			/* we only changed when the console had already
@@ -2095,12 +2118,9 @@
 
 static void con_flush_chars(struct tty_struct *tty)
 {
-	unsigned int currcons;
 	struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
 
-	currcons = vt->vc_num;
-	if (vcmode != KD_GRAPHICS)
-		set_cursor(currcons);
+	set_cursor(vt->vc_num);
 }
 
 /*
@@ -2155,8 +2175,6 @@
  * This routine initializes console interrupts, and does nothing
  * else. If you want the screen to clear, call tty_write with
  * the appropriate escape-sequence.
- *
- * FIXME: return early if we don't _have_ a video card installed.
  */
 
 struct tty_driver console_driver;
@@ -2239,6 +2257,8 @@
 		}
 	}
 	currcons = fg_console = 0;
+	master_display_fg = vc_cons[currcons].d;
+	set_origin(currcons);
 	save_screen();
 	gotoxy(currcons,x,y);
 	csi_J(currcons, 0);
@@ -2260,6 +2280,42 @@
 }
 
 /*
+ *	If we support more console drivers, this function is used
+ *	when a driver wants to take over some existing consoles
+ *	and become default driver for newly opened ones.
+ */
+
+#ifndef VT_BUF_VRAM_ONLY
+
+void take_over_console(struct consw *csw, int first, int last, int deflt)
+{
+	int i;
+	const char *desc;
+
+	if (deflt)
+		conswitchp = csw;
+	desc = csw->con_startup();
+	if (!desc) return;
+
+	for (i = first; i <= last; i++) {
+		if (!vc_cons[i].d || !vc_cons[i].d->vc_sw)
+			continue;
+		if (i == fg_console &&
+		    vc_cons[i].d->vc_sw->con_save_screen)
+			vc_cons[i].d->vc_sw->con_save_screen(vc_cons[i].d);
+		vc_cons[i].d->vc_sw->con_deinit(vc_cons[i].d);
+		vc_cons[i].d->vc_sw = csw;
+		vc_cons[i].d->vc_sw->con_init(vc_cons[i].d, 0);
+		}
+	printk("Console: switching to %s %s %dx%d\n",
+	       vc_cons[fg_console].d->vc_can_do_color ? "colour" : "mono",
+	       desc, vc_cons[fg_console].d->vc_cols, vc_cons[fg_console].d->vc_rows);
+	set_palette();
+}
+
+#endif
+
+/*
  *	Screen blanking
  */
 
@@ -2273,11 +2329,13 @@
 
 void vesa_blank(void)
 {
-    vc_cons[fg_console].d->vc_sw->con_blank(vesa_blank_mode + 1);
+    struct vc_data *c = vc_cons[fg_console].d;
+    c->vc_sw->con_blank(c, vesa_blank_mode + 1);
 }
 
 void vesa_powerdown(void)
 {
+    struct vc_data *c = vc_cons[fg_console].d;
     /*
      *  Power down if currently suspended (1 or 2),
      *  suspend if currently blanked (0),
@@ -2286,11 +2344,11 @@
      */
     switch (vesa_blank_mode) {
 	case VESA_NO_BLANKING:
-	    vc_cons[fg_console].d->vc_sw->con_blank(VESA_VSYNC_SUSPEND+1);
+	    c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1);
 	    break;
 	case VESA_VSYNC_SUSPEND:
 	case VESA_HSYNC_SUSPEND:
-	    vc_cons[fg_console].d->vc_sw->con_blank(VESA_POWERDOWN+1);
+	    c->vc_sw->con_blank(c, VESA_POWERDOWN+1);
 	    break;
     }
 }
@@ -2305,17 +2363,28 @@
 
 void do_blank_screen(int nopowersave)
 {
-	int currcons;
+	int currcons = fg_console;
 
 	if (console_blanked)
 		return;
 
+	/* entering graphics mode? */
+	if (nopowersave) {
+		save_screen();
+		hide_cursor(currcons);
+		sw->con_blank(vc_cons[currcons].d, -1);
+		console_blanked = fg_console + 1;
+		set_origin(currcons);
+		return;
+	}
+
 	/* don't blank graphics */
 	if (vt_cons[fg_console]->vc_mode != KD_TEXT) {
 		console_blanked = fg_console + 1;
-		hide_cursor(fg_console);
 		return;
 	}
+
+	hide_cursor(fg_console);
 	if(vesa_off_interval && !nopowersave) {
 		timer_table[BLANK_TIMER].fn = vesa_powerdown_screen;
 		timer_table[BLANK_TIMER].expires = jiffies + vesa_off_interval;
@@ -2325,9 +2394,8 @@
 		timer_table[BLANK_TIMER].fn = unblank_screen;
 	}
 
-	currcons = fg_console;
 	save_screen();
-	sw->con_blank(1);
+	sw->con_blank(vc_cons[currcons].d, 1);
 	console_blanked = fg_console + 1;
 
 	if(!nopowersave)
@@ -2358,16 +2426,12 @@
 
 	currcons = fg_console;
 	console_blanked = 0;
-	if (sw->con_blank(0))
+	if (sw->con_blank(vc_cons[currcons].d, 0))
 		/* Low-level driver cannot restore -> do it ourselves */
 		update_screen(fg_console);
 	set_cursor(fg_console);
 }
 
-/*
- * If a blank_screen is due to a timer, then a power save is allowed.
- * If it is related to console_switching, then avoid vesa_blank().
- */
 static void blank_screen(void)
 {
 	do_blank_screen(0);
@@ -2400,7 +2464,7 @@
 void set_palette(void)
 {
     if (vt_cons[fg_console]->vc_mode != KD_GRAPHICS)
-	conswitchp->con_set_palette(vc_cons[fg_console].d, color_table);
+	vc_cons[fg_console].d->vc_sw->con_set_palette(vc_cons[fg_console].d, color_table);
 }
 
 int set_get_cmap(unsigned char *arg, int set)
@@ -2579,3 +2643,7 @@
 EXPORT_SYMBOL(default_blu);
 EXPORT_SYMBOL(video_font_height);
 EXPORT_SYMBOL(video_scan_lines);
+
+#ifndef VT_BUF_VRAM_ONLY
+EXPORT_SYMBOL(take_over_console);
+#endif
diff -u --recursive --new-file v2.1.109/linux/drivers/char/console_macros.h linux/drivers/char/console_macros.h
--- v2.1.109/linux/drivers/char/console_macros.h	Thu Jul 16 18:09:24 1998
+++ linux/drivers/char/console_macros.h	Sat Jul 18 13:55:47 1998
@@ -62,6 +62,8 @@
 #define bell_pitch	(vc_cons[currcons].d->vc_bell_pitch)
 #define bell_duration	(vc_cons[currcons].d->vc_bell_duration)
 #define cursor_type	(vc_cons[currcons].d->vc_cursor_type)
+#define display_fg	(vc_cons[currcons].d->vc_display_fg)
+
 #define vcmode		(vt_cons[currcons]->vc_mode)
 
 #define structsize	(sizeof(struct vc_data) + sizeof(struct vt_struct))
diff -u --recursive --new-file v2.1.109/linux/drivers/char/fbmem.c linux/drivers/char/fbmem.c
--- v2.1.109/linux/drivers/char/fbmem.c	Thu Jul 16 18:09:24 1998
+++ linux/drivers/char/fbmem.c	Sat Jul 18 13:55:47 1998
@@ -83,8 +83,6 @@
 extern void hpfb_setup(char *options, int *ints);
 extern void sbusfb_init(void);
 extern void sbusfb_setup(char *options, int *ints);
-extern void promfb_init(void);
-extern void promfb_setup(char *options, int *ints);
 
 static struct {
 	const char *name;
@@ -145,9 +143,6 @@
 #ifdef CONFIG_FB_SBUS
 	{ "sbus", sbusfb_init, sbusfb_setup },
 #endif
-#ifdef CONFIG_FB_PROM
-	{ "prom", promfb_init, promfb_setup },
-#endif
 #ifdef CONFIG_GSP_RESOLVER
 	/* Not a real frame buffer device... */
 	{ "resolver", NULL, resolver_video_setup },
@@ -474,27 +469,6 @@
 	NULL		/* fsync 	*/
 };
 
-static inline void take_over_console(struct consw *sw)
-{
-    int i;
-    extern void set_palette(void);
-
-    conswitchp = sw;
-    conswitchp->con_startup();
-
-    for (i = 0; i < MAX_NR_CONSOLES; i++) {
-	if (!vc_cons[i].d || !vc_cons[i].d->vc_sw)
-	    continue;
-	if (i == fg_console &&
-	    vc_cons[i].d->vc_sw->con_save_screen)
-		vc_cons[i].d->vc_sw->con_save_screen(vc_cons[i].d);
-	vc_cons[i].d->vc_sw->con_deinit(vc_cons[i].d);
-	vc_cons[i].d->vc_sw = conswitchp;
-	vc_cons[i].d->vc_sw->con_init(vc_cons[i].d, 0);
-    }
-    set_palette();
-}
-
 int
 register_framebuffer(struct fb_info *fb_info)
 {
@@ -523,7 +497,7 @@
 
 	if (first) {
 		first = 0;
-		take_over_console(&fb_con);
+		take_over_console(&fb_con, 0, MAX_NR_CONSOLES-1, 1);
 	}
 
 	return 0;
diff -u --recursive --new-file v2.1.109/linux/drivers/char/h8.c linux/drivers/char/h8.c
--- v2.1.109/linux/drivers/char/h8.c	Wed Jun 24 22:54:05 1998
+++ linux/drivers/char/h8.c	Sun Jul 19 20:44:41 1998
@@ -1,6 +1,4 @@
 /*
- */
-/*
  * Hitachi H8/337 Microcontroller driver
  *
  * The H8 is used to deal with the power and thermal environment
@@ -27,6 +25,7 @@
 #include <linux/miscdevice.h>
 #include <linux/lists.h>
 #include <linux/ioport.h>
+#include <linux/poll.h>
 
 #define __KERNEL_SYSCALLS__
 #include <asm/unistd.h>
@@ -55,12 +54,6 @@
 int          h8_display_blank(void);
 int          h8_display_unblank(void);
 
-static int   h8_open(struct inode *, struct file *);
-static void  h8_release(struct inode *, struct file *);
-static long  h8_read(struct inode *, struct file *, char *, u_long);
-static int   h8_select(struct inode *, struct file *, int, select_table *);
-static int   h8_ioctl(struct inode *, struct file *, u_int, u_long);
-
 static void  h8_intr(int irq, void *dev_id, struct pt_regs *regs);
 
 #ifdef CONFIG_PROC_FS
@@ -113,14 +106,14 @@
 
 static struct file_operations h8_fops = {
         NULL,           /* lseek */
-        h8_read,
+        NULL,
         NULL,           /* write */
         NULL,           /* readdir */
-        h8_select,
-        h8_ioctl,
+        NULL,
+        NULL,
         NULL,           /* mmap */
-        h8_open,
-        h8_release,
+        NULL,
+        NULL,
         NULL,           /* fsync */
         NULL            /* fasync */
 };
@@ -328,7 +321,7 @@
         request_region(h8_base, 8, "h8");
 
 #ifdef CONFIG_PROC_FS
-        proc_register_dynamic(&proc_root, &h8_proc_entry);
+        proc_register(&proc_root, &h8_proc_entry);
 #endif
 
 	QUEUE_INIT(&h8_actq, link, h8_cmd_q_t *);
@@ -362,7 +355,7 @@
         printk("H8 at 0x%x IRQ %d\n", h8_base, h8_irq);
 
 #ifdef CONFIG_PROC_FS
-        proc_register_dynamic(&proc_root, &h8_proc_entry);
+        proc_register(&proc_root, &h8_proc_entry);
 #endif
 
         misc_register(&h8_device);
@@ -438,38 +431,6 @@
         return p - buf;
 }
 #endif
-
-static long h8_read(struct inode *inode, struct file *fp, char *buf,
-		    u_long count)
-{
-	printk("h8_read: IMPDEL\n");
-	return 0;
-}
-
-static int h8_select(struct inode *inode, struct file *fp, int sel_type,
-                     select_table * wait)
-{
-	printk("h8_select: IMPDEL\n");
-	return 0;
-}
-
-static int h8_ioctl(struct inode * inode, struct file *filp,
-                    u_int cmd, u_long arg)
-{
-	printk("h8_ioctl: IMPDEL\n");
-	return 0;
-}
-
-static void h8_release(struct inode * inode, struct file * filp)
-{
-	printk("h8_release: IMPDEL\n");
-}
-
-static int h8_open(struct inode * inode, struct file * filp)
-{
-	printk("h8_open: IMPDEL\n");
-	return 0;
-}
 
 /* Called from console driver -- must make sure h8_enabled. */
 int h8_display_blank(void)
diff -u --recursive --new-file v2.1.109/linux/drivers/char/hfmodem/Makefile linux/drivers/char/hfmodem/Makefile
--- v2.1.109/linux/drivers/char/hfmodem/Makefile	Tue Aug  5 09:48:55 1997
+++ linux/drivers/char/hfmodem/Makefile	Mon Jul 20 10:05:16 1998
@@ -25,7 +25,7 @@
 .PHONY:		all
 
 gentbl:		gentbl.c
-		$(HOSTCC) -Wall $< -o $@ -lm
+		$(HOSTCC) $(HOSTCFLAGS) $< -o $@ -lm
 
 TBLHDR		:= tables.h
 
diff -u --recursive --new-file v2.1.109/linux/drivers/char/hfmodem/refclock.c linux/drivers/char/hfmodem/refclock.c
--- v2.1.109/linux/drivers/char/hfmodem/refclock.c	Thu Jul 16 18:09:24 1998
+++ linux/drivers/char/hfmodem/refclock.c	Sat Jul 18 11:47:49 1998
@@ -68,7 +68,7 @@
 #ifdef __i386__
 __initfunc(static void i386_capability(void))
 {
-	if (boot_cpu_data.x86_capability & X86_FEATURE_TSC))
+	if (boot_cpu_data.x86_capability & X86_FEATURE_TSC)
 		rdtsc_ok = 1;
 	else
 		printk(KERN_INFO "%s: cpu does not support the rdtsc instruction\n", hfmodem_drvname);
diff -u --recursive --new-file v2.1.109/linux/drivers/char/i2c.c linux/drivers/char/i2c.c
--- v2.1.109/linux/drivers/char/i2c.c	Wed Apr  8 19:36:26 1998
+++ linux/drivers/char/i2c.c	Sun Jul 19 20:45:45 1998
@@ -5,6 +5,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -34,11 +35,18 @@
 static struct i2c_driver *drivers[I2C_DRIVER_MAX];
 static int bus_count = 0, driver_count = 0;
 
+extern int i2c_tuner_init(void);
+extern int msp3400c_init(void);
+
 int i2c_init(void)
 {
 	printk(KERN_INFO "i2c: initialized%s\n",
 		scan ? " (i2c bus scan enabled)" : "");
 	/* anything to do here ? */
+#ifdef CONFIG_VIDEO_BT848
+	i2c_tuner_init();
+	msp3400c_init();
+#endif	
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.109/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.1.109/linux/drivers/char/lp.c	Thu Jul 16 18:09:24 1998
+++ linux/drivers/char/lp.c	Mon Jul 20 14:00:10 1998
@@ -156,7 +156,7 @@
 {
 	if (!parport_yield_blocking (lp_table[minor].dev))
 	{
-		if (need_resched)
+		if (current->need_resched)
 			schedule ();
 	} else
 		lp_table[minor].irq_missed = 1;
@@ -499,7 +499,7 @@
 			status = (r_str(minor) & 0x40);
 			udelay(50);
 			counter++;
-			if (need_resched)
+			if (current->need_resched)
 				schedule ();
 		} while ((status == 0x40) && (counter < 20));
 		if (counter == 20) { 
@@ -519,7 +519,7 @@
 			status=(r_str(minor) & 0x40);
 			udelay(20);
 			counter++;
-			if (need_resched)
+			if (current->need_resched)
 				schedule ();
 		} while ( (status == 0) && (counter < 20) );
 		if (counter == 20) { /* Timeout */
diff -u --recursive --new-file v2.1.109/linux/drivers/char/lp_m68k.c linux/drivers/char/lp_m68k.c
--- v2.1.109/linux/drivers/char/lp_m68k.c	Tue Mar 17 22:18:14 1998
+++ linux/drivers/char/lp_m68k.c	Mon Jul 20 17:44:55 1998
@@ -102,7 +102,7 @@
 
 	do {
 		count ++;
-		if(need_resched)
+		if (current->need_resched)
 			schedule();
 	} while (lp_table[dev]->lp_is_busy(dev) && count < lp_table[dev]->chars);
 
diff -u --recursive --new-file v2.1.109/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.1.109/linux/drivers/char/mem.c	Wed Jun 24 22:54:05 1998
+++ linux/drivers/char/mem.c	Mon Jul 20 14:00:11 1998
@@ -263,45 +263,55 @@
  */
 static inline size_t read_zero_pagealigned(char * buf, size_t size)
 {
+	struct mm_struct *mm;
 	struct vm_area_struct * vma;
 	unsigned long addr=(unsigned long)buf;
 
+	mm = current->mm;
+	/* Oops, this was forgotten before. -ben */
+	down(&mm->mmap_sem);
+
 	/* For private mappings, just map in zero pages. */
-	for (vma = find_vma(current->mm, addr); vma; vma = vma->vm_next) {
+	for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
 		unsigned long count;
 
 		if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0)
-			return size;
+			goto out_up;
 		if (vma->vm_flags & VM_SHARED)
 			break;
 		count = vma->vm_end - addr;
 		if (count > size)
 			count = size;
 
-		flush_cache_range(current->mm, addr, addr + count);
-		zap_page_range(current->mm, addr, count);
+		flush_cache_range(mm, addr, addr + count);
+		zap_page_range(mm, addr, count);
         	zeromap_page_range(addr, count, PAGE_COPY);
-        	flush_tlb_range(current->mm, addr, addr + count);
+        	flush_tlb_range(mm, addr, addr + count);
 
 		size -= count;
 		buf += count;
 		addr += count;
 		if (size == 0)
-			return 0;
+			goto out_up;
 	}
+
+	up(&mm->mmap_sem);
 	
 	/* The shared case is hard. Let's do the conventional zeroing. */ 
 	do {
 		unsigned long unwritten = clear_user(buf, PAGE_SIZE);
 		if (unwritten)
 			return size + unwritten - PAGE_SIZE;
-		if (need_resched)
+		if (current->need_resched)
 			schedule();
 		buf += PAGE_SIZE;
 		size -= PAGE_SIZE;
 	} while (size);
 
 	return size;
+out_up:
+	up(&mm->mmap_sem);
+	return size;
 }
 
 static ssize_t read_zero(struct file * file, char * buf, 
@@ -565,6 +575,9 @@
 #endif
 #ifdef CONFIG_FTAPE
 	ftape_init();
+#endif
+#ifdef CONFIG_VIDEO_BT848
+	i2c_init();
 #endif
 #ifdef CONFIG_VIDEO_DEV
 	videodev_init();
diff -u --recursive --new-file v2.1.109/linux/drivers/char/radio-aimslab.c linux/drivers/char/radio-aimslab.c
--- v2.1.109/linux/drivers/char/radio-aimslab.c	Tue Jun 23 10:01:22 1998
+++ linux/drivers/char/radio-aimslab.c	Sat Jul 18 14:14:17 1998
@@ -43,6 +43,7 @@
 	int port;
 	int curvol;
 	unsigned long curfreq;
+	int muted;
 };
 
 
@@ -51,7 +52,7 @@
 static void sleep_delay(long n)
 {
 	/* Sleep nicely for 'n' uS */
-	int d=n/1000000/HZ;
+	int d=n/(1000000/HZ);
 	if(!d)
 		udelay(n);
 	else
@@ -77,26 +78,33 @@
 	outb(0xd8, io);		/* volume steady + sigstr + on	*/
 }
 
-static void rt_mute(void)
+static void rt_mute(struct rt_device *dev)
 {
-	outb(0x48, io);			/* volume down but still "on"	*/
-	sleep_delay(2000000);		/* make sure it's totally down	*/
-	outb(0xc0, io);			/* volume steady, off		*/
+	dev->muted = 1;
+	outb(0xd0, io);			/* volume steady, off		*/
 }
 
 static int rt_setvol(struct rt_device *dev, int vol)
 {
 	int i;
 
-	if(vol == dev->curvol)		/* no change needed */
+	if(vol == dev->curvol) {	/* requested volume = current */
+		if (dev->muted) {	/* user is unmuting the card  */
+			dev->muted = 0;
+			outb (0xd8, io);	/* enable card */
+		}	
+	
 		return 0;
+	}
 
 	if(vol == 0) {			/* volume = 0 means mute the card */
-		rt_mute();
-		dev->curvol = 0;
+		outb(0x48, io);		/* volume down but still "on"	*/
+		sleep_delay(2000000);	/* make sure it's totally down	*/
+		outb(0xd0, io);		/* volume steady, off		*/
 		return 0;
 	}
 
+	dev->muted = 0;
 	if(vol > dev->curvol)
 		for(i = dev->curvol; i < vol; i++) 
 			rt_incvol();
@@ -116,7 +124,7 @@
 
 void send_0_byte(int port, struct rt_device *dev)
 {
-	if (dev->curvol == 0) {
+	if ((dev->curvol == 0) || (dev->muted)) {
 		outb_p(128+64+16+  1, port);   /* wr-enable + data low */
 		outb_p(128+64+16+2+1, port);   /* clock */
 	}
@@ -129,7 +137,7 @@
 
 void send_1_byte(int port, struct rt_device *dev)
 {
-	if (dev->curvol == 0) {
+	if ((dev->curvol == 0) || (dev->muted)) {
 		outb_p(128+64+16+4  +1, port);   /* wr-enable+data high */
 		outb_p(128+64+16+4+2+1, port);   /* clock */
 	} 
@@ -172,7 +180,7 @@
 	send_0_byte (io, dev);		/* 22: spacing (0 = 25 kHz)   */
 	send_1_byte (io, dev);		/* 23: AM/FM (FM = 1, always) */
 
-	if (dev->curvol == 0)
+	if ((dev->curvol == 0) || (dev->muted))
 		outb (0xd0, io);	/* volume steady + sigstr */
 	else
 		outb (0xd8, io);	/* volume steady + sigstr + on */
@@ -262,10 +270,8 @@
 			if(v.audio) 
 				return -EINVAL;
 
-			if(v.flags&VIDEO_AUDIO_MUTE) {
-				rt_mute();
-				rt->curvol=0;
-			}
+			if(v.flags&VIDEO_AUDIO_MUTE) 
+				rt_mute(rt);
 			else
 				rt_setvol(rt,v.volume/6554);	
 
@@ -322,9 +328,15 @@
 		
 	request_region(io, 2, "rtrack");
 	printk(KERN_INFO "AIMSlab Radiotrack/radioreveal card driver.\n");
-	/* mute card - prevents noisy bootups */
-	rt_mute();
+
+ 	/* mute card - prevents noisy bootups */
+
+	/* this ensures that the volume is all the way down  */
+	outb(0x48, io);		/* volume down but still "on"	*/
+	sleep_delay(2000000);	/* make sure it's totally down	*/
+	outb(0xc0, io);		/* steady volume, mute card	*/
 	rtrack_unit.curvol = 0;
+
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.109/linux/drivers/char/radio-sf16fmi.c linux/drivers/char/radio-sf16fmi.c
--- v2.1.109/linux/drivers/char/radio-sf16fmi.c	Tue Jun  9 11:57:29 1998
+++ linux/drivers/char/radio-sf16fmi.c	Sat Jul 18 14:14:17 1998
@@ -39,7 +39,7 @@
 static int users = 0;
 
 /* local things */
-#define RSF16_ENCODE(x)	((x*(1000/RADIO_FM_RES)+10700)/50)
+#define RSF16_ENCODE(x)	((x*(1000/4)+10700)/50)
 
 static void outbits(int bits, int data, int port)
 {
diff -u --recursive --new-file v2.1.109/linux/drivers/char/radio-zoltrix.c linux/drivers/char/radio-zoltrix.c
--- v2.1.109/linux/drivers/char/radio-zoltrix.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/radio-zoltrix.c	Sat Jul 18 14:14:17 1998
@@ -0,0 +1,337 @@
+/* zoltrix radio plus driver for Linux radio support
+ * (c) 1998 C. van Schaik <carl@leg.uct.ac.za>
+ *
+ * BUGS  
+ *  The signal strength query is unsurprisingly inaccurate.  And it seems
+ *  to indicate that (on my card, at least) the frequency setting isn't
+ *  too great.  It seems to work in a similar way to a car stereo which
+ *  flickers when it is near or on a station...
+ *
+ *  There seems to be a problem with the volume setting that I must still
+ *  figure out. This is a minor problem... It still works but you may
+ *  have to set the card lounder to get the same volume.
+ *
+ *  Some code derived from code by Frans Brinkman
+ */
+
+#include <linux/module.h>	/* Modules                        */
+#include <linux/init.h>		/* Initdata                       */
+#include <linux/ioport.h>	/* check_region, request_region   */
+#include <linux/delay.h>	/* udelay                 */
+#include <asm/io.h>		/* outb, outb_p                   */
+#include <asm/uaccess.h>	/* copy to/from user              */
+#include <linux/videodev.h>	/* kernel radio structs           */
+#include <linux/config.h>	/* CONFIG_RADIO_ZOLTRIX_PORT      */
+
+#ifndef CONFIG_RADIO_ZOLTRIX_PORT
+#define CONFIG_RADIO_ZOLTRIX_PORT -1
+#endif
+
+static int io = CONFIG_RADIO_ZOLTRIX_PORT;
+static int users = 0;
+
+struct zol_device {
+	int port;
+	int curvol;
+	unsigned long curfreq;
+	int muted;
+};
+
+
+/* local things */
+
+static void sleep_delay(long n)
+{
+	/* Sleep nicely for 'n' uS */
+	int d = n / (1000000 / HZ);
+	if (!d)
+		udelay(n);
+	else {
+		/* Yield CPU time */
+		unsigned long x = jiffies;
+		while ((jiffies - x) <= d)
+			schedule();
+	}
+}
+
+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 */
+}
+
+static int zol_setvol(struct zol_device *dev, int vol)
+{
+	int l;
+
+	if (vol == dev->curvol) {	/* requested volume = current */
+		if (dev->muted) {	/* user is unmuting the card  */
+			dev->muted = 0;
+			outb(vol, io);
+			sleep_delay(20000);
+			l = inb(io + 2);
+		}
+		return 0;
+	}
+	if (vol == 0) {		/* volume = 0 means mute the card */
+		outb(0, io);
+		outb(0, io);
+		l = inb(io + 3);
+		return 0;
+	}
+	dev->muted = 0;
+	dev->curvol = vol;
+
+	outb(vol, io);
+	sleep_delay(20000);
+	l = inb(io + 2);
+
+	return 0;
+}
+
+static int zol_setfreq(struct zol_device *dev, unsigned long freq)
+{
+	/* tunes the radio to the desired frequency */
+	unsigned long long bitmask, f, m;
+	int i, l;
+
+	m = (freq * 25 / 4 - 8800) * 2;
+	f = (unsigned long long) m + 0x4d1c;
+
+	bitmask = 0xc480402c10080000ull;
+	i = 45;
+
+	outb(0x00, io);
+	outb(0x00, io);
+	sleep_delay(10000);
+	inb(io + 3);
+	outb(0x40, io);
+	outb(0xc0, io);
+
+	bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ ( /*stereo */ 0 << 31));
+	while (i--) {
+		if ((bitmask & 0x8000000000000000ull) != 0) {
+			outb(0x80, io);
+			sleep_delay(50);
+			outb(0x00, io);
+			sleep_delay(50);
+			outb(0x80, io);
+			sleep_delay(50);
+		} else {
+			outb(0xc0, io);
+			sleep_delay(50);
+			outb(0x40, io);
+			sleep_delay(50);
+			outb(0xc0, io);
+			sleep_delay(50);
+		}
+		bitmask *= 2;
+	}
+	/* termination sequence */
+	outb(0x80, io);
+	outb(0xc0, io);
+	outb(0x40, io);
+	outb(0x00, io);
+	sleep_delay(10000);
+	l = inb(io + 2);
+	sleep_delay(10000);
+	l = inb(io + 1);
+	outb(dev->curvol, io);
+	sleep_delay(10000);
+	l = inb(io + 2);
+	return 0;
+}
+
+/* Get signal strenght */
+int zol_getsigstr(struct zol_device *dev)
+{
+	int a, b;
+	outb(0x00, io);
+	sleep_delay(10000);
+	a = inb(io + 2);
+	sleep_delay(20000);
+	b = inb(io + 1);
+	outb(0x00, io);
+
+	if (((a | b) & 255) != 0x0ff)
+		return (1);
+	else
+		return (0);
+
+	if (inb(io) & 2)	/* bit set = no signal present    */
+		return 0;
+	return 1;		/* signal present               */
+}
+
+static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+	struct zol_device *rt = dev->priv;
+
+	switch (cmd) {
+	case VIDIOCGCAP:
+		{
+			struct video_capability v;
+			v.type = VID_TYPE_TUNER;
+			v.channels = 1;
+			v.audios = 1;
+			/* No we don't do pictures */
+			v.maxwidth = 0;
+			v.maxheight = 0;
+			v.minwidth = 0;
+			v.minheight = 0;
+			if (copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+	case VIDIOCGTUNER:
+		{
+			struct video_tuner v;
+			if (copy_from_user(&v, arg, sizeof(v)) != 0)
+				return -EFAULT;
+			if (v.tuner)	/* Only 1 tuner */
+				return -EINVAL;
+			v.rangelow = (int) (88.0 * 16);
+			v.rangehigh = (int) (108.0 * 16);
+			v.flags = 0;
+			v.mode = VIDEO_MODE_AUTO;
+			v.signal = 0xFFFF * zol_getsigstr(rt);
+			if (copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+	case VIDIOCSTUNER:
+		{
+			struct video_tuner v;
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			if (v.tuner != 0)
+				return -EINVAL;
+			/* Only 1 tuner so no setting needed ! */
+			return 0;
+		}
+	case VIDIOCGFREQ:
+		if (copy_to_user(arg, &rt->curfreq, sizeof(rt->curfreq)))
+			return -EFAULT;
+		return 0;
+	case VIDIOCSFREQ:
+		if (copy_from_user(&rt->curfreq, arg, sizeof(rt->curfreq)))
+			return -EFAULT;
+		zol_setfreq(rt, rt->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 * 6554;
+			strcpy(v.name, "Radio");
+			if (copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+	case VIDIOCSAUDIO:
+		{
+			struct video_audio v;
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			if (v.audio)
+				return -EINVAL;
+
+			if (v.flags & VIDEO_AUDIO_MUTE)
+				zol_mute(rt);
+			else
+				zol_setvol(rt, v.volume / 6554);
+
+			return 0;
+		}
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+static int zol_open(struct video_device *dev, int flags)
+{
+	if (users)
+		return -EBUSY;
+	users++;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static void zol_close(struct video_device *dev)
+{
+	users--;
+	MOD_DEC_USE_COUNT;
+}
+
+static struct zol_device zoltrix_unit;
+
+static struct video_device zoltrix_radio =
+{
+	"Zoltrix Radio Plus",
+	VID_TYPE_TUNER,
+	VID_HARDWARE_ZOLTRIX,
+	zol_open,
+	zol_close,
+	NULL,			/* Can't read  (no capture ability) */
+	NULL,			/* Can't write */
+	zol_ioctl,
+	NULL,
+	NULL
+};
+
+__initfunc(int zoltrix_init(struct video_init *v))
+{
+	if (check_region(io, 2)) {
+		printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io);
+		return -EBUSY;
+	}
+	zoltrix_radio.priv = &zoltrix_unit;
+
+	if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO) == -1)
+		return -EINVAL;
+
+	request_region(io, 2, "zoltrix");
+	printk(KERN_INFO "Zoltrix Radio Plus card driver.\n");
+
+	/* mute card - prevents noisy bootups */
+
+	/* this ensures that the volume is all the way down  */
+
+	outb(0, io);
+	outb(0, io);
+	sleep_delay(20000);
+	inb(io + 3);
+
+	zoltrix_unit.curvol = 0;
+
+	return 0;
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("C.van Schaik");
+MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus.");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)");
+
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+	if (io == -1) {
+		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+		return -EINVAL;
+	}
+	return zoltrix_init(NULL);
+}
+
+void cleanup_module(void)
+{
+	video_unregister_device(&zoltrix_radio);
+	release_region(io, 2);
+}
+
+#endif
diff -u --recursive --new-file v2.1.109/linux/drivers/char/radio.c linux/drivers/char/radio.c
--- v2.1.109/linux/drivers/char/radio.c	Tue Nov  4 10:23:25 1997
+++ linux/drivers/char/radio.c	Wed Dec 31 16:00:00 1969
@@ -1,234 +0,0 @@
-/*
- * Radio Card Device Driver for Linux
- *
- * (c) 1997 Matthew Kirkwood <weejock@ferret.lmh.ox.ac.uk>
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-
-#include <linux/miscdevice.h>
-
-#include <asm/uaccess.h>
-
-#include <linux/config.h>
-
-#include <linux/radio.h>
-#ifdef CONFIG_RADIO_RTRACK
-#include "rtrack.h"
-#endif
-#ifdef CONFIG_RADIO_WINRADIO
-#include "winradio.h"
-#endif
-
-int radio_open(struct inode *inode, struct file *file);
-int radio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-
-/* /dev/radio interface */
-static struct file_operations radio_fops = {
-	NULL,			/* seek */
-	NULL,			/* read */
-	NULL,			/* write */
-	NULL,			/* readdir */
-	NULL,			/* select */
-	&radio_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	&radio_open,		/* we're not allowed NULL, it seems... */
-	NULL			/* release */
-};
-
-static struct miscdevice radio_miscdevice = {
-	RADIO_MINOR,		/* minor device number */
-	"radio",		/* title */
-	&radio_fops,		/* file operations */
-	NULL, NULL		/* previous and next (not our business) */
-};
-
-
-static struct radio_device *firstdevice, *lastdevice;
-static int numdevices;
-
-__initfunc(void radio_init(void))
-{
-	/* register the handler for the device number... */
-	if(misc_register(&radio_miscdevice)) {
-		printk("radio: couldn't register misc device\n");
-		return;
-	}
-
-	/* do some general initialisation stuff */
-	lastdevice = firstdevice = NULL;
-	numdevices = 0;
-
-#ifdef	CONFIG_RADIO_RTRACK
-	radiotrack_init();
-#endif
-#ifdef	CONFIG_RADIO_WINRADIO
-	printk("oooops.  no winradio support yet... :-(\n");
-#endif
-/* etc.... */
-
-	printk("radio: registered %d devices\n", numdevices);
-}
-
-
-/* according to drivers/char/misc.c, the "open" call must not be NULL.
- * I'm not sure if I approve, but I didn't write it, so...
- */
-int radio_open(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-
-/* append a device to the linked list... */
-int radio_add_device(struct radio_device *newdev)
-{
-	if(firstdevice == NULL) {
-		firstdevice = newdev;
-	} else {
-		lastdevice->next = newdev;
-	}
-	lastdevice = newdev; numdevices++;
-	newdev->cap->dev_num=numdevices;
-	newdev->next = NULL;			/* don't need, but... */
-	return(numdevices);
-}
-
-struct radio_device *getdev(int index)
-{
-struct radio_device *retval;
-
-	if(index > numdevices)
-		return NULL;		/* let's have a bit less of that */
-
-	retval = firstdevice;
-	for(;index;index--)
-		retval = retval->next;
-
-	return retval;
-}
-
-
-/* interface routine */
-int radio_ioctl(struct inode *inode, struct file *file,
-		unsigned int cmd, unsigned long arg)
-{
-struct radio_device *dev;
-struct radio_ctl *ctl_arg = (struct radio_ctl*)arg;
-int nowrite;
-int val, ret;
-
-	if((void*)arg == NULL)
-		return -EFAULT;		/* XXX - check errnos are OK */
-
-
-	switch(cmd) {
-	case RADIO_NUMDEVS:
-		return (put_user(numdevices,(int*)arg) ? -EFAULT : 0);
-
-
-	case RADIO_GETCAPS:
-	/* p'raps I should verify for read then write ?? */
-		if(verify_area(VERIFY_WRITE, (void*)arg, sizeof(struct radio_cap)))
-			return -EFAULT;
-		if((dev = getdev(((struct radio_cap*)arg)->dev_num)) == NULL)
-			return -EINVAL;
-		copy_to_user((void*)arg, dev->cap, sizeof(struct radio_cap));
-		return 0;
-
-
-	case RADIO_GETBNDCAP:
-		if(verify_area(VERIFY_WRITE, (void*)arg, sizeof(struct radio_band)))
-			return -EFAULT;
-
-		if((dev = getdev(((struct radio_band*)arg)->dev_num)) == NULL)
-			return -EINVAL;
-
-		val = ((struct radio_band*)arg)->index;
-		if(val >= dev->cap->num_bwidths)
-			return -EINVAL;			/* XXX errno */
-
-		copy_to_user((void*)arg, (dev->bands)+(val*sizeof(struct radio_band)),
-			sizeof(struct radio_band));
-		return 0;
-	}
-
-
-/* now, we know that arg points to a struct radio_ctl */
-	/* get the requested device */
-	if(verify_area(VERIFY_READ, ctl_arg, sizeof(struct radio_ctl)))
-		return -EFAULT;
-
-	if((dev = getdev(ctl_arg->dev_num)) == NULL)
-		return -EINVAL;
-
-	nowrite = verify_area(VERIFY_WRITE, ctl_arg, sizeof(struct radio_ctl));
-
-	val = ctl_arg->value;
-
-	switch(cmd) {
-	case RADIO_SETVOL:
-		if((val < dev->cap->volmin) || (val > dev->cap->volmax))
-			return -EINVAL;
-		if((ret = (*(dev->setvol))(dev, val)))
-			return ret;
-		dev->curvol = val;
-		return 0;
-
-	case RADIO_GETVOL:
-		if(nowrite)
-			return -EFAULT;
-		ctl_arg->value = dev->curvol;
-		return 0;
-
-
-	case RADIO_SETBAND:
-		if(val >= dev->cap->num_bwidths)
-			return -EINVAL;
-		if((ret = (*(dev->setband))(dev, val)))
-			return ret;
-		dev->curband = val;
-		return 0;
-
-	case RADIO_GETBAND:
-		if(nowrite)
-			return -EFAULT;
-		ctl_arg->value = dev->curband;
-		return 0;
-
-
-	case RADIO_SETFREQ: {
-	struct radio_band *bp;
-
-		bp = (dev->bands) + ((dev->curband) * sizeof(struct radio_band));
-		if((val < bp->freqmin) || (val > bp->freqmax))
-			return -EINVAL;
-		if((ret = (*(dev->setfreq))(dev, val)))
-			return ret;
-		dev->curfreq = val;
-		return 0;
-	}
-
-	case RADIO_GETFREQ:
-		if(nowrite)
-			return -EFAULT;
-		ctl_arg->value = dev->curfreq;
-		return 0;
-
-
-	case RADIO_GETSIGSTR:
-		if(nowrite)
-			return -EFAULT;
-		ctl_arg->value = (*(dev->getsigstr))(dev);
-		return 0;
-
-
-	default:
-		return -ENOSYS;
-	}
-}
diff -u --recursive --new-file v2.1.109/linux/drivers/char/random.c linux/drivers/char/random.c
--- v2.1.109/linux/drivers/char/random.c	Thu Jul 16 18:09:24 1998
+++ linux/drivers/char/random.c	Mon Jul 20 14:00:11 1998
@@ -1268,7 +1268,7 @@
 		nbytes -= i;
 		buf += i;
 		add_timer_randomness(r, &extract_timer_state, nbytes);
-		if (to_user && need_resched)
+		if (to_user && current->need_resched)
 			schedule();
 	}
 
diff -u --recursive --new-file v2.1.109/linux/drivers/char/rsf16fmi.h linux/drivers/char/rsf16fmi.h
--- v2.1.109/linux/drivers/char/rsf16fmi.h	Tue Jun  9 11:57:29 1998
+++ linux/drivers/char/rsf16fmi.h	Sat Jul 18 14:14:17 1998
@@ -8,8 +8,6 @@
 #ifndef __RSF16FMI_H
 #define __RSF16FMI_H
 
-#include <linux/radio.h>
-
 int radiosf16fmi_init(void);
 
 #endif /* __RSF16FMI_H */
diff -u --recursive --new-file v2.1.109/linux/drivers/char/rtrack.c linux/drivers/char/rtrack.c
--- v2.1.109/linux/drivers/char/rtrack.c	Sun Jun  7 11:16:30 1998
+++ linux/drivers/char/rtrack.c	Wed Dec 31 16:00:00 1969
@@ -1,213 +0,0 @@
-/* radiotrack (radioreveal) driver for Linux radio support
- * (c) 1997 M. Kirkwood
- */
-/* TODO: Allow for more than one of these foolish entities :-) */
-
-/* Notes on the hardware (reverse engineered from other peoples'
- * reverse engineering of AIMS' code :-)
- *
- *  Frequency control is done digitally -- ie out(port,encodefreq(95.8));
- *
- *  The signal strength query is unsurprisingly inaccurate.  And it seems
- *  to indicate that (on my card, at least) the frequency setting isn't
- *  too great.  (I have to tune up .025MHz from what the freq should be
- *  to get a report that the thing is tuned.)
- *
- *  Volume control is (ugh) analogue:
- *   out(port, start_increasing_volume);
- *   wait(a_wee_while);
- *   out(port, stop_changing_the_volume);
- *  
- */
-
-#include <linux/config.h>
-#include <linux/radio.h>
-#include <linux/ioport.h>
-
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include "rtrack.h"
-
-/* Let's just be a bit careful here, shall we? */
-#if (CONFIG_RADIO_RTRACK_PORT != 0x20f) && (CONFIG_RADIO_RTRACK_PORT != 0x30f)
-#error Invalid port specified for RadioTrack
-#endif
-
-/* local prototypes */
-void outbits(int bits, int data, int port);
-void decvol(int port);
-void incvol(int port);
-void mute(int port);
-void unmute(int port);
-
-/* public structurey-type things */
-int rt_port = CONFIG_RADIO_RTRACK_PORT;
-
-struct radio_cap rt_cap = {
-	0,			/* device index (not dealt with here) */
-	RADIO_TYPE_RTRACK,	/* type */
-	1,			/* number of bandwidths */
-	0, 10			/* volmin, volmax */
-};
-
-/* we only get one band/protocol with radiotrack */
-struct radio_band rt_band = {
-	0,			/* device index */
-	0,			/* bandwidth "index" */
-	RADIO_PROTOCOL_FM,
-	RADIO_BAND_FM_STD,
-	RADIO_FM_FRTOINT(88.0),	/* freq range */
-	RADIO_FM_FRTOINT(108.0),
-	0,1			/* sig strength range */
-};
-
-/* p'raps these should become struct radio_ops and struct radio_status? */
-struct radio_device rt_dev = {
-	&rt_cap,
-	&rt_band,
-	&rt_setvol,
-	0,				/* curvol */
-	&rt_setband,
-	0,				/* curband */
-	&rt_setfreq,
-	0,				/* curfreq */
-	&rt_getsigstr,
-	NULL,				/* next (to be filled in later) */
-	&rt_port			/* misc */
-};
-
-
-void radiotrack_init()
-{
-int dev_num, i;
-
-/* XXX - probe here?? - XXX */
-
-/* try to grab the i/o port */
-	if(check_region(rt_port,2)) {
-		printk("rtrack.c: port 0x%x already used\n", rt_port);
-		return;
-	}
-
-	request_region(rt_port,2,"rtrack");
-
-	dev_num = radio_add_device(&rt_dev);
-/* initialise the card */
-	/* set the volume very low */
-	for(i=rt_cap.volmax; i>rt_cap.volmin; i--)
-		decvol(rt_port);
-	rt_dev.curvol = rt_cap.volmin;
-}
-
-
-int rt_setvol(struct radio_device *dev, int vol)
-{
-int port, i;
-
-	if(vol == dev->curvol)
-		return 0;
-
-	port = *(int*)(dev->misc);
-	if(vol == 0)
-		mute(port);
-
-	if(vol > dev->curvol)
-		for(i = dev->curvol; i < vol; i++)
-			incvol(port);
-	else
-		for(i = dev->curvol; i > vol; i--)
-			decvol(port);
-
-	if(dev->curvol == 0)
-		unmute(port);
-
-	return 0;
-}
-
-
-int rt_setband(struct radio_device *dev, int band)
-{
-/* we know in advance that we only have one band, and
- * the wrapper checks the validity of all the inputs
- */
-	return 0;
-}
-
-int rt_setfreq(struct radio_device *dev, int freq)
-{
-int myport = *(int*)(dev->misc);
-
-	outbits(16, RTRACK_ENCODE(freq), myport);
-	outbits(8, 0xa0, myport);
-/* XXX - get rid of this once setvol is implemented properly - XXX */
-/* these insist on turning the thing on.  not sure I approve... */
-	mdelay(1);
-	outb(0, myport);
-	outb(0xc8, myport);
-
-	return 0;
-}
-
-int rt_getsigstr(struct radio_device *dev)
-{
-int res;
-int myport = *(int*)(dev->misc);
-
-	outb(0xf8, myport);
-	mdelay(200);
-	res = (int)inb(myport);
-	mdelay(10);
-	outb(0xe8, myport);
-	if(res == 0xfd)
-		return 1;
-	else
-		return 0;
-}
-
-
-/* local things */
-void outbits(int bits, int data, int port)
-{
-	while(bits--) {
-		if(data & 1) {
-			outw(5, port);
-			outw(5, port);
-			outw(7, port);
-			outw(7, port);
-		} else {
-			outw(1, port);
-			outw(1, port);
-			outw(3, port);
-			outw(3, port);
-		}
-		data>>=1;
-	}
-}
-
-void decvol(int port)
-{
-	outb(0x48, port);
-	mdelay(100);
-	outb(0xc8, port);
-}
-
-void incvol(int port)
-{
-	outb(0x88, port);
-	mdelay(100);
-	outb(0xc8, port);
-}
-
-void mute(int port)
-{
-	outb(0, port);
-	outb(0xc0, port);
-}
-
-void unmute(int port)
-{
-	outb(0, port);
-	outb(0xc8, port);
-}
diff -u --recursive --new-file v2.1.109/linux/drivers/char/rtrack.h linux/drivers/char/rtrack.h
--- v2.1.109/linux/drivers/char/rtrack.h	Tue Nov  4 10:23:25 1997
+++ linux/drivers/char/rtrack.h	Wed Dec 31 16:00:00 1969
@@ -1,25 +0,0 @@
-/* RadioTrack (RadioReveal) include file.
- * (c) 1997 M. Kirkwood
- *
- * Not in include/linux/ because there's no need for anyone
- * to know about these details, I reckon.
- */
-
-#ifndef __RTRACK_H
-#define __RTRACK_H
-
-#include <linux/radio.h>
-
-void radiotrack_init(void);
-int rt_setvol(struct radio_device *dev, int vol);
-int rt_setband(struct radio_device *dev, int vol);
-int rt_setfreq(struct radio_device *dev, int vol);
-int rt_getsigstr(struct radio_device *dev);
-
-/* frequency encoding stuff... */
-/* we have to careful not to introduce fp stuff here */
-#define	RTRACK_ENCODE(x)	(((((x)*2)/5)-(40*88))+0xf6c)
-#define	RTRACK_DECODE(x)	(((((x)-0xf6c)+(40*88))*5)/2)
-/* we shouldn't actually need the decode macro (or the excessive bracketing :-) */
-
-#endif /* __RTRACK_H */
diff -u --recursive --new-file v2.1.109/linux/drivers/char/saa5249.c linux/drivers/char/saa5249.c
--- v2.1.109/linux/drivers/char/saa5249.c	Tue Jun  9 11:57:29 1998
+++ linux/drivers/char/saa5249.c	Mon Jul 20 17:45:23 1998
@@ -48,8 +48,6 @@
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/malloc.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -130,7 +128,7 @@
 
 #define RESCHED \
         do { \
-          if (need_resched) \
+          if (current->need_resched) \
             schedule(); \
         } while (0)
 
diff -u --recursive --new-file v2.1.109/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.1.109/linux/drivers/char/tty_io.c	Tue Jun 23 10:01:22 1998
+++ linux/drivers/char/tty_io.c	Mon Jul 20 14:00:11 1998
@@ -633,7 +633,7 @@
 		ret = -ERESTARTSYS;
 		if (signal_pending(current))
 			break;
-		if (need_resched)
+		if (current->need_resched)
 			schedule();
 	}
 	if (written) {
diff -u --recursive --new-file v2.1.109/linux/drivers/char/tuner.c linux/drivers/char/tuner.c
--- v2.1.109/linux/drivers/char/tuner.c	Tue Jun 23 10:01:22 1998
+++ linux/drivers/char/tuner.c	Sat Jul 18 14:14:17 1998
@@ -12,8 +12,8 @@
 
 #include "tuner.h"
 
-int debug = 0; /* insmod parameter */
-int type  = 0; /* tuner type */
+static int debug = 0; /* insmod parameter */
+static int type  = 0; /* tuner type */
 
 #define dprintk     if (debug) printk
 
@@ -248,7 +248,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-int msp3400c_init(void)
+int i2c_tuner_init(void)
 #endif
 {
 	i2c_register_driver(&i2c_driver_tuner);
diff -u --recursive --new-file v2.1.109/linux/drivers/char/videodev.c linux/drivers/char/videodev.c
--- v2.1.109/linux/drivers/char/videodev.c	Tue Jun  9 11:57:29 1998
+++ linux/drivers/char/videodev.c	Sat Jul 18 14:14:17 1998
@@ -27,6 +27,10 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
 
 #define VIDEO_NUM_DEVICES	256 
 
@@ -38,6 +42,7 @@
 
 #ifdef CONFIG_VIDEO_BT848
 extern int init_bttv_cards(struct video_init *);
+extern int i2c_tuner_init(struct video_init *);
 #endif
 #ifdef CONFIG_VIDEO_SAA5249
 extern int init_saa_5249(struct video_init *);
@@ -60,6 +65,7 @@
 
 static struct video_init video_init_list[]={
 #ifdef CONFIG_VIDEO_BT848
+	{"i2c-tuner", i2c_tuner_init},
 	{"bttv", init_bttv_cards},
 #endif	
 #ifdef CONFIG_VIDEO_SAA5249
@@ -132,8 +138,17 @@
 		return -ENODEV;
 		
 	vfl=video_device[minor];
-	if(vfl==NULL)
-		return -ENODEV;
+	if(vfl==NULL) {
+#ifdef CONFIG_KMOD
+		char modname[20];
+
+		sprintf (modname, "char-major-%d-%d", VIDEO_MAJOR, minor);
+		request_module(modname);
+		vfl=video_device[minor];
+		if (vfl==NULL)
+#endif
+			return -ENODEV;
+	}
 	if(vfl->busy)
 		return -EBUSY;
 	vfl->busy=1;		/* In case vfl->open sleeps */
diff -u --recursive --new-file v2.1.109/linux/drivers/misc/parport_arc.c linux/drivers/misc/parport_arc.c
--- v2.1.109/linux/drivers/misc/parport_arc.c	Tue Jun 23 10:01:23 1998
+++ linux/drivers/misc/parport_arc.c	Sat Jul 18 14:16:03 1998
@@ -58,6 +58,16 @@
 #endif
 }
 
+static void arc_fill_inode(struct inode *inode, int fill)
+{
+#ifdef MODULE
+	if (fill)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
+#endif
+}
+
 static struct parport_operations parport_arc_ops = 
 {
 	arc_write_data,
@@ -103,7 +113,8 @@
 	arc_examine_irq,
 
 	arc_inc_use_count,
-	arc_dec_use_count
+	arc_dec_use_count,
+	arc_fill_inode
 };
 
 /* --- Initialisation code -------------------------------- */
diff -u --recursive --new-file v2.1.109/linux/drivers/misc/parport_ax.c linux/drivers/misc/parport_ax.c
--- v2.1.109/linux/drivers/misc/parport_ax.c	Tue Jun 23 10:01:23 1998
+++ linux/drivers/misc/parport_ax.c	Sat Jul 18 14:16:03 1998
@@ -300,6 +300,16 @@
 #endif
 }
 
+static void parport_ax_fill_inode(struct inode *inode, int fill)
+{
+#ifdef MODULE
+	if (fill)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
+#endif
+}
+
 static struct parport_operations parport_ax_ops = 
 {
 	parport_ax_write_data,
@@ -345,7 +355,8 @@
 	parport_ax_examine_irq,
 
 	parport_ax_inc_use_count,
-	parport_ax_dec_use_count
+	parport_ax_dec_use_count,
+	parport_ax_fill_inode
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/misc/parport_ieee1284.c linux/drivers/misc/parport_ieee1284.c
--- v2.1.109/linux/drivers/misc/parport_ieee1284.c	Mon Dec  1 11:06:01 1997
+++ linux/drivers/misc/parport_ieee1284.c	Mon Jul 20 17:44:19 1998
@@ -30,7 +30,7 @@
 		if ((status & mask) == result)
 			return 0;
 		udelay(25);
-		if (need_resched)
+		if (current->need_resched)
 			schedule();
 	}
 	current->state = TASK_INTERRUPTIBLE;
diff -u --recursive --new-file v2.1.109/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c
--- v2.1.109/linux/drivers/misc/parport_pc.c	Thu Jul 16 18:09:25 1998
+++ linux/drivers/misc/parport_pc.c	Sat Jul 18 14:16:03 1998
@@ -261,6 +261,16 @@
 #endif
 }
 
+static void parport_pc_fill_inode(struct inode *inode, int fill)
+{
+#ifdef MODULE
+	if (fill)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
+#endif
+}
+
 struct parport_operations parport_pc_ops = 
 {
 	parport_pc_write_data,
@@ -306,7 +316,8 @@
 	parport_pc_examine_irq,
 
 	parport_pc_inc_use_count,
-	parport_pc_dec_use_count
+	parport_pc_dec_use_count,
+	parport_pc_fill_inode
 };
 
 /* --- Mode detection ------------------------------------- */
diff -u --recursive --new-file v2.1.109/linux/drivers/misc/parport_procfs.c linux/drivers/misc/parport_procfs.c
--- v2.1.109/linux/drivers/misc/parport_procfs.c	Thu May  7 22:51:50 1998
+++ linux/drivers/misc/parport_procfs.c	Sun Jul 19 20:40:43 1998
@@ -175,6 +175,33 @@
 	return len;
 }
 
+static int autoprobe_read_proc (char *page, char **start, off_t off,
+				int count, int *eof, void *data)
+{
+	struct parport *pp = (struct parport *) data;
+	int len = 0;
+	const char *str;
+
+	if ((str = pp->probe_info.class_name) != NULL)
+		len += sprintf (page+len, "CLASS:%s;\n", str);
+
+	if ((str = pp->probe_info.model) != NULL)
+		len += sprintf (page+len, "MODEL:%s;\n", str);
+
+	if ((str = pp->probe_info.mfr) != NULL)
+		len += sprintf (page+len, "MANUFACTURER:%s;\n", str);
+
+	if ((str = pp->probe_info.description) != NULL)
+		len += sprintf (page+len, "DESCRIPTION:%s;\n", str);
+
+	if ((str = pp->probe_info.cmdset) != NULL)
+		len += sprintf (page+len, "COMMAND SET:%s;\n", str);
+
+	*start = 0;
+	*eof   = 1;
+	return strlen (page);
+}
+
 static inline void destroy_proc_entry(struct proc_dir_entry *root, 
 				      struct proc_dir_entry **d)
 {
@@ -199,7 +226,8 @@
 
 static struct proc_dir_entry *new_proc_entry(const char *name, mode_t mode,
 					     struct proc_dir_entry *parent,
-					     unsigned short ino)
+					     unsigned short ino,
+					     struct parport *p)
 {
 	struct proc_dir_entry *ent;
 
@@ -219,9 +247,12 @@
 	ent->namelen = strlen(name);
 	ent->mode = mode;
 
-	if (S_ISDIR(mode)) 
+	if (S_ISDIR(mode))
+	{
+		if (p && p->ops)
+			ent->fill_inode = p->ops->fill_inode;
 		ent->nlink = 2;
-	else
+	} else
 		ent->nlink = 1;
 
 	proc_register(parent, ent);
@@ -229,10 +260,29 @@
 	return ent;
 }
 
+/*
+ * This is called as the fill_inode function when an inode
+ * is going into (fill = 1) or out of service (fill = 0).
+ * We use it here to manage the module use counts.
+ *
+ * Note: only the top-level directory needs to do this; if
+ * a lower level is referenced, the parent will be as well.
+ */
+static void parport_modcount(struct inode *inode, int fill)
+{
+#ifdef MODULE
+	if (fill)
+		inc_parport_count();
+	else
+		dec_parport_count();
+#endif
+}
 
 int parport_proc_init(void)
 {
-	base = new_proc_entry("parport", S_IFDIR, &proc_root,PROC_PARPORT);
+	base = new_proc_entry("parport", S_IFDIR, &proc_root,PROC_PARPORT,
+			      NULL);
+	base->fill_inode = &parport_modcount;
 
 	if (base == NULL) {
 		printk(KERN_ERR "Unable to initialise /proc/parport.\n");
@@ -244,8 +294,11 @@
 
 void parport_proc_cleanup(void)
 {
-	if (base) proc_unregister(&proc_root,base->low_ino);
-	base = NULL;
+	if (base) {
+		proc_unregister(&proc_root,base->low_ino);
+		kfree(base);
+		base = NULL;
+	}
 }
 
 int parport_proc_register(struct parport *pp)
@@ -260,12 +313,12 @@
 	strncpy(pp->pdir.name, pp->name + strlen("parport"), 
 		sizeof(pp->pdir.name));
 
-	pp->pdir.entry = new_proc_entry(pp->pdir.name, S_IFDIR, base, 0);
+	pp->pdir.entry = new_proc_entry(pp->pdir.name, S_IFDIR, base, 0, pp);
 	if (pp->pdir.entry == NULL)
 		goto out_fail;
 
 	pp->pdir.irq = new_proc_entry("irq", S_IFREG | S_IRUGO | S_IWUSR, 
-				      pp->pdir.entry, 0);
+				      pp->pdir.entry, 0, pp);
 	if (pp->pdir.irq == NULL)
 		goto out_fail;
 
@@ -273,19 +326,27 @@
 	pp->pdir.irq->write_proc = irq_write_proc;
 	pp->pdir.irq->data = pp;
 	
-	pp->pdir.devices = new_proc_entry("devices", 0, pp->pdir.entry, 0);
+	pp->pdir.devices = new_proc_entry("devices", 0, pp->pdir.entry, 0, pp);
 	if (pp->pdir.devices == NULL)
 		goto out_fail;
 
 	pp->pdir.devices->read_proc = devices_read_proc;
 	pp->pdir.devices->data = pp;
 	
-	pp->pdir.hardware = new_proc_entry("hardware", 0, pp->pdir.entry, 0);
+	pp->pdir.hardware = new_proc_entry("hardware", 0, pp->pdir.entry, 0,
+					   pp);
 	if (pp->pdir.hardware == NULL)
 		goto out_fail;
 
 	pp->pdir.hardware->read_proc = hardware_read_proc;
 	pp->pdir.hardware->data = pp;
+
+	pp->pdir.probe = new_proc_entry("autoprobe", 0, pp->pdir.entry, 0, pp);
+	if (pp->pdir.probe == NULL)
+		goto out_fail;
+
+	pp->pdir.probe->read_proc = autoprobe_read_proc;
+	pp->pdir.probe->data = pp;
 
 	return 0;
 
diff -u --recursive --new-file v2.1.109/linux/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c
--- v2.1.109/linux/drivers/misc/parport_share.c	Thu Jul 16 18:09:25 1998
+++ linux/drivers/misc/parport_share.c	Mon Jul 20 13:54:08 1998
@@ -37,6 +37,7 @@
 #define PARPORT_DEFAULT_TIMESLICE	(HZ/5)
 
 static struct parport *portlist = NULL, *portlist_tail = NULL;
+spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED;
 
 void (*parport_probe_hook)(struct parport *port) = NULL;
 
@@ -45,9 +46,7 @@
 {
 #ifdef CONFIG_KMOD
 	if (portlist == NULL) {
-#if defined(CONFIG_PARPORT_PC_MODULE) || defined(CONFIG_PARPORT_AX_MODULE) || defined(CONFIG_PARPORT_ARC_MODULE)
 		request_module("parport_lowlevel");
-#endif /* CONFIG_PARPORT_LOWLEVEL_MODULE */
 #ifdef CONFIG_PNP_PARPORT_MODULE
 		request_module("parport_probe");
 #endif /* CONFIG_PNP_PARPORT_MODULE */
@@ -67,6 +66,8 @@
 {
 	struct parport *tmp;
 	int portnum;
+	char *name;
+	unsigned long flags;
 
 	/* Check for a previously registered port.
 	   NOTE: we will ignore irq and dma if we find a previously
@@ -109,22 +110,26 @@
 	tmp->flags = 0;
 	tmp->ops = ops;
 	tmp->number = portnum;
+	memset (&tmp->probe_info, 0, sizeof (struct parport_device_info));
 	spin_lock_init (&tmp->lock);
 
-	tmp->name = kmalloc(15, GFP_KERNEL);
-	if (!tmp->name) {
+	name = kmalloc(15, GFP_KERNEL);
+	if (!name) {
 		printk(KERN_ERR "parport: memory squeeze\n");
 		kfree(tmp);
 		return NULL;
 	}
-	sprintf(tmp->name, "parport%d", portnum);
+	sprintf(name, "parport%d", portnum);
+	tmp->name = name;
 
 	/* Chain the entry to our list. */
+	spin_lock_irqsave (&parportlist_lock, flags);
 	if (portlist_tail)
 		portlist_tail->next = tmp;
 	portlist_tail = tmp;
 	if (!portlist)
 		portlist = tmp;
+	spin_unlock_irqrestore (&parportlist_lock, flags);
 
 	tmp->probe_info.class = PARPORT_CLASS_LEGACY;  /* assume the worst */
 	tmp->waithead = tmp->waittail = NULL;
@@ -135,7 +140,8 @@
 void parport_unregister_port(struct parport *port)
 {
 	struct parport *p;
-	kfree(port->name);
+	unsigned long flags;
+	spin_lock_irqsave (&parportlist_lock, flags);
 	if (portlist == port) {
 		if ((portlist = port->next) == NULL)
 			portlist_tail = NULL;
@@ -146,19 +152,35 @@
 			if ((p->next = port->next) == NULL)
 				portlist_tail = p;
 		}
+		else printk (KERN_WARNING
+			     "%s not found in port list!\n", port->name);
 	}
+	spin_unlock_irqrestore (&parportlist_lock, flags);
+	if (port->probe_info.class_name)
+		kfree (port->probe_info.class_name);
+	if (port->probe_info.mfr)
+		kfree (port->probe_info.mfr);
+	if (port->probe_info.model)
+		kfree (port->probe_info.model);
+	if (port->probe_info.cmdset)
+		kfree (port->probe_info.cmdset);
+	if (port->probe_info.description)
+		kfree (port->probe_info.description);
+	kfree(port->name);
 	kfree(port);
 }
 
 void parport_quiesce(struct parport *port)
 {
 	if (port->devices) {
-		printk(KERN_WARNING "%s: attempt to quiesce active port.\n", port->name);
+		printk(KERN_WARNING "%s: attempt to quiesce active port.\n",
+		       port->name);
 		return;
 	}
 
 	if (port->flags & PARPORT_FLAG_COMA) {
-		printk(KERN_WARNING "%s: attempt to quiesce comatose port.\n", port->name);
+		printk(KERN_WARNING "%s: attempt to quiesce comatose port.\n",
+		       port->name);
 		return;
 	}
 
@@ -173,6 +195,7 @@
 			  int flags, void *handle)
 {
 	struct pardevice *tmp;
+	unsigned long flgs;
 
 	if (flags & PARPORT_DEV_LURK) {
 		if (!pf || !kf) {
@@ -181,15 +204,6 @@
 		}
 	}
 
-	/* We may need to claw back the port hardware. */
-	if (port->flags & PARPORT_FLAG_COMA) {
-		if (port->ops->claim_resources(port)) {
-			printk(KERN_WARNING "%s: unable to get hardware to register %s.\n", port->name, name);
-			return NULL;
-		}
-		port->flags &= ~PARPORT_FLAG_COMA;
-	}
-
 	tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL);
 	if (tmp == NULL) {
 		printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name);
@@ -203,7 +217,20 @@
 		return NULL;
 	}
 
-	tmp->name = (char *) name;
+	/* We may need to claw back the port hardware. */
+	if (port->flags & PARPORT_FLAG_COMA) {
+		if (port->ops->claim_resources(port)) {
+			printk(KERN_WARNING
+			       "%s: unable to get hardware to register %s.\n",
+			       port->name, name);
+			kfree (tmp->state);
+			kfree (tmp);
+			return NULL;
+		}
+		port->flags &= ~PARPORT_FLAG_COMA;
+	}
+
+	tmp->name = name;
 	tmp->port = port;
 	tmp->preempt = pf;
 	tmp->wakeup = kf;
@@ -215,10 +242,12 @@
 
 	/* Chain this onto the list */
 	tmp->prev = NULL;
+	spin_lock_irqsave (&port->lock, flgs);
 	tmp->next = port->devices;
 	if (port->devices)
 		port->devices->prev = tmp;
 	port->devices = tmp;
+	spin_unlock_irqrestore (&port->lock, flgs);
 
 	inc_parport_count();
 	port->ops->inc_use_count();
@@ -286,7 +315,7 @@
 
 try_again:
 	/* Preempt any current device */
-	if ((oldcad = port->cad)) {
+	if ((oldcad = port->cad) != NULL) {
 		if (oldcad->preempt) {
 			if (oldcad->preempt(oldcad->private))
 				goto blocked;
@@ -439,7 +468,7 @@
 	/* If anybody is waiting, find out who's been there longest and
 	   then wake them up. (Note: no locking required) */
 	for (pd = port->waithead; pd; pd = pd->waitnext) {
-		if (pd->waiting & 2) {
+		if (pd->waiting & 2) { /* sleeping in claim_or_block */
 			parport_claim(pd);
 			if (waitqueue_active(&pd->wait_q))
 				wake_up(&pd->wait_q);
diff -u --recursive --new-file v2.1.109/linux/drivers/net/3c501.c linux/drivers/net/3c501.c
--- v2.1.109/linux/drivers/net/3c501.c	Thu Feb 12 20:56:07 1998
+++ linux/drivers/net/3c501.c	Mon Jul 20 17:23:24 1998
@@ -1,4 +1,4 @@
-/* 3c501.c: A 3Com 3c501 ethernet driver for linux. */
+/* 3c501.c: A 3Com 3c501 Ethernet driver for Linux. */
 /*
     Written 1992,1993,1994  Donald Becker
 
@@ -64,14 +64,14 @@
 
     	The driver is less efficient than it could be. It switches through
     receive mode even if more transmits are queued. If this worries you buy
-    a real ethernet card.
+    a real Ethernet card.
 
     	The combination of slow receive restart and no real multicast
     filter makes the board unusable with a kernel compiled for IP
     multicasting in a real multicast environment. That's down to the board,
     but even with no multicast programs running a multicast IP kernel is
     in group 224.0.0.1 and you will therefore be listening to all multicasts.
-    One nv conference running over that ethernet and you can give up.
+    One nv conference running over that Ethernet and you can give up.
 
 */
 
@@ -564,7 +564,7 @@
 			 *	Timed out
 			 */
 			if (el_debug)
-				printk("%s: Transmit failed 16 times, ethernet jammed?\n",dev->name);
+				printk("%s: Transmit failed 16 times, Ethernet jammed?\n",dev->name);
 			outb(AX_SYS, AX_CMD);
 			lp->stats.tx_aborted_errors++;
 		}
@@ -749,7 +749,7 @@
 	int ioaddr = dev->base_addr;
 
 	if (el_debug > 2)
-		printk("%s: Shutting down ethercard at %#x.\n", dev->name, ioaddr);
+		printk("%s: Shutting down Ethernet card at %#x.\n", dev->name, ioaddr);
 
 	dev->tbusy = 1;
 	dev->start = 0;
diff -u --recursive --new-file v2.1.109/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
--- v2.1.109/linux/drivers/net/3c509.c	Thu May  7 22:51:50 1998
+++ linux/drivers/net/3c509.c	Mon Jul 20 17:23:32 1998
@@ -47,11 +47,9 @@
 #include <linux/module.h>
 
 #include <linux/config.h>	/* for CONFIG_MCA */
-#include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/interrupt.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/in.h>
 #include <linux/malloc.h>
@@ -136,7 +134,7 @@
 static int el3_open(struct device *dev);
 static int el3_start_xmit(struct sk_buff *skb, struct device *dev);
 static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void update_stats(int addr, struct device *dev);
+static void update_stats(struct device *dev);
 static struct enet_statistics *el3_get_stats(struct device *dev);
 static int el3_rx(struct device *dev);
 static int el3_close(struct device *dev);
@@ -533,10 +531,11 @@
 	dev->interrupt = 1;
 
 	ioaddr = dev->base_addr;
-	status = inw(ioaddr + EL3_STATUS);
 
-	if (el3_debug > 4)
+	if (el3_debug > 4) {
+		status = inw(ioaddr + EL3_STATUS);
 		printk("%s: interrupt, status %4.4x.\n", dev->name, status);
+	}
 
 	while ((status = inw(ioaddr + EL3_STATUS)) &
 		   (IntLatch | RxComplete | StatsFull)) {
@@ -555,7 +554,7 @@
 		if (status & (AdapterFailure | RxEarly | StatsFull)) {
 			/* Handle all uncommon interrupts. */
 			if (status & StatsFull)				/* Empty statistics. */
-				update_stats(ioaddr, dev);
+				update_stats(dev);
 			if (status & RxEarly) {				/* Rx early is unused. */
 				el3_rx(dev);
 				outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
@@ -602,7 +601,7 @@
 
 	save_flags(flags);
 	cli();
-	update_stats(dev->base_addr, dev);
+	update_stats(dev);
 	restore_flags(flags);
 	return &lp->stats;
 }
@@ -612,9 +611,10 @@
 	operation, and it's simpler for the rest of the driver to assume that
 	window 1 is always valid rather than use a special window-state variable.
 	*/
-static void update_stats(int ioaddr, struct device *dev)
+static void update_stats(struct device *dev)
 {
 	struct el3_private *lp = (struct el3_private *)dev->priv;
+	int ioaddr = dev->base_addr;
 
 	if (el3_debug > 5)
 		printk("   Updating the statistics.\n");
@@ -760,7 +760,7 @@
 	/* But we explicitly zero the IRQ line select anyway. */
 	outw(0x0f00, ioaddr + WN0_IRQ);
 
-	update_stats(ioaddr, dev);
+	update_stats(dev);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -770,6 +770,14 @@
 static int debug = -1;
 static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int xcvr[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+
+MODULE_PARM(debug,"i");
+MODULE_PARM(irq,"1-8i");
+MODULE_PARM(xcvr,"1-8i");
+
+MODULE_PARM(debug,"i");
+MODULE_PARM(irq,"1-8i");
+MODULE_PARM(xcvr,"1-8i");
 
 int
 init_module(void)
diff -u --recursive --new-file v2.1.109/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.1.109/linux/drivers/net/3c59x.c	Sun Jun  7 11:16:31 1998
+++ linux/drivers/net/3c59x.c	Mon Jul 20 17:23:32 1998
@@ -1,6 +1,6 @@
 /* EtherLinkXL.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */
 /*
-	Written 1996-1997 by Donald Becker.
+	Written 1996-1998 by Donald Becker.
 
 	This software may be used and distributed according to the terms
 	of the GNU Public License, incorporated herein by reference.
@@ -15,17 +15,28 @@
 */
 
 static char *version =
-"3c59x.c:v0.47H 12/4/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
+"3c59x.c:v0.99E 5/12/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 int rx_copybreak = 200;
+static const rx_copybreak = 200;
 /* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
-static const int mtu = 1500;
+static const 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). */
+#ifdef VORTEX_DEBUG
+static int vortex_debug = VORTEX_DEBUG;
+#else
+static int vortex_debug = 1;
+#endif
+
+/* Some values here only for performance evaluation and path-coverage
+   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
 
@@ -44,6 +55,7 @@
 #define RX_RING_SIZE	32
 #define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
 
+#include <linux/config.h>
 #ifdef MODULE
 #ifdef MODVERSIONS
 #include <linux/modversions.h>
@@ -65,6 +77,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/bios32.h>
 #include <linux/timer.h>
 #include <asm/irq.h>			/* For NR_IRQS only. */
 #include <asm/bitops.h>
@@ -82,7 +95,7 @@
 #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__)
+#if defined(__alpha)
 #error "The Alpha architecture is only support with kernel version 2.0."
 #endif
 #define virt_to_bus(addr)  ((unsigned long)addr)
@@ -92,6 +105,11 @@
 #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)
@@ -110,10 +128,10 @@
 #define udelay(microsec)	do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
 #endif
 
-#if LINUX_VERSION_CODE < 0x20115
+#if LINUX_VERSION_CODE < 0x20138
 #define test_and_set_bit(val, addr) set_bit(val, addr)
-#include <linux/bios32.h>
-#elif defined(MODULE)
+#endif
+#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");
@@ -126,13 +144,6 @@
 MODULE_PARM(compaq_prod_id, "i");
 #endif
 
-/* "Knobs" for adjusting internal parameters. */
-/* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
-#define VORTEX_DEBUG 1
-/* Some values here only for performance evaluation and path-coverage
-   debugging. */
-static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0;
-
 /* Operational parameter that usually are not changed. */
 
 /* The Vortex size is twice that of the original EtherLinkIII series: the
@@ -147,21 +158,19 @@
 {"Vortex", vortex_pci_probe, VORTEX_TOTAL_SIZE, NULL};
 #endif
 
-#ifdef VORTEX_DEBUG
-static int vortex_debug = VORTEX_DEBUG;
-#else
-static int vortex_debug = 1;
-#endif
-
-/* Set iff a MII transceiver on any interface requires mdio preamble. */
+/* 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, with the EISA ones last. */
+/* Caution!  These entries must be consistent. */
 static const int product_ids[] = {
-	0x5900, 0x5950, 0x5951, 0x5952, 0x9000, 0x9001, 0x9050, 0x9051, 0x9055,
-	0, 0};
+	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",
@@ -170,11 +179,8 @@
 	"3c905 Boomerang 100baseTx",
 	"3c905 Boomerang 100baseT4",
 	"3c905B Cyclone 100baseTx",
-	"3c592 EISA 10mbps Demon/Vortex",
-	"3c597 EISA Fast Demon/Vortex",
+	"3c575",						/* Cardbus Boomerang */
 };
-#define DEMON10_INDEX 9
-#define DEMON100_INDEX 10
 
 /*
 				Theory of Operation
@@ -186,7 +192,7 @@
 versions of the FastEtherLink cards.  The supported product IDs are
   3c590, 3c592, 3c595, 3c597, 3c900, 3c905
 
-The ISA 3c515 is supported with a separate driver, 3c515.c, included with
+The ISA 3c515 is supported with a seperate driver, 3c515.c, included with
 the kernel source or available from
     cesdis.gsfc.nasa.gov:/pub/linux/drivers/3c515.html
 
@@ -204,7 +210,7 @@
 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 separate
+The 3c900 "Boomerang" series uses a full-bus-master interface with seperate
 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
@@ -288,7 +294,7 @@
 
 /* Bits in the general status register. */
 enum vortex_status {
-	IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
+	IntLatch = 0x0001, HostError = 0x0002, TxComplete = 0x0004,
 	TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
 	IntReq = 0x0040, StatsFull = 0x0080,
 	DMADone = 1<<8, DownComplete = 1<<9, UpComplete = 1<<10,
@@ -328,7 +334,7 @@
 	struct w3_config_fields {
 		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:3, pad21:1, autoselect:1;
+		unsigned int ram_split:2, pad18:2, xcvr:4, autoselect:1;
 		int pad24:7;
 	} u;
 };
@@ -358,13 +364,15 @@
 struct boom_rx_desc {
 	u32 next;					/* Last entry points to 0.   */
 	s32 status;
-	u32 addr;					/* Up to addr/len possible.. */
-	s32 length;					/* set high bit to indicate last pair. */
+	u32 addr;					/* Up to 63 addr/len pairs possible. */
+	s32 length;					/* Set LAST_FRAG to indicate last pair. */
 };
 /* Values for the Rx status entry. */
 enum rx_desc_status {
 	RxDComplete=0x00008000, RxDError=0x4000,
 	/* See boomerang_rx() for actual error bits */
+	IPChksumErr=1<<25, TCPChksumErr=1<<26, UDPChksumErr=1<<27,
+	IPChksumValid=1<<29, TCPChksumValid=1<<30, UDPChksumValid=1<<31,
 };
 
 struct boom_tx_desc {
@@ -377,9 +385,13 @@
 /* Values for the Tx status entry. */
 enum tx_desc_status {
 	CRCDisable=0x2000, TxDComplete=0x8000,
+	AddIPChksum=0x02000000, AddTCPChksum=0x04000000, AddUDPChksum=0x08000000,
 	TxIntrUploaded=0x80000000,		/* IRQ when in FIFO, but maybe not sent. */
 };
 
+/* Chip features we care about in vp->capabilities, read from the EEPROM. */
+enum ChipCaps { CapBusMaster=0x20 };
+
 struct vortex_private {
 	char devname[8];			/* "ethN" string, also for kernel debug. */
 	const char *product_name;
@@ -394,19 +406,28 @@
 	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
 	struct enet_statistics 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;
+
+	/* The remainder are related to chip state, mostly media selection. */
+	int in_interrupt;
 	struct timer_list timer;	/* Media selection timer. */
 	int options;				/* User-settable misc. driver options. */
-	int last_rx_packets;		/* For media autoselection. */
-	unsigned int available_media:8,	/* From Wn3_Options */
+	unsigned int
 	  media_override:3, 			/* Passed-in media type. */
-	  default_media:3,			/* Read from the EEPROM. */
+	  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;
-	u16 capabilities;			/* Adapter capabilities word. */
-	u16 info1, info2;			/* Software information information. */
-	unsigned char phys[2];		/* MII device addresses. */
+	u16 status_enable;
+	u16 available_media;				/* From Wn3_Options. */
+	u16 capabilities, info1, info2;		/* Various, from EEPROM. */
+	u16 advertising;					/* NWay media advertisement */
+	unsigned char phys[2];				/* MII device addresses. */
 };
 
 /* The action to take with a media selection timer tick.
@@ -414,15 +435,15 @@
  */
 enum xcvr_types {
 	XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
-	XCVR_100baseFx, XCVR_MII=6, XCVR_Default=8,
+	XCVR_100baseFx, XCVR_MII=6, XCVR_NWAY=8, XCVR_ExtMII=9, XCVR_Default=10,
 };
 
 static struct media_table {
-  char *name;
-  unsigned int media_bits:16,		/* Bits to set in Wn4_Media register. */
-	mask:8,				/* The transceiver-present bit in Wn3_Config.*/
-	next:8;				/* The media type to try next. */
-  short wait;			/* Time before we check media status. */
+	char *name;
+	unsigned int media_bits:16,		/* Bits to set in Wn4_Media register. */
+		mask:8,				/* The transceiver-present bit in Wn3_Config.*/
+		next:8;				/* The media type to try next. */
+	int wait;			/* Time before we check media status. */
 } media_tbl[] = {
   {	"10baseT",   Media_10TP,0x08, XCVR_10base2, (14*HZ)/10},
   { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10},
@@ -430,14 +451,16 @@
   { "10base2",   0,			0x10, XCVR_AUI,		(1*HZ)/10},
   { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10},
   { "100baseFX", Media_Lnk, 0x04, XCVR_MII,		(14*HZ)/10},
-  { "MII",		 0,			0x40, XCVR_10baseT, 3*HZ },
+  { "MII",		 0,			0x41, XCVR_10baseT, 3*HZ },
   { "undefined", 0,			0x01, XCVR_10baseT, 10000},
+  { "Autonegotiate", 0,		0x41, XCVR_10baseT, 3*HZ},
+  { "MII-External",	 0,		0x41, XCVR_10baseT, 3*HZ },
   { "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, const char *product_name,
+										  int irq, int device_id,
 										  int options, int card_idx);
 static int vortex_probe1(struct device *dev);
 static int vortex_open(struct device *dev);
@@ -481,31 +504,94 @@
 /* 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,};
-#ifdef MODULE
 static int full_duplex[8] = {-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;
-#endif
 
 #ifdef MODULE
 /* Variables to work-around the Compaq PCI BIOS32 problem. */
-static int compaq_ioaddr = 0, compaq_irq = 0;
+static int compaq_ioaddr = 0, compaq_irq = 0, compaq_device_id = 0x5900;
 
 static int debug = -1;
 
+#ifdef CARDBUS
+
+#include <pcmcia/driver_ops.h>
+
+static dev_node_t *vortex_attach(dev_locator_t *loc)
+{
+	u16 dev_id;
+	u32 io;
+	u8 bus, devfn, irq;
+	struct device *dev;
+
+	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_DEVICE_ID, &dev_id);
+	io &= ~3;
+	dev = vortex_found_device(NULL, io, irq, dev_id, 0, -1);
+	if (dev) {
+		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
+		strcpy(node->dev_name, dev->name);
+		node->major = node->minor = 0;
+		node->next = NULL;
+		MOD_INC_USE_COUNT;
+		return node;
+	}
+	return NULL;
+}
+
+static void vortex_detach(dev_node_t *node)
+{
+	struct device **devp, **next;
+	printk(KERN_INFO "vortex_detach(%s)\n", node->dev_name);
+	for (devp = &root_vortex_dev; *devp; devp = next) {
+		next = &((struct vortex_private *)(*devp)->priv)->next_module;
+		if (strcmp((*devp)->name, node->dev_name) == 0) break;
+	}
+	if (*devp) {
+		struct device *dev = *devp;
+		if (dev->flags & IFF_UP)
+			vortex_close(dev);
+		dev->flags &= ~(IFF_UP|IFF_RUNNING);
+		unregister_netdev(dev);
+		kfree(dev);
+		*devp = *next;
+		kfree(node);
+		MOD_DEC_USE_COUNT;
+	}
+}
+
+struct driver_operations vortex_ops = {
+	"3c59x_cb", vortex_attach, NULL, NULL, vortex_detach
+};
+
+#endif  /* Cardbus support */
+
+
 int
 init_module(void)
 {
-	int cards_found;
-
 	if (debug >= 0)
 		vortex_debug = debug;
 	if (vortex_debug)
 		printk(version);
 
 	root_vortex_dev = NULL;
-	cards_found = vortex_scan(0);
-	return cards_found ? 0 : -ENODEV;
+#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;
+	}
+#endif
 }
 
 #else
@@ -525,28 +611,22 @@
 static int vortex_scan(struct device *dev)
 {
 	int cards_found = 0;
-	const char *product_name;
 
-#ifndef NO_PCI					/* Allow an EISA-only driver. */
+	/* Allow an EISA-only driver. */
+#if defined(CONFIG_PCI) || (defined(MODULE) && !defined(NO_PCI))
 	/* Ideally we would detect all cards in slot order.  That would
 	   be best done a central PCI probe dispatch, which wouldn't work
 	   well with the current structure.  So instead we detect 3Com cards
 	   in slot order. */
-	if (pci_present()) {
+	if (pcibios_present()) {
 		static int pci_index = 0;
 		unsigned char pci_bus, pci_device_fn;
 
 		for (;pci_index < 0xff; pci_index++) {
-#if LINUX_VERSION_CODE >= 0x20155
-			unsigned int pci_irq_line;
-			struct pci_dev *pdev;
-#else
-			unsigned char pci_irq_line;
-#endif
-			unsigned char pci_latency;
-			unsigned short pci_command, new_command, vendor, device;
-			unsigned int pci_ioaddr;
-			int board_index = 0;
+			u8 pci_latency;
+			u16 pci_command, new_command, vendor, device;
+			int irq;
+			long ioaddr;
 
 			if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
 									pci_index, &pci_bus, &pci_device_fn)
@@ -556,42 +636,42 @@
 									 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);
+			{
 #if LINUX_VERSION_CODE >= 0x20155
-			pdev = pci_find_slot(pci_bus, pci_device_fn);
-			pci_irq_line = pdev->irq;
-			pci_ioaddr = pdev->base_address[0];
+				struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
+				ioaddr = pdev->base_address[0];
+				irq = pdev->irq;
 #else
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-									 PCI_INTERRUPT_LINE, &pci_irq_line);
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-									  PCI_BASE_ADDRESS_0, &pci_ioaddr);
+				u32 pci_ioaddr;
+				u8 pci_irq_line;
+				pcibios_read_config_byte(pci_bus, pci_device_fn,
+										 PCI_INTERRUPT_LINE, &pci_irq_line);
+				pcibios_read_config_dword(pci_bus, pci_device_fn,
+										  PCI_BASE_ADDRESS_0, &pci_ioaddr);
+				ioaddr = pci_ioaddr;
+				irq = pci_irq_line;
 #endif
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-									 PCI_COMMAND, &pci_command);
+			}
 			/* Remove I/O space marker in bit 0. */
-			pci_ioaddr &= ~3;
+			ioaddr &= ~3;
 
 			if (vendor != TCOM_VENDOR_ID)
 				continue;
 
-			for (board_index = 0; product_ids[board_index]; board_index++) {
-				if (device == product_ids[board_index])
-					break;
-			}
-			if (product_ids[board_index])
-				product_name = product_names[board_index];
-			else if ((device & 0xfff0) == 0x9000)
-				product_name = "3c900";
-			else if ((device & 0xfff0) == 0x9050)
-				product_name = "3c905";
-			else {
-				printk("Unknown 3Com PCI ethernet adapter type %4.4x detected:"
-					   " not configured.\n", device);
+			if (ioaddr == 0) {
+				printk(KERN_WARNING "  A 3Com network adapter has been found, "
+					   "however it has not been assigned an I/O address.\n"
+					   "  You may need to power-cycle the machine for this "
+					   "device to work!\n");
 				continue;
 			}
-			if (check_region(pci_ioaddr, VORTEX_TOTAL_SIZE))
+
+			if (check_region(ioaddr, VORTEX_TOTAL_SIZE))
 				continue;
 
+			/* Activate the card. */
 			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"
@@ -601,21 +681,26 @@
 										  PCI_COMMAND, new_command);
 			}
 
-			dev = vortex_found_device(dev, pci_ioaddr, pci_irq_line,
-									  product_name, dev && dev->mem_start
+			dev = vortex_found_device(dev, ioaddr, irq,
+									  device, dev && dev->mem_start
 									  ? dev->mem_start : options[cards_found],
 									  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. */
-				unsigned char new_latency = (device&0xff00) == 0x5900 ? 248 : 32;
+				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;
+				
 				pcibios_read_config_byte(pci_bus, pci_device_fn,
 										 PCI_LATENCY_TIMER, &pci_latency);
 				if (pci_latency < new_latency) {
-					printk("%s: Overriding PCI latency"
+					printk(KERN_INFO "%s: Overriding PCI latency"
 						   " timer (CFLT) setting of %d, new value is %d.\n",
 						   dev->name, pci_latency, new_latency);
 					pcibios_write_config_byte(pci_bus, pci_device_fn,
@@ -631,24 +716,19 @@
 	/* Now check all slots of the EISA bus. */
 	if (EISA_bus) {
 		static int ioaddr = 0x1000;
-		for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
-			int product_id;
-			char *product_name;
+		for ( ; ioaddr < 0x9000; ioaddr += 0x1000) {
+			int device_id;
 			if (check_region(ioaddr, VORTEX_TOTAL_SIZE))
 				continue;
 			/* Check the standard EISA ID register for an encoded '3Com'. */
 			if (inw(ioaddr + 0xC80) != 0x6d50)
 				continue;
 			/* Check for a product that we support, 3c59{2,7} any rev. */
-			product_id = inw(ioaddr + 0xC82) & 0xF0FF;
-			if (product_id == 0x7059) 		/* 597 */
-				product_name = "3c597 EISA Fast Demon/Vortex";
-			else if (product_id == 0x2059)	/* 592 */
-				product_name = "3c592 EISA 10mbps Demon/Vortex";
-			else
+			device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83);
+			if ((device_id & 0xFF00) != 0x5900)
 				continue;
 			vortex_found_device(dev, ioaddr, inw(ioaddr + 0xC88) >> 12,
-								product_name,  dev && dev->mem_start
+								device_id,  dev && dev->mem_start
 								? dev->mem_start : options[cards_found],
 								cards_found);
 			dev = 0;
@@ -659,7 +739,7 @@
 #ifdef MODULE
 	/* Special code to work-around the Compaq PCI BIOS32 problem. */
 	if (compaq_ioaddr) {
-		vortex_found_device(dev, compaq_ioaddr, compaq_irq, "3Com Vortex",
+		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++;
@@ -674,17 +754,40 @@
 
 static struct device *
 vortex_found_device(struct device *dev, int ioaddr, int irq,
-					const char *product_name, int options, int card_idx)
+					int device_id, int option, int card_idx)
 {
 	struct vortex_private *vp;
+	const char *product_name;
+	int board_index = 0;
+
+	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;
+	}
 
 #ifdef MODULE
 	/* Allocate and fill new device structure. */
-	int dev_size = sizeof(struct device) +
-		sizeof(struct vortex_private) + 15;		/* Pad for alignment */
+	{
+		int dev_size = sizeof(struct device) +
+			sizeof(struct vortex_private) + 15;		/* Pad for alignment */
 
-	dev = (struct device *) kmalloc(dev_size, GFP_KERNEL);
-	memset(dev, 0, dev_size);
+		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;
@@ -693,17 +796,17 @@
 	dev->irq = irq;
 	dev->init = vortex_probe1;
 	vp->product_name = product_name;
-	vp->options = options;
+	vp->options = option;
 	if (card_idx >= 0) {
 		if (full_duplex[card_idx] >= 0)
 			vp->full_duplex = full_duplex[card_idx];
 	} else
-		vp->full_duplex = (options >= 0 && (options & 0x10) ? 1 : 0);
+		vp->full_duplex = (option > 0 && (option & 0x10) ? 1 : 0);
 
-	if (options >= 0) {
-		vp->media_override = ((options & 7) == XCVR_10baseTOnly) ?
-			XCVR_10baseT  :  options & 7;
-		vp->bus_master = (options & 16) ? 1 : 0;
+	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;
@@ -726,11 +829,11 @@
 
 	vp  = (struct vortex_private *)dev->priv;
 	vp->product_name = product_name;
-	vp->options = options;
-	if (options >= 0) {
-		vp->media_override = ((options & 7) == 2)  ?  0  :  options & 7;
-		vp->full_duplex = (options & 8) ? 1 : 0;
-		vp->bus_master = (options & 16) ? 1 : 0;
+	vp->options = option;
+	if (option >= 0) {
+		vp->media_override = ((option & 7) == 2)  ?  0  :  option & 7;
+		vp->full_duplex = (option & 8) ? 1 : 0;
+		vp->bus_master = (option & 16) ? 1 : 0;
 	} else {
 		vp->media_override = 7;
 		vp->full_duplex = 0;
@@ -746,63 +849,87 @@
 {
 	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("%s: 3Com %s at %#3x,", dev->name,
-		   vp->product_name, ioaddr);
+	printk(KERN_INFO "%s: 3Com %s at %#3x,",
+		   dev->name, vp->product_name, ioaddr);
 
 	/* Read the station address from the EEPROM. */
 	EL3WINDOW(0);
-	for (i = 0; i < 0x18; i++) {
-		u16 *phys_addr = (u16 *)dev->dev_addr;
+	for (i = 0; i < 0x40; i++) {
 		int timer;
+#ifdef CARDBUS
+		outw(0x230 + i, ioaddr + Wn0EepromCmd);
+#else
 		outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
+#endif
 		/* Pause for at least 162 us. for the read to take place. */
-		for (timer = 4; timer >= 0; timer--) {
+		for (timer = 10; timer >= 0; timer--) {
 			udelay(162);
 			if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0)
 				break;
 		}
 		eeprom[i] = inw(ioaddr + Wn0EepromData);
-		checksum ^= eeprom[i];
-		if (i >= 10 && i < 13)
-			phys_addr[i - 10] = htons(inw(ioaddr + Wn0EepromData));
 	}
+	for (i = 0; i < 0x18; i++)
+		checksum ^= eeprom[i];
 	checksum = (checksum ^ (checksum >> 8)) & 0xff;
+	if (checksum != 0x00) {		/* Grrr, needless incompatible change 3Com. */
+		while (i < 0x21)
+			checksum ^= eeprom[i++];
+		checksum = (checksum ^ (checksum >> 8)) & 0xff;
+	}
 	if (checksum != 0x00)
 		printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
+
+	for (i = 0; i < 3; i++)
+		ether_addr[i] = htons(eeprom[i + 10]);
 	for (i = 0; i < 6; i++)
 		printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
 	printk(", IRQ %d\n", dev->irq);
 	/* Tell them about an invalid IRQ. */
 	if (vortex_debug && (dev->irq <= 0 || dev->irq >= NR_IRQS))
-		printk(" *** Warning: this IRQ is unlikely to work! ***\n");
+		printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",
+			   dev->irq);
+
+	/* Extract our information from the EEPROM data. */
+	vp->info1 = eeprom[13];
+	vp->info2 = eeprom[15];
+	vp->capabilities = eeprom[16];
+
+	if (vp->info1 & 0x8000)
+		vp->full_duplex = 1;
 
 	{
 		char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
 		union wn3_config config;
 		EL3WINDOW(3);
 		vp->available_media = inw(ioaddr + Wn3_Options);
+		if ((vp->available_media & 0xff) == 0)		/* Broken 3c916 */
+			vp->available_media = 0x40;
 		config.i = inl(ioaddr + Wn3_Config);
 		if (vortex_debug > 1)
-			printk("  Internal config register is %4.4x, transceivers %#x.\n",
-				   config.i, inw(ioaddr + Wn3_Options));
-		printk("  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
+			printk(KERN_DEBUG "  Internal config register is %4.4x, "
+				   "transceivers %#x.\n", config.i, inw(ioaddr + Wn3_Options));
+		printk(KERN_INFO "  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
 			   8 << config.u.ram_size,
 			   config.u.ram_width ? "word" : "byte",
 			   ram_split[config.u.ram_split],
 			   config.u.autoselect ? "autoselect/" : "",
+			   config.u.xcvr ? "NWay Autonegotiation" :
 			   media_tbl[config.u.xcvr].name);
-		dev->if_port = config.u.xcvr;
 		vp->default_media = config.u.xcvr;
 		vp->autoselect = config.u.autoselect;
 	}
+
 	if (vp->media_override != 7) {
-		printk("  Media override to transceiver type %d (%s).\n",
+		printk(KERN_INFO "  Media override to transceiver type %d (%s).\n",
 			   vp->media_override, media_tbl[vp->media_override].name);
 		dev->if_port = vp->media_override;
-	}
+	} else
+		dev->if_port = vp->default_media;
 
 	if (dev->if_port == XCVR_MII) {
 		int phy, phy_idx = 0;
@@ -810,31 +937,34 @@
 		for (phy = 0; phy < 32 && phy_idx < sizeof(vp->phys); phy++) {
 			int mii_status;
 			mdio_sync(ioaddr, 32);
-			mii_status = mdio_read(ioaddr, phy, 0);
-			if (mii_status != 0xffff) {
+			mii_status = mdio_read(ioaddr, phy, 1);
+			if (mii_status  &&  mii_status != 0xffff) {
 				vp->phys[phy_idx++] = phy;
-				printk("%s: MII transceiver found at address %d.\n",
-					   dev->name, 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;
 			}
 		}
 		if (phy_idx == 0) {
-			printk("%s: ***WARNING*** No MII transceivers found!\n",
-				   dev->name);
-			vp->phys[0] = 0;
+			printk(KERN_WARNING"  ***WARNING*** No MII transceivers found!\n");
+			vp->phys[0] = 24;
+		} else {
+			vp->advertising = mdio_read(ioaddr, vp->phys[0], 4);
+			if (vp->full_duplex) {
+				/* Only advertise the FD media types. */
+				vp->advertising &= 0x015F;
+				mdio_write(ioaddr, vp->phys[0], 4, vp->advertising);
+			}
 		}
 	}
 
-	vp->info1 = eeprom[13];
-	vp->info2 = eeprom[15];
-	vp->capabilities = eeprom[16];
-	if (vp->capabilities & 0x20) {
-	  vp->full_bus_master_tx = 1;
-	  printk("  Enabling bus-master transmits and %s receives.\n",
-			 (vp->info2 & 1) ? "early" : "whole-frame" );
-	  vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2;
+	if (vp->capabilities & CapBusMaster) {
+		vp->full_bus_master_tx = 1;
+		printk(KERN_INFO"  Enabling bus-master transmits and %s receives.\n",
+			   (vp->info2 & 1) ? "early" : "whole-frame" );
+		vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2;
 	}
 
 	/* We do a request_region() to register /proc/ioports info. */
@@ -856,86 +986,6 @@
 
 	return 0;
 }
-
-/* Read and write the MII registers using software-generated serial
-   MDIO protocol.  The maxium data clock rate is 2.5 Mhz. */
-#define mdio_delay() udelay(1)
-
-#define MDIO_SHIFT_CLK	0x01
-#define MDIO_DIR_WRITE	0x04
-#define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE)
-#define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE)
-#define MDIO_DATA_READ	0x02
-#define MDIO_ENB_IN		0x00
-
-static void mdio_sync(int ioaddr, int bits)
-{
-	int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
-
-	/* Establish sync by sending at least 32 logic ones. */ 
-	while (-- bits >= 0) {
-		outw(MDIO_DATA_WRITE1, mdio_addr);
-		mdio_delay();
-		outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-}
-static int mdio_read(int 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;
-
-	if (mii_preamble_required)
-		mdio_sync(ioaddr, 32);
-
-	/* Shift the read command bits out. */
-	for (i = 14; i >= 0; i--) {
-		int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
-		outw(dataval, mdio_addr);
-		mdio_delay();
-		outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	/* Read the two transition, 16 data, and wire-idle bits. */
-	for (i = 19; i > 0; i--) {
-		outw(MDIO_ENB_IN, mdio_addr);
-		mdio_delay();
-		retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
-		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	return retval>>1 & 0xffff;
-}
-
-static void mdio_write(int ioaddr, int phy_id, int location, int value)
-{
-	int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
-	int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
-	int i;
-
-	if (mii_preamble_required)
-		mdio_sync(ioaddr, 32);
-
-	/* Shift the command bits out. */
-	for (i = 31; i >= 0; i--) {
-		int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
-		outw(dataval, mdio_addr);
-		mdio_delay();
-		outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-	/* Leave the interface idle. */
-	for (i = 1; i >= 0; i--) {
-		outw(MDIO_ENB_IN, mdio_addr);
-		mdio_delay();
-		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
-		mdio_delay();
-	}
-
-	return;
-}
 
 
 static int
@@ -952,7 +1002,7 @@
 
 	if (vp->media_override != 7) {
 		if (vortex_debug > 1)
-			printk("%s: Media override to transceiver %d (%s).\n",
+			printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n",
 				   dev->name, vp->media_override,
 				   media_tbl[vp->media_override].name);
 		dev->if_port = vp->media_override;
@@ -963,7 +1013,7 @@
 			dev->if_port = media_tbl[dev->if_port].next;
 
 		if (vortex_debug > 1)
-			printk("%s: Initial media type %s.\n",
+			printk(KERN_DEBUG "%s: Initial media type %s.\n",
 				   dev->name, media_tbl[dev->if_port].name);
 
 		init_timer(&vp->timer);
@@ -979,8 +1029,6 @@
 
 	if (dev->if_port == XCVR_MII) {
 		int mii_reg1, mii_reg5;
-		/* We cheat here: we know that we are using the 83840 transceiver
-		   which summarizes the FD status in an extended register. */
 		EL3WINDOW(4);
 		/* Read BMSR (reg1) only to clear old status. */
 		mii_reg1 = mdio_read(ioaddr, vp->phys[0], 1);
@@ -991,7 +1039,7 @@
 				 || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */
 			vp->full_duplex = 1;
 		if (vortex_debug > 1)
-			printk("%s: MII #%d status %4.4x, link partner capability %4.4x,"
+			printk(KERN_INFO "%s: MII #%d status %4.4x, link partner capability %4.4x,"
 				   " setting %s-duplex.\n", dev->name, vp->phys[0],
 				   mii_reg1, mii_reg5, vp->full_duplex ? "full" : "half");
 		EL3WINDOW(3);
@@ -1002,18 +1050,18 @@
 		 (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);
 
 	if (vortex_debug > 1) {
-		printk("%s: vortex_open() InternalConfig %8.8x.\n",
+		printk(KERN_DEBUG "%s: vortex_open() InternalConfig %8.8x.\n",
 			dev->name, config.i);
 	}
 
 	outw(TxReset, ioaddr + EL3_CMD);
-	for (i = 20; i >= 0 ; i--)
+	for (i = 2000; i >= 0 ; i--)
 		if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
 			break;
 
 	outw(RxReset, ioaddr + EL3_CMD);
 	/* Wait a few ticks for the RxReset command to complete. */
-	for (i = 20; i >= 0 ; i--)
+	for (i = 2000; i >= 0 ; i--)
 		if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
 			break;
 
@@ -1021,8 +1069,7 @@
 
 #ifdef SA_SHIRQ
 	/* Use the now-standard shared IRQ implementation. */
-	if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ,
-					vp->product_name, dev)) {
+	if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, dev->name, dev)) {
 		return -EAGAIN;
 	}
 #else
@@ -1037,7 +1084,7 @@
 
 	if (vortex_debug > 1) {
 		EL3WINDOW(4);
-		printk("%s: vortex_open() irq %d media status %4.4x.\n",
+		printk(KERN_DEBUG "%s: vortex_open() irq %d media status %4.4x.\n",
 			   dev->name, dev->irq, inw(ioaddr + Wn4_Media));
 	}
 
@@ -1077,7 +1124,7 @@
 		outw(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD);
 		outl(0x0020, ioaddr + PktStatus);
 		if (vortex_debug > 2)
-			printk("%s:  Filling in the Rx ring.\n", dev->name);
+			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]);
@@ -1111,6 +1158,7 @@
 	set_rx_mode(dev);
 	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
 
+	vp->in_interrupt = 0;
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
@@ -1118,16 +1166,16 @@
 	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
 	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
 	/* Allow status bits to be seen. */
-	outw(SetStatusEnb | AdapterFailure|IntReq|StatsFull|TxComplete|
-		 (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
-		 (vp->full_bus_master_rx ? UpComplete : RxComplete) |
-		 (vp->bus_master ? DMADone : 0),
-		 ioaddr + EL3_CMD);
+	vp->status_enable = SetStatusEnb | HostError|IntReq|StatsFull|TxComplete|
+		(vp->full_bus_master_tx ? DownComplete : TxAvailable) |
+		(vp->full_bus_master_rx ? UpComplete : RxComplete) |
+		(vp->bus_master ? DMADone : 0);
+	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
-		 | AdapterFailure | TxComplete
+		 | HostError | TxComplete
 		 | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
 			ioaddr + EL3_CMD);
 
@@ -1146,7 +1194,7 @@
 	int ok = 0;
 
 	if (vortex_debug > 1)
-		printk("%s: Media selection timer tick happened, %s.\n",
+		printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n",
 			   dev->name, media_tbl[dev->if_port].name);
 
 	save_flags(flags);	cli(); {
@@ -1159,10 +1207,10 @@
 		if (media_status & Media_LnkBeat) {
 		  ok = 1;
 		  if (vortex_debug > 1)
-			printk("%s: Media %s has link beat, %x.\n",
+			printk(KERN_DEBUG "%s: Media %s has link beat, %x.\n",
 				   dev->name, media_tbl[dev->if_port].name, media_status);
 		} else if (vortex_debug > 1)
-		  printk("%s: Media %s is has no link beat, %x.\n",
+		  printk(KERN_DEBUG "%s: Media %s is has no link beat, %x.\n",
 				   dev->name, media_tbl[dev->if_port].name, media_status);
 
 		break;
@@ -1171,7 +1219,7 @@
 			  int mii_reg1 = mdio_read(ioaddr, vp->phys[0], 1);
 			  int mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);
 			  if (vortex_debug > 1)
-				  printk("%s: MII #%d status register is %4.4x, "
+				  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)
@@ -1180,7 +1228,7 @@
 		  }
 	  default:					/* Other media types handled by Tx timeouts. */
 		if (vortex_debug > 1)
-		  printk("%s: Media %s is has no indication, %x.\n",
+		  printk(KERN_DEBUG "%s: Media %s is has no indication, %x.\n",
 				 dev->name, media_tbl[dev->if_port].name, media_status);
 		ok = 1;
 	  }
@@ -1193,11 +1241,13 @@
 		if (dev->if_port == XCVR_Default) { /* Go back to default. */
 		  dev->if_port = vp->default_media;
 		  if (vortex_debug > 1)
-			printk("%s: Media selection failing, using default %s port.\n",
+			printk(KERN_DEBUG "%s: Media selection failing, using default "
+				   "%s port.\n",
 				   dev->name, media_tbl[dev->if_port].name);
 		} else {
 		  if (vortex_debug > 1)
-			printk("%s: Media selection failed, now trying %s port.\n",
+			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);
@@ -1216,7 +1266,7 @@
 	  EL3WINDOW(old_window);
 	}   restore_flags(flags);
 	if (vortex_debug > 1)
-	  printk("%s: Media selection timer finished, %s.\n",
+	  printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",
 			 dev->name, media_tbl[dev->if_port].name);
 
 #endif /* AUTOMEDIA*/
@@ -1227,84 +1277,59 @@
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	int ioaddr = dev->base_addr;
-	int i;
+	int j;
 
-	printk("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
+	printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
 		   dev->name, inb(ioaddr + TxStatus),
 		   inw(ioaddr + EL3_STATUS));
 	/* Slight code bloat to be user friendly. */
 	if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
-		printk("%s: Transmitter encountered 16 collisions --"
+		printk(KERN_ERR "%s: Transmitter encountered 16 collisions --"
 			   " network cable problem?\n", dev->name);
 	if (inw(ioaddr + EL3_STATUS) & IntLatch) {
-		printk("%s: Interrupt posted but not handled --"
+		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);
 	}
-#ifndef final_version
+	outw(TxReset, ioaddr + EL3_CMD);
+	for (j = 200; j >= 0 ; j--)
+		if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+			break;
+
+#if ! defined(final_version) && LINUX_VERSION_CODE >= 0x10300
 	if (vp->full_bus_master_tx) {
-		printk("  Flags; bus-master %d, full %d; dirty %d current %d.\n",
+		int i;
+		printk(KERN_DEBUG "  Flags; bus-master %d, full %d; dirty %d "
+			   "current %d.\n",
 			   vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx);
-		printk("  Transmit list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
+		printk(KERN_DEBUG "  Transmit list %8.8x vs. %p.\n",
+			   inl(ioaddr + DownListPtr),
 			   &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
 		for (i = 0; i < TX_RING_SIZE; i++) {
-			printk("  %d: @%p  length %8.8x status %8.8x\n", 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);
 		}
 	}
-#ifdef notdef
-	if (vp->full_bus_master_rx) {
-		printk("  Switching to non-bus-master receives.\n");
-		outw(SetStatusEnb | AdapterFailure|IntReq|StatsFull |
-			 (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
-			 RxComplete | (vp->bus_master ? DMADone : 0),
-			 ioaddr + EL3_CMD);
-	}
-	/* Issue TX_RESET and TX_START commands. */
-	outw(TxReset, ioaddr + EL3_CMD);
-	for (i = 20; i >= 0 ; i--)
-	  if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
-		break;
-#endif
 #endif
+	vp->stats.tx_errors++;
 	if (vp->full_bus_master_tx) {
-	  /*  Change 6/25/97 Michael Sievers sieversm@mail.desy.de
-              The card has been resetted, but the Tx Ring is still full.
-		 Since the card won't know where to resume, 'update' the
-		 Tx Ring. Probably, we'll lose 16 packets this way, these
-		 will be accounted for as 'dropped'. The code to update the
-		 Tx Ring is taken from the Interrupt handler. */
-   
-	  unsigned int dirty_tx = vp->dirty_tx;
-	  
-	  if (vortex_debug > 0)
-		  printk("%s: Freeing Tx ring entries:", dev->name);
-	  while (vp->cur_tx - dirty_tx > 0) {
-		int entry = dirty_tx % TX_RING_SIZE;
-		if (inl(ioaddr + DownListPtr) ==
-			virt_to_bus(&vp->tx_ring[entry]))
-		  break;			/* It still hasn't been processed. */
-		if (vp->tx_skbuff[entry]) {
-			if (vortex_debug > 0)
-				printk(" %d\n", entry);
-			dev_kfree_skb(vp->tx_skbuff[entry]);
-			vp->tx_skbuff[entry] = 0;
-			vp->stats.tx_dropped++;
-		}
 		if (vortex_debug > 0)
-			printk(".\n");
-		vp->stats.tx_errors++;
-		dirty_tx++;
-	  }
-	  vp->dirty_tx = dirty_tx;
-	  vp->tx_full= 0;
-	} else {     /* not bus-master, no Tx ring to clear */
-	  vp->stats.tx_errors++;
-	  vp->stats.tx_dropped++;
-	}
+			printk(KERN_DEBUG "%s: Resetting the Tx ring pointer.\n",
+				   dev->name);
+		if (vp->cur_tx - vp->dirty_tx > 0  &&  inl(ioaddr + DownListPtr) == 0)
+			outl(virt_to_bus(&vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]),
+				 ioaddr + DownListPtr);
+		if (vp->tx_full && (vp->cur_tx - vp->dirty_tx <= TX_RING_SIZE - 1)) {
+			vp->tx_full = 0;
+			clear_bit(0, (void*)&dev->tbusy);
+		}
+		outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
+		outw(DownUnstall, ioaddr + EL3_CMD);
+	} else
+		vp->stats.tx_dropped++;
 	
 	/* Issue Tx Enable */
 	outw(TxEnable, ioaddr + EL3_CMD);
@@ -1312,20 +1337,99 @@
 	
 	/* Switch to register set 7 for normal use. */
 	EL3WINDOW(7);
-	
-	/* The TxFreeThreshold has to be set again after a reset! */
-	if (vp->full_bus_master_tx) {  
-	  outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
-	  /* This is to be sure that all bus-master Tx features
-		 are correctly re-initialized after a reset, although
-		 the DownListPtr should already be 0 at this point. */
-	  outl(0, ioaddr + DownListPtr);
+}
+
+/*
+ * Handle uncommon interrupt sources.  This is a seperate 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;
+	int do_tx_reset = 0;
+	int i;
+
+	if (status & TxComplete) {			/* Really "TxError" for us. */
+		unsigned char tx_status = inb(ioaddr + TxStatus);
+		/* Presumably a tx-timeout. We must merely re-enable. */
+		if (vortex_debug > 2
+			|| (tx_status != 0x88 && vortex_debug > 0))
+			printk(KERN_DEBUG"%s: Transmit error, Tx status register %2.2x.\n",
+				   dev->name, tx_status);
+		if (tx_status & 0x14)  vp->stats.tx_fifo_errors++;
+		if (tx_status & 0x38)  vp->stats.tx_aborted_errors++;
+		outb(0, ioaddr + TxStatus);
+		if (tx_status & 0x30)
+			do_tx_reset = 1;
+		else					/* Merely re-enable the transmitter. */
+			outw(TxEnable, ioaddr + EL3_CMD);
 	}
-	/* finally, allow new Transmits */
-	dev->tbusy = 0;
-	/* End of Michael Sievers <sieversm@mail.desy.de> changes. */
+	if (status & RxEarly) {				/* Rx early is unused. */
+		vortex_rx(dev);
+		outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
+	}
+	if (status & StatsFull) {			/* Empty statistics. */
+		static int DoneDidThat = 0;
+		if (vortex_debug > 4)
+			printk(KERN_DEBUG "%s: Updating stats.\n", dev->name);
+		update_stats(ioaddr, dev);
+		/* HACK: Disable statistics as an interrupt source. */
+		/* This occurs when we have the wrong media type! */
+		if (DoneDidThat == 0  &&
+			inw(ioaddr + EL3_STATUS) & StatsFull) {
+			printk(KERN_WARNING "%s: Updating statistics failed, disabling "
+				   "stats as an interrupt source.\n", dev->name);
+			EL3WINDOW(5);
+			outw(SetIntrEnb | (inw(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD);
+			EL3WINDOW(7);
+			DoneDidThat++;
+		}
+	}
+	if (status & IntReq)		/* Restore all interrupt sources.  */
+		outw(ioaddr + EL3_CMD, vp->status_enable);
+	if (status & HostError) {
+		u16 fifo_diag;
+		EL3WINDOW(4);
+		fifo_diag = inw(ioaddr + Wn4_FIFODiag);
+		if (vortex_debug > 0)
+			printk(KERN_ERR "%s: Host error, FIFO diagnostic register %4.4x.\n",
+				   dev->name, fifo_diag);
+		/* Adapter failure requires Tx/Rx reset and reinit. */
+		if (vp->full_bus_master_tx) {
+			outw(TotalReset | 0xff, ioaddr + EL3_CMD);
+			for (i = 2000; i >= 0 ; i--)
+				if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+					break;
+			/* Re-enable the receiver. */
+			outw(RxEnable, ioaddr + EL3_CMD);
+			outw(TxEnable, ioaddr + EL3_CMD);
+		} else if (fifo_diag & 0x0400)
+			do_tx_reset = 1;
+		if (fifo_diag & 0x3000) {
+			outw(RxReset, ioaddr + EL3_CMD);
+			for (i = 2000; i >= 0 ; i--)
+				if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+					break;
+			/* Set the Rx filter to the current state. */
+			set_rx_mode(dev);
+			outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
+			outw(AckIntr | HostError, ioaddr + EL3_CMD);
+		}
+	}
+	if (do_tx_reset) {
+		int j;
+		outw(TxReset, ioaddr + EL3_CMD);
+		for (j = 200; j >= 0 ; j--)
+			if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+				break;
+		outw(TxEnable, ioaddr + EL3_CMD);
+	}
+
 }
 
+
 static int
 vortex_start_xmit(struct sk_buff *skb, struct device *dev)
 {
@@ -1343,7 +1447,7 @@
 #ifdef VORTEX_BUS_MASTER
 	if (vp->bus_master) {
 		/* Set the bus-master controller to transfer the packet. */
-		outl((int)(skb->data), ioaddr + Wn7_MasterAddr);
+		outl(virt_to_bus(skb->data), ioaddr + Wn7_MasterAddr);
 		outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
 		vp->tx_skb = skb;
 		outw(StartDMADown, ioaddr + EL3_CMD);
@@ -1351,9 +1455,9 @@
 	} else {
 		/* ... and the packet rounded to a doubleword. */
 		outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-		dev_kfree_skb (skb);
+		DEV_FREE_SKB(skb);
 		if (inw(ioaddr + TxFree) > 1536) {
-			dev->tbusy = 0;
+			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);
@@ -1361,9 +1465,9 @@
 #else
 	/* ... and the packet rounded to a doubleword. */
 	outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-	dev_kfree_skb (skb);
+	DEV_FREE_SKB(skb);
 	if (inw(ioaddr + TxFree) > 1536) {
-		dev->tbusy = 0;
+		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);
@@ -1373,20 +1477,20 @@
 
 	/* Clear the Tx status stack. */
 	{
-		short tx_status;
+		int tx_status;
 		int i = 32;
 
 		while (--i > 0	&&	(tx_status = inb(ioaddr + TxStatus)) > 0) {
 			if (tx_status & 0x3C) {		/* A Tx-disabling error occurred.  */
 				if (vortex_debug > 2)
-				  printk("%s: Tx error, status %2.2x.\n",
+				  printk(KERN_DEBUG "%s: Tx error, status %2.2x.\n",
 						 dev->name, tx_status);
 				if (tx_status & 0x04) vp->stats.tx_fifo_errors++;
 				if (tx_status & 0x38) vp->stats.tx_aborted_errors++;
 				if (tx_status & 0x30) {
 					int j;
 					outw(TxReset, ioaddr + EL3_CMD);
-					for (j = 20; j >= 0 ; j--)
+					for (j = 200; j >= 0 ; j--)
 						if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
 							break;
 				}
@@ -1417,11 +1521,11 @@
 		int i;
 
 		if (vortex_debug > 3)
-			printk("%s: Trying to send a packet, Tx index %d.\n",
+			printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
 				   dev->name, vp->cur_tx);
 		if (vp->tx_full) {
 			if (vortex_debug >0)
-				printk("%s: Tx Ring full, refusing to send buffer.\n",
+				printk(KERN_WARNING "%s: Tx Ring full, refusing to send buffer.\n",
 					   dev->name);
 			return 1;
 		} 
@@ -1436,7 +1540,7 @@
 		cli();
 		outw(DownStall, ioaddr + EL3_CMD);
 		/* Wait for the stall to complete. */
-		for (i = 60; i >= 0 ; i--)
+		for (i = 600; i >= 0 ; i--)
 			if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
 				break;
 		prev_entry->next = virt_to_bus(&vp->tx_ring[entry]);
@@ -1452,7 +1556,7 @@
 			vp->tx_full = 1;
 		else {					/* Clear previous interrupt enable. */
 			prev_entry->status &= ~TxIntrUploaded;
-			dev->tbusy = 0;
+			clear_bit(0, (void*)&dev->tbusy);
 		}
 		dev->trans_start = jiffies;
 		return 0;
@@ -1468,186 +1572,108 @@
 #else
 	struct device *dev = (struct device *)(irq2dev_map[irq]);
 #endif
-	struct vortex_private *lp;
+	struct vortex_private *vp;
 	int ioaddr, status;
 	int latency;
-	int i = max_interrupt_work;
+	int work_done = max_interrupt_work;
 
-	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+	vp = (struct vortex_private *)dev->priv;
+	if (test_and_set_bit(0, (void*)&vp->in_interrupt)) {
 		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
 		return;
 	}
 
+	dev->interrupt = 1;
 	ioaddr = dev->base_addr;
 	latency = inb(ioaddr + Timer);
-	lp = (struct vortex_private *)dev->priv;
 
 	status = inw(ioaddr + EL3_STATUS);
 
 	if (vortex_debug > 4)
-		printk("%s: interrupt, status %4.4x, timer %d.\n", dev->name,
-			   status, latency);
-#ifdef notdef
-	/* This code guard against bogus hangs, but fails with shared IRQs. */
-	if ((status & ~0xE000) == 0x0000) {
-		static int donedidthis=0;
-		/* Some interrupt controllers store a bogus interrupt from boot-time.
-		   Ignore a single early interrupt, but don't hang the machine for
-		   other interrupt problems. */
-		if (donedidthis++ > 100) {
-			printk("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
-				   dev->name, status, dev->start);
-			FREE_IRQ(dev->irq, dev);
-		}
-	}
-#endif
-
+		printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
+			   dev->name, status, latency);
 	do {
 		if (vortex_debug > 5)
-				printk("%s: In interrupt loop, status %4.4x.\n",
+				printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n",
 					   dev->name, status);
 		if (status & RxComplete)
 			vortex_rx(dev);
+		if (status & UpComplete) {
+			outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
+			boomerang_rx(dev);
+		}
 
 		if (status & TxAvailable) {
 			if (vortex_debug > 5)
-				printk("	TX room bit was handled.\n");
+				printk(KERN_DEBUG "	TX room bit was handled.\n");
 			/* There's room in the FIFO for a full-sized packet. */
 			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-			dev->tbusy = 0;
+			clear_bit(0, (void*)&dev->tbusy);
 			mark_bh(NET_BH);
 		}
-		if (status & TxComplete) { /* Really "TxError" for us. */
-			unsigned char tx_status = inb(ioaddr + TxStatus);
-			/* Presumably a tx-timeout. We must merely re-enable. */
-			if (vortex_debug > 2
-				|| (tx_status != 0x88 && vortex_debug > 0))
-				printk("%s: Transmit error, Tx status register %2.2x.\n",
-					   dev->name, tx_status);
-			if (tx_status & 0x04) lp->stats.tx_fifo_errors++;
-			if (tx_status & 0x38) lp->stats.tx_aborted_errors++;
-			outb(0, ioaddr + TxStatus);
-			outw(TxEnable, ioaddr + EL3_CMD);
-		}
+
 		if (status & DownComplete) {
-			unsigned int dirty_tx = lp->dirty_tx;
+			unsigned int dirty_tx = vp->dirty_tx;
 
-			while (lp->cur_tx - dirty_tx > 0) {
+			while (vp->cur_tx - dirty_tx > 0) {
 				int entry = dirty_tx % TX_RING_SIZE;
 				if (inl(ioaddr + DownListPtr) ==
-					virt_to_bus(&lp->tx_ring[entry]))
+					virt_to_bus(&vp->tx_ring[entry]))
 					break;			/* It still hasn't been processed. */
-				if (lp->tx_skbuff[entry]) {
-					dev_kfree_skb(lp->tx_skbuff[entry]);
-					lp->tx_skbuff[entry] = 0;
+				if (vp->tx_skbuff[entry]) {
+					DEV_FREE_SKB(vp->tx_skbuff[entry]);
+					vp->tx_skbuff[entry] = 0;
 				}
-				/* lp->stats.tx_packets++;  Counted below. */
+				/* vp->stats.tx_packets++;  Counted below. */
 				dirty_tx++;
 			}
-			lp->dirty_tx = dirty_tx;
+			vp->dirty_tx = dirty_tx;
 			outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
-			if (lp->tx_full && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
-				lp->tx_full= 0;
-				dev->tbusy = 0;
+			if (vp->tx_full && (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
+				vp->tx_full= 0;
+				clear_bit(0, (void*)&dev->tbusy);
 				mark_bh(NET_BH);
 			}
 		}
 #ifdef VORTEX_BUS_MASTER
 		if (status & DMADone) {
 			outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
-			dev->tbusy = 0;
-			dev_kfree_skb (lp->tx_skb); /* Release the transfered buffer */
+			clear_bit(0, (void*)&dev->tbusy);
+			DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
 			mark_bh(NET_BH);
 		}
 #endif
-		if (status & UpComplete) {
-			boomerang_rx(dev);
-			outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
-		}
-		if (status & (AdapterFailure | RxEarly | StatsFull)) {
-			/* Handle all uncommon interrupts at once. */
-			if (status & RxEarly) {				/* Rx early is unused. */
-				vortex_rx(dev);
-				outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
-			}
-			if (status & StatsFull) { 	/* Empty statistics. */
-				static int DoneDidThat = 0;
-				if (vortex_debug > 4)
-					printk("%s: Updating stats.\n", dev->name);
-				update_stats(ioaddr, dev);
-				/* DEBUG HACK: Disable statistics as an interrupt source. */
-				/* This occurs when we have the wrong media type! */
-				if (DoneDidThat == 0  &&
-					inw(ioaddr + EL3_STATUS) & StatsFull) {
-					int win, reg;
-					printk("%s: Updating stats failed, disabling stats as an"
-						   " interrupt source.\n", dev->name);
-					for (win = 0; win < 8; win++) {
-						EL3WINDOW(win);
-						printk("\n Vortex window %d:", win);
-						for (reg = 0; reg < 16; reg++)
-							printk(" %2.2x", inb(ioaddr+reg));
-					}
-					EL3WINDOW(7);
-					outw(SetIntrEnb | TxAvailable | RxComplete | AdapterFailure
-						 | UpComplete | DownComplete | TxComplete,
-						 ioaddr + EL3_CMD);
-					DoneDidThat++;
-				}
-			}
-			if (status & AdapterFailure) {
-				u16 fifo_diag;
-				EL3WINDOW(4);
-				fifo_diag = inw(ioaddr + Wn4_FIFODiag);
-				if (vortex_debug > 0)
-					printk("%s: Host error, FIFO diagnostic register %4.4x.\n",
-						   dev->name, fifo_diag);
-				/* Adapter failure requires Tx/Rx reset and reinit. */
-				if (lp->full_bus_master_tx) {
-					int j;
-					outw(TotalReset | 0xff, ioaddr + EL3_CMD);
-					for (j = 200; j >= 0 ; j--)
-					if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
-						break;
-					/* Re-enable the receiver. */
-					outw(RxEnable, ioaddr + EL3_CMD);
-					outw(TxEnable, ioaddr + EL3_CMD);
-				} else if (fifo_diag & 0x0400) {
-					int j;
-					outw(TxReset, ioaddr + EL3_CMD);
-					for (j = 20; j >= 0 ; j--)
-						if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
-							break;
-					outw(TxEnable, ioaddr + EL3_CMD);
-				}
-				if (fifo_diag & 0x2000) {
-					outw(RxReset, ioaddr + EL3_CMD);
-					/* Set the Rx filter to the current state. */
-					set_rx_mode(dev);
-					outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
-					outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
-				}
+		/* Check for all uncommon interrupts at once. */
+		if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq))
+			vortex_error(dev, status);
+
+		if (--work_done < 0) {
+			if ((status & (0x7fe - (UpComplete | DownComplete))) == 0) {
+				/* Just ack these and return. */
+				outw(AckIntr | UpComplete | DownComplete, ioaddr + EL3_CMD);
+			} else {
+				printk(KERN_WARNING "%s: Too much work in interrupt, status "
+					   "%4.4x.  Temporarily disabling functions (%4.4x).\n",
+					   dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
+				/* Disable all pending interrupts. */
+				outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
+				outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
+				/* Set a timer to reenable interrupts. */
+				
+				break;
 			}
 		}
-
-		if (--i < 0) {
-			printk("%s: Too much work in interrupt, status %4.4x.  "
-				   "Disabling functions (%4.4x).\n",
-				   dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
-			/* Disable all pending interrupts. */
-			outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
-			outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
-			break;
-		}
 		/* Acknowledge the IRQ. */
 		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
 
 	} while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
 
 	if (vortex_debug > 4)
-		printk("%s: exiting interrupt, status %4.4x.\n", dev->name, status);
+		printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
+			   dev->name, status);
 
 	dev->interrupt = 0;
+	clear_bit(0, (void*)&vp->in_interrupt);
 	return;
 }
 
@@ -1660,13 +1686,13 @@
 	short rx_status;
 
 	if (vortex_debug > 5)
-		printk("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
+		printk(KERN_DEBUG"   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
 			   inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
 	while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
 		if (rx_status & 0x4000) { /* Error, update stats. */
 			unsigned char rx_error = inb(ioaddr + RxErrors);
 			if (vortex_debug > 2)
-				printk(" Rx error: status %2.2x.\n", rx_error);
+				printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error);
 			vp->stats.rx_errors++;
 			if (rx_error & 0x01)  vp->stats.rx_over_errors++;
 			if (rx_error & 0x02)  vp->stats.rx_length_errors++;
@@ -1675,12 +1701,12 @@
 			if (rx_error & 0x10)  vp->stats.rx_length_errors++;
 		} else {
 			/* The packet length: up to 4.5K!. */
-			short pkt_len = rx_status & 0x1fff;
+			int pkt_len = rx_status & 0x1fff;
 			struct sk_buff *skb;
 
 			skb = DEV_ALLOC_SKB(pkt_len + 5);
 			if (vortex_debug > 4)
-				printk("Receiving packet size %d status %4.4x.\n",
+				printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n",
 					   pkt_len, rx_status);
 			if (skb != NULL) {
 				skb->dev = dev;
@@ -1706,8 +1732,8 @@
 						break;
 				continue;
 			} else if (vortex_debug)
-				printk("%s: Couldn't allocate a sk_buff of size %d.\n",
-					   dev->name, pkt_len);
+				printk(KERN_NOTICE "%s: No memory to allocate a sk_buff of "
+					   "size %d.\n", dev->name, pkt_len);
 		}
 		outw(RxDiscard, ioaddr + EL3_CMD);
 		vp->stats.rx_dropped++;
@@ -1730,13 +1756,15 @@
 	int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx;
 
 	if (vortex_debug > 5)
-		printk("   In boomerang_rx(), status %4.4x, rx_status %4.4x.\n",
+		printk(KERN_DEBUG "  In boomerang_rx(), status %4.4x, rx_status "
+			   "%4.4x.\n",
 			   inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
-	while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) {
+	while ((--rx_work_limit >= 0) &&
+			((rx_status = vp->rx_ring[entry].status) & RxDComplete)) {
 		if (rx_status & RxDError) { /* Error, update stats. */
 			unsigned char rx_error = rx_status >> 16;
 			if (vortex_debug > 2)
-				printk(" Rx error: status %2.2x.\n", rx_error);
+				printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error);
 			vp->stats.rx_errors++;
 			if (rx_error & 0x01)  vp->stats.rx_over_errors++;
 			if (rx_error & 0x02)  vp->stats.rx_length_errors++;
@@ -1745,11 +1773,11 @@
 			if (rx_error & 0x10)  vp->stats.rx_length_errors++;
 		} else {
 			/* The packet length: up to 4.5K!. */
-			short pkt_len = rx_status & 0x1fff;
+			int pkt_len = rx_status & 0x1fff;
 			struct sk_buff *skb;
 
 			if (vortex_debug > 4)
-				printk("Receiving packet size %d status %4.4x.\n",
+				printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n",
 					   pkt_len, rx_status);
 
 			/* Check if the packet is long enough to just accept without
@@ -1772,18 +1800,34 @@
 				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)
-					printk("%s: Warning -- the skbuff addresses do not match"
-						   " in boomerang_rx: %p vs. %p / %p.\n", dev->name,
-						   bus_to_virt(vp->rx_ring[entry].addr),
-						   skb->head, 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);
 				rx_nocopy++;
 			}
 #if LINUX_VERSION_CODE > 0x10300
 			skb->protocol = eth_type_trans(skb, dev);
+			{					/* Use hardware checksum info. */
+				int csum_bits = rx_status & 0xee000000;
+				if (csum_bits &&
+					(csum_bits == (IPChksumValid | TCPChksumValid) ||
+					 csum_bits == (IPChksumValid | UDPChksumValid))) {
+					skb->ip_summed = CHECKSUM_UNNECESSARY;
+					rx_csumhits++;
+				}
+			}
 #else
 			skb->len = pkt_len;
 #endif
@@ -1792,8 +1836,6 @@
 			vp->stats.rx_packets++;
 		}
 		entry = (++vp->cur_rx) % RX_RING_SIZE;
-		if (--rx_work_limit < 0)
-			break;
 	}
 	/* Refill the Rx ring buffers. */
 	for (; vp->dirty_rx < vp->cur_rx; vp->dirty_rx++) {
@@ -1801,8 +1843,10 @@
 		entry = vp->dirty_rx % RX_RING_SIZE;
 		if (vp->rx_skbuff[entry] == NULL) {
 			skb = DEV_ALLOC_SKB(PKT_BUF_SZ);
-			if (skb == NULL)
+			if (skb == NULL) {
+				printk(KERN_DEBUG "%s: in boomerang_rx -- could not allocate skbuff\n", dev->name);
 				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 */
@@ -1813,7 +1857,14 @@
 			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;
 }
 
@@ -1828,16 +1879,16 @@
 	dev->tbusy = 1;
 
 	if (vortex_debug > 1) {
-		printk("%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
+		printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
 			   dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus));
-		printk("%s: vortex close stats: rx_nocopy %d rx_copy %d"
-			   " tx_queued %d.\n",
-			   dev->name, rx_nocopy, rx_copy, queued_packet);
+		printk(KERN_DEBUG "%s: vortex close stats: rx_nocopy %d rx_copy %d"
+			   " tx_queued %d Rx pre-checksummed %d.\n",
+			   dev->name, rx_nocopy, rx_copy, queued_packet, rx_csumhits);
 	}
 
 	del_timer(&vp->timer);
 
-	/* Turn off statistics ASAP.  We update lp->stats below. */
+	/* Turn off statistics ASAP.  We update vp->stats below. */
 	outw(StatsDisable, ioaddr + EL3_CMD);
 
 	/* Disable the receiver and transmitter. */
@@ -1865,7 +1916,7 @@
 #if LINUX_VERSION_CODE < 0x20100
 				vp->rx_skbuff[i]->free = 1;
 #endif
-				dev_kfree_skb (vp->rx_skbuff[i]);
+				DEV_FREE_SKB(vp->rx_skbuff[i]);
 				vp->rx_skbuff[i] = 0;
 			}
 	}
@@ -1873,7 +1924,7 @@
 		outl(0, ioaddr + DownListPtr);
 		for (i = 0; i < TX_RING_SIZE; i++)
 			if (vp->tx_skbuff[i]) {
-				dev_kfree_skb(vp->tx_skbuff[i]);
+				DEV_FREE_SKB(vp->tx_skbuff[i]);
 				vp->tx_skbuff[i] = 0;
 			}
 	}
@@ -1945,7 +1996,7 @@
 	int phy = vp->phys[0] & 0x1f;
 
 	if (vortex_debug > 2)
-		printk("%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",
+		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]);
 
@@ -1957,7 +2008,7 @@
 		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
 		return 0;
 	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
-		if (!capable(CAP_NET_ADMIN))
+		if (!suser())
 			return -EPERM;
 		mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
 		return 0;
@@ -1975,11 +2026,11 @@
 set_rx_mode(struct device *dev)
 {
 	int ioaddr = dev->base_addr;
-	short new_mode;
+	int new_mode;
 
 	if (dev->flags & IFF_PROMISC) {
-		if (vortex_debug > 3)
-			printk("%s: Setting promiscuous mode.\n", dev->name);
+		if (vortex_debug > 0)
+			printk(KERN_NOTICE "%s: Setting promiscuous mode.\n", dev->name);
 		new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm;
 	} else	if ((dev->mc_list)  ||  (dev->flags & IFF_ALLMULTI)) {
 		new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast;
@@ -1996,6 +2047,97 @@
 	set_rx_mode(dev);
 }
 #endif
+
+
+/* MII transceiver control section.
+   Read and write the MII registers using software-generated serial
+   MDIO protocol.  See the MII specifications or DP83840A data sheet
+   for details. */
+
+/* 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_SHIFT_CLK	0x01
+#define MDIO_DIR_WRITE	0x04
+#define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE)
+#define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE)
+#define MDIO_DATA_READ	0x02
+#define MDIO_ENB_IN		0x00
+
+/* Generate the preamble required for initial synchronization and
+   a few older transceivers. */
+static void mdio_sync(int ioaddr, int bits)
+{
+	int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+
+	/* Establish sync by sending at least 32 logic ones. */ 
+	while (-- bits >= 0) {
+		outw(MDIO_DATA_WRITE1, mdio_addr);
+		mdio_delay();
+		outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+}
+
+static int mdio_read(int 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;
+
+	if (mii_preamble_required)
+		mdio_sync(ioaddr, 32);
+
+	/* Shift the read command bits out. */
+	for (i = 14; i >= 0; i--) {
+		int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+		outw(dataval, mdio_addr);
+		mdio_delay();
+		outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	/* Read the two transition, 16 data, and wire-idle bits. */
+	for (i = 19; i > 0; i--) {
+		outw(MDIO_ENB_IN, mdio_addr);
+		mdio_delay();
+		retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	return retval>>1 & 0xffff;
+}
+
+static void mdio_write(int ioaddr, int phy_id, int location, int value)
+{
+	int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
+	int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+	int i;
+
+	if (mii_preamble_required)
+		mdio_sync(ioaddr, 32);
+
+	/* Shift the command bits out. */
+	for (i = 31; i >= 0; i--) {
+		int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+		outw(dataval, mdio_addr);
+		mdio_delay();
+		outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	/* Leave the interface idle. */
+	for (i = 1; i >= 0; i--) {
+		outw(MDIO_ENB_IN, mdio_addr);
+		mdio_delay();
+		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+
+	return;
+}
+
 
 #ifdef MODULE
 void
@@ -2003,6 +2145,10 @@
 {
 	struct device *next_dev;
 
+#ifdef CARDBUS
+	unregister_driver(&vortex_ops);
+#endif
+
 	/* 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;
@@ -2018,7 +2164,9 @@
 
 /*
  * Local variables:
- *  compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c"
+ *  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"
  *  c-indent-level: 4
  *  c-basic-offset: 4
  *  tab-width: 4
diff -u --recursive --new-file v2.1.109/linux/drivers/net/82596.c linux/drivers/net/82596.c
--- v2.1.109/linux/drivers/net/82596.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/82596.c	Mon Jul 20 17:22:35 1998
@@ -0,0 +1,1356 @@
+/* 82596.c: A generic 82596 ethernet driver for linux. */
+/*
+   Based on Apricot.c
+   Written 1994 by Mark Evans.
+   This driver is for the Apricot 82596 bus-master interface
+
+   Modularised 12/94 Mark Evans
+
+
+   Modified to support the 82596 ethernet chips on 680x0 VME boards.
+   by Richard Hirst <richard@sleepie.demon.co.uk>
+   Renamed to be 82596.c
+
+   *** Untested on Apricot hardware, and may require some hacking
+   *** to make it work.  The old 82596.c reported hasn't worked
+   *** since 1.3.xx anyway.  I have been unable to find any users
+   *** of Apricot hardware to test this on.
+
+   Most of my modifications relate to the braindead big-endian
+   implementation by Intel.  When the i596 is operating in
+   'big-endian' mode, it thinks a 32 bit value of 0x12345678
+   should be stored as 0x56781234.  This is a real pain, when
+   you have linked lists which are shared by the 680x0 and the
+   i596.
+
+   Driver skeleton
+   Written 1993 by Donald Becker.
+   Copyright 1993 United States Government as represented by the Director,
+   National Security Agency. This software may only be used and distributed
+   according to the terms of the GNU Public License as modified by SRC,
+   incorporated herein by reference.
+
+   The author may be reached as becker@super.org or
+   C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+
+ */
+
+static const char *version = "82596.c:v1.0 15/07/98\n";
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/pgtable.h>	/*?? */
+
+#ifdef CONFIG_MVME16x_NET
+#include <asm/mvme16xhw.h>
+#endif
+#ifdef CONFIG_BVME6000_NET
+#include <asm/bvme6000hw.h>
+#endif
+
+/*
+ * Define various macros for Channel Attention, word swapping etc., dependant
+ * on architecture.  MVME and BVME are 680x0 based, otherwise it is Intel.
+ */
+
+#ifdef __mc68000__
+#define WSWAPrfd(x)  ((struct i596_rfd *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define WSWAPrbd(x)  ((struct i596_rbd *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define WSWAPiscp(x) ((struct i596_iscp *)(((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define WSWAPscb(x)  ((struct i596_scb *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define WSWAPcmd(x)  ((struct i596_cmd *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define WSWAPtbd(x)  ((struct i596_tbd *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define WSWAPchar(x) ((char *)            (((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define ISCP_BUSY	0x00010000
+#define MACH_IS_APRICOT	0
+#else
+#define WSWAPrfd(x)	x
+#define WSWAPiscp(x)	((struct i596_iscp *)(x))
+#define WSWAPscb(x)	((struct i596_scb *)(x))
+#define WSWAPcmd(x)	x
+#define WSWAPtbd(x)	x
+#define WSWAPchar(x)	x
+#define ISCP_BUSY	0x0001
+#define MACH_IS_APRICOT	1
+#endif
+
+/*
+ * The MPU_PORT command allows direct access to the 82596. With PORT access
+ * the following commands are available (p5-18). The 32-bit port command
+ * must be word-swapped with the most significant word written first.
+ * This only applies to VME boards.
+ */
+#define PORT_RESET		0x00	/* reset 82596 */
+#define PORT_SELFTEST		0x01	/* selftest */
+#define PORT_ALTSCP		0x02	/* alternate SCB address */
+#define PORT_ALTDUMP		0x03	/* Alternate DUMP address */
+
+#ifndef HAVE_PORTRESERVE
+#define check_region(addr, size)	0
+#define request_region(addr, size,name)	do ; while(0)
+#endif
+
+#ifndef HAVE_ALLOC_SKB
+#define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority)
+#define kfree_skbmem(buff, size) kfree_s(buff,size)
+#endif
+
+#define APRICOT_DEBUG 2
+
+#ifdef APRICOT_DEBUG
+int i596_debug = APRICOT_DEBUG;
+#else
+int i596_debug = 1;
+#endif
+
+#define I596_TOTAL_SIZE 17
+
+#define I596_NULL -1
+
+#define CMD_EOL		0x8000	/* The last command of the list, stop. */
+#define CMD_SUSP	0x4000	/* Suspend after doing cmd. */
+#define CMD_INTR	0x2000	/* Interrupt after doing cmd. */
+
+#define CMD_FLEX	0x0008	/* Enable flexible memory model */
+
+enum commands {
+	CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
+	CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
+};
+
+#define STAT_C		0x8000	/* Set to 0 after execution */
+#define STAT_B		0x4000	/* Command being executed */
+#define STAT_OK		0x2000	/* Command executed ok */
+#define STAT_A		0x1000	/* Command aborted */
+
+#define	 CUC_START	0x0100
+#define	 CUC_RESUME	0x0200
+#define	 CUC_SUSPEND    0x0300
+#define	 CUC_ABORT	0x0400
+#define	 RX_START	0x0010
+#define	 RX_RESUME	0x0020
+#define	 RX_SUSPEND	0x0030
+#define	 RX_ABORT	0x0040
+
+struct i596_reg {
+	unsigned short porthi;
+	unsigned short portlo;
+	unsigned long ca;
+};
+
+struct i596_cmd {
+	unsigned short status;
+	unsigned short command;
+	struct i596_cmd *next;
+};
+
+#define EOF		0x8000
+#define SIZE_MASK	0x3fff
+
+struct i596_tbd {
+	unsigned short size;
+	unsigned short pad;
+	struct i596_tbd *next;
+	char *data;
+};
+
+struct tx_cmd {
+	struct i596_cmd cmd;
+	struct i596_tbd *tbd;
+	unsigned short size;
+	unsigned short pad;
+	struct sk_buff *skb;	/* So we can free it after tx */
+};
+
+struct i596_rfd {
+	unsigned short stat;
+	unsigned short cmd;
+	struct i596_rfd *next;
+	long rbd;
+	unsigned short count;
+	unsigned short size;
+	char data[1532];
+};
+
+#define RX_RING_SIZE 16
+
+struct i596_scb {
+	unsigned short status;
+	unsigned short command;
+	struct i596_cmd *cmd;
+	struct i596_rfd *rfd;
+	unsigned long crc_err;
+	unsigned long align_err;
+	unsigned long resource_err;
+	unsigned long over_err;
+	unsigned long rcvdt_err;
+	unsigned long short_err;
+	unsigned short t_on;
+	unsigned short t_off;
+};
+
+struct i596_iscp {
+	unsigned long stat;
+	struct i596_scb *scb;
+};
+
+struct i596_scp {
+	unsigned long sysbus;
+	unsigned long pad;
+	struct i596_iscp *iscp;
+};
+
+struct i596_private {
+	volatile struct i596_scp scp;
+	volatile struct i596_iscp iscp;
+	volatile struct i596_scb scb;
+	struct i596_cmd set_add;
+	char eth_addr[8];
+	struct i596_cmd set_conf;
+	char i596_config[16];
+	struct i596_cmd tdr;
+	unsigned long stat;
+	int last_restart __attribute__((aligned(4)));
+	struct i596_rfd *rx_tail;
+	struct i596_cmd *cmd_tail;
+	struct i596_cmd *cmd_head;
+	int cmd_backlog;
+	unsigned long last_cmd;
+	struct net_device_stats stats;
+};
+
+char init_setup[] =
+{
+	0x8E,			/* length, prefetch on */
+	0xC8,			/* fifo to 8, monitor off */
+#ifdef CONFIG_VME
+	0xc0,			/* don't save bad frames */
+#else
+	0x80,			/* don't save bad frames */
+#endif
+	0x2E,			/* No source address insertion, 8 byte preamble */
+	0x00,			/* priority and backoff defaults */
+	0x60,			/* interframe spacing */
+	0x00,			/* slot time LSB */
+	0xf2,			/* slot time and retries */
+	0x00,			/* promiscuous mode */
+	0x00,			/* collision detect */
+	0x40,			/* minimum frame length */
+	0xff,
+	0x00,
+	0x7f /*  *multi IA */ };
+
+static int i596_open(struct device *dev);
+static int i596_start_xmit(struct sk_buff *skb, struct device *dev);
+static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int i596_close(struct device *dev);
+static struct net_device_stats *i596_get_stats(struct device *dev);
+static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd);
+static void print_eth(char *);
+static void set_multicast_list(struct device *dev);
+
+static int ticks_limit = 25;
+static int max_cmd_backlog = 16;
+
+
+static inline void CA(struct device *dev)
+{
+#ifdef CONFIG_MVME16x_NET
+	if (MACH_IS_MVME16x) {
+		((struct i596_reg *) dev->base_addr)->ca = 1;
+	}
+#endif
+#ifdef CONFIG_BVME6000_NET
+	if (MACH_IS_BVME6000) {
+		volatile u32 i = *(volatile u32 *) (dev->base_addr);
+	}
+#endif
+#ifdef CONFIG_APRICOT_i596
+	if (MACH_IS_APRICOT) {
+		outw(0, (short) (dev->base_addr) + 4);
+	}
+#endif
+}
+
+
+static inline void MPU_PORT(struct device *dev, int c, volatile void *x)
+{
+#ifdef CONFIG_MVME16x_NET
+	if (MACH_IS_MVME16x) {
+		struct i596_reg *p = (struct i596_reg *) (dev->base_addr);
+		p->porthi = ((c) | (u32) (x)) & 0xffff;
+		p->portlo = ((c) | (u32) (x)) >> 16;
+	}
+#endif
+#ifdef CONFIG_BVME6000_NET
+	if (MACH_IS_BVME6000) {
+		u32 v = (u32) (c) | (u32) (x);
+		v = ((u32) (v) << 16) | ((u32) (v) >> 16);
+		*(volatile u32 *) dev->base_addr = v;
+		udelay(1);
+		*(volatile u32 *) dev->base_addr = v;
+	}
+#endif
+}
+
+
+#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET)
+static void i596_error(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct device *dev = dev_id;
+	struct i596_cmd *cmd;
+
+	struct i596_private *lp = (struct i596_private *) dev->priv;
+	printk("i596_error: lp = 0x%08x\n", (u32) lp);
+	printk("scp at %08x, .sysbus = %08x, .iscp = %08x\n",
+	       (u32) & lp->scp, (u32) lp->scp.sysbus, (u32) lp->scp.iscp);
+	printk("iscp at %08x, .stat = %08x, .scb = %08x\n",
+	       (u32) & lp->iscp, (u32) lp->iscp.stat, (u32) lp->iscp.scb);
+	printk("scb at %08x, .status = %04x, .command = %04x\n",
+	       (u32) & lp->scb, lp->scb.status, lp->scb.command);
+	printk("   .cmd = %08x, .rfd = %08x\n", (u32) lp->scb.cmd,
+	       (u32) lp->scb.rfd);
+	cmd = WSWAPcmd(lp->scb.cmd);
+	while (cmd && (u32) cmd < 0x1000000) {
+		printk("cmd at %08x, .status = %04x, .command = %04x, .next = %08x\n",
+		  (u32) cmd, cmd->status, cmd->command, (u32) cmd->next);
+		cmd = WSWAPcmd(cmd->next);
+	}
+	while (1);
+}
+#endif
+
+static inline int init_rx_bufs(struct device *dev, int num)
+{
+	struct i596_private *lp = (struct i596_private *) dev->priv;
+	int i;
+	struct i596_rfd *rfd;
+
+	lp->scb.rfd = (struct i596_rfd *) I596_NULL;
+
+	if (i596_debug > 1)
+		printk("%s: init_rx_bufs %d.\n", dev->name, num);
+
+	for (i = 0; i < num; i++) {
+		if (!(rfd = (struct i596_rfd *) kmalloc(sizeof(struct i596_rfd), GFP_KERNEL)))
+			 break;
+
+		rfd->stat = 0x0000;
+		rfd->rbd = I596_NULL;
+		rfd->count = 0;
+		rfd->size = 1532;
+		if (i == 0) {
+			rfd->cmd = CMD_EOL;
+			lp->rx_tail = rfd;
+		} else
+			rfd->cmd = 0x0000;
+
+		rfd->next = lp->scb.rfd;
+		lp->scb.rfd = WSWAPrfd(rfd);
+	}
+
+	if (i != 0)
+		lp->rx_tail->next = lp->scb.rfd;
+
+	return (i);
+}
+
+static inline void remove_rx_bufs(struct device *dev)
+{
+	struct i596_private *lp = (struct i596_private *) dev->priv;
+	struct i596_rfd *rfd = WSWAPrfd(lp->scb.rfd);
+
+	lp->rx_tail->next = (struct i596_rfd *) I596_NULL;
+
+	do {
+		lp->scb.rfd = rfd->next;
+		kfree(rfd);
+		rfd = WSWAPrfd(lp->scb.rfd);
+	}
+	while (rfd != lp->rx_tail);
+}
+
+static inline void init_i596_mem(struct device *dev)
+{
+	struct i596_private *lp = (struct i596_private *) dev->priv;
+#if !defined(CONFIG_MVME16x_NET) && !defined(CONFIG_BVME6000_NET)
+	short ioaddr = dev->base_addr;
+#endif
+	int boguscnt = 100000;
+	unsigned long flags;
+
+#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET)
+#ifdef CONFIG_MVME16x_NET
+	if (MACH_IS_MVME16x) {
+		volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
+
+		/* Disable all ints for now */
+		pcc2[0x28] = 1;
+		pcc2[0x2a] = 0x40;
+		pcc2[0x2b] = 0x40;	/* Set snooping bits now! */
+	}
+#endif
+#ifdef CONFIG_BVME6000_NET
+	if (MACH_IS_BVME6000) {
+		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
+
+		*ethirq = 1;
+	}
+#endif
+
+	MPU_PORT(dev, PORT_RESET, 0);
+
+	udelay(100);		/* Wait 100us - seems to help */
+
+	/* change the scp address */
+
+	MPU_PORT(dev, PORT_ALTSCP, &lp->scp);
+
+#else
+
+	/* change the scp address */
+	outw(0, ioaddr);
+	outw(0, ioaddr);
+	outb(4, ioaddr + 0xf);
+	outw(((((int) &lp->scp) & 0xffff) | 2), ioaddr);
+	outw((((int) &lp->scp) >> 16) & 0xffff, ioaddr);
+#endif
+
+	lp->last_cmd = jiffies;
+
+#ifdef CONFIG_MVME16x_NET
+	if (MACH_IS_MVME16x)
+		lp->scp.sysbus = 0x00000054;
+#endif
+#ifdef CONFIG_BVME6000_NET
+	if (MACH_IS_BVME6000)
+		lp->scp.sysbus = 0x0000004c;
+#endif
+#ifdef CONFIG_APRICOT_i596
+	if (MACH_IS_APRICOT)
+		lp->scp.sysbus = 0x00440000;
+#endif
+
+	lp->scp.iscp = WSWAPiscp(&(lp->iscp));
+	lp->iscp.scb = WSWAPscb(&(lp->scb));
+	lp->iscp.stat = ISCP_BUSY;
+	lp->cmd_backlog = 0;
+
+	lp->cmd_head = lp->scb.cmd = (struct i596_cmd *) I596_NULL;
+
+	if (i596_debug > 1)
+		printk("%s: starting i82596.\n", dev->name);
+
+#if !defined(CONFIG_MVME16x_NET) && !defined(CONFIG_BVME6000_NET)
+	(void) inb(ioaddr + 0x10);
+	outb(4, ioaddr + 0xf);
+#endif
+	CA(dev);
+
+	while (lp->iscp.stat)
+		if (--boguscnt == 0) {
+			printk("%s: i82596 initialization timed out with status %4.4x, cmd %4.4x.\n",
+			     dev->name, lp->scb.status, lp->scb.command);
+			break;
+		}
+	lp->scb.command = 0;
+
+#ifdef CONFIG_MVME16x_NET
+	if (MACH_IS_MVME16x) {
+		volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
+
+		/* Enable ints, etc. now */
+		pcc2[0x2a] = 0x08;
+		pcc2[0x2a] = 0x55;	/* Edge sensitive */
+		pcc2[0x2b] = 0x55;
+	}
+#endif
+#ifdef CONFIG_BVME6000_NET
+	if (MACH_IS_BVME6000) {
+		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
+
+		*ethirq = 3;
+	}
+#endif
+
+	memcpy(lp->i596_config, init_setup, 14);
+	lp->set_conf.command = CmdConfigure;
+	i596_add_cmd(dev, &lp->set_conf);
+
+	memcpy(lp->eth_addr, dev->dev_addr, 6);
+	lp->set_add.command = CmdSASetup;
+	i596_add_cmd(dev, &lp->set_add);
+
+	lp->tdr.command = CmdTDR;
+	i596_add_cmd(dev, &lp->tdr);
+
+	boguscnt = 200000;
+
+	save_flags(flags);
+	cli();
+
+	while (lp->scb.command)
+		if (--boguscnt == 0) {
+			printk("%s: receive unit start timed out with status %4.4x, cmd %4.4x.\n",
+			     dev->name, lp->scb.status, lp->scb.command);
+			break;
+		}
+	lp->scb.command = RX_START;
+	CA(dev);
+
+	restore_flags(flags);
+
+	boguscnt = 2000;
+	while (lp->scb.command)
+		if (--boguscnt == 0) {
+			printk("i82596 init timed out with status %4.4x, cmd %4.4x.\n",
+			       lp->scb.status, lp->scb.command);
+			break;
+		}
+	return;
+}
+
+static inline int i596_rx(struct device *dev)
+{
+	struct i596_private *lp = (struct i596_private *) dev->priv;
+	struct i596_rfd *rfd;
+	int frames = 0;
+
+	if (i596_debug > 3)
+		printk("i596_rx()\n");
+
+	rfd = WSWAPrfd(lp->scb.rfd);	/* Reference next frame descriptor to check */
+
+	while ((rfd->stat) & STAT_C) {	/* Loop while we have complete frames */
+		if (i596_debug > 2)
+			print_eth(rfd->data);
+
+		if ((rfd->stat) & STAT_OK) {
+			/* a good frame */
+			int pkt_len = rfd->count & 0x3fff;
+			struct sk_buff *skb = dev_alloc_skb(pkt_len);
+
+			frames++;
+
+			if (skb == NULL) {
+				printk("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
+				lp->stats.rx_dropped++;
+			} else {
+				skb->dev = dev;
+				memcpy(skb_put(skb, pkt_len), rfd->data, pkt_len);
+				skb->protocol = eth_type_trans(skb, dev);
+				netif_rx(skb);
+				lp->stats.rx_packets++;
+				lp->stats.rx_bytes += pkt_len;
+			}
+		} else {
+			lp->stats.rx_errors++;
+			if ((rfd->stat) & 0x0001)
+				lp->stats.collisions++;
+			if ((rfd->stat) & 0x0080)
+				lp->stats.rx_length_errors++;
+			if ((rfd->stat) & 0x0100)
+				lp->stats.rx_over_errors++;
+			if ((rfd->stat) & 0x0200)
+				lp->stats.rx_fifo_errors++;
+			if ((rfd->stat) & 0x0400)
+				lp->stats.rx_frame_errors++;
+			if ((rfd->stat) & 0x0800)
+				lp->stats.rx_crc_errors++;
+			if ((rfd->stat) & 0x1000)
+				lp->stats.rx_length_errors++;
+		}
+
+		/* Clear the buffer descriptor count and EOF + F flags */
+
+		rfd->stat = 0;
+		rfd->count = 0;
+		rfd->cmd = CMD_EOL;
+		lp->rx_tail->cmd = 0;
+		lp->rx_tail = rfd;
+		lp->scb.rfd = rfd->next;
+		rfd = WSWAPrfd(lp->scb.rfd);	/* Next frame descriptor to check */
+	}
+
+	if (i596_debug > 3)
+		printk("frames %d\n", frames);
+
+	return 0;
+}
+
+static inline void i596_cleanup_cmd(struct i596_private *lp)
+{
+	struct i596_cmd *ptr;
+	int boguscnt = 1000;
+
+	if (i596_debug > 4)
+		printk("i596_cleanup_cmd\n");
+
+	while (lp->cmd_head != (struct i596_cmd *) I596_NULL) {
+		ptr = lp->cmd_head;
+
+		lp->cmd_head = WSWAPcmd(lp->cmd_head->next);
+		lp->cmd_backlog--;
+
+		switch ((ptr->command) & 0x7) {
+		case CmdTx:
+			{
+				struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+				struct sk_buff *skb = tx_cmd->skb;
+
+				dev_kfree_skb(skb);
+
+				lp->stats.tx_errors++;
+				lp->stats.tx_aborted_errors++;
+
+				ptr->next = (struct i596_cmd *) I596_NULL;
+				kfree(tx_cmd);
+				break;
+			}
+		case CmdMulticastList:
+			{
+				ptr->next = (struct i596_cmd *) I596_NULL;
+				kfree(ptr);
+				break;
+			}
+		default:
+			ptr->next = (struct i596_cmd *) I596_NULL;
+		}
+	}
+
+	while (lp->scb.command)
+		if (--boguscnt == 0) {
+			printk("i596_cleanup_cmd timed out with status %4.4x, cmd %4.4x.\n",
+			       lp->scb.status, lp->scb.command);
+			break;
+		}
+	lp->scb.cmd = WSWAPcmd(lp->cmd_head);
+}
+
+static inline void i596_reset(struct device *dev, struct i596_private *lp, int ioaddr)
+{
+	int boguscnt = 1000;
+	unsigned long flags;
+
+	if (i596_debug > 1)
+		printk("i596_reset\n");
+
+	save_flags(flags);
+	cli();
+
+	while (lp->scb.command)
+		if (--boguscnt == 0) {
+			printk("i596_reset timed out with status %4.4x, cmd %4.4x.\n",
+			       lp->scb.status, lp->scb.command);
+			break;
+		}
+	dev->start = 0;
+	dev->tbusy = 1;
+
+	lp->scb.command = CUC_ABORT | RX_ABORT;
+	CA(dev);
+
+	/* wait for shutdown */
+	boguscnt = 4000;
+
+	while (lp->scb.command)
+		if (--boguscnt == 0) {
+			printk("i596_reset 2 timed out with status %4.4x, cmd %4.4x.\n",
+			       lp->scb.status, lp->scb.command);
+			break;
+		}
+	restore_flags(flags);
+
+	i596_cleanup_cmd(lp);
+	i596_rx(dev);
+
+	dev->start = 1;
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	init_i596_mem(dev);
+}
+
+static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd)
+{
+	struct i596_private *lp = (struct i596_private *) dev->priv;
+	int ioaddr = dev->base_addr;
+	unsigned long flags;
+	int boguscnt = 1000;
+
+	if (i596_debug > 4)
+		printk("i596_add_cmd\n");
+
+	cmd->status = 0;
+	cmd->command |= (CMD_EOL | CMD_INTR);
+	cmd->next = (struct i596_cmd *) I596_NULL;
+	save_flags(flags);
+	cli();
+
+	/*
+	 * RGH  300597:  Looks to me like there could be a race condition
+	 * here.  Just because we havn't picked up all the command items
+	 * yet, doesn't mean that the 82596 hasn't finished processing
+	 * them.  So, we may need to do a CUC_START anyway.
+	 * Maybe not.  If it interrupts saying the CU is idle when there
+	 * is still something in the cmd queue, the int handler with restart
+	 * the CU.
+	 */
+
+	if (lp->cmd_head != (struct i596_cmd *) I596_NULL) {
+		lp->cmd_tail->next = WSWAPcmd(cmd);
+	} else {
+		lp->cmd_head = cmd;
+		while (lp->scb.command)
+			if (--boguscnt == 0) {
+				printk("i596_add_cmd timed out with status %4.4x, cmd %4.4x.\n",
+				       lp->scb.status, lp->scb.command);
+				break;
+			}
+		lp->scb.cmd = WSWAPcmd(cmd);
+		lp->scb.command = CUC_START;
+		CA(dev);
+	}
+	lp->cmd_tail = cmd;
+	lp->cmd_backlog++;
+
+	lp->cmd_head = WSWAPcmd(lp->scb.cmd);	/* Is this redundant?  RGH 300597 */
+	restore_flags(flags);
+
+	if (lp->cmd_backlog > max_cmd_backlog) {
+		unsigned long tickssofar = jiffies - lp->last_cmd;
+
+		if (tickssofar < ticks_limit)
+			return;
+
+		printk("%s: command unit timed out, status resetting.\n", dev->name);
+
+		i596_reset(dev, lp, ioaddr);
+	}
+}
+
+static int i596_open(struct device *dev)
+{
+	int i;
+
+	if (i596_debug > 1)
+		printk("%s: i596_open() irq %d.\n", dev->name, dev->irq);
+
+	if (request_irq(dev->irq, &i596_interrupt, 0, "apricot", dev))
+		return -EAGAIN;
+#ifdef CONFIG_MVME16x_NET
+	if (MACH_IS_MVME16x) {
+		if (request_irq(0x56, &i596_error, 0, "apricot_error", dev))
+			return -EAGAIN;
+	}
+#endif
+	if ((i = init_rx_bufs(dev, RX_RING_SIZE)) < RX_RING_SIZE)
+		printk("%s: only able to allocate %d receive buffers\n", dev->name, i);
+
+	if (i < 4) {
+		free_irq(dev->irq, dev);
+		return -EAGAIN;
+	}
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+	MOD_INC_USE_COUNT;
+
+	/* Initialize the 82596 memory */
+	init_i596_mem(dev);
+
+	return 0;		/* Always succeed */
+}
+
+static int i596_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+	struct i596_private *lp = (struct i596_private *) dev->priv;
+	int ioaddr = dev->base_addr;
+	struct tx_cmd *tx_cmd;
+
+	if (i596_debug > 2)
+		printk("%s: 82596 start xmit\n", dev->name);
+
+	/* Transmitter timeout, serious problems. */
+	if (dev->tbusy) {
+		int tickssofar = jiffies - dev->trans_start;
+		if (tickssofar < 5)
+			return 1;
+		printk("%s: transmit timed out, status resetting.\n",
+		       dev->name);
+		lp->stats.tx_errors++;
+		/* Try to restart the adaptor */
+		if (lp->last_restart == lp->stats.tx_packets) {
+			if (i596_debug > 1)
+				printk("Resetting board.\n");
+
+			/* Shutdown and restart */
+			i596_reset(dev, lp, ioaddr);
+		} else {
+			/* Issue a channel attention signal */
+			if (i596_debug > 1)
+				printk("Kicking board.\n");
+			lp->scb.command = CUC_START | RX_START;
+			CA(dev);
+			lp->last_restart = lp->stats.tx_packets;
+		}
+		dev->tbusy = 0;
+		dev->trans_start = jiffies;
+	}
+	if (i596_debug > 3)
+		printk("%s: i596_start_xmit() called\n", dev->name);
+
+	/* Block a timer-based transmit from overlapping.  This could better be
+	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0)
+		printk("%s: Transmitter access conflict.\n", dev->name);
+	else {
+		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+		dev->trans_start = jiffies;
+
+		tx_cmd = (struct tx_cmd *) kmalloc((sizeof(struct tx_cmd) + sizeof(struct i596_tbd)), GFP_ATOMIC);
+		if (tx_cmd == NULL) {
+			printk("%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name);
+			lp->stats.tx_dropped++;
+
+			dev_kfree_skb(skb);
+		} else {
+			struct i596_tbd *tbd = (struct i596_tbd *) (tx_cmd + 1);
+			tx_cmd->tbd = WSWAPtbd(tbd);
+			tbd->next = (struct i596_tbd *) I596_NULL;
+
+			tx_cmd->cmd.command = CMD_FLEX | CmdTx;
+			tx_cmd->skb = skb;
+
+			tx_cmd->pad = 0;
+			tx_cmd->size = 0;
+			tbd->pad = 0;
+			tbd->size = EOF | length;
+
+			tbd->data = WSWAPchar(skb->data);
+
+			if (i596_debug > 3)
+				print_eth(skb->data);
+			i596_add_cmd(dev, (struct i596_cmd *) tx_cmd);
+
+			lp->stats.tx_packets++;
+			lp->stats.tx_bytes += length;
+		}
+	}
+
+	dev->tbusy = 0;
+
+	return 0;
+}
+
+
+static void print_eth(char *add)
+{
+	int i;
+
+	printk("print_eth(%08x)\n", (unsigned int) add);
+	printk("Dest  ");
+	for (i = 0; i < 6; i++)
+		printk(" %2.2X", (unsigned char) add[i]);
+	printk("\n");
+
+	printk("Source");
+	for (i = 0; i < 6; i++)
+		printk(" %2.2X", (unsigned char) add[i + 6]);
+	printk("\n");
+	printk("type %2.2X%2.2X\n", (unsigned char) add[12], (unsigned char) add[13]);
+}
+
+__initfunc(int i82596_probe(struct device *dev))
+{
+	int i;
+	struct i596_private *lp;
+	char eth_addr[6];
+
+#ifdef CONFIG_MVME16x_NET
+	if (MACH_IS_MVME16x) {
+		static int probed = 0;
+
+		if (mvme16x_config & MVME16x_CONFIG_NO_ETHERNET) {
+			printk("Ethernet probe disabled - chip not present\n");
+			return ENODEV;
+		}
+		if (probed)
+			return ENODEV;
+		probed++;
+		memcpy(eth_addr, (void *) 0xfffc1f2c, 6);	/* YUCK! Get addr from NOVRAM */
+		dev->base_addr = MVME_I596_BASE;
+		dev->irq = (unsigned) MVME16x_IRQ_I596;
+	}
+#endif
+#ifdef CONFIG_BVME6000_NET
+	if (MACH_IS_BVME6000) {
+		volatile unsigned char *rtc = (unsigned char *) BVME_RTC_BASE;
+		unsigned char msr = rtc[3];
+		int i;
+
+		rtc[3] |= 0x80;
+		for (i = 0; i < 6; i++)
+			eth_addr[i] = rtc[i * 4 + 7];	/* Stored in RTC RAM at offset 1 */
+		rtc[3] = msr;
+		dev->base_addr = BVME_I596_BASE;
+		dev->irq = (unsigned) BVME_IRQ_I596;
+	}
+#endif
+#ifdef CONFIG_APRICOT_INTEL
+	int checksum = 0;
+	int ioaddr = 0x300;
+
+	/* this is easy the ethernet interface can only be at 0x300 */
+	/* first check nothing is already registered here */
+
+	if (check_region(ioaddr, I596_TOTAL_SIZE))
+		return ENODEV;
+
+	for (i = 0; i < 8; i++) {
+		eth_addr[i] = inb(ioaddr + 8 + i);
+		checksum += eth_addr[i];
+	}
+
+	/* checksum is a multiple of 0x100, got this wrong first time
+	   some machines have 0x100, some 0x200. The DOS driver doesn't
+	   even bother with the checksum */
+
+	if (checksum % 0x100)
+		return ENODEV;
+
+	/* Some other boards trip the checksum.. but then appear as ether
+	   address 0. Trap these - AC */
+
+	if (memcmp(eth_addr, "\x00\x00\x49", 3) != 0)
+		return ENODEV;
+
+	request_region(ioaddr, I596_TOTAL_SIZE, "i596");
+
+	dev->base_addr = ioaddr;
+	dev->irq = 10;
+#endif
+	ether_setup(dev);
+	printk("%s: 82596 at %#3lx,", dev->name, dev->base_addr);
+
+	for (i = 0; i < 6; i++)
+		printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]);
+
+	printk(" IRQ %d.\n", dev->irq);
+
+	if (i596_debug > 0)
+		printk(version);
+
+	/* The APRICOT-specific entries in the device structure. */
+	dev->open = &i596_open;
+	dev->stop = &i596_close;
+	dev->hard_start_xmit = &i596_start_xmit;
+	dev->get_stats = &i596_get_stats;
+	dev->set_multicast_list = &set_multicast_list;
+
+	dev->mem_start = (int) kmalloc(sizeof(struct i596_private) + 0x0f, GFP_KERNEL);
+	/* align for scp */
+	dev->priv = (void *) ((dev->mem_start + 0xf) & 0xfffffff0);
+
+	lp = (struct i596_private *) dev->priv;
+	if (i596_debug)
+		printk("%s: lp at 0x%08lx, lp->scb at 0x%08lx\n"
+		,dev->name, (unsigned long) lp, (unsigned long) &lp->scb);
+	memset((void *) lp, 0, sizeof(struct i596_private));
+	lp->scb.command = 0;
+	lp->scb.cmd = (struct i596_cmd *) I596_NULL;
+	lp->scb.rfd = (struct i596_rfd *) I596_NULL;
+
+	return 0;
+}
+
+static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct device *dev = dev_id;
+	struct i596_private *lp;
+	short ioaddr;
+	int boguscnt = 2000;
+	unsigned short status, ack_cmd = 0;
+
+#ifdef CONFIG_BVME6000_NET
+	if (MACH_IS_BVME6000) {
+		if (*(char *) BVME_LOCAL_IRQ_STAT & BVME_ETHERR) {
+			i596_error(BVME_IRQ_I596, NULL, NULL);
+			return;
+		}
+	}
+#endif
+	if (dev == NULL) {
+		printk("i596_interrupt(): irq %d for unknown device.\n", irq);
+		return;
+	}
+	if (i596_debug > 3)
+		printk("%s: i596_interrupt(): irq %d\n", dev->name, irq);
+
+	if (dev->interrupt)
+		printk("%s: Re-entering the interrupt handler.\n", dev->name);
+
+	dev->interrupt = 1;
+
+	ioaddr = dev->base_addr;
+
+	lp = (struct i596_private *) dev->priv;
+
+	while (lp->scb.command)
+		if (--boguscnt == 0) {
+			printk("%s: i596 interrupt, timeout status %4.4x command %4.4x.\n", dev->name, lp->scb.status, lp->scb.command);
+			break;
+		}
+	status = lp->scb.status;
+
+	if (i596_debug > 4)
+		printk("%s: i596 interrupt, status %4.4x.\n", dev->name, status);
+
+	ack_cmd = status & 0xf000;
+
+	if ((status & 0x8000) || (status & 0x2000)) {
+		struct i596_cmd *ptr;
+
+		if ((i596_debug > 4) && (status & 0x8000))
+			printk("%s: i596 interrupt completed command.\n", dev->name);
+		if ((i596_debug > 4) && (status & 0x2000))
+			printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700);
+
+		while ((lp->cmd_head != (struct i596_cmd *) I596_NULL) && (lp->cmd_head->status & STAT_C)) {
+			ptr = lp->cmd_head;
+
+			if (i596_debug > 2)
+				printk("cmd_head->status = %04x, ->command = %04x\n",
+				       lp->cmd_head->status, lp->cmd_head->command);
+			lp->cmd_head = WSWAPcmd(lp->cmd_head->next);
+			lp->cmd_backlog--;
+
+			switch ((ptr->command) & 0x7) {
+			case CmdTx:
+				{
+					struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+					struct sk_buff *skb = tx_cmd->skb;
+
+					if ((ptr->status) & STAT_OK) {
+						if (i596_debug > 2)
+							print_eth(skb->data);
+					} else {
+						lp->stats.tx_errors++;
+						if ((ptr->status) & 0x0020)
+							lp->stats.collisions++;
+						if (!((ptr->status) & 0x0040))
+							lp->stats.tx_heartbeat_errors++;
+						if ((ptr->status) & 0x0400)
+							lp->stats.tx_carrier_errors++;
+						if ((ptr->status) & 0x0800)
+							lp->stats.collisions++;
+						if ((ptr->status) & 0x1000)
+							lp->stats.tx_aborted_errors++;
+					}
+
+					dev_kfree_skb(skb);
+
+					ptr->next = (struct i596_cmd *) I596_NULL;
+					kfree(tx_cmd);
+					break;
+				}
+			case CmdMulticastList:
+				{
+					ptr->next = (struct i596_cmd *) I596_NULL;
+					kfree(ptr);
+					break;
+				}
+			case CmdTDR:
+				{
+					unsigned long status = *((unsigned long *) (ptr + 1));
+
+					if (status & 0x8000) {
+						if (i596_debug > 3)
+							printk("%s: link ok.\n", dev->name);
+					} else {
+						if (status & 0x4000)
+							printk("%s: Transceiver problem.\n", dev->name);
+						if (status & 0x2000)
+							printk("%s: Termination problem.\n", dev->name);
+						if (status & 0x1000)
+							printk("%s: Short circuit.\n", dev->name);
+
+						if (i596_debug > 1)
+							printk("%s: Time %ld.\n", dev->name, status & 0x07ff);
+					}
+					break;
+				}
+			case CmdConfigure:
+				{
+					ptr->next = (struct i596_cmd *) I596_NULL;
+					/* Zap command so set_multicast_list() knows it is free */
+					ptr->command = 0;
+					break;
+				}
+			default:
+				ptr->next = (struct i596_cmd *) I596_NULL;
+			}
+			lp->last_cmd = jiffies;
+		}
+
+		ptr = lp->cmd_head;
+		while ((ptr != (struct i596_cmd *) I596_NULL) && (ptr != lp->cmd_tail)) {
+			ptr->command &= 0x1fff;
+			ptr = WSWAPcmd(ptr->next);
+		}
+
+		if ((lp->cmd_head != (struct i596_cmd *) I596_NULL) && (dev->start))
+			ack_cmd |= CUC_START;
+		lp->scb.cmd = WSWAPcmd(lp->cmd_head);
+	}
+	if ((status & 0x1000) || (status & 0x4000)) {
+		if ((i596_debug > 4) && (status & 0x4000))
+			printk("%s: i596 interrupt received a frame.\n", dev->name);
+		/* Only RX_START if stopped - RGH 07-07-96 */
+		if (status & 0x1000) {
+			if (dev->start)
+				ack_cmd |= RX_START;
+			if (i596_debug > 1)
+				printk("%s: i596 interrupt receive unit inactive %x.\n", dev->name, status & 0x00f0);
+		}
+		i596_rx(dev);
+	}
+	/* acknowledge the interrupt */
+
+/*      COMMENTED OUT <<<<<
+   if ((lp->scb.cmd != (struct i596_cmd *) I596_NULL) && (dev->start))
+   ack_cmd |= CUC_START;
+ */
+	boguscnt = 1000;
+	while (lp->scb.command)
+		if (--boguscnt == 0) {
+			printk("%s: i596 interrupt, timeout status %4.4x command %4.4x.\n", dev->name, lp->scb.status, lp->scb.command);
+			break;
+		}
+	lp->scb.command = ack_cmd;
+
+#ifdef CONFIG_MVME16x_NET
+	if (MACH_IS_MVME16x) {
+		/* Ack the interrupt */
+
+		volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
+
+		pcc2[0x2a] |= 0x08;
+	}
+#endif
+#ifdef CONFIG_BVME6000_NET
+	if (MACH_IS_BVME6000) {
+		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
+
+		*ethirq = 1;
+		*ethirq = 3;
+	}
+#endif
+#ifdef CONFIG_APRICOT_INTEL
+	(void) inb(ioaddr + 0x10);
+	outb(4, ioaddr + 0xf);
+#endif
+	CA(dev);
+
+	if (i596_debug > 4)
+		printk("%s: exiting interrupt.\n", dev->name);
+
+	dev->interrupt = 0;
+	return;
+}
+
+static int i596_close(struct device *dev)
+{
+	struct i596_private *lp = (struct i596_private *) dev->priv;
+	int boguscnt = 2000;
+	unsigned long flags;
+
+	dev->start = 0;
+	dev->tbusy = 1;
+
+	if (i596_debug > 1)
+		printk("%s: Shutting down ethercard, status was %4.4x.\n",
+		       dev->name, lp->scb.status);
+
+	save_flags(flags);
+	cli();
+
+	while (lp->scb.command)
+		if (--boguscnt == 0) {
+			printk("%s: close1 timed timed out with status %4.4x, cmd %4.4x.\n",
+			     dev->name, lp->scb.status, lp->scb.command);
+			break;
+		}
+	lp->scb.command = CUC_ABORT | RX_ABORT;
+	CA(dev);
+
+	boguscnt = 2000;
+
+	while (lp->scb.command)
+		if (--boguscnt == 0) {
+			printk("%s: close2 timed timed out with status %4.4x, cmd %4.4x.\n",
+			     dev->name, lp->scb.status, lp->scb.command);
+			break;
+		}
+	restore_flags(flags);
+
+	i596_cleanup_cmd(lp);
+
+#ifdef CONFIG_MVME16x_NET
+	if (MACH_IS_MVME16x) {
+		volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
+
+		/* Disable all ints */
+		pcc2[0x28] = 1;
+		pcc2[0x2a] = 0x40;
+		pcc2[0x2b] = 0x40;	/* Set snooping bits now! */
+	}
+#endif
+#ifdef CONFIG_BVME6000_NET
+	if (MACH_IS_BVME6000) {
+		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
+
+		*ethirq = 1;
+	}
+#endif
+
+	free_irq(dev->irq, dev);
+	remove_rx_bufs(dev);
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+static struct net_device_stats *
+ i596_get_stats(struct device *dev)
+{
+	struct i596_private *lp = (struct i596_private *) dev->priv;
+
+	return &lp->stats;
+}
+
+/*
+ *    Set or clear the multicast filter for this adaptor.
+ */
+
+static void set_multicast_list(struct device *dev)
+{
+	struct i596_private *lp = (struct i596_private *) dev->priv;
+	struct i596_cmd *cmd;
+	int config = 0;
+
+	if (i596_debug > 1)
+		printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n", dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF", dev->flags & IFF_ALLMULTI ? "ON" : "OFF");
+
+	if ((dev->flags & IFF_PROMISC) && !(lp->i596_config[8] & 0x01)) {
+		lp->i596_config[8] |= 0x01;
+		config = 1;
+	}
+	if (!(dev->flags & IFF_PROMISC) && (lp->i596_config[8] & 0x01)) {
+		lp->i596_config[8] &= ~0x01;
+		config = 1;
+	}
+	if ((dev->flags & IFF_ALLMULTI) && (lp->i596_config[11] & 0x20)) {
+		lp->i596_config[11] &= ~0x20;
+		config = 1;
+	}
+	if (!(dev->flags & IFF_ALLMULTI) && !(lp->i596_config[11] & 0x20)) {
+		lp->i596_config[11] |= 0x20;
+		config = 1;
+	}
+	if (config) {
+		if (lp->set_conf.command)
+			printk("%s: config change request already queued\n",
+			       dev->name);
+		else {
+			lp->set_conf.command = CmdConfigure;
+			i596_add_cmd(dev, &lp->set_conf);
+		}
+	}
+	if (dev->mc_count > 0) {
+		struct dev_mc_list *dmi;
+		unsigned char *cp;
+		cmd = (struct i596_cmd *) kmalloc(sizeof(struct i596_cmd) + 2 + dev->mc_count * 6, GFP_ATOMIC);
+		if (cmd == NULL) {
+			printk("%s: set_multicast Memory squeeze.\n", dev->name);
+			return;
+		}
+		cmd->command = CmdMulticastList;
+		*((unsigned short *) (cmd + 1)) = dev->mc_count * 6;
+		cp = ((unsigned char *) (cmd + 1)) + 2;
+		for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
+			memcpy(cp, dmi->dmi_addr, 6);
+			if (i596_debug > 1)
+				printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, *(cp + 0), *(cp + 1), *(cp + 2), *(cp + 3), *(cp + 4), *(cp + 5));
+			cp += 6;
+		}
+		if (i596_debug > 2)
+			print_eth(((char *) (cmd + 1)) + 2);
+		i596_add_cmd(dev, cmd);
+	}
+}
+
+#ifdef HAVE_DEVLIST
+static unsigned int i596_portlist[] __initdata =
+{0x300, 0};
+struct netdev_entry i596_drv =
+{"apricot", i82596_probe, I596_TOTAL_SIZE, apricot_portlist};
+#endif
+
+#ifdef MODULE
+static char devicename[9] =
+{0,};
+static struct device dev_apricot =
+{
+	devicename,		/* device name inserted by /linux/drivers/net/net_init.c */
+	0, 0, 0, 0,
+	0x300, 10,
+	0, 0, 0, NULL, i82596_probe};
+
+static int io = 0x300;
+static int irq = 10;
+MODULE_PARM(irq, "i");
+
+int init_module(void)
+{
+	dev_apricot.base_addr = io;
+	dev_apricot.irq = irq;
+	if (register_netdev(&dev_apricot) != 0)
+		return -EIO;
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	unregister_netdev(&dev_apricot);
+	kfree((void *) dev_apricot.mem_start);
+	dev_apricot.priv = NULL;
+
+	/* If we don't do this, we can't re-insmod it later. */
+	release_region(dev_apricot.base_addr, I596_TOTAL_SIZE);
+}
+
+#endif				/* MODULE */
+
+/*
+ * Local variables:
+ *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 82596.c"
+ * End:
+ */
diff -u --recursive --new-file v2.1.109/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.1.109/linux/drivers/net/8390.c	Tue Jun 23 10:01:23 1998
+++ linux/drivers/net/8390.c	Sun Jul 19 20:48:55 1998
@@ -238,7 +238,7 @@
 	else
 	{	/* We should never get here. */
 		if (ei_debug)
-			printk(KERN_DEBUG "%s: No Tx buffers free! irq=%d tx1=%d tx2=%d last=%d\n",
+			printk(KERN_DEBUG "%s: No Tx buffers free! irq=%ld tx1=%d tx2=%d last=%d\n",
 				dev->name, dev->interrupt, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
 		ei_local->irqlock = 0;
 		dev->tbusy = 1;
diff -u --recursive --new-file v2.1.109/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.1.109/linux/drivers/net/Makefile	Wed Jun 24 22:54:06 1998
+++ linux/drivers/net/Makefile	Mon Jul 20 17:22:35 1998
@@ -22,6 +22,8 @@
 CONFIG_PPPDEF_MODULE  :=
 CONFIG_7990_BUILTIN :=
 CONFIG_7990_MODULE :=
+CONFIG_82596_BUILTIN :=
+CONFIG_82596_MODULE :=
 
 ifeq ($(CONFIG_ISDN),y)
   ifeq ($(CONFIG_ISDN_PPP),y)
@@ -573,10 +575,26 @@
 endif
 
 ifeq ($(CONFIG_APRICOT),y)
-L_OBJS += apricot.o
+CONFIG_82596_BUILTIN = y
 else
   ifeq ($(CONFIG_APRICOT),m)
-  M_OBJS += apricot.o
+  CONFIG_82596_MODULE = y
+  endif
+endif
+
+ifeq ($(CONFIG_MVME16x_NET),y)
+CONFIG_82596_BUILTIN = y
+else
+  ifeq ($(CONFIG_MVME16x_NET),m)
+  CONFIG_82596_MODULE = y
+  endif
+endif
+
+ifeq ($(CONFIG_BVME6000_NET),y)
+CONFIG_82596_BUILTIN = y
+else
+  ifeq ($(CONFIG_BVME6000_NET),m)
+  CONFIG_82596_MODULE = y
   endif
 endif
 
@@ -700,6 +718,16 @@
 else
   ifdef CONFIG_7990_MODULE
   M_OBJS += 7990.o
+  endif
+endif
+
+# If anything built-in uses the 82596, then build it into the kernel also.
+# If not, but a module uses it, build as a module.
+ifdef CONFIG_82596_BUILTIN
+L_OBJS += 82596.o
+else
+  ifdef CONFIG_82596_MODULE
+  M_OBJS += 82596.o
   endif
 endif
 
diff -u --recursive --new-file v2.1.109/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.1.109/linux/drivers/net/Space.c	Wed Jun 24 22:54:06 1998
+++ linux/drivers/net/Space.c	Mon Jul 20 17:22:35 1998
@@ -5,22 +5,21 @@
  *
  *		Holds initial configuration information for devices.
  *
- * NOTE:	This file is a nice idea, but its current format does not work
- *		well for drivers that support multiple units, like the SLIP
- *		driver.  We should actually have only one pointer to a driver
- *		here, with the driver knowing how many units it supports.
- *		Currently, the SLIP driver abuses the "base_addr" integer
- *		field of the 'device' structure to store the unit number...
- *		-FvK
- *
  * Version:	@(#)Space.c	1.0.7	08/12/93
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Donald J. Becker, <becker@super.org>
  *
+ * Changelog:
+ *		Paul Gortmaker (06/98): 
+ *		 - sort probes in a sane way, make sure all (safe) probes
+ *		   get run once & failed autoprobes don't autoprobe again.
+ *
  *	FIXME:
- *		Sort the device chain fastest first.
+ *		Phase out placeholder dev entries put in the linked list
+ *		here in favour of drivers using init_etherdev(NULL, ...)
+ *		combined with a single find_all_devs() function (for 2.3)
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -62,7 +61,7 @@
 extern int fmv18x_probe(struct device *);
 extern int eth16i_probe(struct device *);
 extern int depca_probe(struct device *);
-extern int apricot_probe(struct device *);
+extern int i82596_probe(struct device *);
 extern int ewrk3_probe(struct device *);
 extern int de4x5_probe(struct device *);
 extern int el1_probe(struct device *);
@@ -98,7 +97,9 @@
 extern int mace_probe(struct device *);
 extern int cs89x0_probe(struct device *dev);
 extern int ethertap_probe(struct device *dev);
-extern int acorn_ethif_probe(struct device *dev);
+extern int ether1_probe (struct device *dev);
+extern int ether3_probe (struct device *dev);
+extern int etherh_probe (struct device *dev);
 extern int am79c961_probe(struct device *dev);
 extern int epic100_probe(struct device *dev);
 extern int rtl8139_probe(struct device *dev);
@@ -119,226 +120,357 @@
 /* HIPPI boards */
 extern int cern_hippi_probe(struct device *);
 
-
-__initfunc(static int ethif_probe(struct device *dev))
+struct devprobe
 {
-    u_long base_addr = dev->base_addr;
+	int (*probe)(struct device *dev);
+	int status;	/* non-zero if autoprobe has failed */
+};
+
+/*
+ * probe_list walks a list of probe functions and calls each so long
+ * as a non-zero ioaddr is given, or as long as it hasn't already failed 
+ * to find a card in the past (as recorded by "status") when asked to
+ * autoprobe (i.e. a probe that fails to find a card when autoprobing
+ * will not be asked to autoprobe again).  It exits when a card is found.
+ */
+__initfunc(static int probe_list(struct device *dev, struct devprobe *plist))
+{
+	struct devprobe *p = plist;
+	unsigned long base_addr = dev->base_addr;
 
-    if ((base_addr == 0xffe0)  ||  (base_addr == 1))
-	return 1;		/* ENXIO */
+	while (p->probe != NULL) {
+		if (base_addr && p->probe(dev) == 0)	/* probe given addr */
+			return 0;
+		else if (p->status == 0) {		/* has autoprobe failed yet? */
+			p->status = p->probe(dev);	/* no, try autoprobe */
+			if (p->status == 0)
+				return 0;
+		}
+		p++;
+	}
+	return -ENODEV;
+}
 
-    if (1
-#ifdef CONFIG_HAPPYMEAL
-	/* Please keep this one first, we'd like the on-board ethernet
-	 * to be probed first before other PCI cards on Ultra/PCI.  -DaveM
-	 */
-	&& happy_meal_probe(dev)
-#endif
+/*
+ * If your probe touches ISA ports (<0x400) in addition to
+ * looking for PCI cards, then put it in the isa_probes
+ * list instead.
+ */
+struct devprobe pci_probes[] __initdata = {
 #ifdef CONFIG_DGRS
-	&& dgrs_probe(dev)
+	{dgrs_probe, 0},
 #endif
-#if defined(CONFIG_VORTEX)
-	&& tc59x_probe(dev)
+#ifdef CONFIG_VORTEX
+	{tc59x_probe, 0},
 #endif
-#if defined(CONFIG_SEEQ8005)
-	&& seeq8005_probe(dev)
+#ifdef CONFIG_DEC_ELCP 
+	{tulip_probe, 0},
 #endif
-#if defined(CONFIG_DEC_ELCP)
-	&& tulip_probe(dev)
+#ifdef CONFIG_NE2K_PCI
+	{ne2k_pci_probe, 0},
 #endif
-#if defined(CONFIG_HP100)
-	&& hp100_probe(dev)
+#ifdef CONFIG_PCNET32
+	{pcnet32_probe, 0},
 #endif	
-#if defined(CONFIG_ULTRA)
-	&& ultra_probe(dev)
-#endif
-#if defined(CONFIG_ULTRAMCA)
-        && ultramca_probe(dev)
+#ifdef CONFIG_EEXPRESS_PRO100	/* Intel EtherExpress Pro/100 */
+	{eepro100_probe, 0},
 #endif
-#if defined(CONFIG_ULTRA32)
-	&& ultra32_probe(dev)
+#ifdef CONFIG_DE4X5             /* DEC DE425, DE434, DE435 adapters */
+	{de4x5_probe, 0},
 #endif
-#if defined(CONFIG_SMC9194)
-	&& smc_init(dev)
+#ifdef CONFIG_TLAN
+	{tlan_probe, 0},
 #endif
-#if defined(CONFIG_WD80x3) || defined(WD80x3)
-	&& wd_probe(dev)
+#ifdef CONFIG_EPIC100
+	{epic100_probe, 0},
 #endif
-#if defined(CONFIG_EL2) || defined(EL2)	/* 3c503 */
-	&& el2_probe(dev)
+#ifdef CONFIG_RTL8139
+	{rtl8139_probe, 0},
 #endif
-#if defined(CONFIG_HPLAN) || defined(HPLAN)
-	&& hp_probe(dev)
+#ifdef CONFIG_YELLOWFIN
+	{yellowfin_probe, 0},
 #endif
-#if defined(CONFIG_HPLAN_PLUS)
-	&& hp_plus_probe(dev)
+	{NULL, 0},
+};
+
+/*
+ * This is a bit of an artificial separation as there are PCI drivers
+ * that also probe for EISA cards (in the PCI group) and there are ISA
+ * drivers that probe for EISA cards (in the ISA group).  These are the
+ * EISA only driver probes.
+ */
+struct devprobe eisa_probes[] __initdata = {
+#ifdef CONFIG_ULTRA32 
+	{ultra32_probe, 0},	
 #endif
-#ifdef CONFIG_AC3200		/* Ansel Communications EISA 3200. */
-	&& ac3200_probe(dev)
+#ifdef CONFIG_AC3200	
+	{ac3200_probe, 0},
 #endif
 #ifdef CONFIG_ES3210
-	&& es_probe(dev)
+	{es_probe, 0},
 #endif
 #ifdef CONFIG_LNE390
-	&& lne390_probe(dev)
+	{lne390_probe, 0},
+#endif
+	{NULL, 0},
+};
+
+struct devprobe sparc_probes[] __initdata = {
+#ifdef CONFIG_HAPPYMEAL
+	{happy_meal_probe, 0},
+#endif
+#ifdef CONFIG_SUNLANCE
+	{sparc_lance_probe, 0},
+#endif
+#ifdef CONFIG_SUNQE
+	{qec_probe, 0},
+#endif
+#ifdef CONFIG_MYRI_SBUS
+	{myri_sbus_probe, 0},
+#endif
+	{NULL, 0},
+};
+
+struct devprobe mca_probes[] __initdata = {
+#ifdef CONFIG_ULTRAMCA 
+	{ultramca_probe, 0},
+#endif
+#ifdef CONFIG_ELMC		/* 3c523 */
+	{elmc_probe, 0},
+#endif
+	{NULL, 0},
+};
+
+/*
+ * ISA probes that touch addresses < 0x400 (including those that also
+ * look for EISA/PCI cards in addition to ISA cards).
+ */
+struct devprobe isa_probes[] __initdata = {
+#ifdef CONFIG_EL3		/* ISA, EISA (MCA someday) 3c5x9 */
+	{el3_probe, 0},
+#endif
+#ifdef CONFIG_HP100 		/* ISA, EISA & PCI */
+	{hp100_probe, 0},
+#endif	
+#ifdef CONFIG_ULTRA 
+	{ultra_probe, 0},
+#endif
+#ifdef CONFIG_WD80x3 
+	{wd_probe, 0},
+#endif
+#ifdef CONFIG_EL2 		/* 3c503 */
+	{el2_probe, 0},
+#endif
+#ifdef CONFIG_HPLAN
+	{hp_probe, 0},
+#endif
+#ifdef CONFIG_HPLAN_PLUS
+	{hp_plus_probe, 0},
 #endif
 #ifdef CONFIG_E2100		/* Cabletron E21xx series. */
-	&& e2100_probe(dev)
+	{e2100_probe, 0},
 #endif
-#if defined(CONFIG_NE2K_PCI)
-	&& ne2k_pci_probe(dev)
+#ifdef CONFIG_NE2000		/* ISA (use ne2k-pci for PCI cards) */
+	{ne_probe, 0},
 #endif
-#if defined(CONFIG_NE2000)
-	&& ne_probe(dev)
+#ifdef CONFIG_SMC9194
+	{smc_init, 0},
+#endif
+#ifdef CONFIG_SEEQ8005 
+	{seeq8005_probe, 0},
 #endif
 #ifdef CONFIG_AT1500
-	&& at1500_probe(dev)
+	{at1500_probe, 0},
 #endif
 #ifdef CONFIG_CS89x0
- 	&& cs89x0_probe(dev)
+ 	{cs89x0_probe, 0},
 #endif
-#ifdef CONFIG_PCNET32
-	&& pcnet32_probe(dev)
-#endif	
 #ifdef CONFIG_AT1700
-	&& at1700_probe(dev)
+	{at1700_probe, 0},
 #endif
 #ifdef CONFIG_FMV18X		/* Fujitsu FMV-181/182 */
-	&& fmv18x_probe(dev)
+	{fmv18x_probe, 0},
 #endif
 #ifdef CONFIG_ETH16I
-	&& eth16i_probe(dev)	/* ICL EtherTeam 16i/32 */
-#endif
-#ifdef CONFIG_EL3		/* 3c509 */
-	&& el3_probe(dev)
+	{eth16i_probe, 0},	/* ICL EtherTeam 16i/32 */
 #endif
 #ifdef CONFIG_ZNET		/* Zenith Z-Note and some IBM Thinkpads. */
-	&& znet_probe(dev)
+	{znet_probe, 0},
 #endif
 #ifdef CONFIG_EEXPRESS		/* Intel EtherExpress */
-	&& express_probe(dev)
+	{express_probe, 0},
 #endif
 #ifdef CONFIG_EEXPRESS_PRO	/* Intel EtherExpress Pro/10 */
-	&& eepro_probe(dev)
-#endif
-#ifdef CONFIG_EEXPRESS_PRO100	/* Intel EtherExpress Pro/100 */
-	&& eepro100_probe(dev)
+	{eepro_probe, 0},
 #endif
 #ifdef CONFIG_DEPCA		/* DEC DEPCA */
-	&& depca_probe(dev)
+	{depca_probe, 0},
 #endif
 #ifdef CONFIG_EWRK3             /* DEC EtherWORKS 3 */
-        && ewrk3_probe(dev)
+    	{ewrk3_probe, 0},
 #endif
-#ifdef CONFIG_DE4X5             /* DEC DE425, DE434, DE435 adapters */
-        && de4x5_probe(dev)
-#endif
-#ifdef CONFIG_APRICOT		/* Apricot I82596 */
-	&& apricot_probe(dev)
+#if defined(CONFIG_APRICOT) || defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET)	/* Intel I82596 */
+	{i82596_probe, 0},
 #endif
 #ifdef CONFIG_EL1		/* 3c501 */
-	&& el1_probe(dev)
+	{el1_probe, 0},
 #endif
-#if	defined(CONFIG_WAVELAN)	/* WaveLAN */
-	&& wavelan_probe(dev)
-#endif	/* defined(CONFIG_WAVELAN) */
-#ifdef CONFIG_EL16		/* 3c507 */
-	&& el16_probe(dev)
+#ifdef CONFIG_WAVELAN		/* WaveLAN */
+	{wavelan_probe, 0},
 #endif
-#ifdef CONFIG_ELMC		/* 3c523 */
-	&& elmc_probe(dev)
+#ifdef CONFIG_EL16		/* 3c507 */
+	{el16_probe, 0},
 #endif
 #ifdef CONFIG_ELPLUS		/* 3c505 */
-	&& elplus_probe(dev)
+	{elplus_probe, 0},
 #endif
-#ifdef CONFIG_DE600		/* D-Link DE-600 adapter */
-	&& de600_probe(dev)
-#endif
-#ifdef CONFIG_DE620		/* D-Link DE-620 adapter */
-	&& de620_probe(dev)
-#endif
-#if defined(CONFIG_SK_G16)
-	&& SK_init(dev)
+#ifdef CONFIG_SK_G16
+	{SK_init, 0},
 #endif
 #ifdef CONFIG_NI5010
-        && ni5010_probe(dev)
+	{ni5010_probe, 0},
 #endif
 #ifdef CONFIG_NI52
-	&& ni52_probe(dev)
+	{ni52_probe, 0},
 #endif
 #ifdef CONFIG_NI65
-        && ni65_probe(dev)
+	{ni65_probe, 0},
+#endif
+	{NULL, 0},
+};
+
+struct devprobe parport_probes[] __initdata = {
+#ifdef CONFIG_DE600		/* D-Link DE-600 adapter */
+	{de600_probe, 0},
+#endif
+#ifdef CONFIG_DE620		/* D-Link DE-620 adapter */
+	{de620_probe, 0},
 #endif
+#ifdef CONFIG_ATP		/* AT-LAN-TEC (RealTek) pocket adaptor. */
+	{atp_init, 0},
+#endif
+	{NULL, 0},
+};
+
+struct devprobe m68k_probes[] __initdata = {
 #ifdef CONFIG_ATARILANCE	/* Lance-based Atari ethernet boards */
-	&& atarilance_probe(dev)
+	{atarilance_probe, 0},
 #endif
 #ifdef CONFIG_A2065		/* Commodore/Ameristar A2065 Ethernet Board */
-	&& a2065_probe(dev)
+	{a2065_probe, 0},
 #endif
 #ifdef CONFIG_ARIADNE		/* Village Tronic Ariadne Ethernet Board */
-	&& ariadne_probe(dev)
+	{ariadne_probe, 0},
 #endif
 #ifdef CONFIG_HYDRA		/* Hydra Systems Amiganet Ethernet board */
-	&& hydra_probe(dev)
+	{hydra_probe, 0},
 #endif
 #ifdef CONFIG_ATARI_BIONET	/* Atari Bionet Ethernet board */
-	&& bionet_probe(dev)
+	{bionet_probe, 0},
 #endif
 #ifdef CONFIG_ATARI_PAMSNET	/* Atari PAMsNet Ethernet board */
-	&& pamsnet_probe(dev)
+	{pamsnet_probe, 0},
 #endif
 #ifdef CONFIG_HPLANCE		/* HP300 internal Ethernet */
-	&& hplance_probe(dev)
-#endif
-#ifdef CONFIG_SUNLANCE
-	&& sparc_lance_probe(dev)
-#endif
-#ifdef CONFIG_TLAN
-	&& tlan_probe(dev)
-#endif
-#ifdef CONFIG_SUNQE
-	&& qec_probe(dev)
-#endif
-#ifdef CONFIG_MYRI_SBUS
-	&& myri_sbus_probe(dev)
+	{hplance_probe, 0},
 #endif
+	{NULL, 0},
+};
+
+struct devprobe ppc_probes[] __initdata = {
 #ifdef CONFIG_MACE
-	&& mace_probe(dev)
+	{mace_probe, 0},
 #endif
+	{NULL, 0},
+};
+
+struct devprobe sgi_probes[] __initdata = {
 #ifdef CONFIG_SGISEEQ
-	&& sgiseeq_probe(dev)
+	{sgiseeq_probe, 0},
 #endif
+	{NULL, 0},
+};
+
+struct devprobe mips_probes[] __initdata = {
 #ifdef CONFIG_MIPS_JAZZ_SONIC
-	&& sonic_probe(dev)
-#endif
-#ifdef CONFIG_ARCH_ACORN
-	&& acorn_ethif_probe(dev)
+	{sonic_probe, 0},
 #endif
-#ifdef CONFIG_ARM_AM79C961A
-	&& am79c961_probe(dev)
+	{NULL, 0},
+};
+
+struct devprobe arm_probes[] __initdata = {
+#ifdef CONFIG_ARM_ETHERH
+	{etherh_probe , 0},
 #endif
-#ifdef CONFIG_EPIC100
-	&& epic100_probe(dev)
+#ifdef CONFIG_ARM_ETHER3
+	{ether3_probe , 0},
 #endif
-#ifdef CONFIG_RTL8139
-        && rtl8139_probe(dev)
+#ifdef CONFIG_ARM_ETHER1
+	{ether1_probe , 0},
 #endif
-#ifdef CONFIG_YELLOWFIN
-        && yellowfin_probe(dev)
+#ifdef CONFIG_ARM_AM79C961A
+	{am79c961_probe, 0},
 #endif
-	&& 1 ) {
-	return 1;	/* -ENODEV or -EAGAIN would be more accurate. */
-    }
-    return 0;
-}
+	{NULL, 0},
+};
+
+/*
+ * Unified ethernet device probe, segmented per architecture and
+ * per bus interface.
+ */
+__initfunc(static int ethif_probe(struct device *dev))
+{
+	unsigned long base_addr = dev->base_addr;
 
+	/* 
+	 * Backwards compatibility - historically an I/O base of 1 was 
+	 * used to indicate not to probe for this ethN interface 
+	 */
+	if (base_addr == 1)
+		return 1;		/* ENXIO */
+
+	/* 
+	 * The arch specific probes are 1st so that any on-board ethernet
+	 * will be probed before other ISA/EISA/MCA/PCI bus cards.
+	 */
+	if (probe_list(dev, arm_probes) == 0)
+		return 0;
+	if (probe_list(dev, m68k_probes) == 0)
+		return 0;
+	if (probe_list(dev, mips_probes) == 0)
+		return 0;
+	if (probe_list(dev, ppc_probes) == 0)
+		return 0;
+	if (probe_list(dev, sgi_probes) == 0)
+		return 0;
+	if (probe_list(dev, sparc_probes) == 0)
+		return 0;
+	if (probe_list(dev, pci_probes) == 0)
+		return 0;
+	if (probe_list(dev, eisa_probes) == 0)
+		return 0;
+	if (probe_list(dev, mca_probes) == 0)
+		return 0;
+        /*
+         * Backwards compatibility - an I/O of 0xffe0 was used to indicate
+         * that we shouldn't do a bunch of potentially risky ISA probes
+         * for ethN (N>1).  Since the widespread use of modules, *nobody*
+         * compiles a kernel with all the ISA drivers built in anymore,
+         * and so we should delete this check in linux 2.3 - Paul G.
+         */
+	if (base_addr != 0xffe0 && probe_list(dev, isa_probes) == 0) 
+		return 0;
+	if (probe_list(dev, parport_probes) == 0)
+		return 0;
+	return -ENODEV;
+}
 
 #ifdef CONFIG_FDDI
 __initfunc(static int fddiif_probe(struct device *dev))
 {
     unsigned long base_addr = dev->base_addr;
 
-    if ((base_addr == 0xffe0)  ||  (base_addr == 1))
+    if (base_addr == 1)
 	    return 1;		/* ENXIO */
 
     if (1
@@ -392,14 +524,6 @@
 #   define NEXT_DEV	(&sdla0_dev)
 #endif
 
-/* Run-time ATtachable (Pocket) devices have a different (not "eth#") name. */
-#ifdef CONFIG_ATP		/* AT-LAN-TEC (RealTek) pocket adaptor. */
-static struct device atp_dev = {
-    "atp0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, atp_init, /* ... */ };
-#   undef NEXT_DEV
-#   define NEXT_DEV	(&atp_dev)
-#endif
-
 #if defined(CONFIG_LTPC)
     extern int ltpc_probe(struct device *);
     static struct device dev_ltpc = {
@@ -439,15 +563,11 @@
 # define ETH0_IRQ 0
 #endif
 
-#if !defined(__sparc__) && !defined(CONFIG_ARCH_ACORN)
-#define ETH_NOPROBE_ADDR 0xffe0
-#else
-#define ETH_NOPROBE_ADDR 0
-#endif
-
 /* "eth0" defaults to autoprobe (== 0), other use a base of 0xffe0 (== -0x20),
-   which means "don't probe".  These entries exist to only to provide empty
-   slots which may be enabled at boot-time. */
+   which means "don't do ISA probes".  Distributions don't ship kernels with
+   all ISA drivers compiled in anymore, so its probably no longer an issue. */
+
+#define ETH_NOPROBE_ADDR 0xffe0
 
 static struct device eth7_dev = {
     "eth7", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe };
diff -u --recursive --new-file v2.1.109/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- v2.1.109/linux/drivers/net/eepro100.c	Thu Jul 16 18:09:25 1998
+++ linux/drivers/net/eepro100.c	Mon Jul 20 13:49:45 1998
@@ -491,6 +491,7 @@
 
 	if (pci_present()) {
 		static int pci_index = 0;
+
 		for (; pci_index < 8; pci_index++) {
 			unsigned char pci_bus, pci_device_fn, pci_latency;
 #if (LINUX_VERSION_CODE >= VERSION(2,1,85))
@@ -507,9 +508,9 @@
 			unsigned short pci_command;
 
 			if (pcibios_find_device(PCI_VENDOR_ID_INTEL,
-									PCI_DEVICE_ID_INTEL_82557,
-									pci_index, &pci_bus,
-									&pci_device_fn))
+						PCI_DEVICE_ID_INTEL_82557,
+						pci_index, &pci_bus,
+						&pci_device_fn))
 			  break;
 #if (LINUX_VERSION_CODE >= VERSION(2,1,85))
 			pdev = pci_find_slot(pci_bus, pci_device_fn);
diff -u --recursive --new-file v2.1.109/linux/drivers/net/hamradio/baycom_epp.c linux/drivers/net/hamradio/baycom_epp.c
--- v2.1.109/linux/drivers/net/hamradio/baycom_epp.c	Thu Jul 16 18:09:25 1998
+++ linux/drivers/net/hamradio/baycom_epp.c	Sat Jul 18 14:16:03 1998
@@ -453,7 +453,7 @@
 		bc->cfg.intclk ? "int" : "ext",
 		bc->cfg.extmodem ? "ext" : "int", bc->cfg.divider,
 		bc->cfg.loopback ? ",loopback" : "");
-	sprintf(portarg, "%d", bc->pdev->port->base);
+	sprintf(portarg, "%ld", bc->pdev->port->base);
 	printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n", bc_drvname, eppconfig_path, portarg, modearg);
 
         for (i = 0; i < current->files->max_fds; i++ )
diff -u --recursive --new-file v2.1.109/linux/drivers/net/hamradio/bpqether.c linux/drivers/net/hamradio/bpqether.c
--- v2.1.109/linux/drivers/net/hamradio/bpqether.c	Thu Feb 12 20:56:08 1998
+++ linux/drivers/net/hamradio/bpqether.c	Sat Jul 18 14:16:03 1998
@@ -318,6 +318,7 @@
 	}
 
 	skb->dev = dev;
+	skb->nh.raw = skb->data;
 	dev->hard_header(skb, dev, ETH_P_BPQ, bpq->dest_addr, NULL, 0);
 	bpq->stats.tx_packets++;
 	bpq->stats.tx_bytes+=skb->len;
diff -u --recursive --new-file v2.1.109/linux/drivers/net/hamradio/soundmodem/Makefile linux/drivers/net/hamradio/soundmodem/Makefile
--- v2.1.109/linux/drivers/net/hamradio/soundmodem/Makefile	Thu Sep  4 13:25:28 1997
+++ linux/drivers/net/hamradio/soundmodem/Makefile	Mon Jul 20 10:05:16 1998
@@ -46,7 +46,7 @@
 .PHONY:		all
 
 gentbl:		gentbl.c
-		$(HOSTCC) -Wall $< -o $@ -lm
+		$(HOSTCC) $(HOSTCFLAGS) $< -o $@ -lm
 
 TBLHDR		:= sm_tbl_afsk1200.h sm_tbl_afsk2400_8.h 
 TBLHDR		+= sm_tbl_afsk2666.h sm_tbl_psk4800.h
diff -u --recursive --new-file v2.1.109/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- v2.1.109/linux/drivers/net/ne.c	Thu Jul 16 18:09:25 1998
+++ linux/drivers/net/ne.c	Sun Jul 19 20:48:55 1998
@@ -530,7 +530,7 @@
     /* This *shouldn't* happen. If it does, it's the last thing you'll see */
     if (ei_status.dmaing) {
 	printk("%s: DMAing conflict in ne_get_8390_hdr "
-	   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+	   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
 	   dev->name, ei_status.dmaing, ei_status.irqlock,
 	   dev->interrupt);
 	return;
@@ -570,7 +570,7 @@
     /* This *shouldn't* happen. If it does, it's the last thing you'll see */
     if (ei_status.dmaing) {
 	printk("%s: DMAing conflict in ne_block_input "
-	   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+	   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
 	   dev->name, ei_status.dmaing, ei_status.irqlock,
 	   dev->interrupt);
 	return;
@@ -639,7 +639,7 @@
     /* This *shouldn't* happen. If it does, it's the last thing you'll see */
     if (ei_status.dmaing) {
 	printk("%s: DMAing conflict in ne_block_output."
-	   "[DMAstat:%d][irqlock:%d][intr:%d]\n",
+	   "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
 	   dev->name, ei_status.dmaing, ei_status.irqlock,
 	   dev->interrupt);
 	return;
diff -u --recursive --new-file v2.1.109/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c
--- v2.1.109/linux/drivers/net/ne2k-pci.c	Thu Jul 16 18:09:25 1998
+++ linux/drivers/net/ne2k-pci.c	Sun Jul 19 20:48:55 1998
@@ -45,7 +45,7 @@
 #include "8390.h"
 
 /* Set statically or when loading the driver module. */
-static debug = 1;
+static int debug = 1;
 
 /* Some defines that people can play with if so inclined. */
 
@@ -446,7 +446,7 @@
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 	if (ei_status.dmaing) {
 		printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr "
-			   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+			   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
 			   dev->name, ei_status.dmaing, ei_status.irqlock,
 			   dev->interrupt);
 		return;
@@ -484,7 +484,7 @@
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 	if (ei_status.dmaing) {
 		printk("%s: DMAing conflict in ne2k_pci_block_input "
-			   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+			   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
 			   dev->name, ei_status.dmaing, ei_status.irqlock,
 			   dev->interrupt);
 		return;
@@ -532,7 +532,7 @@
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 	if (ei_status.dmaing) {
 		printk("%s: DMAing conflict in ne2k_pci_block_output."
-			   "[DMAstat:%d][irqlock:%d][intr:%d]\n",
+			   "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
 			   dev->name, ei_status.dmaing, ei_status.irqlock,
 			   dev->interrupt);
 		return;
diff -u --recursive --new-file v2.1.109/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c
--- v2.1.109/linux/drivers/net/sk_g16.c	Sun Jun  7 11:16:32 1998
+++ linux/drivers/net/sk_g16.c	Sun Jul 19 20:48:55 1998
@@ -2002,7 +2002,7 @@
 	printk("## Device Name: %s Base Address: %#06lx IRQ: %d\n", 
                dev->name, dev->base_addr, dev->irq);
 	       
-	printk("##   FLAGS: start: %d tbusy: %ld int: %d\n", 
+	printk("##   FLAGS: start: %d tbusy: %ld int: %ld\n", 
                dev->start, dev->tbusy, dev->interrupt);
 
 	printk("## next device: %#08x init function: %#08x\n", 
diff -u --recursive --new-file v2.1.109/linux/drivers/net/tlan.c linux/drivers/net/tlan.c
--- v2.1.109/linux/drivers/net/tlan.c	Wed Jun 24 22:54:07 1998
+++ linux/drivers/net/tlan.c	Sun Jul 19 20:51:24 1998
@@ -3,20 +3,23 @@
  *  Linux ThunderLAN Driver
  *
  *  tlan.c
- *  by James Banks, james.banks@caldera.com
+ *  by James Banks
  *
- *  (C) 1997 Caldera, Inc.
+ *  (C) 1997-1998 Caldera, Inc.
+ *  (C) 1998 James Banks
  *
  *  This software may be used and distributed according to the terms
  *  of the GNU Public License, incorporated herein by reference.
  *
- ** This file is best viewed/edited with tabstop=4 and colums>=132.
+ ** This file is best viewed/edited with columns>=132.
  *
  ** Useful (if not required) reading:
  *
  *		Texas Instruments, ThunderLAN Programmer's Guide,
  *			TI Literature Number SPWU013A
  *			available in PDF format from www.ti.com
+ *		Level One, LXT901 and LXT970 Data Sheets
+ *			available in PDF format from www.level1.com
  *		National Semiconductor, DP83840A Data Sheet
  *			available in PDF format from www.national.com
  *		Microchip Technology, 24C01A/02A/04A Data Sheet
@@ -29,6 +32,7 @@
 
 #include "tlan.h"
 
+#include <linux/bios32.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/etherdevice.h>
@@ -49,53 +53,105 @@
 
 static  int		debug = 0;
 static	int		aui = 0;
+static	int		sa_int = 0;
+static	int		bbuf = 0;
+static	int		duplex = 0;
+static	int		speed = 0;
 static	u8		*TLanPadBuffer;
 static	char		TLanSignature[] = "TLAN";
-static	int		TLanVersionMajor = 0;
-static	int		TLanVersionMinor = 38;
+static	int		TLanVersionMajor = 1;
+static	int		TLanVersionMinor = 0;
 
 
-static	TLanPciId TLanDeviceList[] = {
+static	TLanAdapterEntry TLanAdapterList[] = {
 	{ PCI_VENDOR_ID_COMPAQ, 
 	  PCI_DEVICE_ID_NETELLIGENT_10,
-	  "Compaq Netelligent 10"
+	  "Compaq Netelligent 10 T PCI UTP",
+	  TLAN_ADAPTER_ACTIVITY_LED,
+	  0x83
 	},
 	{ PCI_VENDOR_ID_COMPAQ,
 	  PCI_DEVICE_ID_NETELLIGENT_10_100,
-	  "Compaq Netelligent 10/100"
+	  "Compaq Netelligent 10/100 TX PCI UTP",
+	  TLAN_ADAPTER_ACTIVITY_LED,
+	  0x83
 	}, 
 	{ PCI_VENDOR_ID_COMPAQ,
 	  PCI_DEVICE_ID_NETFLEX_3P_INTEGRATED,
-	  "Compaq Integrated NetFlex-3/P"
+	  "Compaq Integrated NetFlex-3/P",
+	  TLAN_ADAPTER_NONE,
+	  0x83
 	}, 
 	{ PCI_VENDOR_ID_COMPAQ,
 	  PCI_DEVICE_ID_NETFLEX_3P,
-	  "Compaq NetFlex-3/P"
+	  "Compaq NetFlex-3/P",
+	  TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY,
+	  0x83
 	},
 	{ PCI_VENDOR_ID_COMPAQ,
 	  PCI_DEVICE_ID_NETFLEX_3P_BNC,
-	  "Compaq NetFlex-3/P"
+	  "Compaq NetFlex-3/P",
+	  TLAN_ADAPTER_NONE,
+	  0x83
 	},
 	{ PCI_VENDOR_ID_COMPAQ,
 	  PCI_DEVICE_ID_NETELLIGENT_10_100_PROLIANT,
-	  "Compaq ProLiant Netelligent 10/100"
+	  "Compaq Netelligent Integrated 10/100 TX UTP",
+	  TLAN_ADAPTER_NONE,
+	  0x83
 	},
 	{ PCI_VENDOR_ID_COMPAQ,
 	  PCI_DEVICE_ID_NETELLIGENT_10_100_DUAL,
-	  "Compaq Dual Port Netelligent 10/100"
+	  "Compaq Netelligent Dual 10/100 TX PCI UTP",
+	  TLAN_ADAPTER_NONE,
+	  0x83
 	},
 	{ PCI_VENDOR_ID_COMPAQ,
 	  PCI_DEVICE_ID_DESKPRO_4000_5233MMX,
-	  "Compaq Deskpro 4000 5233MMX"
+	  "Compaq Netelligent 10/100 TX Embedded UTP",
+	  TLAN_ADAPTER_NONE,
+	  0x83
+	},
+	{ PCI_VENDOR_ID_OLICOM,
+	  PCI_DEVICE_ID_OLICOM_OC2183,
+	  "Olicom OC-2183/2185",
+	  TLAN_ADAPTER_USE_INTERN_10,
+	  0xF8
+	},
+	{ PCI_VENDOR_ID_OLICOM,
+	  PCI_DEVICE_ID_OLICOM_OC2325,
+	  "Olicom OC-2325",
+	  TLAN_ADAPTER_UNMANAGED_PHY,
+	  0xF8
+	},
+	{ PCI_VENDOR_ID_OLICOM,
+	  PCI_DEVICE_ID_OLICOM_OC2326,
+	  "Olicom OC-2326",
+	  TLAN_ADAPTER_USE_INTERN_10,
+	  0xF8
+	},
+	{ PCI_VENDOR_ID_COMPAQ,
+	  PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100,
+	  "Compaq Netelligent 10/100 TX UTP",
+	  TLAN_ADAPTER_ACTIVITY_LED,
+	  0x83
+	},
+	{ PCI_VENDOR_ID_COMPAQ,
+	  PCI_DEVICE_ID_NETELLIGENT_10_T2,
+	  "Compaq Netelligent 10 T/2 PCI UTP/Coax",
+	  TLAN_ADAPTER_NONE,
+	  0x83
 	},
 	{ 0,
 	  0,
-	  NULL
+	  NULL,
+	  0,
+	  0
 	} /* End of List */
 };
 
 
-static int	TLan_PciProbe( u8 *, u8 *, int *, u8 *, u32 *, u32 * );
+static int	TLan_PciProbe( u8 *, u8 *, u8 *, u8 *, u32 *, u32 * );
 static int	TLan_Init( struct device * );
 static int	TLan_Open(struct device *dev);
 static int	TLan_StartTx(struct sk_buff *, struct device *);
@@ -116,28 +172,37 @@
 static void	TLan_Timer( unsigned long );
 
 static void	TLan_ResetLists( struct device * );
+static void	TLan_FreeLists( struct device * );
 static void	TLan_PrintDio( u16 );
 static void	TLan_PrintList( TLanList *, char *, int );
 static void	TLan_ReadAndClearStats( struct device *, int );
-static int	TLan_Reset( struct device * );
+static void	TLan_ResetAdapter( struct device * );
+static void	TLan_FinishReset( struct device * );
 static void	TLan_SetMac( struct device *, int areg, char *mac );
 
-static int	TLan_PhyNop( struct device * );
 static void	TLan_PhyPrint( struct device * );
-static void	TLan_PhySelect( struct device * );
+static void	TLan_PhyDetect( struct device * );
+static void	TLan_PhyPowerDown( struct device * );
+static void	TLan_PhyPowerUp( struct device * );
+static void	TLan_PhyReset( struct device * );
+static void	TLan_PhyStartLink( struct device * );
+static void	TLan_PhyFinishAutoNeg( struct device * );
+/*
+static int	TLan_PhyNop( struct device * );
 static int	TLan_PhyInternalCheck( struct device * );
 static int	TLan_PhyInternalService( struct device * );
 static int	TLan_PhyDp83840aCheck( struct device * );
+*/
 
-static int	TLan_MiiReadReg(u16, u16, u16, u16 *);
+static int	TLan_MiiReadReg( struct device *, u16, u16, u16 * );
 static void	TLan_MiiSendData( u16, u32, unsigned );
-static void	TLan_MiiSync(u16);
-static void	TLan_MiiWriteReg(u16, u16, u16, u16);
+static void	TLan_MiiSync( u16 );
+static void	TLan_MiiWriteReg( struct device *, u16, u16, u16 );
 
 static void	TLan_EeSendStart( u16 );
 static int	TLan_EeSendByte( u16, u8, int );
 static void	TLan_EeReceiveByte( u16, u8 *, int );
-static int	TLan_EeReadByte( u16, u8, u8 * );
+static int	TLan_EeReadByte( struct device *, u8, u8 * );
 
 
 static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = {
@@ -151,6 +216,25 @@
 	TLan_HandleRxEOC
 };
 
+static inline void
+TLan_SetTimer( struct device *dev, u32 ticks, u32 type )
+{
+	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
+
+	cli();
+	if ( priv->timer.function != NULL ) {
+		return;
+	}
+	priv->timer.function = &TLan_Timer;
+	sti();
+
+	priv->timer.data = (unsigned long) dev;
+	priv->timer.expires = jiffies + ticks;
+	priv->timerSetAt = jiffies;
+	priv->timerType = type;
+	add_timer( &priv->timer );
+
+} /* TLan_SetTimer */
 
 
 /*****************************************************************************
@@ -176,7 +260,7 @@
 	 *
 	 *	This function begins the setup of the driver creating a
 	 *	pad buffer, finding all TLAN devices (matching
-	 *	TLanDeviceList entries), and creating and initializing a
+	 *	TLanAdapterList entries), and creating and initializing a
 	 *	device structure for each adapter.
 	 *
 	 **************************************************************/
@@ -188,14 +272,14 @@
 	struct device	*dev;
 	size_t		dev_size;
 	u8		dfn;
-	u32		dl_ix;
+	u32		index;
 	int		failed;
 	int		found;
 	u32		io_base;
-	int		irq;
+	u8		irq;
 	u8		rev;
 
-	printk( "TLAN driver, v%d.%d, (C) 1997 Caldera, Inc.\n",
+	printk( "TLAN driver, v%d.%d, (C) 1997-8 Caldera, Inc.\n",
 		TLanVersionMajor,
 		TLanVersionMinor
 	      );
@@ -211,8 +295,7 @@
 
 	dev_size = sizeof(struct device) + sizeof(TLanPrivateInfo);
 
-	while ( ( found = TLan_PciProbe( &bus, &dfn, &irq, &rev, &io_base, &dl_ix ) ) )
- {
+	while ( ( found = TLan_PciProbe( &bus, &dfn, &irq, &rev, &io_base, &index ) ) ) {
 		dev = (struct device *) kmalloc( dev_size, GFP_KERNEL );
 		if ( dev == NULL ) {
 			printk( "TLAN:  Could not allocate memory for device.\n" );
@@ -227,23 +310,37 @@
 		dev->irq = irq;
 		dev->init = TLan_Init;
 
-		priv->pciBus = bus;
-		priv->pciDeviceFn = dfn;
-		priv->pciRevision = rev;
-		priv->pciEntry = dl_ix;
+		priv->adapter =    &TLanAdapterList[index];
+		priv->adapterRev = rev;
+		priv->aui =        aui;
+		if ( ( duplex != 1 ) && ( duplex != 2 ) ) {
+			duplex = 0;
+		}
+		priv->duplex =     duplex;
+		if ( ( speed != 10 ) && ( speed != 100 ) ) {
+			speed = 0;
+		}
+		priv->speed =      speed;
+		priv->sa_int =     sa_int;
+		priv->debug =      debug;
 
 		ether_setup( dev );
 
 		failed = register_netdev( dev );
 
 		if ( failed ) {
-			printk( "TLAN:  Could not register network device.  Freeing struct.\n" );
+			printk( "TLAN:  Could not register device.\n" );
 			kfree( dev );
 		} else {
 			priv->nextDevice = TLanDevices;
 			TLanDevices = dev;
 			TLanDevicesInstalled++;
-			printk("TLAN:  %s irq=%2d io=%04x, %s\n", dev->name, (int) irq, io_base, TLanDeviceList[dl_ix].deviceName );
+			printk("TLAN:  %s irq=%2d io=%04x, %s, Rev. %d\n",
+				dev->name,
+				(int) dev->irq,
+				(int) dev->base_addr,
+				priv->adapter->deviceLabel,
+				priv->adapterRev );
 		}
 	}
 	
@@ -276,11 +373,12 @@
 	struct device	*dev;
 	TLanPrivateInfo	*priv;
 
-	while (TLanDevicesInstalled) {
+	while ( TLanDevicesInstalled ) {
 		dev = TLanDevices;
 		priv = (TLanPrivateInfo *) dev->priv;
-		if ( priv->dmaStorage )
+		if ( priv->dmaStorage ) {
 			kfree( priv->dmaStorage );
+		}
 		release_region( dev->base_addr, 0x10 );
 		unregister_netdev( dev );
 		TLanDevices = priv->nextDevice;
@@ -315,54 +413,79 @@
 	 
 extern int tlan_probe( struct device *dev )
 {
+	TLanPrivateInfo	*priv;
 	static int	pad_allocated = 0;
 	int		found;
-	TLanPrivateInfo	*priv;
-	u8		bus, dfn, rev;
-	int		irq;
-	u32		io_base, dl_ix;
-
-	found = TLan_PciProbe( &bus, &dfn, &irq, &rev, &io_base, &dl_ix );
-	if ( found ) {
-		dev->priv = kmalloc( sizeof(TLanPrivateInfo), GFP_KERNEL );
-		if ( dev->priv == NULL ) {
-			printk( "TLAN:  Could not allocate memory for device.\n" );
+	u8		bus, dfn, irq, rev;
+	u32		io_base, index;
+
+	found = TLan_PciProbe( &bus, &dfn, &irq, &rev, &io_base, &index );
+
+	if ( ! found ) {
+		return -ENODEV;
+	}
+
+	dev->priv = kmalloc( sizeof(TLanPrivateInfo), GFP_KERNEL );
+	
+	if ( dev->priv == NULL ) {
+		printk( "TLAN:  Could not allocate memory for device.\n" );
+		return  -ENOMEM;
+	}
+
+	memset( dev->priv, 0, sizeof(TLanPrivateInfo) );
+
+	if ( ! pad_allocated ) {
+		TLanPadBuffer = (u8 *) kmalloc( TLAN_MIN_FRAME_SIZE, 
+//						( GFP_KERNEL | GFP_DMA )
+						( GFP_KERNEL )
+					      );
+		if ( TLanPadBuffer == NULL ) {
+			printk( "TLAN:  Could not allocate memory for padding.\n" );
+			kfree( dev->priv );
+			return -ENOMEM;
+		} else {
+			pad_allocated = 1;
+			memset( TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE );
 		}
-		memset( dev->priv, 0, sizeof(TLanPrivateInfo) );
-		priv = (TLanPrivateInfo *) dev->priv;
+	}
 
-		dev->name = priv->devName;
-		strcpy( priv->devName, "    " );
+	priv = (TLanPrivateInfo *) dev->priv;
 
-		dev = init_etherdev( dev, sizeof(TLanPrivateInfo) );
+	dev->name = priv->devName;
+	strcpy( priv->devName, "    " );
 
-		dev->base_addr = io_base;
-		dev->irq = irq;
+	dev = init_etherdev( dev, sizeof(TLanPrivateInfo) );
 
-		priv->pciBus = bus;
-		priv->pciDeviceFn = dfn;
-		priv->pciRevision = rev;
-		priv->pciEntry = dl_ix;
-
-		if ( ! pad_allocated ) {
-			TLanPadBuffer = (u8 *) kmalloc( TLAN_MIN_FRAME_SIZE, GFP_KERNEL | GFP_DMA );
-			if ( TLanPadBuffer == NULL ) {
-				printk( "TLAN:  Could not allocate memory for pad buffer.\n" );
-			} else {
-				pad_allocated = 1;
-				memset( TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE );
-			}
-		}
-		printk("TLAN %d.%d:  %s irq=%2d io=%04x, %s\n",TLanVersionMajor,
-			TLanVersionMinor,
-			dev->name, 
-			(int) irq, 
-			io_base, 
-			TLanDeviceList[dl_ix].deviceName );
-		TLan_Init( dev );
+	dev->base_addr = io_base;
+	dev->irq = irq;
+
+
+	priv->adapter =    &TLanAdapterList[index];
+	priv->adapterRev = rev;
+	priv->aui =        dev->mem_start & 0x01;
+	priv->duplex =     ( ( dev->mem_start & 0x0C ) == 0x0C ) ? 0 : ( dev->mem_start & 0x0C ) >> 2;
+	priv->speed =      ( ( dev->mem_start & 0x30 ) == 0x30 ) ? 0 : ( dev->mem_start & 0x30 ) >> 4;
+	if ( priv->speed == 0x1 ) {
+		priv->speed = TLAN_SPEED_10;
+	} else if ( priv->speed == 0x2 ) {
+		priv->speed = TLAN_SPEED_100;
 	}
+	priv->sa_int =     dev->mem_start & 0x02;
+	priv->debug =      dev->mem_end;
+
+
+	printk("TLAN %d.%d:  %s irq=%2d io=%04x, %s, Rev. %d\n",
+		TLanVersionMajor,
+		TLanVersionMinor,
+		dev->name, 
+		(int) irq, 
+		io_base,
+		priv->adapter->deviceLabel,
+		priv->adapterRev );
+
+	TLan_Init( dev );
 			
-   	return ( ( found ) ? 0 : -ENODEV );
+   	return 0;
 
 } /* tlan_probe */
 
@@ -390,7 +513,7 @@
 	 *				of the adapter.
 	 *
 	 *	This function searches for an adapter with PCI vendor
-	 *	and device IDs matching those in the TLanDeviceList.
+	 *	and device IDs matching those in the TLanAdapterList.
 	 *	The function 'remembers' the last device it found,
 	 *	and so finds a new device (if anymore are to be found)
 	 *	each time the function is called.  It then looks up
@@ -398,7 +521,7 @@
 	 *
 	 **************************************************************/
 
-int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, int *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix )
+int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix )
 {
 	static int dl_index = 0;
 	static int pci_index = 0;
@@ -409,43 +532,43 @@
 	int	reg;
 
 
-	if ( ! pci_present() ) {
+	if ( ! pcibios_present() ) {
 		printk( "TLAN:   PCI Bios not present.\n" );
 		return 0;
 	}
 
-	for (; TLanDeviceList[dl_index].vendorId != 0; dl_index++) {
+	for (; TLanAdapterList[dl_index].vendorId != 0; dl_index++) {
 
 		not_found = pcibios_find_device(
-			TLanDeviceList[dl_index].vendorId,
-			TLanDeviceList[dl_index].deviceId,
+			TLanAdapterList[dl_index].vendorId,
+			TLanAdapterList[dl_index].deviceId,
 			pci_index,
 			pci_bus,
 			pci_dfn
 		);
 
 		if ( ! not_found ) {
-			struct pci_dev *pdev = pci_find_slot(*pci_bus, *pci_dfn);
 
 			TLAN_DBG(
 				TLAN_DEBUG_GNRL,
 				"TLAN:  found: Vendor Id = 0x%hx, Device Id = 0x%hx\n",
-				TLanDeviceList[dl_index].vendorId,
-				TLanDeviceList[dl_index].deviceId
+				TLanAdapterList[dl_index].vendorId,
+				TLanAdapterList[dl_index].deviceId
 			);
 
-			pci_read_config_byte ( pdev, PCI_REVISION_ID, pci_rev);
-			*pci_irq = pdev->irq;
-			pci_read_config_word ( pdev, PCI_COMMAND, &pci_command);
-			pci_read_config_byte ( pdev, PCI_LATENCY_TIMER, &pci_latency);
+			pcibios_read_config_byte ( *pci_bus,  *pci_dfn, PCI_REVISION_ID, pci_rev);
+			pcibios_read_config_byte ( *pci_bus,  *pci_dfn, PCI_INTERRUPT_LINE, pci_irq);
+			pcibios_read_config_word ( *pci_bus,  *pci_dfn, PCI_COMMAND, &pci_command);
+			pcibios_read_config_dword( *pci_bus,  *pci_dfn, PCI_BASE_ADDRESS_0, pci_io_base);
+			pcibios_read_config_byte ( *pci_bus,  *pci_dfn, PCI_LATENCY_TIMER, &pci_latency);
 
 			if (pci_latency < 0x10) {
-				pci_write_config_byte( pdev, PCI_LATENCY_TIMER, 0xff);
+				pcibios_write_config_byte( *pci_bus, *pci_dfn, PCI_LATENCY_TIMER, 0xff);
 				TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:    Setting latency timer to max.\n");
 			}
 
-			for ( reg = 0; reg <= 5; reg ++ ) {
-				*pci_io_base = pdev->base_address[reg];
+			for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg +=4 ) {
+				pcibios_read_config_dword( *pci_bus, *pci_dfn, reg, pci_io_base);
 				if ((pci_command & PCI_COMMAND_IO) && (*pci_io_base & 0x3)) {
 					*pci_io_base &= PCI_BASE_ADDRESS_IO_MASK;
 					TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:    IO mapping is available at %x.\n", *pci_io_base);
@@ -458,8 +581,9 @@
 			if ( *pci_io_base == 0 )
 				printk("TLAN:    IO mapping not available, ignoring device.\n");
 
-			if (pci_command & PCI_COMMAND_MASTER) {
-				TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:    Bus mastering is active.\n");
+			if ( ! ( pci_command & PCI_COMMAND_MASTER ) ) {
+				pcibios_write_config_word ( *pci_bus,  *pci_dfn, PCI_COMMAND, pci_command | PCI_COMMAND_MASTER );
+				printk( "TLAN:  Activating PCI bus mastering for this device.\n" );
 			}
 
 			pci_index++;
@@ -500,9 +624,9 @@
 
 int TLan_Init( struct device *dev )
 {
-	int				dma_size;
-	int				err;
-	int				i;
+	int		dma_size;
+	int		err;
+	int		i;
 	TLanPrivateInfo	*priv;
 
 	priv = (TLanPrivateInfo *) dev->priv;
@@ -517,8 +641,14 @@
 	}
 	request_region( dev->base_addr, 0x10, TLanSignature );
 
-	dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
+	if ( bbuf ) {
+		dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
 	           * ( sizeof(TLanList) + TLAN_MAX_FRAME_SIZE );
+	} else {
+		dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
+	           * ( sizeof(TLanList) );
+	}
+
 	priv->dmaStorage = kmalloc( dma_size, GFP_KERNEL | GFP_DMA );
 	if ( priv->dmaStorage == NULL ) {
 		printk( "TLAN:  Could not allocate lists and buffers for %s.\n",
@@ -529,19 +659,24 @@
 	priv->rxList = (TLanList *) 
 		       ( ( ( (u32) priv->dmaStorage ) + 7 ) & 0xFFFFFFF8 );
 	priv->txList = priv->rxList + TLAN_NUM_RX_LISTS;
-	priv->rxBuffer = (u8 *) ( priv->txList + TLAN_NUM_TX_LISTS );
-	priv->txBuffer = priv->rxBuffer
-			 + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE );
+
+	if ( bbuf ) {
+		priv->rxBuffer = (u8 *) ( priv->txList + TLAN_NUM_TX_LISTS );
+		priv->txBuffer = priv->rxBuffer
+				 + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE );
+	}
 
 	err = 0;
 	for ( i = 0;  i < 6 ; i++ )
-		err |= TLan_EeReadByte( dev->base_addr,
-					(u8) 0x83 + i,
+		err |= TLan_EeReadByte( dev,
+					(u8) priv->adapter->addrOfs + i,
 					(u8 *) &dev->dev_addr[i] );
-	if ( err )
+	if ( err ) {
 		printk( "TLAN:  %s: Error reading MAC from eeprom: %d\n",
 			dev->name,
 			err );
+	}
+
 	dev->addr_len = 6;
 
 	dev->open = &TLan_Open;
@@ -550,12 +685,6 @@
 	dev->get_stats = &TLan_GetStats;
 	dev->set_multicast_list = &TLan_SetMulticastList;
 
-#ifndef MODULE
-
-	aui = dev->mem_start & 0x01;
-	debug = dev->mem_end;
-
-#endif /* MODULE */
 
 	return 0;
 
@@ -583,16 +712,21 @@
 
 int TLan_Open( struct device *dev )
 {
-	int				err;
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
+	int		err;
 
 	priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION );
-	err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev);
+	if ( priv->sa_int ) {
+		TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:   Using SA_INTERRUPT\n" ); 
+		err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ | SA_INTERRUPT, TLanSignature, dev );
+	} else {
+		err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev );
+	}
 	if ( err ) {
-		printk( "TLAN:  Cannot open %s because IRQ %d is already in use.\n", dev->name , dev->irq );
+		printk( "TLAN:  Cannot open %s because IRQ %d is already in use.\n", dev->name, dev->irq );
 		return -EAGAIN;
 	}
-
+	
 	MOD_INC_USE_COUNT;
 
 	dev->tbusy = 0;
@@ -604,27 +738,9 @@
 	*/
 	TLan_ResetLists( dev );
 	TLan_ReadAndClearStats( dev, TLAN_IGNORE );
-	TLan_Reset( dev );
-	TLan_Reset( dev );
-	TLan_SetMac( dev, 0, dev->dev_addr );
-	outb( ( TLAN_HC_INT_ON >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );
-	if ( debug >= 1 )
-		outb( ( TLAN_HC_REQ_INT >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );
-
-	init_timer( &priv->timer );
-	priv->timer.data = (unsigned long) dev;
-	priv->timer.function = &TLan_Timer;
-	if ( priv->phyFlags & TLAN_PHY_AUTONEG ) {
-		priv->timer.expires = jiffies + TLAN_TIMER_LINK_DELAY;
-		priv->timerSetAt = jiffies;
-		priv->timerType = TLAN_TIMER_LINK;
-		add_timer( &priv->timer );
-	} else {
-		outl( virt_to_bus( priv->rxList ), dev->base_addr + TLAN_CH_PARM );
-		outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );
-	}
+	TLan_ResetAdapter( dev );
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  Device %s opened.  Revision = %x\n", dev->name, priv->tlanRev );
+	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Opened.  TLAN Chip Rev: %x\n", dev->name, priv->tlanRev );
 
 	return 0;
 
@@ -657,27 +773,37 @@
 int TLan_StartTx( struct sk_buff *skb, struct device *dev )
 {
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
-	TLanList		*tail_list;
-	u8				*tail_buffer;
-	int				pad;
+	TLanList	*tail_list;
+	u8		*tail_buffer;
+	int		pad;
 
 	if ( ! priv->phyOnline ) {
 		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  %s PHY is not ready\n", dev->name );
-		dev_kfree_skb( skb );
+		dev_kfree_skb( skb, FREE_WRITE );
 		return 0;
 	}
 
 	tail_list = priv->txList + priv->txTail;
+
 	if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) {
 		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  %s is busy (Head=%d Tail=%d)\n", dev->name, priv->txHead, priv->txTail );
 		dev->tbusy = 1;
 		priv->txBusyCount++;
 		return 1;
 	}
+
 	tail_list->forward = 0;
-	tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE );
-	memcpy( tail_buffer, skb->data, skb->len );
+
+	if ( bbuf ) {
+		tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE );
+		memcpy( tail_buffer, skb->data, skb->len );
+	} else {
+		tail_list->buffer[0].address = virt_to_bus( skb->data );
+		tail_list->buffer[9].address = (u32) skb;
+	}
+
 	pad = TLAN_MIN_FRAME_SIZE - skb->len;
+
 	if ( pad > 0 ) {
 		tail_list->frameSize = (u16) skb->len + pad;
 		tail_list->buffer[0].count = (u32) skb->len;
@@ -689,7 +815,7 @@
 		tail_list->buffer[1].count = 0;
 		tail_list->buffer[1].address = 0;
 	}
-	/* are we transferring? */
+
 	cli();
 	tail_list->cStat = TLAN_CSTAT_READY;
 	if ( ! priv->txInProgress ) {
@@ -700,17 +826,19 @@
 		outl( TLAN_HC_GO | TLAN_HC_ACK, dev->base_addr + TLAN_HOST_CMD );
 	} else {
 		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Adding buffer %d to TX channel\n", priv->txTail );
-		if ( priv->txTail == 0 )
+		if ( priv->txTail == 0 ) {
 			( priv->txList + ( TLAN_NUM_TX_LISTS - 1 ) )->forward = virt_to_bus( tail_list );
-		else
+		} else {
 			( priv->txList + ( priv->txTail - 1 ) )->forward = virt_to_bus( tail_list );
+		}
 	}
 	sti();
-	priv->txTail++;
-	if ( priv->txTail >= TLAN_NUM_TX_LISTS )
-		priv->txTail = 0;
 
-	dev_kfree_skb( skb );
+	CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS );
+
+	if ( bbuf ) {
+		dev_kfree_skb( skb, FREE_WRITE );
+	}
 		
 	dev->trans_start = jiffies;
 	return 0;
@@ -743,35 +871,34 @@
 
 void TLan_HandleInterrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	u32				ack;
+	u32		ack;
 	struct device	*dev;
-	u32				host_cmd;
-	u16				host_int;
-	int				type;
+	u32		host_cmd;
+	u16		host_int;
+	int		type;
 
 	dev = (struct device *) dev_id;
 
-	if ( dev->interrupt )
-		printk( "TLAN:   Re-entering interrupt handler for %s: %d.\n" , dev->name, dev->interrupt );
-	dev->interrupt++;
-
 	cli();
+	if ( dev->interrupt ) {
+		printk( "TLAN:   Re-entering interrupt handler for %s: %ld.\n" , dev->name, dev->interrupt );
+	}
+	dev->interrupt++;
 
 	host_int = inw( dev->base_addr + TLAN_HOST_INT );
-	outw( host_int, dev->base_addr + TLAN_HOST_INT ); /* Deactivate Ints */
+	outw( host_int, dev->base_addr + TLAN_HOST_INT );
 
 	type = ( host_int & TLAN_HI_IT_MASK ) >> 2;
 
 	ack = TLanIntVector[type]( dev, host_int );
 
-	sti();
-
 	if ( ack ) {
 		host_cmd = TLAN_HC_ACK | ack | ( type << 18 );
 		outl( host_cmd, dev->base_addr + TLAN_HOST_CMD );
 	}
 
 	dev->interrupt--;
+	sti();
 
 } /* TLan_HandleInterrupts */
 
@@ -802,10 +929,11 @@
 
 	TLan_ReadAndClearStats( dev, TLAN_RECORD );
 	outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
-	if ( priv->timerSetAt != 0 )
+	if ( priv->timer.function != NULL )
 		del_timer( &priv->timer );
 	free_irq( dev->irq, dev );
-	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:   Device %s closed.\n", dev->name );
+	TLan_FreeLists( dev );
+	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  Device %s closed.\n", dev->name );
 
 	MOD_DEC_USE_COUNT;
 
@@ -882,11 +1010,11 @@
 void TLan_SetMulticastList( struct device *dev )
 {	
 	struct dev_mc_list	*dmi = dev->mc_list;
-	u32					hash1 = 0;
-	u32					hash2 = 0;
-	int					i;
-	u32					offset;
-	u8					tmp;
+	u32			hash1 = 0;
+	u32			hash2 = 0;
+	int			i;
+	u32			offset;
+	u8			tmp;
 
 	if ( dev->flags & IFF_PROMISC ) {
 		tmp = TLan_DioRead8( dev->base_addr, TLAN_NET_CMD );
@@ -989,19 +1117,24 @@
 u32 TLan_HandleTxEOF( struct device *dev, u16 host_int )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
-	int				eoc = 0;
-	TLanList		*head_list;
-	u32				ack = 1;
+	int		eoc = 0;
+	TLanList	*head_list;
+	u32		ack = 1;
 
 	TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Handling TX EOF (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );
 	host_int = 0;
 	head_list = priv->txList + priv->txHead;
+
+	if ( ! bbuf ) {
+		dev_kfree_skb( (struct sk_buff *) head_list->buffer[9].address, FREE_WRITE );
+		head_list->buffer[9].address = 0;
+	}
+
 	if ( head_list->cStat & TLAN_CSTAT_EOC )
 		eoc = 1;
 	if ( ! head_list->cStat & TLAN_CSTAT_FRM_CMP ) {
 		printk( "TLAN:  Received interrupt for uncompleted TX frame.\n" );
 	}
-	/* printk( "Ack %d CSTAT=%hx\n", priv->txHead, head_list->cStat ); */
 
 #if LINUX_KERNEL_VERSION > 0x20100
 	priv->stats->tx_bytes += head_list->frameSize;
@@ -1009,9 +1142,7 @@
 
 	head_list->cStat = TLAN_CSTAT_UNUSED;
 	dev->tbusy = 0;
-	priv->txHead++;
-	if ( priv->txHead >= TLAN_NUM_TX_LISTS )
-		priv->txHead = 0;
+	CIRC_INC( priv->txHead, TLAN_NUM_TX_LISTS );
 	if ( eoc ) {
 		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Handling TX EOC (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );
 		head_list = priv->txList + priv->txHead;
@@ -1022,17 +1153,13 @@
 			priv->txInProgress = 0;
 		}
 	}
-	TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
-	if ( priv->phyFlags & TLAN_PHY_ACTIVITY ) {
-		if ( priv->timerSetAt == 0 ) {
-			/* printk("TxEOF Starting timer...\n"); */
-			priv->timerSetAt = jiffies;
-			priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
-			priv->timerType = TLAN_TIMER_ACT;
-			add_timer( &priv->timer );
-		} else if ( priv->timerType == TLAN_TIMER_ACT ) {
+
+	if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {
+		TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
+		if ( priv->timer.function == NULL ) {
+			TLan_SetTimer( dev, TLAN_TIMER_ACT_DELAY, TLAN_TIMER_ACTIVITY );
+		} else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {
 			priv->timerSetAt = jiffies;
-			/* printk("TxEOF continuing timer...\n"); */
 		}
 	}
 
@@ -1093,7 +1220,7 @@
 	 *	of the list.  If the frame was the last in the Rx
 	 *	channel (EOC), the function restarts the receive channel
 	 *	by sending an Rx Go command to the adapter.  Then it
-	 *	activates/continues the activity LED.
+	 *	activates/continues the the activity LED.
 	 *
 	 **************************************************************/
 
@@ -1112,11 +1239,14 @@
 	host_int = 0;
 	head_list = priv->rxList + priv->rxHead;
 	tail_list = priv->rxList + priv->rxTail;
-	if ( head_list->cStat & TLAN_CSTAT_EOC )
+
+	if ( head_list->cStat & TLAN_CSTAT_EOC ) {
 		eoc = 1;
+	}
+
 	if ( ! head_list->cStat & TLAN_CSTAT_FRM_CMP ) {
 		printk( "TLAN:  Received interrupt for uncompleted RX frame.\n" );
-	} else {
+	} else if ( bbuf ) {
 		skb = dev_alloc_skb( head_list->frameSize + 7 );
 		if ( skb == NULL ) { 
 			printk( "TLAN:  Couldn't allocate memory for received data.\n" );
@@ -1125,7 +1255,6 @@
 			skb->dev = dev;
 			skb_reserve( skb, 2 );
 			t = (void *) skb_put( skb, head_list->frameSize );
-			/* printk( " %hd %p %p\n", head_list->frameSize, skb->data, t ); */
 
 #if LINUX_KERNEL_VERSION > 0x20100
 			priv->stats->rx_bytes += head_list->frameSize;
@@ -1135,17 +1264,39 @@
 			skb->protocol = eth_type_trans( skb, dev );
 			netif_rx( skb );
 		}
+	} else {
+		skb = (struct sk_buff *) head_list->buffer[9].address;
+		head_list->buffer[9].address = 0;
+		skb_trim( skb, head_list->frameSize );
+
+#if LINUX_KERNEL_VERSION > 0x20100
+			priv->stats->rx_bytes += head_list->frameSize;
+#endif
+
+		skb->protocol = eth_type_trans( skb, dev );
+		netif_rx( skb );
+
+		skb = dev_alloc_skb( TLAN_MAX_FRAME_SIZE + 7 );
+		if ( skb == NULL ) {
+			printk( "TLAN:  Couldn't allocate memory for received data.\n" );
+			/* If this ever happened it would be a problem */
+		} else {
+			skb->dev = dev;
+			skb_reserve( skb, 2 );
+			t = (void *) skb_put( skb, TLAN_MAX_FRAME_SIZE );
+			head_list->buffer[0].address = virt_to_bus( t );
+			head_list->buffer[9].address = (u32) skb;
+		}
 	}
+
 	head_list->forward = 0;
 	head_list->frameSize = TLAN_MAX_FRAME_SIZE;
 	head_list->buffer[0].count = TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;
 	tail_list->forward = virt_to_bus( head_list );
-	priv->rxHead++;
-	if ( priv->rxHead >= TLAN_NUM_RX_LISTS )
-		priv->rxHead = 0;
-	priv->rxTail++;
-	if ( priv->rxTail >= TLAN_NUM_RX_LISTS )
-		priv->rxTail = 0;
+
+	CIRC_INC( priv->rxHead, TLAN_NUM_RX_LISTS );
+	CIRC_INC( priv->rxTail, TLAN_NUM_RX_LISTS );
+
 	if ( eoc ) { 
 		TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE:  Handling RX EOC (Head=%d Tail=%d)\n", priv->rxHead, priv->rxTail );
 		head_list = priv->rxList + priv->rxHead;
@@ -1153,19 +1304,16 @@
 		ack |= TLAN_HC_GO | TLAN_HC_RT;
 		priv->rxEocCount++;
 	}
-	TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
-	if ( priv->phyFlags & TLAN_PHY_ACTIVITY ) {
-		if ( priv->timerSetAt == 0 )  {
-			/* printk("RxEOF Starting timer...\n"); */
-			priv->timerSetAt = jiffies;
-			priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
-			priv->timerType = TLAN_TIMER_ACT;
-			add_timer( &priv->timer );
-		} else if ( priv->timerType == TLAN_TIMER_ACT ) {
-			/* printk("RxEOF tarting continuing timer...\n"); */
+
+	if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {
+		TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
+		if ( priv->timer.function == NULL )  {
+			TLan_SetTimer( dev, TLAN_TIMER_ACT_DELAY, TLAN_TIMER_ACTIVITY );
+		} else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {
 			priv->timerSetAt = jiffies;
 		}
 	}
+
 	dev->last_rx = jiffies;
 
 	return ack;
@@ -1195,7 +1343,7 @@
 u32 TLan_HandleDummy( struct device *dev, u16 host_int )
 {
 	host_int = 0;
-	printk( "TLAN:  Dummy interrupt on %s.\n", dev->name );
+	printk( "TLAN:  Test interrupt on %s.\n", dev->name );
 	return 1;
 
 } /* TLan_HandleDummy */
@@ -1270,45 +1418,49 @@
 
 u32 TLan_HandleStatusCheck( struct device *dev, u16 host_int )
 {	
-	u32				ack;
-	u32				error;
-	u8				net_sts;
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
+	u32		ack;
+	u32		error;
+	u8		net_sts;
+	u32		phy;
+	u16		tlphy_ctl;
+	u16		tlphy_sts;
 	
 	ack = 1;
 	if ( host_int & TLAN_HI_IV_MASK ) {
 		error = inl( dev->base_addr + TLAN_CH_PARM );
-		printk( "TLAN:   Adaptor Check on device %s err = 0x%x\n", dev->name, error );
+		printk( "TLAN:  %s: Adaptor Error = 0x%x\n", dev->name, error );
 		TLan_ReadAndClearStats( dev, TLAN_RECORD );
 		outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
+		TLan_FreeLists( dev );
 		TLan_ResetLists( dev );
-		TLan_Reset( dev );
+		TLan_ResetAdapter( dev );
 		dev->tbusy = 0;
-		TLan_SetMac( dev, 0, dev->dev_addr );
-		if ( priv->timerType == 0 ) {
-			if ( priv->phyFlags & TLAN_PHY_AUTONEG ) {
-				priv->timer.expires = jiffies + TLAN_TIMER_LINK_DELAY;
-				priv->timerSetAt = jiffies;
-				priv->timerType = TLAN_TIMER_LINK;
-				add_timer( &priv->timer );
-			} else {
-				/*printk( " RX GO---->\n" ); */
-				outl( virt_to_bus( priv->rxList ), dev->base_addr + TLAN_CH_PARM );
-				outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );
-			}
-		}
 		ack = 0;
 	} else {
+		TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Status Check\n", dev->name );
+		phy = priv->phy[priv->phyNum];
+
 		net_sts = TLan_DioRead8( dev->base_addr, TLAN_NET_STS );
-		if ( net_sts )
+		if ( net_sts ) {
 			TLan_DioWrite8( dev->base_addr, TLAN_NET_STS, net_sts );
-		if ( net_sts & TLAN_NET_STS_MIRQ ) {
-			(*priv->phyService)( dev );
+			TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s:    Net_Sts = %x\n", dev->name, (unsigned) net_sts );
+		}
+		if ( ( net_sts & TLAN_NET_STS_MIRQ ) &&  ( priv->phyNum == 0 ) ) {
+			TLan_MiiReadReg( dev, phy, TLAN_TLPHY_STS, &tlphy_sts );
+			TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl );
+        		if ( ! ( tlphy_sts & TLAN_TS_POLOK ) && ! ( tlphy_ctl & TLAN_TC_SWAPOL ) ) {
+                		tlphy_ctl |= TLAN_TC_SWAPOL;
+                		TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl);
+        		} else if ( ( tlphy_sts & TLAN_TS_POLOK ) && ( tlphy_ctl & TLAN_TC_SWAPOL ) ) {
+                		tlphy_ctl &= ~TLAN_TC_SWAPOL;
+                		TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl);
+        		}
+
 			if (debug) {
 				TLan_PhyPrint( dev );
 			}
 		}
-		TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  Status Check! %s Net_Sts=%x\n", dev->name, (unsigned) net_sts );
 	}
 
 	return ack;
@@ -1341,8 +1493,8 @@
 u32 TLan_HandleRxEOC( struct device *dev, u16 host_int )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
-	TLanList		*head_list;
-	u32				ack = 1;
+	TLanList	*head_list;
+	u32		ack = 1;
 
 	host_int = 0;
 	if (  priv->tlanRev < 0x30 ) {
@@ -1402,34 +1554,44 @@
 void TLan_Timer( unsigned long data )
 {
 	struct device	*dev = (struct device *) data;
-	u16		gen_sts;
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
+	u32		elapsed;
 
-	/* printk( "TLAN:  %s Entered Timer, type = %d\n", dev->name, priv->timerType ); */
+	priv->timer.function = NULL;
 
 	switch ( priv->timerType ) {
-		case TLAN_TIMER_LINK:
-			TLan_MiiReadReg( dev->base_addr, priv->phyAddr, MII_GEN_STS, &gen_sts );
-			if ( gen_sts & MII_GS_LINK ) {
-				priv->phyOnline = 1;
-				outl( virt_to_bus( priv->rxList ), dev->base_addr + TLAN_CH_PARM );
-				outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );
-				priv->timerSetAt = 0;
-				priv->timerType = 0;
-			} else {
-				priv->timer.expires = jiffies + ( TLAN_TIMER_LINK_DELAY * 2 );
-				add_timer( &priv->timer );
-			}
+		case TLAN_TIMER_PHY_PDOWN:
+			TLan_PhyPowerDown( dev );
 			break;
-		case TLAN_TIMER_ACT:
-			if ( jiffies - priv->timerSetAt >= TLAN_TIMER_ACT_DELAY ) {
-				TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
-				priv->timerSetAt = 0;
-				priv->timerType = 0;
-			} else {
-				priv->timer.expires = priv->timerSetAt + TLAN_TIMER_ACT_DELAY;
-				add_timer( &priv->timer );
+		case TLAN_TIMER_PHY_PUP:
+			TLan_PhyPowerUp( dev );
+			break;
+		case TLAN_TIMER_PHY_RESET:
+			TLan_PhyReset( dev );
+			break;
+		case TLAN_TIMER_PHY_START_LINK:
+			TLan_PhyStartLink( dev );
+			break;
+		case TLAN_TIMER_PHY_FINISH_AN:
+			TLan_PhyFinishAutoNeg( dev );
+			break;
+		case TLAN_TIMER_FINISH_RESET:
+			TLan_FinishReset( dev );
+			break;
+		case TLAN_TIMER_ACTIVITY:
+			cli();
+			if ( priv->timer.function == NULL ) {
+				elapsed = jiffies - priv->timerSetAt;
+				if ( elapsed >= TLAN_TIMER_ACT_DELAY ) {
+					TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
+				} else  {
+					priv->timer.function = &TLan_Timer;
+					priv->timer.expires = priv->timerSetAt + TLAN_TIMER_ACT_DELAY;
+					sti();
+					add_timer( &priv->timer );
+				}
 			}
+			sti();
 			break;
 		default:
 			break;
@@ -1468,13 +1630,19 @@
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
 	int		i;
 	TLanList	*list;
+	struct sk_buff	*skb;
+	void		*t = NULL;
 
 	priv->txHead = 0;
 	priv->txTail = 0;
 	for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
 		list = priv->txList + i;
 		list->cStat = TLAN_CSTAT_UNUSED;
-		list->buffer[0].address = virt_to_bus( priv->txBuffer + ( i * TLAN_MAX_FRAME_SIZE ) );
+		if ( bbuf ) {
+			list->buffer[0].address = virt_to_bus( priv->txBuffer + ( i * TLAN_MAX_FRAME_SIZE ) );
+		} else {
+			list->buffer[0].address = 0;
+		}
 		list->buffer[2].count = 0;
 		list->buffer[2].address = 0;
 	}
@@ -1486,7 +1654,21 @@
 		list->cStat = TLAN_CSTAT_READY;
 		list->frameSize = TLAN_MAX_FRAME_SIZE;
 		list->buffer[0].count = TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;
-		list->buffer[0].address = virt_to_bus( priv->rxBuffer + ( i * TLAN_MAX_FRAME_SIZE ) );
+		if ( bbuf ) {
+			list->buffer[0].address = virt_to_bus( priv->rxBuffer + ( i * TLAN_MAX_FRAME_SIZE ) );
+		} else {
+			skb = dev_alloc_skb( TLAN_MAX_FRAME_SIZE + 7 );
+			if ( skb == NULL ) {
+				printk( "TLAN:  Couldn't allocate memory for received data.\n" );
+				/* If this ever happened it would be a problem */
+			} else {
+				skb->dev = dev;
+				skb_reserve( skb, 2 );
+				t = (void *) skb_put( skb, TLAN_MAX_FRAME_SIZE );
+			}
+			list->buffer[0].address = virt_to_bus( t );
+			list->buffer[9].address = (u32) skb;
+		}
 		list->buffer[1].count = 0;
 		list->buffer[1].address = 0;
 		if ( i < TLAN_NUM_RX_LISTS - 1 )
@@ -1498,6 +1680,36 @@
 } /* TLan_ResetLists */
 
 
+void TLan_FreeLists( struct device *dev )
+{
+	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
+	int		i;
+	TLanList	*list;
+	struct sk_buff	*skb;
+
+	if ( ! bbuf ) {
+		for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
+			list = priv->txList + i;
+			skb = (struct sk_buff *) list->buffer[9].address;
+			if ( skb ) {
+				dev_kfree_skb( skb, FREE_WRITE );
+				list->buffer[9].address = 0;
+			}
+		}
+
+		for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {
+			list = priv->rxList + i;
+			skb = (struct sk_buff *) list->buffer[9].address;
+			if ( skb ) {
+				dev_kfree_skb( skb, FREE_READ );
+				list->buffer[9].address = 0;
+			}
+		}
+	}
+
+} /* TLan_FreeLists */
+
+
 
 
 	/***************************************************************
@@ -1509,7 +1721,7 @@
 	 *		io_base		Base IO port of the device of
 	 *				which to print DIO registers.
 	 *
-	 *	This function prints out all the internal (DIO)
+	 *	This function prints out all the the internal (DIO)
 	 *	registers of a TLAN chip.
 	 *
 	 **************************************************************/
@@ -1588,11 +1800,11 @@
 void TLan_ReadAndClearStats( struct device *dev, int record )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
-	u32				tx_good, tx_under;
-	u32				rx_good, rx_over;
-	u32				def_tx, crc, code;
-	u32				multi_col, single_col;
-	u32				excess_col, late_col, loss;
+	u32		tx_good, tx_under;
+	u32		rx_good, rx_over;
+	u32		def_tx, crc, code;
+	u32		multi_col, single_col;
+	u32		excess_col, late_col, loss;
 
 	outw( TLAN_GOOD_TX_FRMS, dev->base_addr + TLAN_DIO_ADR );
 	tx_good  = inb( dev->base_addr + TLAN_DIO_DATA );
@@ -1660,7 +1872,8 @@
 	 *
 	 **************************************************************/
 
-int TLan_Reset( struct device *dev )
+void
+TLan_ResetAdapter( struct device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	int		i;
@@ -1668,11 +1881,14 @@
 	u32		data;
 	u8		data8;
 
+	priv->tlanFullDuplex = FALSE;
 /*  1.	Assert reset bit. */
 
 	data = inl(dev->base_addr + TLAN_HOST_CMD);
 	data |= TLAN_HC_AD_RST;
 	outl(data, dev->base_addr + TLAN_HOST_CMD);
+	
+	udelay(1000);
 
 /*  2.	Turn off interrupts. ( Probably isn't necessary ) */
 
@@ -1708,37 +1924,97 @@
 		data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC;
 		TLan_DioWrite8( dev->base_addr, TLAN_INT_DIS, data8 );
 	}
-	TLan_PhySelect( dev );
+	TLan_PhyDetect( dev );
 	data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN;
-	if ( priv->phyFlags & TLAN_PHY_BIT_RATE ) {
+	if ( priv->adapter->flags & TLAN_ADAPTER_BIT_RATE_PHY ) {
 		data |= TLAN_NET_CFG_BIT;
-		if ( aui == 1 ) {
+		if ( priv->aui == 1 ) {
 			TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x0a );
+		} else if ( priv->duplex == TLAN_DUPLEX_FULL ) {
+			TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x00 );
+			priv->tlanFullDuplex = TRUE;
 		} else {
 			TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x08 );
 		}
 	}
-	if ( priv->phyFlags & TLAN_PHY_INTERNAL ) {
+	if ( priv->phyNum == 0 ) {
 		data |= TLAN_NET_CFG_PHY_EN;
 	}
 	TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data );
-	(*priv->phyCheck)( dev ); 
-	data8 = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP;
-	TLan_DioWrite8( dev->base_addr, TLAN_NET_CMD, data8 );
-	data8 = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5; 
-	if ( priv->phyFlags & TLAN_PHY_INTS ) {
-		data8 |= TLAN_NET_MASK_MASK7; 
+
+	if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
+		TLan_FinishReset( dev );
+	} else {
+		TLan_PhyPowerDown( dev );
 	}
-	TLan_DioWrite8( dev->base_addr, TLAN_NET_MASK, data8 );
+
+} /* TLan_ResetAdapter */
+
+
+
+
+void
+TLan_FinishReset( struct device *dev )
+{
+	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
+	u8		data;
+	u32		phy;
+	u8		sio;
+	u16		status;
+	u16		tlphy_ctl;
+
+	phy = priv->phy[priv->phyNum];
+
+	data = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP;
+	if ( priv->tlanFullDuplex ) {
+		data |= TLAN_NET_CMD_DUPLEX;
+	}
+	TLan_DioWrite8( dev->base_addr, TLAN_NET_CMD, data );
+	data = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5; 
+	if ( priv->phyNum == 0 ) {
+		data |= TLAN_NET_MASK_MASK7; 
+	}
+	TLan_DioWrite8( dev->base_addr, TLAN_NET_MASK, data );
 	TLan_DioWrite16( dev->base_addr, TLAN_MAX_RX, TLAN_MAX_FRAME_SIZE );
 
-	if ( priv->phyFlags & TLAN_PHY_UNMANAGED ) {
-		priv->phyOnline = 1;
+	if ( ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) || ( priv->aui ) ) {
+		status = MII_GS_LINK;
+		printk( "TLAN:  %s: Link forced.\n", dev->name );
+	} else {
+		TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
+		udelay( 1000 );
+		TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
+		if ( status & MII_GS_LINK ) {
+			printk( "TLAN:  %s: Link active.\n", dev->name );
+			TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
+		}
 	}
 
-	return 0;
+	if ( priv->phyNum == 0 ) {
+        	TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl );
+        	tlphy_ctl |= TLAN_TC_INTEN;
+        	TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl );
+        	sio = TLan_DioRead8( dev->base_addr, TLAN_NET_SIO );
+        	sio |= TLAN_NET_SIO_MINTEN;
+        	TLan_DioWrite8( dev->base_addr, TLAN_NET_SIO, sio );
+	}
+
+	if ( status & MII_GS_LINK ) {
+		TLan_SetMac( dev, 0, dev->dev_addr );
+		priv->phyOnline = 1;
+		outb( ( TLAN_HC_INT_ON >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );
+		if ( debug >= 1 ) {
+			outb( ( TLAN_HC_REQ_INT >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );
+		}
+		outl( virt_to_bus( priv->rxList ), dev->base_addr + TLAN_CH_PARM );
+		outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );
+	} else {
+		printk( "TLAN:  %s: Link inactive, will retry in 10 secs...\n", dev->name );
+		TLan_SetTimer( dev, 1000, TLAN_TIMER_FINISH_RESET );
+		return;
+	}
 
-} /* TLan_Reset */
+} /* TLan_FinishReset */
 
 
 
@@ -1754,7 +2030,7 @@
 	 *		areg	The AREG to set the address in (0 - 3).
 	 *		mac	A pointer to an array of chars.  Each
 	 *			element stores one byte of the address.
-	 *			That is, it isn't in ASCII.
+	 *			IE, it isn't in ascii.
 	 *
 	 *	This function transfers a MAC address to one of the
 	 *	TLAN AREGs (address registers).  The TLAN chip locks
@@ -1788,56 +2064,10 @@
 
 	ThunderLAN Driver PHY Layer Routines
 
-	The TLAN chip can drive any number of PHYs (physical devices).  Rather
-	than having lots of 'if' or '#ifdef' statements, I have created a
-	second driver layer for the PHYs.  Each PHY can be identified from its
-	id in registers 2 and 3, and can be given a Check and Service routine
-	that will be called when the adapter is reset and when the adapter
-	receives a Network Status interrupt, respectively.
-	
 ******************************************************************************
 *****************************************************************************/
 
 
-static TLanPhyIdEntry	TLanPhyIdTable[] = {
-	  { 0x4000,
-	    0x5014,
-	    &TLan_PhyInternalCheck,
-	    &TLan_PhyInternalService,
-	    TLAN_PHY_ACTIVITY | TLAN_PHY_INTS | TLAN_PHY_INTERNAL },
-	  { 0x4000,
-	    0x5015,
-	    &TLan_PhyInternalCheck,
-	    &TLan_PhyInternalService,
-	    TLAN_PHY_ACTIVITY | TLAN_PHY_INTS | TLAN_PHY_INTERNAL },
-	  { 0x4000,
-	    0x5016,
-	    &TLan_PhyInternalCheck,
-	    &TLan_PhyInternalService,
-	    TLAN_PHY_ACTIVITY | TLAN_PHY_INTS | TLAN_PHY_INTERNAL },
-	  { 0x2000,
-	    0x5C00,
-	    &TLan_PhyDp83840aCheck,
-	    &TLan_PhyNop,
-	    TLAN_PHY_ACTIVITY | TLAN_PHY_AUTONEG },
-	  { 0x2000,
-	    0x5C01,
-	    &TLan_PhyDp83840aCheck,
-	    &TLan_PhyNop,
-	    TLAN_PHY_ACTIVITY | TLAN_PHY_AUTONEG },
-	  { 0x7810,
-	    0x0000,
-	    &TLan_PhyDp83840aCheck,
-	    &TLan_PhyNop,
-	    TLAN_PHY_AUTONEG },
-	  { 0x0000,
-	    0x0000,
-	    NULL,
-	    NULL,
-	    0
-	  }
-	};
-
 
 	/*********************************************************************
 	 *	TLan_PhyPrint
@@ -1845,10 +2075,10 @@
 	 *	Returns:
 	 *		Nothing
 	 *	Parms:
-	 *		dev	A pointer to the device structure of the adapter
-	 *			which the desired PHY is located.
+	 *		dev	A pointer to the device structure of the
+	 *			TLAN device having the PHYs to be detailed.
 	 *				
-	 *	This function prints the registers a PHY.
+	 *	This function prints the registers a PHY (aka tranceiver).
 	 *
 	 ********************************************************************/
 
@@ -1856,30 +2086,27 @@
 {
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
 	u16 i, data0, data1, data2, data3, phy;
-	u32 io;
 
-	phy = priv->phyAddr;
-	io = dev->base_addr;
+	phy = priv->phy[priv->phyNum];
 
-	if ( ( phy > 0 ) && ( phy <= TLAN_PHY_MAX_ADDR ) ) {
+	if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
+		printk( "TLAN:   Device %s, Unmanaged PHY.\n", dev->name );
+	} else if ( phy <= TLAN_PHY_MAX_ADDR ) {
 		printk( "TLAN:   Device %s, PHY 0x%02x.\n", dev->name, phy );
 		printk( "TLAN:      Off.  +0     +1     +2     +3 \n" );
                 for ( i = 0; i < 0x20; i+= 4 ) {
 			printk( "TLAN:      0x%02x", i );
-			TLan_MiiReadReg( io, phy, i, &data0 );
+			TLan_MiiReadReg( dev, phy, i, &data0 );
 			printk( " 0x%04hx", data0 );
-			TLan_MiiReadReg( io, phy, i + 1, &data1 );
+			TLan_MiiReadReg( dev, phy, i + 1, &data1 );
 			printk( " 0x%04hx", data1 );
-			TLan_MiiReadReg( io, phy, i + 2, &data2 );
+			TLan_MiiReadReg( dev, phy, i + 2, &data2 );
 			printk( " 0x%04hx", data2 );
-			TLan_MiiReadReg( io, phy, i + 3, &data3 );
+			TLan_MiiReadReg( dev, phy, i + 3, &data3 );
 			printk( " 0x%04hx\n", data3 );
 		}
 	} else {
-		printk( "TLAN:   Device %s, PHY 0x%02x (Unmanaged/Unknown).\n",
-			dev->name,
-			phy
-		      );
+		printk( "TLAN:   Device %s, Invalid PHY.\n", dev->name );
 	}
 
 } /* TLan_PhyPrint */
@@ -1888,7 +2115,7 @@
 
 
 	/*********************************************************************
-	 *	TLan_PhySelect
+	 *	TLan_PhyDetect
 	 *
 	 *	Returns:
 	 *		Nothing
@@ -1896,352 +2123,271 @@
 	 *		dev	A pointer to the device structure of the adapter
 	 *			for which the PHY needs determined.
 	 *
-	 *	This function decides which PHY amoung those attached to the
-	 *	TLAN chip is to be used.  The TLAN chip can be attached to
-	 *	multiple PHYs, and the driver needs to decide which one to
-	 *	talk to.  Currently this routine picks the PHY with the lowest
-	 *	address as the internal PHY address is 0x1F, the highest
-	 *	possible.  This strategy assumes that there can be only one
-	 *	other PHY, and, if it exists, it is the one to be used.  If
-	 *	token ring PHYs are ever supported, this routine will become
-	 *	a little more interesting...
+	 *	So far I've found that adapters which have external PHYs
+	 *	may also use the internal PHY for part of the functionality.
+	 *	(eg, AUI/Thinnet).  This function finds out if this TLAN
+	 *	chip has an internal PHY, and then finds the first external
+	 *	PHY (starting from address 0) if it exists).
 	 *
 	 ********************************************************************/
 
-void TLan_PhySelect( struct device *dev )
+void TLan_PhyDetect( struct device *dev )
 {
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
-	int		 	phy;
-	int			entry;
-	u16			id_hi[TLAN_PHY_MAX_ADDR + 1];
-	u16			id_lo[TLAN_PHY_MAX_ADDR + 1];
-	u16			hi;
-	u16			lo;
-	u16			vendor;
-	u16			device;
-
-	priv->phyCheck = &TLan_PhyNop;	/* Make sure these aren't ever NULL */
-	priv->phyService = &TLan_PhyNop;
-	
-	vendor = TLanDeviceList[priv->pciEntry].vendorId;
-	device = TLanDeviceList[priv->pciEntry].deviceId;
+	u16		control;
+	u16		hi;
+	u16		lo;
+	u32		phy;
 
-	/*
-	 * This is a bit uglier than I'd like, but the 0xF130 device must
-	 * NOT be assigned a valid PHY as it uses an unmanaged, bit-rate
-	 * PHY.  It is simplest just to use another goto, rather than
-	 * nesting the two for loops in the if statement.
-	 */
-	if ( ( vendor == PCI_VENDOR_ID_COMPAQ ) &&
-	     ( device == PCI_DEVICE_ID_NETFLEX_3P ) ) {
-		entry = 0;
-		phy = 0;
-		goto FINISH;
+	if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
+		priv->phyNum = 0xFFFF;
+		return;
 	}
 
-	for ( phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++ ) {
-		hi = lo = 0;
-		TLan_MiiReadReg( dev->base_addr, phy, MII_GEN_ID_HI, &hi );
-		TLan_MiiReadReg( dev->base_addr, phy, MII_GEN_ID_LO, &lo );
-		id_hi[phy] = hi;
-		id_lo[phy] = lo;
-		TLAN_DBG( TLAN_DEBUG_GNRL,
-			  "TLAN: Phy %2x, hi = %hx, lo = %hx\n",
-			  phy,
-			  hi,
-			  lo
-			);
+	TLan_MiiReadReg( dev, TLAN_PHY_MAX_ADDR, MII_GEN_ID_HI, &hi );
+
+	if ( hi != 0xFFFF ) {
+		priv->phy[0] = TLAN_PHY_MAX_ADDR;
+	} else {
+		priv->phy[0] = TLAN_PHY_NONE;
 	}
 
+	priv->phy[1] = TLAN_PHY_NONE;
 	for ( phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++ ) {
-		if ( ( aui == 1 ) && ( phy != TLAN_PHY_MAX_ADDR ) ) {
-			if ( id_hi[phy] != 0xFFFF ) {
-				TLan_MiiSync(dev->base_addr);
-				TLan_MiiWriteReg(dev->base_addr,
-						 phy,
-						 MII_GEN_CTL,
-						 MII_GC_PDOWN | 
-						 MII_GC_LOOPBK | 
-						 MII_GC_ISOLATE );
-
-			}
-			continue;
-		}
-		for ( entry = 0; TLanPhyIdTable[entry].check; entry++) {
-			if ( ( id_hi[phy] == TLanPhyIdTable[entry].idHi ) &&
-			     ( id_lo[phy] == TLanPhyIdTable[entry].idLo ) ) {
-				TLAN_DBG( TLAN_DEBUG_GNRL,
-					  "TLAN: Selected Phy %hx\n",
-					  phy
-					);
-				goto FINISH;
+		TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &control );
+		TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &hi );
+		TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &lo );
+		if ( ( control != 0xFFFF ) || ( hi != 0xFFFF ) || ( lo != 0xFFFF ) ) {
+			TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: PHY found at %02x %04x %04x %04x\n", phy, control, hi, lo );
+			if ( ( priv->phy[1] == TLAN_PHY_NONE ) && ( phy != TLAN_PHY_MAX_ADDR ) ) {
+				priv->phy[1] = phy;
 			}
 		}
 	}
 
-	entry = 0;
-	phy = 0;
-
-FINISH:
-	
-	if ( ( entry == 0 ) && ( phy == 0 ) ) {
-		priv->phyAddr = phy;
-		priv->phyEntry = entry;
-		priv->phyCheck = TLan_PhyNop;
-		priv->phyService = TLan_PhyNop;
-		priv->phyFlags = TLAN_PHY_BIT_RATE | 
-                                 TLAN_PHY_UNMANAGED |
-				 TLAN_PHY_ACTIVITY;
+	if ( priv->phy[1] != TLAN_PHY_NONE ) {
+		priv->phyNum = 1;
+	} else if ( priv->phy[0] != TLAN_PHY_NONE ) {
+		priv->phyNum = 0;
 	} else {
-		priv->phyAddr = phy;
-		priv->phyEntry = entry;
-		priv->phyCheck = TLanPhyIdTable[entry].check;
-		priv->phyService = TLanPhyIdTable[entry].service;
-		priv->phyFlags = TLanPhyIdTable[entry].flags;
+		printk( "TLAN:  Cannot initialize device, no PHY was found!\n" );
 	}
 
-} /* TLan_PhySelect */
+} /* TLan_PhyDetect */
 
 
 
 
-	/***************************************************************
-	 *	TLan_PhyNop
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	A pointer to a device structure.
-	 *
-	 *	This function does nothing and is meant as a stand-in
-	 *	for when a Check or Service function would be
-	 *	meaningless.
-	 *
-	 **************************************************************/
+void TLan_PhyPowerDown( struct device *dev )
+{
+	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
+	u16		value;
+
+	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Powering down PHY(s).\n", dev->name );
+	value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE;
+	TLan_MiiSync( dev->base_addr );
+	TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
+	if ( ( priv->phyNum == 0 ) && ( priv->phy[1] != TLAN_PHY_NONE ) && ( ! ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) ) ) {
+		TLan_MiiSync( dev->base_addr );
+		TLan_MiiWriteReg( dev, priv->phy[1], MII_GEN_CTL, value );
+	}
 
-int TLan_PhyNop( struct device *dev )
+	/* Wait for 5 jiffies (50 ms) and powerup
+	 * This is abitrary.  It is intended to make sure the
+	 * tranceiver settles.
+	 */
+	TLan_SetTimer( dev, 5, TLAN_TIMER_PHY_PUP );
+
+} /* TLan_PhyPowerDown */
+
+
+
+
+void TLan_PhyPowerUp( struct device *dev )
 {
-	dev = NULL;
-	return 0;
+	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
+	u16		value;
 
-} /* TLan_PhyNop */
+	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Powering up PHY.\n", dev->name );
+	TLan_MiiSync( dev->base_addr );
+	value = MII_GC_LOOPBK;
+	TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
+
+	/* Wait for 50 jiffies (500 ms) and reset the
+	 * tranceiver.  The TLAN docs say both 50 ms and
+	 * 500 ms, so do the longer, just in case
+	 */
+	TLan_SetTimer( dev, 50, TLAN_TIMER_PHY_RESET );
 
+} /* TLan_PhyPowerUp */
 
 
 
-	/***************************************************************
-	 *  TLan_PhyInternalCheck
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	A pointer to a device structure of the
-	 *			adapter	holding the PHY to be checked.
-	 *
-	 *	This function resets the internal PHY on a TLAN chip.
-	 *	See Chap. 7, "Physical Interface (PHY)" of "ThunderLAN
-	 *	Programmer's Guide"
-	 *
-	 **************************************************************/
 
-int TLan_PhyInternalCheck( struct device *dev )
+void TLan_PhyReset( struct device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
-	u16				gen_ctl;
-	u32				io;
-	u16				phy;
-	u16				value;
-	u8				sio;
-
-	io = dev->base_addr;
-	phy = priv->phyAddr;
-
-	TLan_MiiReadReg( io, phy, MII_GEN_CTL, &gen_ctl );
-	if ( gen_ctl & MII_GC_PDOWN ) {
-		TLan_MiiSync( io );
-		TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE );
-		TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK );
-		mdelay(50);
-		TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_RESET | MII_GC_LOOPBK );
-		TLan_MiiSync( io );
-	}
-
-	TLan_MiiReadReg( io, phy, MII_GEN_CTL, &value );
-	while ( value & MII_GC_RESET )
-		TLan_MiiReadReg( io, phy, MII_GEN_CTL, &value );
-
-	/* TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK | MII_GC_DUPLEX ); */
-	/* TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_DUPLEX ); */
-	TLan_MiiWriteReg( io, phy, MII_GEN_CTL, 0 );
-
-	mdelay(500);
-
-	TLan_MiiReadReg( io, phy, TLAN_TLPHY_CTL, &value );
-	if ( aui ) 
-		value |= TLAN_TC_AUISEL;
-	else
-		value &= ~TLAN_TC_AUISEL;
-	TLan_MiiWriteReg( io, phy, TLAN_TLPHY_CTL, value );
-
-	/* Read Possible Latched Link Status */
-	TLan_MiiReadReg( io, phy, MII_GEN_STS, &value ); 
-	/* Read Real Link Status */
-       	TLan_MiiReadReg( io, phy, MII_GEN_STS, &value ); 
-	if ( ( value & MII_GS_LINK ) || aui ) {
-		priv->phyOnline = 1;
-		TLan_DioWrite8( io, TLAN_LED_REG, TLAN_LED_LINK );
-	} else {
-		priv->phyOnline = 0;
-		TLan_DioWrite8( io, TLAN_LED_REG, 0 );
-	}
+	u16		phy;
+	u16		value;
 
-	/* Enable Interrupts */
-       	TLan_MiiReadReg( io, phy, TLAN_TLPHY_CTL, &value );
-	value |= TLAN_TC_INTEN;
-	TLan_MiiWriteReg( io, phy, TLAN_TLPHY_CTL, value );
-
-	sio = TLan_DioRead8( io, TLAN_NET_SIO );
-	sio |= TLAN_NET_SIO_MINTEN;
-	TLan_DioWrite8( io, TLAN_NET_SIO, sio );
-			
-	return 0;
+	phy = priv->phy[priv->phyNum];
 
-} /* TLanPhyInternalCheck */
+	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Reseting PHY.\n", dev->name );
+	TLan_MiiSync( dev->base_addr );
+	value = MII_GC_LOOPBK | MII_GC_RESET;
+	TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, value );
+	TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value );
+	while ( value & MII_GC_RESET ) {
+		TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value );
+	}
+	TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0 );
 
+	/* Wait for 50 jiffies (500 ms) and initialize.
+	 * I don't remember why I wait this long.
+	 */
+	TLan_SetTimer( dev, 50, TLAN_TIMER_PHY_START_LINK );
+
+} /* TLan_PhyReset */
 
 
 
-	/***************************************************************
-	 *	TLan_PhyInternalService
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	A pointer to a device structure of the
-	 *			adapter	holding the PHY to be serviced.
-	 *
-	 *	This function services an interrupt generated by the
-	 *	internal PHY.  It can turn on/off the link LED.  See
-	 *	Chap. 7, "Physical Interface (PHY)" of "ThunderLAN
-	 *	Programmer's Guide".
-	 *
-	 **************************************************************/
 
-int TLan_PhyInternalService( struct device *dev )
+void TLan_PhyStartLink( struct device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
-	u16			tlphy_sts;
-	u16			gen_sts;
-	u16			an_exp;
-	u32			io;
-	u16			phy;
-
-	io = dev->base_addr;
-	phy = priv->phyAddr;
-
-	TLan_MiiReadReg( io, phy, TLAN_TLPHY_STS, &tlphy_sts );
-	TLan_MiiReadReg( io, phy, MII_GEN_STS, &gen_sts ); 
-	TLan_MiiReadReg( io, phy, MII_AN_EXP, &an_exp ); 
-	if ( ( gen_sts & MII_GS_LINK ) || aui ) {
-		priv->phyOnline = 1;
-		TLan_DioWrite8( io, TLAN_LED_REG, TLAN_LED_LINK );
-	} else {
-		priv->phyOnline = 0;
-		TLan_DioWrite8( io, TLAN_LED_REG, 0 );
-	}
+	u16		ability;
+	u16		control;
+	u16		data;
+	u16		phy;
+	u16		status;
+	u16		tctl;
+
+	phy = priv->phy[priv->phyNum];
+
+	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Trying to activate link.\n", dev->name );
+	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
+	if ( ( status & MII_GS_AUTONEG ) && 
+	     ( priv->duplex == TLAN_DUPLEX_DEFAULT ) && 
+	     ( priv->speed == TLAN_SPEED_DEFAULT ) &&
+	     ( ! priv->aui ) ) {
+		ability = status >> 11;
+
+		if ( priv->speed == TLAN_SPEED_10 ) {
+			ability &= 0x0003;
+		} else if ( priv->speed == TLAN_SPEED_100 ) {
+			ability &= 0x001C;
+		}
 
-        if ( ( tlphy_sts & TLAN_TS_POLOK ) == 0) {
-                u16     value;
-                TLan_MiiReadReg( io, phy, TLAN_TLPHY_CTL, &value);
-                value |= TLAN_TC_SWAPOL;
-                TLan_MiiWriteReg( io, phy, TLAN_TLPHY_CTL, value);
-        }
+		if ( priv->duplex == TLAN_DUPLEX_FULL ) {
+			ability &= 0x000A;
+		} else if ( priv->duplex == TLAN_DUPLEX_HALF ) {
+			ability &= 0x0005;
+		}
 
-	return 0;
+		TLan_MiiWriteReg( dev, phy, MII_AN_ADV, ( ability << 5 ) | 1 );
+       		TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 );
+		TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1200 );
+
+		/* Wait for 400 jiffies (4 sec) for autonegotiation
+		 * to complete.  The max spec time is less than this
+		 * but the card need additional time to start AN.
+		 * .5 sec should be plenty extra.
+		 */
+		printk( "TLAN:  %s: Starting autonegotiation.\n", dev->name );
+		TLan_SetTimer( dev, 400, TLAN_TIMER_PHY_FINISH_AN );
+		return;
+	}
 
-} /* TLan_PhyInternalService */
+	if ( ( priv->aui ) && ( priv->phyNum != 0 ) ) {
+		priv->phyNum = 0;
+		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
+		TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
+		TLan_SetTimer( dev, 4, TLAN_TIMER_PHY_PDOWN );
+		return;
+	} else if ( priv->phyNum == 0 ) {
+        	TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tctl );
+		if ( priv->aui ) {
+                	tctl |= TLAN_TC_AUISEL;
+		} else {
+                	tctl &= ~TLAN_TC_AUISEL;
+			control = 0;
+			if ( priv->duplex == TLAN_DUPLEX_FULL ) {
+				control |= MII_GC_DUPLEX;
+				priv->tlanFullDuplex = TRUE;
+			}
+			if ( priv->speed == TLAN_SPEED_100 ) {
+				control |= MII_GC_SPEEDSEL;
+			}
+       			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, control );
+		}
+        	TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl );
+	}
 
+	/* Wait for 100 jiffies (1 sec) to give the tranceiver time
+	 * to establish link.
+	 */
+	TLan_SetTimer( dev, 100, TLAN_TIMER_FINISH_RESET );
 
+} /* TLan_PhyStartLink */
 
 
-	/***************************************************************
-	 *	TLan_PhyDp83840aCheck
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	A pointer to a device structure of the
-	 *			adapter holding the PHY to be reset.
-	 *
-	 *	This function resets a National Semiconductor DP83840A
-	 *	10/100 Mb/s PHY device.  See National Semiconductor's
-	 *	data sheet for more info.  This PHY is used on Compaq
-	 *	Netelligent 10/100 cards.
-	 *
-	 **************************************************************/
 
-static int TLan_PhyDp83840aCheck( struct device *dev )
+
+void TLan_PhyFinishAutoNeg( struct device *dev )
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
-	u16			gen_ctl;
-	u32			io;
-	u16			phy;
-	u16			value;
-	u8			sio;
-
-	io = dev->base_addr;
-	phy = priv->phyAddr;
-
-	TLan_MiiReadReg( io, phy, MII_GEN_CTL, &gen_ctl );
-	if ( gen_ctl & MII_GC_PDOWN ) {
-		TLan_MiiSync( io );
-		TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE );
-		TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK );
-		mdelay(500);
-		TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_RESET | MII_GC_LOOPBK );
-		TLan_MiiSync( io );
-	}
-
-	TLan_MiiReadReg( io, phy, MII_GEN_CTL, &value );
-	while ( value & MII_GC_RESET )
-		TLan_MiiReadReg( io, phy, MII_GEN_CTL, &value );
-
-	/* TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK | MII_GC_DUPLEX ); */
-	/* TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_DUPLEX ); */
-	TLan_MiiWriteReg( io, phy, MII_GEN_CTL, 0 );
-	TLan_MiiReadReg( io, phy, MII_AN_ADV, &value );
-	value &= ~0x0140;
-	TLan_MiiWriteReg( io, phy, MII_AN_ADV, value );
-       	TLan_MiiWriteReg( io, phy, MII_GEN_CTL, 0x1000 );
-	TLan_MiiWriteReg( io, phy, MII_GEN_CTL, 0x1200 );
-
-	mdelay(50);
-#if 0
-	/* Read Possible Latched Link Status */
-	TLan_MiiReadReg( io, phy, MII_GEN_STS, &value ); 
-	/* Read Real Link Status */
-	TLan_MiiReadReg( io, phy, MII_GEN_STS, &value ); 
-	if ( value & MII_GS_LINK ) {
-		priv->phyOnline = 1;
-		TLan_DioWrite8( io, TLAN_LED_REG, TLAN_LED_LINK );
-	} else {
-		priv->phyOnline = 0;
-		TLan_DioWrite8( io, TLAN_LED_REG, 0 );
+	u16		an_adv;
+	u16		an_lpa;
+	u16		data;
+	u16		mode;
+	u16		phy;
+	u16		status;
+	
+	phy = priv->phy[priv->phyNum];
+
+	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
+	if ( ! ( status & MII_GS_AUTOCMPLT ) ) {
+		/* Wait for 800 jiffies (8 sec) to give the process
+		 * more time.  Perhaps we should fail after a while.
+		 */
+		printk( "TLAN:  Giving autonegotiation more time.\n" );
+		TLan_SetTimer( dev, 800, TLAN_TIMER_PHY_FINISH_AN );
+		return;
 	}
 
-	/* Enable Interrupts */
-	TLan_MiiReadReg( io, phy, TLAN_TLPHY_CTL, &value );
-	value |= TLAN_TC_INTEN;
-	TLan_MiiWriteReg( io, phy, TLAN_TLPHY_CTL, value );
-#endif
-	sio = TLan_DioRead8( dev->base_addr, TLAN_NET_SIO );
-	sio &= ~TLAN_NET_SIO_MINTEN;
-	TLan_DioWrite8( dev->base_addr, TLAN_NET_SIO, sio );
-/*	priv->phyOnline = 1; */
-			
-	return 0;
+	printk( "TLAN:  %s: Autonegotiation complete.\n", dev->name );
+	TLan_MiiReadReg( dev, phy, MII_AN_ADV, &an_adv );
+	TLan_MiiReadReg( dev, phy, MII_AN_LPA, &an_lpa );
+	mode = an_adv & an_lpa & 0x03E0;
+	if ( mode & 0x0100 ) {
+		priv->tlanFullDuplex = TRUE;
+	} else if ( ! ( mode & 0x0080 ) && ( mode & 0x0040 ) ) {
+		priv->tlanFullDuplex = TRUE;
+	}
+
+	if ( ( ! ( mode & 0x0180 ) ) && ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) && ( priv->phyNum != 0 ) ) {
+		priv->phyNum = 0;
+		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
+		TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
+		TLan_SetTimer( dev, 40, TLAN_TIMER_PHY_PDOWN );
+		return;
+	}
+
+	if ( priv->phyNum == 0 ) {
+		if ( ( priv->duplex == TLAN_DUPLEX_FULL ) || ( an_adv & an_lpa & 0x0040 ) ) {
+			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, MII_GC_AUTOENB | MII_GC_DUPLEX );
+			printk( "TLAN:  Starting internal PHY with DUPLEX\n" );
+		} else {
+			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, MII_GC_AUTOENB );
+			printk( "TLAN:  Starting internal PHY with HALF-DUPLEX\n" );
+		}
+	}
 
-} /* TLan_PhyDp83840aCheck */
+	/* Wait for 10 jiffies (100 ms).  No reason in partiticular.
+	 */
+	TLan_SetTimer( dev, 10, TLAN_TIMER_FINISH_RESET );
+		
+} /* TLan_PhyFinishAutoNeg */
 
 
 
@@ -2266,9 +2412,10 @@
 	 *		1	otherwise.
 	 *
 	 *	Parms:
-	 *		base_port	The base IO port of the adapter in
-	 *				question.
-	 *		dev		The address of the PHY to be queried.
+	 *		dev		The device structure containing
+	 *				The io address and interrupt count
+	 *				for this device.
+	 *		phy		The address of the PHY to be queried.
 	 *		reg		The register whose contents are to be
 	 *				retreived.
 	 *		val		A pointer to a variable to store the
@@ -2281,30 +2428,32 @@
 	 *
 	 **************************************************************/
 
-int TLan_MiiReadReg(u16 base_port, u16 dev, u16 reg, u16 *val)
+int TLan_MiiReadReg( struct device *dev, u16 phy, u16 reg, u16 *val )
 {
 	u8	nack;
-	u16 sio, tmp;
-	u32 i;
+	u16	sio, tmp;
+	u32	i;
 	int	err;
-	int minten;
+	int	minten;
 
 	err = FALSE;
-	outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
-	sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
+	outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
+	sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
 
-	cli();
+	if ( dev->interrupt == 0 )
+		cli();
+	dev->interrupt++;
 
-	TLan_MiiSync(base_port);
+	TLan_MiiSync(dev->base_addr);
 
 	minten = TLan_GetBit( TLAN_NET_SIO_MINTEN, sio );
 	if ( minten )
 		TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);
 
-	TLan_MiiSendData( base_port, 0x1, 2 );		/* Start ( 01b ) */
-	TLan_MiiSendData( base_port, 0x2, 2 );		/* Read  ( 10b ) */
-	TLan_MiiSendData( base_port, dev, 5 );		/* Device #      */
-	TLan_MiiSendData( base_port, reg, 5 );		/* Register #    */
+	TLan_MiiSendData( dev->base_addr, 0x1, 2 );	/* Start ( 01b ) */
+	TLan_MiiSendData( dev->base_addr, 0x2, 2 );	/* Read  ( 10b ) */
+	TLan_MiiSendData( dev->base_addr, phy, 5 );	/* Device #      */
+	TLan_MiiSendData( dev->base_addr, reg, 5 );	/* Register #    */
 
 
 	TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio);		/* Change direction */
@@ -2340,7 +2489,9 @@
 
 	*val = tmp;
 
-	sti();
+	dev->interrupt--;
+	if ( dev->interrupt == 0 )
+		sti();
 
 	return err;
 
@@ -2434,9 +2585,9 @@
 	 *	Returns:
 	 *		Nothing
 	 *	Parms:
-	 *		base_port	The base IO port of the adapter in
-	 *				question.
-	 *		dev		The address of the PHY to be written to.
+	 *		dev		The device structure for the device
+	 *				to write to.
+	 *		phy		The address of the PHY to be written to.
 	 *		reg		The register whose contents are to be
 	 *				written.
 	 *		val		The value to be written to the register.
@@ -2448,29 +2599,31 @@
 	 *
 	 **************************************************************/
 
-void TLan_MiiWriteReg(u16 base_port, u16 dev, u16 reg, u16 val)
+void TLan_MiiWriteReg( struct device *dev, u16 phy, u16 reg, u16 val )
 {
-	u16 sio;
+	u16	sio;
 	int	minten;
 
-	outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
-	sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
+	outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
+	sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
 
-	cli();
+	if ( dev->interrupt == 0 )
+		cli();
+	dev->interrupt++;
 
-	TLan_MiiSync( base_port );
+	TLan_MiiSync( dev->base_addr );
 
 	minten = TLan_GetBit( TLAN_NET_SIO_MINTEN, sio );
 	if ( minten )
 		TLan_ClearBit( TLAN_NET_SIO_MINTEN, sio );
 
-	TLan_MiiSendData( base_port, 0x1, 2 );		/* Start ( 01b ) */
-	TLan_MiiSendData( base_port, 0x1, 2 );		/* Write ( 01b ) */
-	TLan_MiiSendData( base_port, dev, 5 );		/* Device #      */
-	TLan_MiiSendData( base_port, reg, 5 );		/* Register #    */
+	TLan_MiiSendData( dev->base_addr, 0x1, 2 );	/* Start ( 01b ) */
+	TLan_MiiSendData( dev->base_addr, 0x1, 2 );	/* Write ( 01b ) */
+	TLan_MiiSendData( dev->base_addr, phy, 5 );	/* Device #      */
+	TLan_MiiSendData( dev->base_addr, reg, 5 );	/* Register #    */
 
-	TLan_MiiSendData( base_port, 0x2, 2 );		/* Send ACK */
-	TLan_MiiSendData( base_port, val, 16 );		/* Send Data */
+	TLan_MiiSendData( dev->base_addr, 0x2, 2 );	/* Send ACK */
+	TLan_MiiSendData( dev->base_addr, val, 16 );	/* Send Data */
 
 	TLan_ClearBit( TLAN_NET_SIO_MCLK, sio );	/* Idle cycle */
 	TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
@@ -2478,10 +2631,15 @@
 	if ( minten )
 		TLan_SetBit( TLAN_NET_SIO_MINTEN, sio );
 
-	sti();
+	dev->interrupt--;
+	if ( dev->interrupt == 0 )
+		sti();
 
 } /* TLan_MiiWriteReg */
 
+
+
+
 /*****************************************************************************
 ******************************************************************************
 
@@ -2654,7 +2812,7 @@
 	 *
 	 *	Returns:
 	 *		No error = 0, else, the stage at which the error
-	 *		occurred.
+	 *		occured.
 	 *	Parms:
 	 *		io_base		The IO port base address for the
 	 *				TLAN device with the EEPROM to
@@ -2670,26 +2828,30 @@
 	 *
 	 **************************************************************/
 
-int TLan_EeReadByte( u16 io_base, u8 ee_addr, u8 *data )
+int TLan_EeReadByte( struct device *dev, u8 ee_addr, u8 *data )
 {
 	int err;
 
-	cli();
+	if ( dev->interrupt == 0 )
+		cli();
+	dev->interrupt++;
 
-	TLan_EeSendStart( io_base );
-	err = TLan_EeSendByte( io_base, 0xA0, TLAN_EEPROM_ACK );
+	TLan_EeSendStart( dev->base_addr );
+	err = TLan_EeSendByte( dev->base_addr, 0xA0, TLAN_EEPROM_ACK );
 	if (err)
 		return 1;
-	err = TLan_EeSendByte( io_base, ee_addr, TLAN_EEPROM_ACK );
+	err = TLan_EeSendByte( dev->base_addr, ee_addr, TLAN_EEPROM_ACK );
 	if (err)
 		return 2;
-	TLan_EeSendStart( io_base );
-	err = TLan_EeSendByte( io_base, 0xA1, TLAN_EEPROM_ACK );
+	TLan_EeSendStart( dev->base_addr );
+	err = TLan_EeSendByte( dev->base_addr, 0xA1, TLAN_EEPROM_ACK );
 	if (err)
 		return 3;
-	TLan_EeReceiveByte( io_base, data, TLAN_EEPROM_STOP );
+	TLan_EeReceiveByte( dev->base_addr, data, TLAN_EEPROM_STOP );
 
-	sti();
+	dev->interrupt--;
+	if ( dev->interrupt == 0 )
+		sti();
 
 	return 0;
 
diff -u --recursive --new-file v2.1.109/linux/drivers/net/tlan.h linux/drivers/net/tlan.h
--- v2.1.109/linux/drivers/net/tlan.h	Sun Nov 30 12:21:45 1997
+++ linux/drivers/net/tlan.h	Sun Jul 19 20:50:04 1998
@@ -5,9 +5,9 @@
  *  Linux ThunderLAN Driver
  *
  *  tlan.h
- *  by James Banks, james.banks@caldera.com
+ *  by James Banks
  *
- *  (C) 1997 Caldera, Inc.
+ *  (C) 1997-1998 Caldera, Inc.
  *
  *  This software may be used and distributed according to the terms
  *  of the GNU Public License, incorporated herein by reference.
@@ -33,23 +33,23 @@
 	 *
 	 ****************************************************************/
 
-#define FALSE				0
-#define TRUE				1
+#define FALSE			0
+#define TRUE			1
 
 #define TLAN_MIN_FRAME_SIZE	64
 #define TLAN_MAX_FRAME_SIZE	1600
 
-#define TLAN_NUM_RX_LISTS 4
-#define TLAN_NUM_TX_LISTS 8
+#define TLAN_NUM_RX_LISTS	4
+#define TLAN_NUM_TX_LISTS	8
 
-#define TLAN_IGNORE	0
-#define TLAN_RECORD	1
+#define TLAN_IGNORE		0
+#define TLAN_RECORD		1
 
 #define TLAN_DBG(lvl, format, args...)	if (debug&lvl) printk( format, ##args );
-#define TLAN_DEBUG_GNRL	0x0001
-#define TLAN_DEBUG_TX	0x0002
-#define TLAN_DEBUG_RX	0x0004 
-#define TLAN_DEBUG_LIST	0x0008
+#define TLAN_DEBUG_GNRL		0x0001
+#define TLAN_DEBUG_TX		0x0002
+#define TLAN_DEBUG_RX		0x0004 
+#define TLAN_DEBUG_LIST		0x0008
 
 
 
@@ -59,23 +59,47 @@
 	 *
 	 ****************************************************************/
 		
-	/* NOTE: These have been moved to pci.h, will use them
-	   eventually */
-#define PCI_DEVICE_ID_NETELLIGENT_10 0xAE34
-#define PCI_DEVICE_ID_NETELLIGENT_10_100 0xAE32
-#define PCI_DEVICE_ID_NETFLEX_3P_INTEGRATED 0xAE35
-#define PCI_DEVICE_ID_NETFLEX_3P 0xF130
-#define PCI_DEVICE_ID_NETFLEX_3P_BNC 0xF150
-#define PCI_DEVICE_ID_NETELLIGENT_10_100_PROLIANT 0xAE43
-#define PCI_DEVICE_ID_NETELLIGENT_10_100_DUAL 0xAE40
-#define PCI_DEVICE_ID_DESKPRO_4000_5233MMX 0xB011
-
+#define PCI_DEVICE_ID_NETELLIGENT_10			0xAE34
+#define PCI_DEVICE_ID_NETELLIGENT_10_100		0xAE32
+#define PCI_DEVICE_ID_NETFLEX_3P_INTEGRATED		0xAE35
+#define PCI_DEVICE_ID_NETFLEX_3P			0xF130
+#define PCI_DEVICE_ID_NETFLEX_3P_BNC			0xF150
+#define PCI_DEVICE_ID_NETELLIGENT_10_100_PROLIANT	0xAE43
+#define PCI_DEVICE_ID_NETELLIGENT_10_100_DUAL		0xAE40
+#define PCI_DEVICE_ID_DESKPRO_4000_5233MMX		0xB011
+#define PCI_DEVICE_ID_NETELLIGENT_10_T2			0xB012
+#define PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100	0xB030
+#ifndef PCI_DEVICE_ID_OLICOM_OC2183
+#define PCI_DEVICE_ID_OLICOM_OC2183			0x0013
+#endif
+#ifndef PCI_DEVICE_ID_OLICOM_OC2325
+#define PCI_DEVICE_ID_OLICOM_OC2325			0x0012
+#endif
+#ifndef PCI_DEVICE_ID_OLICOM_OC2326
+#define PCI_DEVICE_ID_OLICOM_OC2326			0x0014
+#endif
 
-typedef struct tlan_pci_id {
+typedef struct tlan_adapter_entry {
 	u16	vendorId;
 	u16	deviceId;
-	char *deviceName;
-} TLanPciId;
+	char	*deviceLabel;
+	u32	flags;
+	u16	addrOfs;
+} TLanAdapterEntry;
+
+#define TLAN_ADAPTER_NONE		0x00000000
+#define TLAN_ADAPTER_UNMANAGED_PHY	0x00000001
+#define TLAN_ADAPTER_BIT_RATE_PHY	0x00000002
+#define TLAN_ADAPTER_USE_INTERN_10	0x00000004
+#define TLAN_ADAPTER_ACTIVITY_LED	0x00000008
+
+#define TLAN_SPEED_DEFAULT	0
+#define TLAN_SPEED_10		10
+#define TLAN_SPEED_100		100
+
+#define TLAN_DUPLEX_DEFAULT	0
+#define TLAN_DUPLEX_HALF	1
+#define TLAN_DUPLEX_FULL	2
 
 
 
@@ -121,25 +145,7 @@
 	 ****************************************************************/
 
 #define TLAN_PHY_MAX_ADDR	0x1F
-
-#define TLAN_PHY_ACTIVITY	0x00000001
-#define TLAN_PHY_AUTONEG	0x00000002
-#define TLAN_PHY_INTS		0x00000004
-#define TLAN_PHY_BIT_RATE	0x00000008
-#define TLAN_PHY_UNMANAGED	0x00000010
-#define TLAN_PHY_INTERNAL	0x00000020
-
-
-typedef int (TLanPhyFunc)( struct device * );
-
-
-typedef struct tlan_phy_id_entry_tag {
-	u16		idHi;
-	u16		idLo;
-	TLanPhyFunc	*check;
-	TLanPhyFunc	*service;
-	u32		flags;
-} TLanPhyIdEntry;
+#define TLAN_PHY_NONE		0x20
 
 
 
@@ -164,21 +170,22 @@
 	u32                     txInProgress;
 	u32                     txTail;
 	u32			txBusyCount;
-	u32                     phyAddr;
-	u32                     phyEntry;
 	u32                     phyOnline;
-	u32                     phyFlags;
-	TLanPhyFunc             *phyCheck;
-	TLanPhyFunc             *phyService;
 	u32			timerSetAt;
 	u32			timerType;
 	struct timer_list	timer;
 	struct net_device_stats	stats;
-	u32                     pciEntry;
-	u8                      pciRevision;
-	u8                      pciBus;
-	u8                      pciDeviceFn;
+	TLanAdapterEntry	*adapter;
+	u32			adapterRev;
+	u32			aui;
+	u32			debug;
+	u32			duplex;
+	u32			phy[2];
+	u32			phyNum;
+	u32			sa_int;
+	u32			speed;
 	u8			tlanRev;
+	u8			tlanFullDuplex;
 	char                    devName[8];
 } TLanPrivateInfo;
 
@@ -191,10 +198,15 @@
 	 ****************************************************************/
 
 #define TLAN_TIMER_LINK			1
-#define TLAN_TIMER_ACT			2
+#define TLAN_TIMER_ACTIVITY		2
+#define TLAN_TIMER_PHY_PDOWN		3
+#define TLAN_TIMER_PHY_PUP		4
+#define TLAN_TIMER_PHY_RESET		5
+#define TLAN_TIMER_PHY_START_LINK	6
+#define TLAN_TIMER_PHY_FINISH_AN	7
+#define TLAN_TIMER_FINISH_RESET		8
 
-#define TLAN_TIMER_LINK_DELAY	230
-#define TLAN_TIMER_ACT_DELAY	10
+#define TLAN_TIMER_ACT_DELAY		10
 
 
 
@@ -215,29 +227,29 @@
 	 *
 	 ****************************************************************/
 
-#define TLAN_HOST_CMD		0x00
+#define TLAN_HOST_CMD			0x00
 #define 	TLAN_HC_GO		0x80000000
-#define		TLAN_HC_STOP	0x40000000
+#define		TLAN_HC_STOP		0x40000000
 #define		TLAN_HC_ACK		0x20000000
-#define		TLAN_HC_CS_MASK 0x1FE00000
+#define		TLAN_HC_CS_MASK		0x1FE00000
 #define		TLAN_HC_EOC		0x00100000
 #define		TLAN_HC_RT		0x00080000
 #define		TLAN_HC_NES		0x00040000
-#define		TLAN_HC_AD_RST	0x00008000
-#define		TLAN_HC_LD_TMR	0x00004000
-#define		TLAN_HC_LD_THR	0x00002000
-#define		TLAN_HC_REQ_INT	0x00001000
-#define		TLAN_HC_INT_OFF	0x00000800
-#define		TLAN_HC_INT_ON	0x00000400
-#define		TLAN_HC_AC_MASK	0x000000FF
-#define TLAN_CH_PARM		0x04
-#define TLAN_DIO_ADR		0x08
-#define		TLAN_DA_ADR_INC	0x8000
-#define		TLAN_DA_RAM_ADR	0x4000
-#define TLAN_HOST_INT		0x0A
-#define		TLAN_HI_IV_MASK	0x1FE0
-#define		TLAN_HI_IT_MASK	0x001C
-#define TLAN_DIO_DATA		0x0C
+#define		TLAN_HC_AD_RST		0x00008000
+#define		TLAN_HC_LD_TMR		0x00004000
+#define		TLAN_HC_LD_THR		0x00002000
+#define		TLAN_HC_REQ_INT		0x00001000
+#define		TLAN_HC_INT_OFF		0x00000800
+#define		TLAN_HC_INT_ON		0x00000400
+#define		TLAN_HC_AC_MASK		0x000000FF
+#define TLAN_CH_PARM			0x04
+#define TLAN_DIO_ADR			0x08
+#define		TLAN_DA_ADR_INC		0x8000
+#define		TLAN_DA_RAM_ADR		0x4000
+#define TLAN_HOST_INT			0x0A
+#define		TLAN_HI_IV_MASK		0x1FE0
+#define		TLAN_HI_IT_MASK		0x001C
+#define TLAN_DIO_DATA			0x0C
 
 
 /* ThunderLAN Internal Register DIO Offsets */
@@ -264,7 +276,7 @@
 #define		TLAN_NET_STS_MIRQ	0x80
 #define		TLAN_NET_STS_HBEAT	0x40
 #define		TLAN_NET_STS_TXSTOP	0x20
-#define		TLAN_NET_STS_RXSTOP 0x10
+#define		TLAN_NET_STS_RXSTOP	0x10
 #define		TLAN_NET_STS_RSRVD	0x0F
 #define TLAN_NET_MASK			0x03
 #define		TLAN_NET_MASK_MASK7	0x80
@@ -283,36 +295,36 @@
 #define		TLAN_NET_CFG_MTEST	0x0100
 #define		TLAN_NET_CFG_PHY_EN	0x0080
 #define		TLAN_NET_CFG_MSMASK	0x007F
-#define TLAN_MAN_TEST		0x06
-#define TLAN_DEF_VENDOR_ID	0x08
-#define TLAN_DEF_DEVICE_ID	0x0A
-#define TLAN_DEF_REVISION	0x0C
-#define TLAN_DEF_SUBCLASS	0x0D
-#define TLAN_DEF_MIN_LAT	0x0E
-#define TLAN_DEF_MAX_LAT	0x0F
+#define TLAN_MAN_TEST			0x06
+#define TLAN_DEF_VENDOR_ID		0x08
+#define TLAN_DEF_DEVICE_ID		0x0A
+#define TLAN_DEF_REVISION		0x0C
+#define TLAN_DEF_SUBCLASS		0x0D
+#define TLAN_DEF_MIN_LAT		0x0E
+#define TLAN_DEF_MAX_LAT		0x0F
 #define TLAN_AREG_0			0x10
 #define TLAN_AREG_1			0x16
 #define TLAN_AREG_2			0x1C
 #define TLAN_AREG_3			0x22
 #define TLAN_HASH_1			0x28
 #define TLAN_HASH_2			0x2C
-#define TLAN_GOOD_TX_FRMS	0x30
-#define TLAN_TX_UNDERUNS	0x33
-#define TLAN_GOOD_RX_FRMS	0x34
-#define TLAN_RX_OVERRUNS	0x37
-#define TLAN_DEFERRED_TX	0x38
-#define TLAN_CRC_ERRORS		0x3A
-#define TLAN_CODE_ERRORS	0x3B
-#define TLAN_MULTICOL_FRMS	0x3C
-#define TLAN_SINGLECOL_FRMS	0x3E
-#define TLAN_EXCESSCOL_FRMS	0x40
-#define TLAN_LATE_COLS		0x41
-#define TLAN_CARRIER_LOSS	0x42
-#define TLAN_ACOMMIT		0x43
-#define TLAN_LED_REG		0x44
-#define		TLAN_LED_ACT	0x10
-#define		TLAN_LED_LINK	0x01
-#define TLAN_BSIZE_REG		0x45
+#define TLAN_GOOD_TX_FRMS		0x30
+#define TLAN_TX_UNDERUNS		0x33
+#define TLAN_GOOD_RX_FRMS		0x34
+#define TLAN_RX_OVERRUNS		0x37
+#define TLAN_DEFERRED_TX		0x38
+#define TLAN_CRC_ERRORS			0x3A
+#define TLAN_CODE_ERRORS		0x3B
+#define TLAN_MULTICOL_FRMS		0x3C
+#define TLAN_SINGLECOL_FRMS		0x3E
+#define TLAN_EXCESSCOL_FRMS		0x40
+#define TLAN_LATE_COLS			0x41
+#define TLAN_CARRIER_LOSS		0x42
+#define TLAN_ACOMMIT			0x43
+#define TLAN_LED_REG			0x44
+#define		TLAN_LED_ACT		0x10
+#define		TLAN_LED_LINK		0x01
+#define TLAN_BSIZE_REG			0x45
 #define TLAN_MAX_RX			0x46
 #define TLAN_INT_DIS			0x48
 #define		TLAN_ID_TX_EOC		0x04
@@ -327,11 +339,11 @@
 
 #define TLAN_INT_NONE			0x0000
 #define TLAN_INT_TX_EOF			0x0001
-#define TLAN_INT_STAT_OVERFLOW	0x0002
+#define TLAN_INT_STAT_OVERFLOW		0x0002
 #define TLAN_INT_RX_EOF			0x0003
 #define TLAN_INT_DUMMY			0x0004
 #define TLAN_INT_TX_EOC			0x0005
-#define TLAN_INT_STATUS_CHECK	0x0006
+#define TLAN_INT_STATUS_CHECK		0x0006
 #define TLAN_INT_RX_EOC			0x0007
 
 
@@ -340,7 +352,7 @@
 
 /* Generic MII/PHY Registers */
 
-#define MII_GEN_CTL				0x00
+#define MII_GEN_CTL			0x00
 #define 	MII_GC_RESET		0x8000
 #define		MII_GC_LOOPBK		0x4000
 #define		MII_GC_SPEEDSEL		0x2000
@@ -351,7 +363,7 @@
 #define		MII_GC_DUPLEX		0x0100
 #define		MII_GC_COLTEST		0x0080
 #define		MII_GC_RESERVED		0x007F
-#define MII_GEN_STS				0x01
+#define MII_GEN_STS			0x01
 #define		MII_GS_100BT4		0x8000
 #define		MII_GS_100BTXFD		0x4000
 #define		MII_GS_100BTXHD		0x2000
@@ -359,19 +371,19 @@
 #define		MII_GS_10BTHD		0x0800
 #define		MII_GS_RESERVED		0x07C0
 #define		MII_GS_AUTOCMPLT	0x0020
-#define		MII_GS_RFLT			0x0010
+#define		MII_GS_RFLT		0x0010
 #define		MII_GS_AUTONEG		0x0008
-#define		MII_GS_LINK			0x0004
+#define		MII_GS_LINK		0x0004
 #define		MII_GS_JABBER		0x0002
 #define		MII_GS_EXTCAP		0x0001
 #define MII_GEN_ID_HI			0x02
 #define MII_GEN_ID_LO			0x03
-#define 	MII_GIL_OUI			0xFC00
+#define 	MII_GIL_OUI		0xFC00
 #define 	MII_GIL_MODEL		0x03F0
 #define 	MII_GIL_REVISION	0x000F
-#define MII_AN_ADV				0x04
-#define MII_AN_LPA				0x05
-#define MII_AN_EXP				0x06
+#define MII_AN_ADV			0x04
+#define MII_AN_LPA			0x05
+#define MII_AN_EXP			0x06
 
 /* ThunderLAN Specific MII/PHY Registers */
 
@@ -394,6 +406,7 @@
 #define		TLAN_TS_RESERVED	0x0FFF
 
 
+#define CIRC_INC( a, b ) if ( ++a >= b ) a = 0
 
 /* Routines to access internal registers. */
 
@@ -456,7 +469,7 @@
 
 
 
-
+#if 0
 inline void TLan_ClearBit(u8 bit, u16 port)
 {
 	outb_p(inb_p(port) & ~bit, port);
@@ -477,6 +490,11 @@
 {
 	outb_p(inb_p(port) | bit, port);
 }
+#endif
+
+#define TLan_ClearBit( bit, port )	outb_p(inb_p(port) & ~bit, port)
+#define TLan_GetBit( bit, port )	((int) (inb_p(port) & bit))
+#define TLan_SetBit( bit, port )	outb_p(inb_p(port) | bit, port)
 
 
 inline	u32	xor( u32 a, u32 b )
diff -u --recursive --new-file v2.1.109/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.1.109/linux/drivers/pci/pci.c	Wed May 20 19:10:39 1998
+++ linux/drivers/pci/pci.c	Mon Jul 20 13:49:28 1998
@@ -1,5 +1,5 @@
 /*
- *	$Id: pci.c,v 1.85 1998/05/12 07:36:01 mj Exp $
+ *	$Id: pci.c,v 1.86 1998/07/15 20:34:47 mj Exp $
  *
  *	PCI Bus Services, see include/linux/pci.h for further explanation.
  *
@@ -161,7 +161,6 @@
 	unsigned char cmd, irq, tmp, hdr_type, is_multi = 0;
 	struct pci_dev *dev, **bus_last;
 	struct pci_bus *child;
-	int reg;
 
 	DBG("pci_scan_bus for bus %d\n", bus->number);
 	bus_last = &bus->devices;
@@ -232,10 +231,7 @@
 		case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */
 			if (class != PCI_CLASS_BRIDGE_CARDBUS)
 				goto bad;
-			for (reg = 0; reg < 2; reg++) {
-				pcibios_read_config_dword(bus->number, devfn, PCI_CB_MEMORY_BASE_0 + (reg << 3), &l);
-				dev->base_address[reg] = (l == 0xffffffff) ? 0 : l;
-			}
+			pci_read_bases(dev, 1);
 			break;
 		default:				    /* unknown header */
 		bad:
@@ -274,12 +270,20 @@
 		if (tmp < 32)
 			pcibios_write_config_byte(bus->number, dev->devfn, PCI_LATENCY_TIMER, 32);
 #endif
+	}
 
+	/*
+	 * After performing arch-dependent fixup of the bus, look behind
+	 * all PCI-to-PCI bridges on this bus.
+	 */
+	pcibios_fixup_bus(bus);
+	for(dev=bus->devices; dev; dev=dev->sibling)
 		/*
 		 * If it's a bridge, scan the bus behind it.
 		 */
-		if (class == PCI_CLASS_BRIDGE_PCI) {
+		if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
 			unsigned int buses;
+			unsigned int devfn = dev->devfn;
 			unsigned short cr;
 
 			/*
@@ -350,7 +354,7 @@
 			  }
 			pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr);
 		}
-	}
+
 	/*
 	 * We've scanned the bus and so we know all about what's on
 	 * the other side of any bridges that may be on this bus plus
diff -u --recursive --new-file v2.1.109/linux/drivers/pnp/parport_probe.c linux/drivers/pnp/parport_probe.c
--- v2.1.109/linux/drivers/pnp/parport_probe.c	Fri Jan 30 11:28:08 1998
+++ linux/drivers/pnp/parport_probe.c	Sun Jul 19 20:40:44 1998
@@ -173,11 +173,18 @@
 				u++;
 			}
 			if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) {
+				if (port->probe_info.mfr)
+					kfree (port->probe_info.mfr);
 				port->probe_info.mfr = strdup(sep);
 			} else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) {
+				if (port->probe_info.model)
+					kfree (port->probe_info.model);
 				port->probe_info.model = strdup(sep);
 			} else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) {
 				int i;
+				if (port->probe_info.class_name)
+					kfree (port->probe_info.class_name);
+				port->probe_info.class_name = strdup(sep);
 				for (u = sep; *u; u++)
 					*u = toupper(*u);
 				for (i = 0; classes[i].token; i++) {
@@ -189,11 +196,16 @@
 				printk(KERN_WARNING "%s probe: warning, class '%s' not understood.\n", port->name, sep);
 				port->probe_info.class = PARPORT_CLASS_OTHER;
 			} else if (!strcmp(p, "CMD") || !strcmp(p, "COMMAND SET")) {
+				if (port->probe_info.cmdset)
+					kfree (port->probe_info.cmdset);
+				port->probe_info.cmdset = strdup(sep);
 				/* if it speaks printer language, it's
 				   probably a printer */
 				if (strstr(sep, "PJL") || strstr(sep, "PCL"))
 					guessed_class = PARPORT_CLASS_PRINTER;
 			} else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) {
+				if (port->probe_info.description)
+					kfree (port->probe_info.description);
 				port->probe_info.description = strdup(sep);
 			}
 		}
@@ -226,10 +238,11 @@
 	int r;
 
 	MOD_INC_USE_COUNT;
-	port->probe_info.model = "Unknown device";
-	port->probe_info.mfr = "Unknown vendor";
-	port->probe_info.description = NULL;
+	port->probe_info.model = strdup ("Unknown device");
+	port->probe_info.mfr = strdup ("Unknown vendor");
+	port->probe_info.description = port->probe_info.cmdset = NULL;
 	port->probe_info.class = PARPORT_CLASS_UNSPEC;
+	port->probe_info.class_name = NULL;
 
 	if (!buffer) {
 		printk(KERN_ERR "%s probe: Memory squeeze.\n", port->name);
diff -u --recursive --new-file v2.1.109/linux/drivers/scsi/ChangeLog.ncr53c8xx linux/drivers/scsi/ChangeLog.ncr53c8xx
--- v2.1.109/linux/drivers/scsi/ChangeLog.ncr53c8xx	Wed Jul  1 19:38:54 1998
+++ linux/drivers/scsi/ChangeLog.ncr53c8xx	Sun Jul 19 14:25:29 1998
@@ -1,3 +1,21 @@
+Sar Jul 18 13:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.0g
+	- Preliminary fixes for Big Endian (sent by Eddie C. Dost).
+	  Big Endian architectures should work again with the driver.
+	  Eddie's patch has been partially applied since current 2.1.109 
+	  does not have all the Sparc changes of the vger tree.
+	- Use of BITS_PER_LONG instead of (~0UL == 0xffffffffUL) has fixed
+	  the problem observed when the driver was compiled using EGCS or 
+	  PGCC.
+
+Mon Jul 13 20:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.0f
+	- Some spelling fixes.
+	- linux/config.h misplaced in ncr53c8xx.h
+	- MODULE_PARM stuff added for linux 2.1.
+	- check INQUIRY response data format is exactly 2. 
+	- use BITS_PER_LONG if defined. 
+
 Sun Jun 28 12:00 1998 Gerard Roudier (groudier@club-internet.fr)
 	* revision 3.0e
 	- Some cleanup, spelling fixes, version checks, documentations 
diff -u --recursive --new-file v2.1.109/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c
--- v2.1.109/linux/drivers/scsi/aha1542.c	Tue Jun 23 10:01:23 1998
+++ linux/drivers/scsi/aha1542.c	Mon Jul 20 17:23:32 1998
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
+#include <linux/init.h>
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/spinlock.h>
@@ -882,7 +883,7 @@
 }
 
 /* called from init/main.c */
-void aha1542_setup( char *str, int *ints)
+__initfunc(void aha1542_setup( char *str, int *ints))
 {
     const char *ahausage = "aha1542: usage: aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]\n";
     static int setup_idx = 0;
diff -u --recursive --new-file v2.1.109/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.1.109/linux/drivers/scsi/ncr53c8xx.c	Wed Jul  1 19:38:55 1998
+++ linux/drivers/scsi/ncr53c8xx.c	Sun Jul 19 14:25:29 1998
@@ -73,7 +73,7 @@
 */
 
 /*
-**	28 June 1998, version 3.0e
+**	16 July 1998, version 3.0g
 **
 **	Supported SCSI-II features:
 **	    Synchronous negotiation
@@ -158,6 +158,17 @@
 #include <linux/types.h>
 
 /*
+**	Define BITS_PER_LONG for earlier linux versions.
+*/
+#ifndef	BITS_PER_LONG
+#if (~0UL) == 0xffffffffUL
+#define	BITS_PER_LONG	32
+#else
+#define	BITS_PER_LONG	64
+#endif
+#endif
+
+/*
 **	Define the BSD style u_int32 type
 */
 typedef u32 u_int32;
@@ -278,7 +289,7 @@
 #define CCB_DONE_EMPTY 0xffffffffUL
 
 /* All 32 bit architectures */
-#if (~0UL) == 0xffffffffUL
+#if BITS_PER_LONG == 32
 #define CCB_DONE_VALID(cp)  (((u_long) cp) != CCB_DONE_EMPTY)
 
 /* All > 32 bit (64 bit) architectures regardless endian-ness */
@@ -760,9 +771,12 @@
 #ifdef	SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
 static struct ncr_driver_setup
 	driver_safe_setup __initdata	= SCSI_NCR_DRIVER_SAFE_SETUP;
-#ifdef	MODULE
+# ifdef	MODULE
 char *ncr53c8xx = 0;	/* command line passed by insmod */
-#endif
+#  if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
+MODULE_PARM(ncr53c8xx, "s");
+#  endif
+# endif
 #endif
 
 /*
@@ -5276,7 +5290,7 @@
 		cp = xpt_que_entry(qp, struct ccb, link_ccbq);
 		xpt_insque_tail(qp, &lp->busy_ccbq);
 		lp->jump_ccb[cp->tag == NO_TAG ? 0 : cp->tag].l_paddr =
-			cpu_to_scr(cp->p_ccb + offsetof(struct ccb, restart));
+			cpu_to_scr(CCB_PHYS (cp, restart));
 		ncr_put_start_queue(np, cp);
 	}
 }
@@ -6855,7 +6869,7 @@
 	if (((script_ofs & 3) == 0) &&
 	    (unsigned)script_ofs < script_size) {
 		printk ("%s: script cmd = %08x\n", ncr_name(np),
-			(int) *(ncrcmd *)(script_base + script_ofs));
+			scr_to_cpu((int) *(ncrcmd *)(script_base + script_ofs)));
 	}
 
         printk ("%s: regdump:", ncr_name(np));
@@ -7732,7 +7746,7 @@
 		**	We just assume lun=0, 1 CCB, no tag.
 		*/
 		if (tp->lp[0]) { 
-			OUTL (nc_dsp, tp->lp[0]->jump_ccb[0].l_paddr);
+			OUTL (nc_dsp, scr_to_cpu(tp->lp[0]->jump_ccb[0].l_paddr));
 			return;
 		}
 	case SIR_RESEL_BAD_TARGET:	/* Will send a TARGET RESET message */
@@ -8398,7 +8412,7 @@
 	cp->start.setup_dsa[1]	 = cpu_to_scr(vtophys(&cp->start.p_phys));
 	cp->start.setup_dsa[2]	 = cpu_to_scr(ncr_reg_bus_addr(nc_dsa));
 	cp->start.schedule.l_cmd = cpu_to_scr(SCR_JUMP);
-	cp->start.p_phys	 = vtophys(&cp->phys);
+	cp->start.p_phys	 = cpu_to_scr(vtophys(&cp->phys));
 
 	bcopy(&cp->start, &cp->restart, sizeof(cp->restart));
 
@@ -8543,7 +8557,7 @@
 {
 	int i;
 
-	lp->p_jump_ccb = vtophys(lp->jump_ccb);
+	lp->p_jump_ccb = cpu_to_scr(vtophys(lp->jump_ccb));
 	for (i = 0 ; i < lp->maxnxs ; i++) {
 #if SCSI_NCR_MAX_TAGS <= 32
 		lp->jump_ccb[i].l_cmd   = cpu_to_scr(SCR_JUMP);
@@ -8680,10 +8694,10 @@
 	/*
 	**	Evaluate trustable target/unit capabilities.
 	**	We only believe device version >= SCSI-2 that 
-	**	use appropriate response data format.
+	**	use appropriate response data format (2).
 	*/
 	inq_byte7 = 0;
-	if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0x7) >= 2)
+	if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2)
 		inq_byte7 = inq_data[7];
 
 	/*
diff -u --recursive --new-file v2.1.109/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h
--- v2.1.109/linux/drivers/scsi/ncr53c8xx.h	Thu Jul 16 18:09:26 1998
+++ linux/drivers/scsi/ncr53c8xx.h	Mon Jul 20 17:33:07 1998
@@ -42,20 +42,10 @@
 #ifndef NCR53C8XX_H
 #define NCR53C8XX_H
 
-#include <linux/config.h>
-
-#if 0
-#define CONFIG_SCSI_NCR53C8XX_PROFILE
-#endif
-
-#ifndef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
-#define CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
-#endif
-
 /*
 **	Name and revision of the driver
 */
-#define SCSI_NCR_DRIVER_NAME		"ncr53c8xx - revision 3.0e"
+#define SCSI_NCR_DRIVER_NAME		"ncr53c8xx - revision 3.0g"
 
 /*
 **	Check supported Linux versions
@@ -64,11 +54,19 @@
 #if !defined(LINUX_VERSION_CODE)
 #include <linux/version.h>
 #endif
+#include <linux/config.h>
 
 #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
 
 /*
-**	These options are'nt tunable from 'make config'
+ *	No more an option, enabled by default.
+ */
+#ifndef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
+#define CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
+#endif
+
+/*
+**	These options are not tunable from 'make config'
 */
 #define	SCSI_NCR_PROC_INFO_SUPPORT
 #define SCSI_NCR_SHARE_IRQ
diff -u --recursive --new-file v2.1.109/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c
--- v2.1.109/linux/drivers/scsi/ppa.c	Sun Jun  7 11:16:34 1998
+++ linux/drivers/scsi/ppa.c	Sat Jul 18 14:16:03 1998
@@ -122,9 +122,6 @@
     nhosts = 0;
     try_again = 0;
 
-    if (!pb)
-	pb = parport_enumerate();
-
     if (!pb) {
 	printk("ppa: parport reports no devices.\n");
 	return 0;
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v2.1.109/linux/drivers/sound/Config.in	Thu Jul 16 18:09:26 1998
+++ linux/drivers/sound/Config.in	Sat Jul 18 14:11:41 1998
@@ -148,6 +148,12 @@
       int 'MAD16 MIDI IRQ 5, 7, 9 or 10' CONFIG_MAD16_MPU_IRQ 9
   fi
   
+  dep_tristate 'Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards' CONFIG_SOUND_WAVEFRONT $CONFIG_SOUND_OSS
+  if [ "$CONFIG_SOUND_WAVEFRONT" = "y" ]; then
+      hex 'I/O base for WaveFront 210, 230, 260, 290, 300, 320, 338 or 330' CONFIG_WAVEFRONT_BASE 330
+      int 'WaveFront IRQ 5, 9, 12 or 15' CONFIG_WAVEFRONT_IRQ 9
+  fi
+
   dep_tristate 'Support for Crystal CS4232 based (PnP) cards' CONFIG_SOUND_CS4232 $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_CS4232" = "y" ]; then
       hex 'CS4232 audio I/O base 530, 604, E80 or F40' CONFIG_CS4232_BASE 530
@@ -157,8 +163,8 @@
       hex 'CS4232 MIDI I/O base 330, 370, 3B0 or 3F0' CONFIG_CS4232_MPU_BASE 330
       int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CONFIG_CS4232_MPU_IRQ 9
   fi
-  
-  dep_tristate 'Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers' CONFIG_SOUND_MAUI $CONFIG_SOUND_OSS
+
+  dep_tristate 'Limited support for Turtle Beach Wave Front (Maui, Tropez) synthesizers' CONFIG_SOUND_MAUI $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_MAUI" = "y" ]; then
       hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' CONFIG_MAUI_BASE 330
       int 'Maui IRQ 5, 9, 12 or 15' CONFIG_MAUI_IRQ 9
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v2.1.109/linux/drivers/sound/Makefile	Thu Jul 16 18:09:26 1998
+++ linux/drivers/sound/Makefile	Mon Jul 20 10:05:16 1998
@@ -49,7 +49,14 @@
 obj-$(CONFIG_SOUND)		+= soundcore.o
 obj-$(CONFIG_SOUND_OSS)		+= sound.o
 obj-$(CONFIG_SOUND_ADLIB)	+= adlib_card.o opl3.o
-obj-$(CONFIG_SOUND_CS4232)	+= cs4232.o ad1848.o uart401.o
+obj-$(CONFIG_SOUND_CS4232)	+= cs4232.o ad1848.o 
+
+# In theory, there's probably no reason to include the uart401 code
+# to support a WaveFront card's CS4232 module. However, it makes
+# reconfiguring things require a recompile, so just leave this
+# here and try not to worry about the extra uart401 module.
+
+obj-$(CONFIG_SOUND_CS4232)	+= uart401.o
 obj-$(CONFIG_SOUND_GUS)		+= gus.o ad1848.o
 obj-$(CONFIG_SOUND_MAD16)	+= mad16.o ad1848.o sb.o uart401.o
 obj-$(CONFIG_SOUND_MAUI)	+= maui.o mpu401.o
@@ -69,7 +76,7 @@
 obj-$(CONFIG_SOUND_VMIDI)	+= v_midi.o
 obj-$(CONFIG_SOUND_YM3812)	+= adlib_card.o opl3.o
 obj-$(CONFIG_VIDC_SOUND)	+= vidc_mod.o
-
+obj-$(CONFIG_SOUND_WAVEFRONT)   += wavefront.o
 #jnx
 obj-$(CONFIG_SOUND_ES1370)	+= es1370.o
 obj-$(CONFIG_SOUND_ES1371)	+= es1371.o
@@ -81,7 +88,8 @@
 
 # Declare multi-part drivers.
 
-list-multi	:= sound.o gus.o pas2.o sb.o softoss2.o vidc_mod.o soundcore.o
+list-multi	:= sound.o gus.o pas2.o sb.o softoss2.o vidc_mod.o \
+    soundcore.o wavefront.o
 
 sound-objs	:= 							\
     dev_table.o soundcard.o sound_syms.o		\
@@ -96,7 +104,7 @@
 sb-objs		:= sb_audio.o sb_card.o sb_common.o sb_midi.o sb_mixer.o
 softoss2-objs	:= softoss.o softoss_rs.o
 vidc_mod-objs	:= vidc.o vidc_audio.o vidc_fill.o vidc_mixer.o vidc_synth.o
-
+wavefront-objs  := wavfront.o wf_midi.o yss225.o
 
 
 # Extract lists of the multi-part drivers.
@@ -179,7 +187,8 @@
 vidc_mod.o: $(vidc_mod-objs)
 	$(LD) -r -o $@ $(vidc_mod-objs)
 
-
+wavefront.o: $(wavefront-objs)
+	$(LD) -r -o $@ $(wavefront-objs)
 
 # Firmware files that need translation
 #
@@ -190,10 +199,10 @@
 # First make the utilities.
 
 bin2hex: bin2hex.c
-	$(HOSTCC) -o bin2hex bin2hex.c
+	$(HOSTCC) $(HOSTCFLAGS) -o bin2hex bin2hex.c
 
 hex2hex: hex2hex.c
-	$(HOSTCC) -o hex2hex hex2hex.c
+	$(HOSTCC) $(HOSTCFLAGS) -o hex2hex hex2hex.c
 
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/README.wavefront linux/drivers/sound/README.wavefront
--- v2.1.109/linux/drivers/sound/README.wavefront	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/README.wavefront	Sat Jul 18 14:11:41 1998
@@ -0,0 +1,375 @@
+	     An OSS/Free Driver for WaveFront soundcards
+	       (Turtle Beach Maui, Tropez, Tropez Plus)
+
+		     Paul Barton-Davis, July 1998
+
+			  VERSION 0.2.2
+
+Driver Status
+-------------
+
+Requires: Kernel 2.1.106 or later
+	  
+As of 7/13/1998, this driver is currently in *BETA* state. This means
+that it compiles and runs, and that I use it on my system (Linux
+2.1.106) with some reasonably demanding applications and uses.  I
+believe the code is approaching an initial "finished" state that
+provides bug-free support for the Tropez Plus.
+
+Please note that to date, the driver has ONLY been tested on a Tropez
+Plus. I would very much like to hear (and help out) people with Tropez
+and Maui cards, since I think the driver can support those cards as
+well. 
+
+Finally, the driver has not been tested as a static (non-modular) part
+of the kernel. Alan Cox's good work in modularizing OSS/Free for Linux
+makes this rather unnecessary.
+
+Some Questions
+--------------
+
+**********************************************************************
+0) What does this driver do that the maui driver did not ?
+**********************************************************************
+
+* can fully initialize a WaveFront card from cold boot - no DOS 
+          utilities needed
+* working patch/sample/program loading and unloading (the maui
+      driver didn't document how to make this work, and assumed
+      user-level preparation of the patch data for writing
+      to the board. ick.)
+* full user-level access to all WaveFront commands
+* for the Tropez Plus, (primitive) control of the YSS225 FX processor
+* Virtual MIDI mode supported - 2 MIDI devices accessible via the
+          WaveFront's MPU401/UART emulation. One
+	  accesses the WaveFront synth, the other accesses the
+	  external MIDI connector. Full MIDI read/write semantics
+	  for both devices.
+* OSS-compliant /dev/sequencer interface for the WaveFront synth,
+	  including native and GUS-format patch downloading.
+* semi-intelligent patch management (prototypical at this point)
+
+
+**********************************************************************
+1) What to do about MIDI interfaces ?
+**********************************************************************
+
+The Tropez Plus (and perhaps other WF cards) can in theory support up
+to 2 physical MIDI interfaces. One of these is connected to the
+ICS2115 chip (the WaveFront synth itself) and is controlled by
+MPU/UART-401 emulation code running as part of the WaveFront OS.  The
+other is controlled by the CS4232 chip present on the board. However,
+physical access to the CS4232 connector is difficult, and it is
+unlikely (though not impossible) that you will want to use it.
+
+An older version of this driver introduced an additional kernel config
+variable which controlled whether or not the CS4232 MIDI interface was
+configured. Because of Alan Cox's work on modularizing the sound
+drivers, and now backporting them to 2.0.34 kernels, there seems to be
+little reason to support "static" configuration variables, and so this
+has been abandoned in favor of *only* module parameters. Specifying
+"mpuio" and "mpuirq" for the cs4232 parameter will result in the
+CS4232 MIDI interface being configured; leaving them unspecified will
+leave it unconfigured (and thus unusable).
+
+BTW, I have heard from one Tropez+ user that the CS4232 interface is
+more reliable than the ICS2115 one. I have had no problems with the
+latter, and I don't have the right cable to test the former one
+out. Reports welcome.
+
+**********************************************************************
+2) Why does line XXX of the code look like this .... ?
+**********************************************************************
+
+Either because its not finished yet, or because you're a better coder
+than I am, or because you don't understand some aspect of how the card
+or the code works. 
+
+I absolutely welcome comments, criticisms and suggestions about the
+design and implementation of the driver. 
+
+**********************************************************************
+3) What files are included ?
+**********************************************************************
+
+   drivers/sound/README.wavefront       -- this file
+   drivers/sound/wavefront.patch	-- patches for the 2.1.106 sound drivers
+					   needed to make the rest of this work
+   drivers/sound/wavfront.c             -- the driver
+   drivers/sound/ys225.h                -- data declarations for FX config
+   drivers/sound/ys225.c                -- data definitions for FX config
+   drivers/sound/wf_midi.c              -- the "uart401" driver 
+   				              to support virtual MIDI mode.
+   include/wavefront.h                  -- the header file
+   Documentation/sound/Tropez+          -- short docs on configuration
+
+**********************************************************************
+4) How do I compile/install/use it ?
+**********************************************************************
+
+PART ONE: install the source code into your sound driver directory
+
+  cd <top-of-your-2.1.106-code-base-e.g.-/usr/src/linux>
+  tar -zxvf <where-you-put/wavefront.tar.gz>
+
+PART TWO: apply the patches
+
+  cd drivers/sound
+  patch < wavefront.patch
+
+PART THREE: configure your kernel
+
+  cd <top of your kernel tree>
+  make xconfig (or whichever config option you use)
+
+         - choose YES for Sound Support	      
+         - choose MODULE (M) for OSS Sound Modules
+         - choose MODULE(M) to YM3812/OPL3 support
+	 - choose MODULE(M) for WaveFront support
+	 - choose MODULE(M) for CS4232 support
+
+	 - choose "N" for everything else (unless you have other
+	      soundcards you want support for)
+
+
+   make dep
+   make boot
+   .
+   .
+   .
+   <whatever you normally do for a kernel install>
+   make modules
+   .
+   .
+   .
+   make modules_isntall
+
+Here's my autoconf.h SOUND section:
+
+/*
+ * Sound
+ */
+#define CONFIG_SOUND 1
+#undef  CONFIG_SOUND_OSS
+#define CONFIG_SOUND_OSS_MODULE 1
+#undef  CONFIG_SOUND_PAS
+#undef  CONFIG_SOUND_SB
+#undef  CONFIG_SOUND_ADLIB
+#undef  CONFIG_SOUND_GUS
+#undef  CONFIG_SOUND_MPU401
+#undef  CONFIG_SOUND_PSS
+#undef  CONFIG_SOUND_MSS
+#undef  CONFIG_SOUND_SSCAPE
+#undef  CONFIG_SOUND_TRIX
+#undef  CONFIG_SOUND_MAD16
+#undef  CONFIG_SOUND_WAVEFRONT
+#define CONFIG_SOUND_WAVEFRONT_MODULE 1
+#undef  CONFIG_SOUND_CS4232
+#define CONFIG_SOUND_CS4232_MODULE 1
+#undef  CONFIG_SOUND_MAUI
+#undef  CONFIG_SOUND_SGALAXY
+#undef  CONFIG_SOUND_OPL3SA1
+#undef  CONFIG_SOUND_SOFTOSS
+#undef  CONFIG_SOUND_YM3812
+#define CONFIG_SOUND_YM3812_MODULE 1
+#undef  CONFIG_SOUND_VMIDI
+#undef  CONFIG_SOUND_UART6850
+/*
+ * Additional low level sound drivers
+ */
+#undef  CONFIG_LOWLEVEL_SOUND
+
+************************************************************
+6) How do I configure my card ?
+************************************************************
+
+You need to edit /etc/conf.modules. Here's mine (edited to show the
+relevant details):
+
+  # Sound system
+  alias char-major-14 wavefront
+  alias synth0 wavefront
+  alias mixer0 cs4232
+  alias audio0 cs4232
+  pre-install wavefront modprobe "-k" "cs4232"
+  post-install wavefront modprobe "-k" "opl3"
+  options wavefront io=0x200 irq=9
+  options cs4232 synthirq=9 synthio=0x200 io=0x530 irq=5 dma=1 dma2=0
+  options opl3 io=0x388
+
+Things to note: 
+
+       the wavefront options "io" and "irq" ***MUST*** match the "synthio"
+       and "synthirq" cs4232 options.
+
+       you can do without the adlib_card module if you don't
+       want to use the OPL/[34] synth on the soundcard
+
+       the adlib_card io parameter is conventionally not adjustable.
+       In theory, any not-in-use IO port address would work, but
+       just use 0x388 and stick with the crowd.
+
+**********************************************************************
+7) What about firmware ?
+**********************************************************************
+
+Turtle Beach have not given me permission to distribute their firmware
+for the ICS2115. However, if you have a WaveFront card, then you
+almost certainly have the firmware, and if not, its freely available
+on their website, at:
+
+   http://www.tbeach.com/tbs/downloads/scardsdown.htm#tropezplus 
+
+The file is called WFOS2001.MOT (for the Tropez+).
+
+This driver, however, doesn't use the pure firmware as distributed,
+but instead relies on a somewhat processed form of it. You can
+generate this very easily. Following an idea from Andrew Veliath's
+Pinnacle driver, the following flex program will generate the
+processed version:
+
+---- cut here -------------------------
+%option main
+%%
+^S[28].*\r$ printf ("%c%.*s", yyleng-1,yyleng-1,yytext);
+<<EOF>> { fputc ('\0', stdout); return; }
+\n {} 
+.  {}
+---- cut here -------------------------
+
+To use it, put the above in file (say, ws.l) compile it like this:
+
+      shell> flex -ows.c ws.l
+      shell> cc -o ws ws.c
+      
+and then use it like this:
+
+    ws < my-copy-of-the-oswf.mot-file > /etc/sound/wavefront.os
+
+If you put it somewhere else, you'll always have to use the wf_ospath
+module parameter (see below) or alter the source code.
+
+**********************************************************************
+7) How do I get it working ?
+**********************************************************************
+
+Optionally, you can reboot with the "new" kernel (even though the only
+changes have really been made to a module).
+
+Then, as root do:
+
+     modprobe wavefront
+
+You should get something like this in /var/log/messages:
+
+    WaveFront: firmware 1.20 already loaded.
+
+or 
+
+    WaveFront: no response to firmware probe, assume raw.
+
+then:
+
+    WaveFront: waiting for memory configuration ...
+    WaveFront: hardware version 1.64
+    WaveFront: available DRAM 8191k
+    WaveFront: 332 samples used (266 real, 13 aliases, 53 multi), 180 empty
+    WaveFront: 128 programs slots in use
+    WaveFront: 256 patch slots filled, 142 in use
+
+The whole process takes about 16 seconds, the longest waits being
+after reporting the hardware version (during the firmware download),
+and after reporting program status (during patch status inquiry).  Its
+shorter (about 10 secs) if the firmware is already loaded (i.e. only
+warm reboots since the last firmware load).
+
+The "available DRAM" line will vary depending on how much added RAM
+your card has. Mine has 8MB.
+
+Next, check /dev/sndstat, which on my machine says:
+---------------------------------------------------------------------
+OSS/Free:3.8s2++-971130
+Load type: Driver loaded as a module
+Kernel: Linux bd 2.1.106 #12 SMP Fri Jul 3 00:37:34 EDT 1998 i486
+Config options: 0
+
+Installed drivers: 
+
+Card config: 
+
+Audio devices:
+0: Crystal audio controller (CS4232) (DUPLEX)
+
+Synth devices:
+0: Turtle Beach WaveFront
+1: Yamaha OPL-3
+
+Midi devices:
+0: WaveFront Internal MIDI
+1: WaveFront External MIDI
+
+Timers:
+0: System clock
+1: Crystal audio controller (CS4232)
+
+Mixers:
+0: Crystal audio controller (CS4232)
+-----------------------------------------------------------
+
+To check basically functionality, use play(1) or splay(1) to send a
+.WAV or other audio file through the audio portion. Then use playmidi
+to play a General MIDI file. Try the "-D 0" to hear the
+difference between sending MIDI to the WaveFront and using the OPL/3,
+which is the default (I think ...). If you have an external synth(s)
+hooked to the soundcard, you can use "-e" to route to the
+external synth(s) (in theory, -D 1 should work as well, but I think
+there is a bug in playmidi which prevents this from doing what it
+should). 
+
+**********************************************************************
+8) What are the module parameters ?
+**********************************************************************
+
+Its best to read wavefront.c for this, but here is a summary:
+
+integers: 
+	  wf_raw  - if set, ignore apparent presence of firmware
+		    loaded onto the ICS2115, reset the whole
+		    board, and initialize it from scratch. (default = 0)
+
+          fx_raw  - if set, always initialize the YSS225 processor
+		    on the Tropez plus. (default = 1)
+
+          < The next 4 are basically for kernel hackers to allow
+	    tweaking the driver for testing purposes. >		    
+
+          wf_short_wait_count - loop counter used when waiting for
+			        status conditions on the board. This
+				is CPU-specific. After this many
+			        loops, the driver will sleep.
+				The default is 5000. I have a 66Mhz 486.
+
+          wf_sleep_interval  - the driver sleeps for
+			       HZ/wf_sleep_interval seconds per sleep.
+			       The default is 50.	
+
+          wf_sleep_tries  - the number of times the driver will sleep
+			    when waiting for a status condition on the
+			    board. The default is 100 (2 secs, if 
+			    wf_sleep_interval is 50).
+
+          wf_debug_default - debugging flags. See sound/wavefront.h
+			     for WF_DEBUG_* values. Default is zero.
+			     Setting this allows you to debug the
+			     driver during module installation.
+strings:
+	  wf_ospath - path to get to the pre-processed OS firmware.
+		    (default: /etc/sound/wavefront.os)
+
+**********************************************************************
+9) Who should I contact if I have problems?
+**********************************************************************
+
+Just me: Paul Barton-Davis <pbd@op.net>
+
+
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/Readme.modules linux/drivers/sound/Readme.modules
--- v2.1.109/linux/drivers/sound/Readme.modules	Thu Jul 16 18:09:26 1998
+++ linux/drivers/sound/Readme.modules	Sat Jul 18 14:11:41 1998
@@ -31,7 +31,7 @@
 alias char-major-14 sb
 post-install sb /sbin/modprobe "-k" "adlib_card"
 options sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330
-options adlib_card io=0x388     # FM synthesizer
+options adlib_card io=0x388     # FM synthetiser
 
   The effect of this is that the sound driver and all necessary bits and
 pieces autoload on demand, assuming you use kerneld (a sound choice) and
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
--- v2.1.109/linux/drivers/sound/ad1848.c	Thu Jul 16 18:09:26 1998
+++ linux/drivers/sound/ad1848.c	Sat Jul 18 14:06:47 1998
@@ -1721,7 +1721,7 @@
 	 */
 
 
-	int my_dev;
+	long my_dev;
 	char dev_name[100];
 	int e;
 
@@ -1951,12 +1951,12 @@
 {
 	unsigned char status;
 	ad1848_info *devc;
-	int dev;
+	long dev;
 	int alt_stat = 0xff;
 	unsigned char c930_stat = 0;
 	int cnt = 0;
 
-	dev = (int)dev_id;
+	dev = (long)dev_id;
 	devc = (ad1848_info *) audio_devs[dev]->devc;
 
 interrupt_again:		/* Jump back here if int status doesn't reset */
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/cs4232.c linux/drivers/sound/cs4232.c
--- v2.1.109/linux/drivers/sound/cs4232.c	Thu Jul 16 18:09:26 1998
+++ linux/drivers/sound/cs4232.c	Sat Jul 18 14:11:41 1998
@@ -8,6 +8,21 @@
  * gets implemented. Just the WSS codec, FM synth and the MIDI ports are
  * supported. Other interfaces are left uninitialized.
  *
+ * ifdef ...WAVEFRONT...
+ * 
+ *   Support is provided for initializing the WaveFront synth
+ *   interface as well, which is logical device #4. Note that if
+ *   you have a Tropez+ card, you probably don't need to setup
+ *   the CS4232-supported MIDI interface, since it corresponds to
+ *   the internal 26-pin header that's hard to access. Using this
+ *   requires an additional IRQ, a resource none too plentiful in
+ *   this environment. Just don't set module parameters mpuio and
+ *   mpuirq, and the MIDI port will be left uninitialized. You can
+ *   still use the ICS2115 hosted MIDI interface which corresponds
+ *   to the 9-pin D connector on the back of the card.
+ *
+ * endif  ...WAVEFRONT...
+ *
  * Supported chips are:
  *      CS4232
  *      CS4236
@@ -17,7 +32,9 @@
  * anyway.
  *
  * Changes
- *	Alan Cox	Modularisation, Basic cleanups.
+ *	Alan Cox		Modularisation, Basic cleanups.
+ *      Paul Barton-Davis	Separated MPU configuration, added
+ *                                       Tropez+ (WaveFront) support
  */
 
 /*
@@ -46,6 +63,9 @@
 #define CS_OUT3(a, b, c)	{CS_OUT(a);CS_OUT(b);CS_OUT(c);}
 
 static int mpu_base = 0, mpu_irq = 0;
+#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
+static int synth_base = 0, synth_irq = 0;
+#endif CONFIG_SOUND_WAVEFRONT_MODULE
 static int mpu_detected = 0;
 
 int probe_cs4232_mpu(struct address_info *hw_config)
@@ -170,6 +190,15 @@
 		}
 #endif
 
+#if defined(CONFIG_SOUND_WAVEFRONT) || defined(CONFIG_SOUND_WAVEFRONT_MODULE)
+		{
+		    CS_OUT2 (0x15, 0x04);	        /* logical device 4 (WaveFront) */
+		    CS_OUT3 (0x47, (synth_base >> 8) & 0xff,
+			     synth_base & 0xff);	/* base */
+		    CS_OUT2 (0x22, synth_irq);     	/* IRQ */
+		    CS_OUT2 (0x33, 0x01);	        /* Activate logical dev 4 */
+		}
+#endif
 		/*
 		 * Finally activate the chip
 		 */
@@ -248,6 +277,7 @@
 {
 	int base = hw_config->io_base, irq = hw_config->irq;
 	int dma1 = hw_config->dma, dma2 = hw_config->dma2;
+	int mixer = audio_devs[hw_config->slots[0]]->mixer_dev;
 
 	if (dma2 == -1)
 		dma2 = dma1;
@@ -257,6 +287,10 @@
 		      dma1,	/* Playback DMA */
 		      dma2,	/* Capture DMA */
 		      0);
+
+	if (mixer >= 0) {
+	    sound_unload_mixerdev (mixer);
+	}
 	sound_unload_audiodev(hw_config->slots[0]);
 #if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
 	if (mpu_base != 0 && mpu_irq != 0 && mpu_detected)
@@ -293,15 +327,27 @@
 int             irq = -1;
 int             dma = -1;
 int             dma2 = -1;
+int             mpuio = -1;
+int             mpuirq = -1;
 
 MODULE_PARM(io,"i");
 MODULE_PARM(irq,"i");
 MODULE_PARM(dma,"i");
 MODULE_PARM(dma2,"i");
+MODULE_PARM(mpuio,"i");
+MODULE_PARM(mpuirq,"i");
+
+#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
+int             synthio = -1;
+int             synthirq = -1;
+MODULE_PARM(synthio,"i");
+MODULE_PARM(synthirq,"i");
+#endif CONFIG_SOUND_WAVEFRONT_MODULE
 
 EXPORT_NO_SYMBOLS;
 
 struct address_info cfg;
+struct address_info mpu_cfg;
 
 /*
  *	Install a CS4232 based card. Need to have ad1848 and mpu401
@@ -310,31 +356,60 @@
 
 int init_module(void)
 {
+
+#ifndef CONFIG_SOUND_WAVEFRONT_MODULE
+
 	if (io == -1 || irq == -1 || dma == -1 || dma2 == -1)
 	{
 		printk(KERN_ERR "cs4232: dma, dma2, irq and io must be set.\n");
 		return -EINVAL;
 	}
+#else 
+	if (synthio == -1 || synthirq == -1 ||
+	    io == -1 || irq == -1 || dma == -1 || dma2 == -1)
+	{
+		printk(KERN_ERR "cs4232: synthio, synthirq, dma, dma2, "
+		       "irq and io must be set.\n");
+		return -EINVAL;
+	}
+
+#endif CONFIG_SOUND_WAVEFRONT_MODULE
+
 	cfg.io_base = io;
 	cfg.irq = irq;
 	cfg.dma = dma;
 	cfg.dma2 = dma2;
 
+#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
+	synth_base = synthio;
+	synth_irq =  synthirq;
+#endif CONFIG_SOUND_WAVEFRONT_MODULE	
+
 	if (probe_cs4232(&cfg) == 0)
 		return -ENODEV;
 
-	probe_cs4232_mpu(&cfg);	/* Bug always returns 0 not OK -- AC */
+	mpu_cfg.io_base = -1;
+	mpu_cfg.irq = -1;
+
+	if (mpuio != -1 && mpuirq != -1) {
+	    mpu_cfg.io_base = mpuio;
+	    mpu_cfg.irq = mpuirq;
+	    probe_cs4232_mpu(&mpu_cfg); /* Bug always returns 0 not OK -- AC */
+	}
 
 	attach_cs4232(&cfg);
-	attach_cs4232_mpu(&cfg);
+
+	if (mpuio != -1 && mpuirq != -1) {
+	    attach_cs4232_mpu(&mpu_cfg);
+	}
+
 	SOUND_LOCK;
 	return 0;
 }
 
 void cleanup_module(void)
 {
-	unload_cs4232_mpu(&cfg);
-	unload_cs4232(&cfg);
+        unload_cs4232(&cfg); /* unloads MPU as well, if needed */
 	SOUND_LOCK_END;
 }
 
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h
--- v2.1.109/linux/drivers/sound/dev_table.h	Thu Jul 16 18:09:26 1998
+++ linux/drivers/sound/dev_table.h	Sat Jul 18 14:11:41 1998
@@ -30,6 +30,7 @@
 #define SNDCARD_OPL3SA1_MPU		40
 #define SNDCARD_SOFTOSS			36
 #define SNDCARD_VMIDI			37
+#define SNDCARD_WAVEFRONT               41
 
 void attach_opl3sa_wss (struct address_info *hw_config);
 int probe_opl3sa_wss (struct address_info *hw_config);
@@ -408,6 +409,8 @@
 
 #ifdef CONFIG_SOUND_CS4232
 	{"CS4232", 0, SNDCARD_CS4232,	"CS4232",		attach_cs4232, probe_cs4232, unload_cs4232},
+#endif
+#ifdef CONFIG_CS4232_MPU_BASE
 	{"CS4232MPU", 0, SNDCARD_CS4232_MPU,	"CS4232 MIDI",		attach_cs4232_mpu, probe_cs4232_mpu, unload_cs4232_mpu},
 #endif
 
@@ -432,6 +435,10 @@
 		attach_uart401, probe_uart401, unload_uart401},
 #endif
 
+#if defined(CONFIG_SOUND_WAVEFRONT)
+	{"WAVEFRONT", 0, SNDCARD_WAVEFRONT,"TB WaveFront", attach_wavefront, probe_wavefront, unload_wavefront},
+#endif
+
 #if defined(CONFIG_SOUND_MAUI)
 	{"MAUI", 0, SNDCARD_MAUI,"TB Maui",	attach_maui, probe_maui, unload_maui},
 #endif
@@ -594,6 +601,10 @@
 #ifdef SB2_BASE
 	{SNDCARD_SB, {SB2_BASE, SB2_IRQ, SB2_DMA, SB2_DMA2}, SND_DEFAULT_ENABLE},
 #endif
+#endif
+
+#if defined(CONFIG_WAVEFRONT) 
+	{SNDCARD_WAVEFRONT, {WAVEFRONT_BASE, WAVEFRONT_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
 
 #ifdef CONFIG_SOUND_MAUI
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c
--- v2.1.109/linux/drivers/sound/mad16.c	Thu Jul 16 18:09:26 1998
+++ linux/drivers/sound/mad16.c	Sat Jul 18 14:11:41 1998
@@ -1033,10 +1033,10 @@
 
 	config_mpu.io_base = mpu_io;
 	config_mpu.irq = mpu_irq;
-	found_mpu = probe_mad16_mpu(&config_mpu);
-
 	attach_mad16(&config);
 
+	found_mpu = probe_mad16_mpu(&config_mpu);
+
 	if (found_mpu)
 		attach_mad16_mpu(&config_mpu);
 
@@ -1047,7 +1047,7 @@
 void cleanup_module(void)
 {
 	if (found_mpu)
-		unload_mad16_mpu(&config);
+		unload_mad16_mpu(&config_mpu);
 	unload_mad16(&config);
 	SOUND_LOCK_END;
 }
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/msnd.c linux/drivers/sound/msnd.c
--- v2.1.109/linux/drivers/sound/msnd.c	Thu Jul 16 18:09:26 1998
+++ linux/drivers/sound/msnd.c	Sat Jul 18 14:11:41 1998
@@ -212,7 +212,7 @@
 int msnd_wait_TXDE(multisound_dev_t *dev)
 {
 	register unsigned int io = dev->io;
-	register int timeout = 5000;
+	register int timeout = 100;
     
 	while(timeout-- > 0)
 		if (inb(io + HP_ISR) & HPISR_TXDE)
@@ -224,7 +224,7 @@
 int msnd_wait_HC0(multisound_dev_t *dev)
 {
 	register unsigned int io = dev->io;
-	register int timeout = 25000;
+	register int timeout = 100;
 
 	while(timeout-- > 0)
 		if (!(inb(io + HP_CVR) & HPCVR_HC))
@@ -291,7 +291,7 @@
 
 int msnd_enable_irq(multisound_dev_t *dev)
 {
-	printk(KERN_INFO LOGNAME ": enable_irq: count %d\n", dev->irq_ref);
+	printk(KERN_DEBUG LOGNAME ": enable_irq: count %d\n", dev->irq_ref);
 
 	if (dev->irq_ref++ != 0)
 		return 0;
@@ -333,6 +333,8 @@
 		dev->irq_ref = 0;
 
 	printk(KERN_DEBUG LOGNAME ": Disabling IRQ\n");
+	
+	udelay(50);
 
 	spin_lock_irqsave(&dev->lock, flags);
 	outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR);
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/msnd.h linux/drivers/sound/msnd.h
--- v2.1.109/linux/drivers/sound/msnd.h	Thu Jul 16 18:09:27 1998
+++ linux/drivers/sound/msnd.h	Sat Jul 18 14:11:41 1998
@@ -24,17 +24,17 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd.h,v 1.3 1998/06/09 20:39:34 andrewtv Exp $
+ * $Id: msnd.h,v 1.4 1998/07/14 22:59:25 andrewtv Exp $
  *
  ********************************************************************/
 #ifndef __MSND_H
 #define __MSND_H
 
-#define VERSION			"0.6"
+#define VERSION			"0.6.2"
 
-#define DEFSAMPLERATE		44100
-#define DEFSAMPLESIZE		16
-#define DEFCHANNELS		2
+#define DEFSAMPLERATE		DSP_DEFAULT_SPEED
+#define DEFSAMPLESIZE		8
+#define DEFCHANNELS		1
 
 #define DEFFIFOSIZE		64
 
@@ -129,6 +129,19 @@
 #define	HIMT_MIDI_IN_UCHAR	0x0E
 #define	HIMT_DSP		0x0F
 
+#define	HDEX_BASE	       	0x92
+#define	HDEX_PLAY_START		(0 + HDEX_BASE)
+#define	HDEX_PLAY_STOP		(1 + HDEX_BASE)
+#define	HDEX_PLAY_PAUSE		(2 + HDEX_BASE)
+#define	HDEX_PLAY_RESUME	(3 + HDEX_BASE)
+#define	HDEX_RECORD_START	(4 + HDEX_BASE)
+#define	HDEX_RECORD_STOP	(5 + HDEX_BASE)
+#define	HDEX_MIDI_IN_START 	(6 + HDEX_BASE)
+#define	HDEX_MIDI_IN_STOP	(7 + HDEX_BASE)
+#define	HDEX_MIDI_OUT_START	(8 + HDEX_BASE)
+#define	HDEX_MIDI_OUT_STOP	(9 + HDEX_BASE)
+#define	HDEX_AUX_REQ		(10 + HDEX_BASE)
+
 #define HIWORD(l)		((WORD)((((DWORD)(l)) >> 16) & 0xFFFF ))
 #define LOWORD(l)		((WORD)(DWORD)(l))
 #define HIBYTE(w)		((BYTE)(((WORD)(w) >> 8 ) & 0xFF ))
@@ -140,6 +153,8 @@
 #define PCTODSP_BASED(w)	(USHORT)(((w)/2) + DSP_BASE_ADDR)
 
 #ifdef SLOWIO
+#  undef outb
+#  undef inb
 #  define outb			outb_p
 #  define inb			inb_p
 #endif
@@ -195,8 +210,9 @@
 	struct SMA0_CommonData *SMA;	/* diff. structure for classic vs. pinnacle */
 	struct DAQueueDataStruct *CurDAQD;
 	struct DAQueueDataStruct *CurDARQD;
-	WORD *pwDSPQData , *pwMIDQData , *pwMODQData;
-	struct JobQueueStruct *DAPQ , *DARQ , *MODQ , *MIDQ , *DSPQ;
+	volatile WORD *pwDSPQData , *pwMIDQData , *pwMODQData;
+	volatile struct JobQueueStruct *DAPQ , *DARQ , *MODQ , *MIDQ , *DSPQ;
+	BYTE bCurrentMidiPatch;
 
 	/* State variables */
 	mode_t mode;
@@ -210,7 +226,10 @@
 #define F_AUDIO_INUSE			6
 #define F_EXT_MIDI_INUSE		7
 #define F_INT_MIDI_INUSE		8
+#define F_WRITEFLUSH			9
+
 	struct wait_queue *writeblock, *readblock;
+	struct wait_queue *writeflush;
 	unsigned long recsrc;
 	int left_levels[16];
 	int right_levels[16];
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/msnd_classic.c linux/drivers/sound/msnd_classic.c
--- v2.1.109/linux/drivers/sound/msnd_classic.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/sound/msnd_classic.c	Sat Jul 18 14:11:41 1998
@@ -453,8 +453,17 @@
 	mdelay(1);
 	if (test_and_clear_bit(F_WRITING, &dev.flags)) {
 
+		set_bit(F_WRITEFLUSH, &dev.flags);
+		interruptible_sleep_on(&dev.writeflush);
+		current->state = TASK_INTERRUPTIBLE;
+		current->timeout = 
+			jiffies + DAP_BUFF_SIZE / 2 * HZ /
+			dev.sample_rate / dev.channels;
+		schedule();
+		current->timeout = 0;
 		msnd_send_dsp_cmd(&dev, HDEX_PLAY_STOP);
 		msnd_disable_irq(&dev);
+		memset_io(dev.base, 0, DAP_BUFF_SIZE * 3);
 
 	}
 	mdelay(1);
@@ -674,8 +683,9 @@
 			} 
 			else if (!test_bit(F_WRITEBLOCK, &dev.flags)) {
 
-				memset_io(dev.base, 0, DAP_BUFF_SIZE * 3);
 				clear_bit(F_WRITING, &dev.flags);
+				if (test_and_clear_bit(F_WRITEFLUSH, &dev.flags))
+					wake_up_interruptible(&dev.writeflush);
 				msnd_disable_irq(&dev);
 
 			}
@@ -728,7 +738,7 @@
 			break;
 
 		default:
-			printk(KERN_INFO LOGNAME ": DSP message %u\n", LOBYTE(wMessage));
+			printk(KERN_DEBUG LOGNAME ": DSP message %u\n", LOBYTE(wMessage));
 			break;
 		}
 		break;
@@ -738,15 +748,19 @@
 			(*dev.midi_in_interrupt)(&dev);
 		break;
 
+	case HIMT_MIDI_OUT:
+		printk(KERN_DEBUG LOGNAME ": MIDI out event\n");
+		break;
+
 	default:
+		printk(KERN_DEBUG LOGNAME ": HIMT message %u\n", HIBYTE(wMessage));
 		break;
 	}
 }
 
 static void intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-	if (test_bit(F_INTERRUPT, &dev.flags) || 
-	    ((multisound_dev_t *)dev_id != &dev))
+	if (test_bit(F_INTERRUPT, &dev.flags))
 		return;
 
 	set_bit(F_INTERRUPT, &dev.flags);
@@ -1261,6 +1275,7 @@
 
 	init_waitqueue(&dev.writeblock);
 	init_waitqueue(&dev.readblock);
+	init_waitqueue(&dev.writeflush);
 	msnd_fifo_init(&dev.DAPF);
 	msnd_fifo_init(&dev.DARF);
 	spin_lock_init(&dev.lock);
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/msnd_classic.h linux/drivers/sound/msnd_classic.h
--- v2.1.109/linux/drivers/sound/msnd_classic.h	Thu Jul 16 18:09:27 1998
+++ linux/drivers/sound/msnd_classic.h	Sat Jul 18 14:11:41 1998
@@ -24,7 +24,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * 
- * $Id: msnd_classic.h,v 1.3 1998/06/09 20:39:34 andrewtv Exp $
+ * $Id: msnd_classic.h,v 1.4 1998/07/14 22:59:25 andrewtv Exp $
  *
  ********************************************************************/
 #ifndef __MSND_CLASSIC_H
@@ -63,19 +63,6 @@
 #define	HIDSP_MIDI_IN_OVER	0x10
 #define	HIDSP_MIDI_OVERRUN_ERR  0x13
 
-#define	HDEX_BASE	       	0x92
-#define	HDEX_PLAY_START		(0 + HDEX_BASE)
-#define	HDEX_PLAY_STOP		(1 + HDEX_BASE)
-#define	HDEX_PLAY_PAUSE		(2 + HDEX_BASE)
-#define	HDEX_PLAY_RESUME	(3 + HDEX_BASE)
-#define	HDEX_RECORD_START	(4 + HDEX_BASE)
-#define	HDEX_RECORD_STOP	(5 + HDEX_BASE)
-#define	HDEX_MIDI_IN_START 	(6 + HDEX_BASE)
-#define	HDEX_MIDI_IN_STOP	(7 + HDEX_BASE)
-#define	HDEX_MIDI_OUT_START	(8 + HDEX_BASE)
-#define	HDEX_MIDI_OUT_STOP	(9 + HDEX_BASE)
-#define	HDEX_AUX_REQ		(10 + HDEX_BASE)
-
 #define	HDEXAR_CLEAR_PEAKS	1
 #define	HDEXAR_IN_SET_POTS	2
 #define	HDEXAR_AUX_SET_POTS	3
@@ -181,6 +168,14 @@
 #  define PERMCODESIZE		sizeof(msndperm)
 #  define INITCODESIZE		sizeof(msndinit)
 #else
+#  ifndef CONFIG_MSNDCLAS_INIT_FILE
+#    define CONFIG_MSNDCLAS_INIT_FILE				\
+				"/etc/sound/msndinit.bin"
+#  endif
+#  ifndef CONFIG_MSNDCLAS_PERM_FILE
+#    define CONFIG_MSNDCLAS_PERM_FILE				\
+				"/etc/sound/msndperm.bin"
+#  endif
 #  define PERMCODEFILE		CONFIG_MSNDCLAS_PERM_FILE
 #  define INITCODEFILE		CONFIG_MSNDCLAS_INIT_FILE
 #  define PERMCODE		dspini
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c
--- v2.1.109/linux/drivers/sound/msnd_pinnacle.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/sound/msnd_pinnacle.c	Sat Jul 18 14:11:41 1998
@@ -485,8 +485,17 @@
 	mdelay(1);
 	if (test_and_clear_bit(F_WRITING, &dev.flags)) {
 
+		set_bit(F_WRITEFLUSH, &dev.flags);
+		interruptible_sleep_on(&dev.writeflush);
+		current->state = TASK_INTERRUPTIBLE;
+		current->timeout = 
+			jiffies + DAP_BUFF_SIZE / 2 * HZ /
+			dev.sample_rate / dev.channels;
+		schedule();
+		current->timeout = 0;
 		msnd_send_dsp_cmd(&dev, HDEX_PLAY_STOP);
 		msnd_disable_irq(&dev);
+		memset_io(dev.base, 0, DAP_BUFF_SIZE * 3);
 
 	}
 	mdelay(1);
@@ -706,8 +715,9 @@
 			} 
 			else if (!test_bit(F_WRITEBLOCK, &dev.flags)) {
 
-				memset_io(dev.base, 0, DAP_BUFF_SIZE * 3);
 				clear_bit(F_WRITING, &dev.flags);
+				if (test_and_clear_bit(F_WRITEFLUSH, &dev.flags))
+					wake_up_interruptible(&dev.writeflush);
 				msnd_disable_irq(&dev);
 
 			}
@@ -761,7 +771,7 @@
 			break;
 
 		default:
-			printk(KERN_INFO LOGNAME ": DSP message %u\n", LOBYTE(wMessage));
+			printk(KERN_DEBUG LOGNAME ": DSP message %u\n", LOBYTE(wMessage));
 			break;
 		}
 		break;
@@ -771,15 +781,19 @@
 			(*dev.midi_in_interrupt)(&dev);
 		break;
 
+	case HIMT_MIDI_OUT:
+		printk(KERN_DEBUG LOGNAME ": MIDI out event\n");
+		break;
+
 	default:
+		printk(KERN_DEBUG LOGNAME ": HIMT message %u\n", HIBYTE(wMessage));
 		break;
 	}
 }
 
 static void intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-	if (test_bit(F_INTERRUPT, &dev.flags) || 
-	    ((multisound_dev_t *)dev_id != &dev))
+	if (test_bit(F_INTERRUPT, &dev.flags))
 		return;
 
 	set_bit(F_INTERRUPT, &dev.flags);
@@ -1293,6 +1307,7 @@
 
 	init_waitqueue(&dev.writeblock);
 	init_waitqueue(&dev.readblock);
+	init_waitqueue(&dev.writeflush);
 	msnd_fifo_init(&dev.DAPF);
 	msnd_fifo_init(&dev.DARF);
 	spin_lock_init(&dev.lock);
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/msnd_pinnacle.h linux/drivers/sound/msnd_pinnacle.h
--- v2.1.109/linux/drivers/sound/msnd_pinnacle.h	Thu Jul 16 18:09:27 1998
+++ linux/drivers/sound/msnd_pinnacle.h	Sat Jul 18 14:11:41 1998
@@ -24,7 +24,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd_pinnacle.h,v 1.3 1998/06/09 20:39:34 andrewtv Exp $
+ * $Id: msnd_pinnacle.h,v 1.4 1998/07/14 22:59:25 andrewtv Exp $
  *
  ********************************************************************/
 #ifndef __MSND_PINNACLE_H
@@ -62,19 +62,6 @@
 #define	HIDSP_MIX_CLIPPING	0x30
 #define HIDSP_DAT_IN_OFF	0x21
 
-#define	HDEX_BASE	       	0x92
-#define	HDEX_PLAY_START		(0 + HDEX_BASE)
-#define	HDEX_PLAY_STOP		(1 + HDEX_BASE)
-#define	HDEX_PLAY_PAUSE		(2 + HDEX_BASE)
-#define	HDEX_PLAY_RESUME	(3 + HDEX_BASE)
-#define	HDEX_RECORD_START	(4 + HDEX_BASE)
-#define	HDEX_RECORD_STOP	(5 + HDEX_BASE)
-#define	HDEX_MIDI_IN_START 	(6 + HDEX_BASE)
-#define	HDEX_MIDI_IN_STOP	(7 + HDEX_BASE)
-#define	HDEX_MIDI_OUT_START	(8 + HDEX_BASE)
-#define	HDEX_MIDI_OUT_STOP	(9 + HDEX_BASE)
-#define	HDEX_AUX_REQ		(10 + HDEX_BASE)
-
 #define	HDEXAR_SET_ANA_IN	0
 #define	HDEXAR_CLEAR_PEAKS	1
 #define	HDEXAR_IN_SET_POTS	2
@@ -237,6 +224,14 @@
 #  define PERMCODESIZE		sizeof(pndsperm)
 #  define INITCODESIZE		sizeof(pndspini)
 #else
+#  ifndef CONFIG_MSNDPIN_INIT_FILE
+#    define CONFIG_MSNDPIN_INIT_FILE				\
+				"/etc/sound/pndspini.bin"
+#  endif
+#  ifndef CONFIG_MSNDPIN_PERM_FILE
+#    define CONFIG_MSNDPIN_PERM_FILE				\
+				"/etc/sound/pndsperm.bin"
+#  endif
 #  define PERMCODEFILE		CONFIG_MSNDPIN_PERM_FILE
 #  define INITCODEFILE		CONFIG_MSNDPIN_INIT_FILE
 #  define PERMCODE		dspini
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/sound_calls.h linux/drivers/sound/sound_calls.h
--- v2.1.109/linux/drivers/sound/sound_calls.h	Wed Apr  8 19:36:27 1998
+++ linux/drivers/sound/sound_calls.h	Sat Jul 18 14:11:41 1998
@@ -272,3 +272,39 @@
 void attach_vidc(struct address_info *hw_config);
 int probe_vidc(struct address_info *hw_config);
 void unload_vidc(struct address_info *hw_config);
+
+/*      From wavefront.c */
+void attach_wavefront (struct address_info *hw_config);
+int probe_wavefront (struct address_info *hw_config);
+void unload_wavefront (struct address_info *hw_config);
+
+/*      From wf_midi.c */
+void attach_wf_mpu(struct address_info * hw_config);
+int probe_wf_mpu(struct address_info *hw_config);
+void unload_wf_mpu(struct address_info *hw_config);
+int virtual_midi_enable (int mididev, struct address_info *);
+void virtual_midi_disable (int mididev);
+
+/*      From wavefront.c */
+void attach_wavefront (struct address_info *hw_config);
+int probe_wavefront (struct address_info *hw_config);
+void unload_wavefront (struct address_info *hw_config);
+
+/*      From wf_midi.c */
+void attach_wf_mpu(struct address_info * hw_config);
+int probe_wf_mpu(struct address_info *hw_config);
+void unload_wf_mpu(struct address_info *hw_config);
+int virtual_midi_enable (int mididev, struct address_info *);
+void virtual_midi_disable (int mididev);
+
+/*      From wavefront.c */
+void attach_wavefront (struct address_info *hw_config);
+int probe_wavefront (struct address_info *hw_config);
+void unload_wavefront (struct address_info *hw_config);
+
+/*      From wf_midi.c */
+void attach_wf_mpu(struct address_info * hw_config);
+int probe_wf_mpu(struct address_info *hw_config);
+void unload_wf_mpu(struct address_info *hw_config);
+int virtual_midi_enable (int mididev, struct address_info *);
+void virtual_midi_disable (int mididev);
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c
--- v2.1.109/linux/drivers/sound/wavfront.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/wavfront.c	Sat Jul 18 14:11:41 1998
@@ -0,0 +1,3412 @@
+/*
+ * sound/wavefront.c
+ *
+ * A low level driver for Turtle Beach WaveFront Series
+ *    (Maui, Tropez, Tropez Plus, and perhaps the Monterey & Rio)
+ *
+ * This driver supports the onboard wavetable synthesizer (an ICS2115),
+ * including patch, sample and program loading and unloading, conversion
+ * of GUS patches during loading, and full user-level access to all
+ * WaveFront commands. It tries to provide semi-intelligent patch and
+ * sample management as well.
+ *
+ * It also provides support for the ICS emulation of an MPU-401.  Full
+ * support for the ICS emulation's "virtual MIDI mode" is provided in
+ * wf_midi.c.
+ *
+ * Support is also provided for the Tropez Plus' onboard FX processor,
+ * a Yamaha YSS225. Currently, code exists to configure the YSS225,
+ * and there is an interface allowing tweaking of any of its memory
+ * addresses. However, I have been unable to decipher the logical
+ * positioning of the configuration info for various effects, so for
+ * now, you just get the YSS225 in the same state as Turtle Beach's
+ * "SETUPSND.EXE" utility leaves it.
+ *
+ * The boards' CODEC (a Crystal CS4232) is supported by cs4232.[co],
+ * This chip also controls the configuration of the card: the wavefront
+ * synth is logical unit 4.
+ *
+ * NOTE: this driver has been written to support multiple WaveFront
+ * cards, but without using PnP to configure the CS4232, all of them
+ * would end up with the same configuration. Further, the current
+ * module loading interface doesn't permit this, since it only allows
+ * once instance of a module (which happens to be equivalent to a
+ * single hardware configuration) to be installed at one time.In
+ * addition, there is a hard limit on the available DMA channels that
+ * also makes installing more than 1 card limited to purely MIDI/synth
+ * activities on the second card. Still, the coding style gets rid of
+ * virtually all globals, which I believe is a better way to code
+ * device drivers (or anything else, for that matter).
+ *
+ **********************************************************************
+ *
+ * Copyright (C) by Paul Barton-Davis 1998
+ *
+ * Some portions of this file are taken from work that is
+ * copyright (C) by Hannu Savolainen 1993-1996
+ *
+ * Although the relevant code here is all new, the handling of
+ * sample/alias/multi- samples is entirely based on a driver by Matt
+ * Martin and Rutger Nijlunsing which demonstrated how to get things
+ * to most aspects of this to work correctly. The GUS patch loading
+ * code has been almost unaltered by me, except to fit formatting and
+ * function names in the rest of the file. Many thanks to them.
+ *
+ * Appreciation and thanks to Hannu Savolainen for his early work on the Maui
+ * driver, and answering a few questions while this one was developed.
+ *
+ * Absolutely NO thanks to Turtle Beach/Voyetra and Yamaha for their
+ * complete lack of help in developing this driver, and in particular
+ * for their utter silence in response to questions about undocumented
+ * aspects of configuring a WaveFront soundcard, particularly the
+ * effects processor.
+ *
+ * This program is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info.  */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/init.h>
+
+#include "sound_config.h"
+#include "soundmodule.h"
+
+#include <linux/wavefront.h>
+
+#define MIDI_SYNTH_NAME	"WaveFront MIDI"
+#define MIDI_SYNTH_CAPS	SYNTH_CAP_INPUT
+#include "midi_synth.h"
+
+#define COPY_FROM_USER(a,b,c) copy_from_user ((a),(b),(c))
+#define COPY_TO_USER(a,b,c)   copy_to_user ((a),(b),(c))
+
+#if defined(CONFIG_SOUND_WAVEFRONT) || defined(CONFIG_SOUND_WAVEFRONT_MODULE)
+
+/* This thing is meant to work as a module */
+
+#ifdef MODULE
+
+/* bitmasks for WaveFront status port value */
+
+#define STAT_INTR_WRITE		0x40
+#define STAT_CAN_WRITE		0x20
+#define STAT_RINTR_ENABLED	0x10
+#define STAT_INTR_READ		0x04
+#define STAT_CAN_READ		0x02
+#define STAT_WINTR_ENABLED	0x01
+
+/*** Module-accessible parameters ***************************************/
+
+int wf_raw = 0; /* we normally check for "raw state" to firmware
+		   loading. if set, then during driver loading, the
+		   state of the board is ignored, and we reset the
+		   board and load the firmware anyway.
+		*/
+		   
+int fx_raw = 1; /* if this is zero, we'll leave the FX processor in
+		   whatever state it is when the driver is loaded.
+		   The default is to download the microprogram and
+		   associated coefficients to set it up for "default"
+		   operation, whatever that means.
+		*/
+
+int wf_debug_default = 0;  /* you can set this to control debugging
+			      during driver loading. it takes any combination
+			      of the WF_DEBUG_* flags defined in
+			      wavefront.h
+			   */
+
+/* XXX this needs to be made firmware and hardware version dependent */
+
+char *wf_ospath = "/etc/sound/wavefront.os"; /* where to find a processed
+						version of the WaveFront OS
+					     */
+
+/* These three don't need to be messed with unless you're trying to
+   tweak the driver for optimal I/O performance. Read wavefront_wait()
+   and wavefront_sleep() to see what they do. You may need or want to
+   tweak them for CPU's different than the 486/66Mhz that I run on.
+*/
+
+int wf_short_wait_count = 5000; /* loops, CPU dependent */
+int wf_sleep_interval = 50;     /* HZ/wf_sleep_interval seconds per sleep */
+int wf_sleep_tries = 100;  /*2sec*/ /* number of times we'll try to sleep */
+
+MODULE_PARM(wf_raw,"i");
+MODULE_PARM(fx_raw,"i");
+MODULE_PARM(wf_debug_default,"i");
+MODULE_PARM(wf_ospath,"s");
+MODULE_PARM(wf_short_wait_count,"i");
+MODULE_PARM(wf_sleep_interval,"i");
+MODULE_PARM(wf_sleep_tries,"i");
+
+/***************************************************************************/
+
+static struct synth_info wavefront_info =
+{"Turtle Beach WaveFront", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_WAVEFRONT,
+ 0, 32, 0, 0, SYNTH_CAP_INPUT};
+
+static int (*midi_load_patch) (int dev, int format, const char *addr,
+			       int offs, int count, int pmgr_flag) = NULL;
+
+
+typedef struct wf_config {
+	int installed;        /* well, is it ? note: doesn't mean "working" */
+	int devno;            /* device number from kernel */
+	int irq;              /* "you were one, one of the few ..." */
+	int base;             /* low i/o port address */
+
+#define mpu_data_port    base 
+#define mpu_command_port base + 1 /* write semantics */
+#define mpu_status_port  base + 1 /* read semantics */
+#define data_port        base + 2 
+#define status_port      base + 3 /* read semantics */
+#define control_port     base + 3 /* write semantics  */
+#define block_port       base + 4 /* 16 bit, writeonly */
+#define last_block_port  base + 6 /* 16 bit, writeonly */
+
+	/* FX ports. These are mapped through the ICS2115 to the YS225.
+	   The ICS2115 takes care of flipping the relevant pins on the
+	   YS225 so that access to each of these ports does the right
+	   thing. Note: these are NOT documented by Turtle Beach.
+	*/
+
+#define fx_status       base + 8 
+#define fx_op           base + 8 
+#define fx_lcr          base + 9 
+#define fx_dsp_addr     base + 0xa
+#define fx_dsp_page     base + 0xb 
+#define fx_dsp_lsb      base + 0xc 
+#define fx_dsp_msb      base + 0xd 
+#define fx_mod_addr     base + 0xe
+#define fx_mod_data     base + 0xf 
+
+	volatile int irq_ok;               /* set by interrupt handler */
+	int opened;                        /* flag, holds open(1) mode */
+	char debug;                        /* debugging flags */
+	unsigned int freemem;              /* installed RAM, in bytes */ 
+	int synthdev;                      /* OSS minor devnum for synth */
+	int mididev;                       /* OSS minor devno for internal MIDI */
+	int ext_mididev;                   /* OSS minor devno for external MIDI */ 
+	char fw_version[2];                /* major = [0], minor = [1] */
+	char hw_version[2];                /* major = [0], minor = [1] */
+	char israw;                        /* needs Motorola microcode */
+	char prog_status[WF_MAX_PROGRAM];  /* WF_SLOT_* */
+	char patch_status[WF_MAX_PATCH];   /* WF_SLOT_* */
+	char sample_status[WF_MAX_SAMPLE]; /* WF_ST_* | WF_SLOT_* */
+	int samples_used;                  /* how many */
+	char interrupts_on;                /* h/w MPU interrupts enabled ? */
+	char rom_samples_rdonly;           /* can we write on ROM samples */
+} wf_config;
+
+static wf_config wfs[WAVEFRONT_MAX_DEVICES];
+
+#define wavefront_status(hw) (inb (hw->status_port))
+
+/* forward references */
+
+static int wffx_ioctl (struct wf_config *, wavefront_fx_info *);
+static int wffx_init (struct wf_config *hw);
+static int wavefront_delete_sample (struct wf_config *hw, int sampnum);
+
+static volatile int irq2hw[17] =
+{-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1};
+
+static volatile int dev2hw[17] =
+{-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1};
+
+typedef struct {
+	int cmd;
+	char *action;
+	unsigned int read_cnt;
+	unsigned int write_cnt;
+	int need_ack;
+} wavefront_command;
+
+static struct {
+	int errno;
+	const char *errstr;
+} wavefront_errors[] = {
+	{ 0x01, "Bad sample number" },
+	{ 0x02, "Out of sample memory" },
+	{ 0x03, "Bad patch number" },
+	{ 0x04, "Error in number of voices" },
+	{ 0x06, "Sample load already in progress" },
+	{ 0x0B, "No sample load request pending" },
+	{ 0x0E, "Bad MIDI channel number" },
+	{ 0x10, "Download Record Error" },
+	{ 0x80, "Success" },
+	{ 0x0, 0x0 }
+};
+
+#define NEEDS_ACK 1
+
+static wavefront_command wavefront_commands[] = {
+	{ WFC_SET_SYNTHVOL, "set synthesizer volume", 0, 1, NEEDS_ACK },
+	{ WFC_GET_SYNTHVOL, "get synthesizer volume", 1, 0, 0},
+	{ WFC_SET_NVOICES, "set number of voices", 0, 1, NEEDS_ACK },
+	{ WFC_GET_NVOICES, "get number of voices", 1, 0, 0 },
+	{ WFC_SET_TUNING, "set synthesizer tuning", 0, 2, NEEDS_ACK },
+	{ WFC_GET_TUNING, "get synthesizer tuning", 2, 0, 0 },
+	{ WFC_DISABLE_CHANNEL, "disable synth channel", 0, 1, NEEDS_ACK },
+	{ WFC_ENABLE_CHANNEL, "enable synth channel", 0, 1, NEEDS_ACK },
+	{ WFC_GET_CHANNEL_STATUS, "get synth channel status", 3, 0, 0 },
+	{ WFC_MISYNTH_OFF, "disable midi-in to synth", 0, 0, NEEDS_ACK },
+	{ WFC_MISYNTH_ON, "enable midi-in to synth", 0, 0, NEEDS_ACK },
+	{ WFC_VMIDI_ON, "enable virtual midi mode", 0, 0, NEEDS_ACK },
+	{ WFC_VMIDI_OFF, "disable virtual midi mode", 0, 0, NEEDS_ACK },
+	{ WFC_MIDI_STATUS, "report midi status", 1, 0, 0 },
+	{ WFC_FIRMWARE_VERSION, "report firmware version", 2, 0, 0 },
+	{ WFC_HARDWARE_VERSION, "report hardware version", 2, 0, 0 },
+	{ WFC_GET_NSAMPLES, "report number of samples", 2, 0, 0 },
+	{ WFC_INSTOUT_LEVELS, "report instantaneous output levels", 7, 0, 0 },
+	{ WFC_PEAKOUT_LEVELS, "report peak output levels", 7, 0, 0 },
+	{ WFC_DOWNLOAD_SAMPLE, "download sample",
+	  0, WF_SAMPLE_BYTES, NEEDS_ACK },
+	{ WFC_DOWNLOAD_BLOCK, "download block", 0, 0, NEEDS_ACK},
+	{ WFC_DOWNLOAD_SAMPLE_HEADER, "download sample header",
+	  0, WF_SAMPLE_HDR_BYTES, NEEDS_ACK },
+	{ WFC_UPLOAD_SAMPLE_HEADER, "upload sample header", 13, 2, 0 },
+
+	/* This command requires a variable number of bytes to be written.
+	   There is a hack in wavefront_cmd() to support this. The actual
+	   count is passed in as the read buffer ptr, cast appropriately.
+	   Ugh.
+	*/
+
+	{ WFC_DOWNLOAD_MULTISAMPLE, "download multisample", 0, 0, NEEDS_ACK },
+
+	/* This one is a hack as well. We just read the first byte of the
+	   response, don't fetch an ACK, and leave the rest to the 
+	   calling function. Ugly, ugly, ugly.
+	*/
+
+	{ WFC_UPLOAD_MULTISAMPLE, "upload multisample", 2, 1, 0 },
+	{ WFC_DOWNLOAD_SAMPLE_ALIAS, "download sample alias",
+	  0, WF_ALIAS_BYTES, NEEDS_ACK },
+	{ WFC_UPLOAD_SAMPLE_ALIAS, "upload sample alias", WF_ALIAS_BYTES, 2, 0},
+	{ WFC_DELETE_SAMPLE, "delete sample", 0, 2, NEEDS_ACK },
+	{ WFC_IDENTIFY_SAMPLE_TYPE, "identify sample type", 5, 2, 0 },
+	{ WFC_UPLOAD_SAMPLE_PARAMS, "upload sample parameters" },
+	{ WFC_REPORT_FREE_MEMORY, "report free memory", 4, 0, 0 },
+	{ WFC_DOWNLOAD_PATCH, "download patch", 0, 134, NEEDS_ACK },
+	{ WFC_UPLOAD_PATCH, "upload patch", 132, 2, 0 },
+	{ WFC_DOWNLOAD_PROGRAM, "download program", 0, 33, NEEDS_ACK },
+	{ WFC_UPLOAD_PROGRAM, "upload program", 32, 1, 0 },
+	{ WFC_DOWNLOAD_EDRUM_PROGRAM, "download enhanced drum program", 0, 9,
+	  NEEDS_ACK},
+	{ WFC_UPLOAD_EDRUM_PROGRAM, "upload enhanced drum program", 8, 1, 0},
+	{ WFC_SET_EDRUM_CHANNEL, "set enhanced drum program channel",
+	  0, 1, NEEDS_ACK },
+	{ WFC_DISABLE_DRUM_PROGRAM, "disable drum program", 0, 1, NEEDS_ACK },
+	{ WFC_REPORT_CHANNEL_PROGRAMS, "report channel program numbers",
+	  32, 0, 0 },
+	{ 0x00 }
+};
+
+wf_config *
+hw_from_dev (int dev)
+
+{
+	int i;
+
+	if ((i = dev2hw[dev]) == -1) {
+		printk (KERN_ERR
+			"WaveFront: no hardware associated with device %d.\n",
+			dev);
+		return 0;
+	}
+
+	return &wfs[i];
+}
+
+static const char *
+wavefront_errorstr (int errnum)
+
+{
+	int i;
+
+	for (i = 0; wavefront_errors[i].errstr; i++) {
+		if (wavefront_errors[i].errno == errnum) {
+			return wavefront_errors[i].errstr;
+		}
+	}
+
+	return "Unknown WaveFront error";
+}
+
+static wavefront_command *
+wavefront_get_command (int cmd) 
+
+{
+	int i;
+
+	for (i = 0; wavefront_commands[i].cmd != 0; i++) {
+		if (cmd == wavefront_commands[i].cmd) {
+			return &wavefront_commands[i];
+		}
+	}
+
+	return (wavefront_command *) 0;
+}
+
+static int
+wavefront_sleep (wf_config *hw, int limit)
+
+{
+	current->timeout = jiffies + limit;
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	current->timeout = 0;
+
+	return signal_pending(current);
+}
+    
+static int
+wavefront_wait (wf_config *hw, int mask)
+
+{
+	int             i;
+
+	for (i = 0; i < wf_short_wait_count; i++) {
+		if (wavefront_status(hw) & mask) {
+			return 1;
+		}
+	}
+
+	for (i = 0; i < wf_sleep_tries; i++) {
+
+		if (wavefront_status(hw) & mask) {
+			return 1;
+		}
+
+		if (wavefront_sleep (hw, HZ/wf_sleep_interval)) {
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static int
+wavefront_read (wf_config *hw)
+{
+	if (wavefront_wait (hw, STAT_CAN_READ))
+		return inb (hw->data_port);
+
+	if (hw->debug & WF_DEBUG_DATA) {
+		printk (KERN_DEBUG "WaveFront: read timeout.\n");
+	}
+	return -1;
+}
+
+static int
+wavefront_write (wf_config *hw, unsigned char data)
+{
+	if (wavefront_wait (hw, STAT_CAN_WRITE)) {
+		outb (data, hw->data_port);
+		return 1;
+	}
+
+	if (hw->debug & WF_DEBUG_DATA) {
+		printk (KERN_DEBUG "WaveFront: write timeout.\n");
+	}
+	return 0;
+}
+
+static int
+wavefront_cmd (wf_config *hw, int cmd,
+	       unsigned char *rbuf,
+	       unsigned char *wbuf)
+
+{
+	int ack;
+	int i;
+	int c;
+	wavefront_command *wfcmd;
+
+	if ((wfcmd = wavefront_get_command (cmd)) == (wavefront_command *) 0) {
+		printk (KERN_WARNING "WaveFront: command 0x%x not supported.\n",
+			cmd);
+		return 1;
+	}
+
+	/* Hack to handle the one variable-size write command. See
+	   wavefront_send_multisample() for the other half of this
+	   gross and ugly strategy.
+	*/
+
+	if (cmd == WFC_DOWNLOAD_MULTISAMPLE) {
+		wfcmd->write_cnt = (unsigned int) rbuf;
+		rbuf = 0;
+	}
+
+	if (hw->debug & WF_DEBUG_CMD) {
+		printk (KERN_DEBUG "Wavefront: 0x%x [%s] (%d,%d,%d)\n",
+			cmd, wfcmd->action, wfcmd->read_cnt, wfcmd->write_cnt,
+			wfcmd->need_ack);
+	}
+    
+	if (!wavefront_write (hw, cmd)) { 
+		if (hw->debug & (WF_DEBUG_IO|WF_DEBUG_CMD)) {
+			printk (KERN_DEBUG "WaveFront: cannot request "
+				"0x%x [%s].\n",
+				cmd, wfcmd->action);
+		}
+		return 1;
+	} 
+
+	if (wfcmd->write_cnt > 0) {
+		if (hw->debug & WF_DEBUG_DATA) {
+			printk (KERN_DEBUG "WaveFront: writing %d bytes "
+				"for 0x%x\n",
+				wfcmd->write_cnt, cmd);
+		}
+
+		for (i = 0; i < wfcmd->write_cnt; i++) {
+			if (!wavefront_write (hw, wbuf[i])) {
+				if (hw->debug & WF_DEBUG_IO) {
+					printk (KERN_DEBUG
+                           "WaveFront: bad write for byte %d of 0x%x [%s].\n",
+						i, cmd, wfcmd->action);
+				}
+				return 1;
+			}
+			if (hw->debug & WF_DEBUG_DATA) {
+				printk (KERN_DEBUG
+                                        "WaveFront: write[%d] = 0x%x\n",
+					i, wbuf[i]);
+			}
+		}
+	}
+
+	if (wfcmd->read_cnt > 0) {
+		if (hw->debug & WF_DEBUG_DATA) {
+			printk (KERN_DEBUG "WaveFront: reading %d ints "
+				"for 0x%x\n",
+				wfcmd->read_cnt, cmd);
+		}
+
+		for (i = 0; i < wfcmd->read_cnt; i++) {
+
+			if ((c = wavefront_read(hw)) == -1) {
+				if (hw->debug & WF_DEBUG_IO) {
+					printk (KERN_DEBUG
+                               "WaveFront: bad read for byte %d of 0x%x [%s].\n",
+						i, cmd, wfcmd->action);
+				}
+				return 1;
+			}
+
+			/* Now handle errors. Lots of special cases here */
+	    
+			if (c == 0xff) { 
+				if ((c = wavefront_read (hw)) == -1) {
+					if (hw->debug & WF_DEBUG_IO) {
+						printk (KERN_DEBUG
+                                 "WaveFront: bad read for error byte at "
+                                  "read byte %d of 0x%x [%s].\n",
+							i, cmd, wfcmd->action);
+					}
+					return 1;
+				}
+
+				/* Can you believe this madness ? */
+
+				if (c == 1 &&
+				    wfcmd->cmd == WFC_IDENTIFY_SAMPLE_TYPE) {
+					rbuf[0] = WF_ST_EMPTY;
+					return 0;
+
+				} else if (c == 3 &&
+					   wfcmd->cmd == WFC_UPLOAD_PATCH) {
+
+					return 3;
+
+				} else if (c == 1 &&
+					   wfcmd->cmd == WFC_UPLOAD_PROGRAM) {
+
+					return 1;
+
+				} else {
+
+					if (hw->debug & WF_DEBUG_IO) {
+						printk (KERN_DEBUG
+                                            "WaveFront: error %d (%s) during "
+                                                "read for byte "
+					          "%d of 0x%x [%s].\n",
+							c,
+							wavefront_errorstr (c),
+							i, cmd, wfcmd->action);
+					}
+					return 1;
+
+				}
+			} else {
+				rbuf[i] = c;
+			}
+
+			if (hw->debug & WF_DEBUG_DATA) {
+				printk (KERN_DEBUG
+					"WaveFront: read[%d] = 0x%x\n",
+					i, rbuf[i]);
+			}
+		}
+	}
+
+	if ((wfcmd->read_cnt == 0 && wfcmd->write_cnt == 0) || wfcmd->need_ack) {
+
+		if (hw->debug & WF_DEBUG_CMD) {
+			printk (KERN_DEBUG "WaveFront: reading ACK for 0x%x\n",
+				cmd);
+		}
+
+		/* Some commands need an ACK, but return zero instead
+		   of the standard value.
+		*/
+	    
+		if ((ack = wavefront_read(hw)) == 0) {
+			ack = WF_ACK;
+		}
+	
+		if (ack != WF_ACK) {
+			if (ack == -1) {
+				if (hw->debug & WF_DEBUG_IO) {
+					printk (KERN_DEBUG
+                               "WaveFront: cannot read ack for 0x%x [%s].\n",
+						cmd, wfcmd->action);
+				}
+				return 1;
+		
+			} else {
+				int err = -1; /* something unknown */
+
+				if (ack == 0xff) { /* explicit error */
+		    
+					if ((err = wavefront_read (hw)) == -1) {
+						if (hw->debug & WF_DEBUG_DATA) {
+							printk (KERN_DEBUG
+                               "WaveFront: cannot read err for 0x%x [%s].\n",
+                                                            cmd, wfcmd->action);
+						}
+					}
+				}
+
+				if (hw->debug & WF_DEBUG_IO) {
+					printk (KERN_DEBUG
+						"WaveFront: 0x%x [%s] "
+						"failed (0x%x, 0x%x, %s)\n",
+						cmd, wfcmd->action, ack, err,
+						wavefront_errorstr (err));
+				}
+				return -err;
+			} 
+		}
+
+		if (hw->debug & WF_DEBUG_DATA) {
+			printk (KERN_DEBUG "WaveFront: ack received "
+				"for 0x%x [%s]\n",
+				cmd, wfcmd->action);
+		}
+	} else {
+		if (hw->debug & WF_DEBUG_CMD) {
+			printk (KERN_DEBUG 
+				"Wavefront: 0x%x [%s] does not need "
+				"ACK (%d,%d,%d)\n",
+				cmd, wfcmd->action, wfcmd->read_cnt,
+				wfcmd->write_cnt, wfcmd->need_ack);
+		}
+	}
+
+	return 0;
+	
+}
+
+/***********************************************************************
+WaveFront: data munging   
+
+Things here are wierd. All data written to the board cannot 
+have its most significant bit set. Any data item with values 
+potentially > 0x7F (127) must be split across multiple bytes.
+
+Sometimes, we need to munge numeric values that are represented on
+the x86 side as 8-32 bit values. Sometimes, we need to munge data
+that is represented on the x86 side as an array of bytes. The most
+efficient approach to handling both cases seems to be to use 2
+different functions for munging and 2 for de-munging. This avoids
+wierd casting and worrying about bit-level offsets.
+
+**********************************************************************/
+
+static 
+unsigned char *
+munge_int32 (unsigned int src,
+	     unsigned char *dst,
+	     unsigned int dst_size)
+{
+	int i;
+
+	for (i = 0;i < dst_size; i++) {
+		*dst = src & 0x7F;  /* Mask high bit of LSB */
+		src = src >> 7;     /* Rotate Right 7 bits  */
+	                            /* Note: we leave the upper bits in place */ 
+
+		dst++;
+ 	};
+	return dst;
+};
+
+static int 
+demunge_int32 (unsigned char* src, int src_size)
+
+{
+	int i;
+ 	int outval = 0;
+	
+ 	for (i = src_size - 1; i >= 0; i--) {
+		outval=(outval<<7)+src[i];
+	}
+
+	return outval;
+};
+
+static 
+unsigned char *
+munge_buf (unsigned char *src, unsigned char *dst, unsigned int dst_size)
+
+{
+	int i;
+	unsigned int last = dst_size / 2;
+
+	for (i = 0; i < last; i++) {
+		*dst++ = src[i] & 0x7f;
+		*dst++ = src[i] >> 7;
+	}
+	return dst;
+}
+
+static 
+unsigned char *
+demunge_buf (unsigned char *src, unsigned char *dst, unsigned int src_bytes)
+
+{
+	int i;
+	unsigned char *end = src + src_bytes;
+    
+	end = src + src_bytes;
+
+	/* NOTE: src and dst *CAN* point to the same address */
+
+	for (i = 0; src != end; i++) {
+		dst[i] = *src++;
+		dst[i] |= (*src++)<<7;
+	}
+
+	return dst;
+}
+
+/***********************************************************************
+WaveFront: sample, patch and program management.
+***********************************************************************/
+
+static int
+wavefront_delete_sample (wf_config *hw, int sample_num)
+
+{
+	unsigned char wbuf[2];
+	int x;
+
+	wbuf[0] = sample_num & 0x7f;
+	wbuf[1] = sample_num >> 7;
+
+	if ((x = wavefront_cmd (hw, WFC_DELETE_SAMPLE, 0, wbuf)) == 0) {
+		hw->sample_status[sample_num] = WF_ST_EMPTY;
+	}
+
+	return x;
+}
+
+static int
+wavefront_get_sample_status (struct wf_config *hw, int assume_rom)
+
+{
+	int i;
+	unsigned char rbuf[32], wbuf[32];
+	unsigned int    sc_real, sc_alias, sc_multi;
+
+	/* check sample status */
+    
+	if (wavefront_cmd (hw, WFC_GET_NSAMPLES, rbuf, wbuf)) {
+		printk ("WaveFront: cannot request sample count.\n");
+	} 
+    
+	sc_real = sc_alias = sc_multi = hw->samples_used = 0;
+    
+	for (i = 0; i < WF_MAX_SAMPLE; i++) {
+	
+		wbuf[0] = i & 0x7f;
+		wbuf[1] = i >> 7;
+
+		if (wavefront_cmd (hw, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) {
+			printk (KERN_WARNING
+				"WaveFront: cannot identify sample "
+				"type of slot %d\n", i);
+			hw->sample_status[i] = WF_ST_EMPTY;
+			continue;
+		}
+
+		hw->sample_status[i] = (WF_SLOT_FILLED|rbuf[0]);
+
+		if (assume_rom) {
+			hw->sample_status[i] |= WF_SLOT_ROM;
+		}
+
+		switch (rbuf[0] & WF_ST_MASK) {
+		case WF_ST_SAMPLE:
+			sc_real++;
+			break;
+		case WF_ST_MULTISAMPLE:
+			sc_multi++;
+			break;
+		case WF_ST_ALIAS:
+			sc_alias++;
+			break;
+		case WF_ST_EMPTY:
+			break;
+
+		default:
+			printk (KERN_WARNING
+				"WaveFront: unknown sample type for "
+				"slot %d (0x%x)\n", 
+				i, rbuf[0]);
+		}
+
+		if (rbuf[0] != WF_ST_EMPTY) {
+			hw->samples_used++;
+		} 
+	}
+
+	printk (KERN_INFO
+		"WaveFront: %d samples used (%d real, %d aliases, %d multi), "
+		"%d empty\n", hw->samples_used, sc_real, sc_alias, sc_multi,
+		WF_MAX_SAMPLE - hw->samples_used);
+
+
+	return 0;
+
+}
+
+static int
+wavefront_get_patch_status (struct wf_config *hw)
+{
+	unsigned char patchbuf[WF_PATCH_BYTES];
+	unsigned char patchnum[2];
+	wavefront_patch *p;
+	int i, x, cnt, cnt2;
+
+	for (i = 0; i < WF_MAX_PATCH; i++) {
+		patchnum[0] = i & 0x7f;
+		patchnum[1] = i >> 7;
+
+		if ((x = wavefront_cmd (hw, WFC_UPLOAD_PATCH, patchbuf,
+					patchnum)) == 0) {
+
+			hw->patch_status[i] |= WF_SLOT_FILLED;
+			p = (wavefront_patch *) patchbuf;
+			hw->sample_status
+				[p->sample_number|(p->sample_msb<<7)] |=
+				WF_SLOT_USED;
+	    
+		} else if (x == 3) { /* Bad patch number */
+			hw->patch_status[i] = 0;
+		} else {
+			printk (KERN_ERR "WaveFront: upload patch "
+				"error 0x%x\n", x);
+			hw->patch_status[i] = 0;
+		}
+	}
+
+	/* program status has already filled in slot_used bits */
+
+	for (i = 0, cnt = 0, cnt2 = 0; i < WF_MAX_PATCH; i++) {
+		if (hw->patch_status[i] & WF_SLOT_FILLED) {
+			cnt++;
+		}
+		if (hw->patch_status[i] & WF_SLOT_USED) {
+			cnt2++;
+		}
+	
+	}
+	printk (KERN_INFO
+		"WaveFront: %d patch slots filled, %d in use\n", cnt, cnt2);
+
+	return 0;
+}
+
+static int
+wavefront_get_program_status (struct wf_config *hw)
+{
+	unsigned char progbuf[WF_PROGRAM_BYTES];
+	wavefront_program prog;
+	unsigned char prognum;
+	int i, x, l, cnt;
+
+	for (i = 0; i < WF_MAX_PROGRAM; i++) {
+		prognum = i;
+
+		if ((x = wavefront_cmd (hw, WFC_UPLOAD_PROGRAM, progbuf,
+					&prognum)) == 0) {
+
+			hw->prog_status[i] |= WF_SLOT_USED;
+
+			demunge_buf (progbuf, (unsigned char *) &prog,
+				     WF_PROGRAM_BYTES);
+
+			for (l = 0; l < WF_NUM_LAYERS; l++) {
+				if (prog.layer[l].mute) {
+					hw->patch_status
+						[prog.layer[l].patch_number] |=
+						WF_SLOT_USED;
+				}
+			}
+		} else if (x == 1) { /* Bad program number */
+			hw->prog_status[i] = 0;
+		} else {
+			printk (KERN_ERR "WaveFront: upload program "
+				"error 0x%x\n", x);
+			hw->prog_status[i] = 0;
+		}
+	}
+
+	for (i = 0, cnt = 0; i < WF_MAX_PROGRAM; i++) {
+		if (hw->prog_status[i]) {
+			cnt++;
+		}
+	}
+
+	printk (KERN_INFO "WaveFront: %d programs slots in use\n", cnt);
+
+	return 0;
+}
+
+static int
+wavefront_send_patch (wf_config *hw, 
+		      wavefront_patch_info *header)
+
+{
+	unsigned char buf[WF_PATCH_BYTES+2];
+	unsigned char *bptr;
+
+	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
+		printk (KERN_DEBUG "WaveFront: downloading patch %d\n",
+			header->number);
+	}
+
+	hw->patch_status[header->number] |= WF_SLOT_FILLED;
+
+	bptr = buf;
+	bptr = munge_int32 (header->number, buf, 2);
+	munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES);
+    
+	if (wavefront_cmd (hw, WFC_DOWNLOAD_PATCH, 0, buf)) {
+		printk (KERN_ERR "WaveFront: download patch failed\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int
+wavefront_send_program (wf_config *hw, 
+			wavefront_patch_info *header)
+
+{
+	unsigned char buf[WF_PROGRAM_BYTES+1];
+	int i;
+
+	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
+		printk (KERN_DEBUG
+			"WaveFront: downloading program %d\n", header->number);
+	}
+
+	hw->prog_status[header->number] = WF_SLOT_USED;
+
+	/* XXX need to zero existing SLOT_USED bit for program_status[i]
+	   where `i' is the program that's being (potentially) overwritten.
+	*/
+    
+	for (i = 0; i < WF_NUM_LAYERS; i++) {
+		if (header->hdr.pr.layer[i].mute) {
+			hw->patch_status[header->hdr.pr.layer[i].patch_number] |=
+				WF_SLOT_USED;
+
+			/* XXX need to mark SLOT_USED for sample used by
+			   patch_number, but this means we have to load it. Ick.
+			*/
+		}
+	}
+
+	buf[0] = header->number;
+	munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES);
+    
+	if (wavefront_cmd (hw, WFC_DOWNLOAD_PROGRAM, 0, buf)) {
+		printk (KERN_WARNING "WaveFront: download patch failed\n");	
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int
+wavefront_freemem (wf_config *hw)
+
+{
+	char rbuf[8];
+
+	if (wavefront_cmd (hw, WFC_REPORT_FREE_MEMORY, rbuf, 0)) {
+		printk (KERN_WARNING "WaveFront: can't get memory stats.\n");
+		return -1;
+	} else {
+		return demunge_int32 (rbuf, 4);
+	}
+}
+
+static int
+wavefront_send_sample (wf_config      *hw,
+		       wavefront_patch_info *header,
+		       UINT16 *dataptr,
+		       int data_is_unsigned)
+
+{
+	/* samples are downloaded via a 16-bit wide i/o port
+	   (you could think of it as 2 adjacent 8-bit wide ports
+	   but its less efficient that way). therefore, all
+	   the blocksizes and so forth listed in the documentation,
+	   and used conventionally to refer to sample sizes,
+	   which are given in 8-bit units (bytes), need to be
+	   divided by 2.
+        */
+
+	UINT16 sample_short;
+	UINT32 length;
+	UINT16 *data_end = 0;
+	unsigned int i;
+	const int max_blksize = 4096/2;
+	unsigned int written;
+	unsigned int blocksize;
+	int dma_ack;
+	int blocknum;
+	unsigned char sample_hdr[WF_SAMPLE_HDR_BYTES];
+	unsigned char *shptr;
+	int skip = 0;
+	int initial_skip = 0;
+
+	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
+		printk (KERN_DEBUG "WaveFront: sample %sdownload for slot %d, "
+			"type %d, %d bytes from 0x%x\n",
+			header->size ? "" : "header ", 
+			header->number, header->subkey, header->size,
+			(int) header->dataptr);
+	}
+
+	if (header->size) {
+
+		/* XXX its a debatable point whether or not RDONLY semantics
+		   on the ROM samples should cover just the sample data or
+		   the sample header. For now, it only covers the sample data,
+		   so anyone is free at all times to rewrite sample headers.
+
+		   My reason for this is that we have the sample headers
+		   available in the WFB file for General MIDI, and so these
+		   can always be reset if needed. The sample data, however,
+		   cannot be recovered without a complete reset and firmware
+		   reload of the ICS2115, which is a very expensive operation.
+
+		   So, doing things this way allows us to honor the notion of
+		   "RESETSAMPLES" reasonably cheaply. Note however, that this
+		   is done purely at user level: there is no WFB parser in
+		   this driver, and so a complete reset (back to General MIDI,
+		   or theoretically some other configuration) is the
+		   responsibility of the user level library. 
+
+		   To try to do this in the kernel would be a little crazy:
+		   we'd need 24 * 512 bytes (12K) of kernel space just to
+		   hold copies of the original sample headers; the whole
+		   patch/program/sample header data is about 158K!!!
+		*/
+
+		if (hw->rom_samples_rdonly) {
+			if (hw->sample_status[header->number] & WF_SLOT_ROM) {
+				printk (KERN_ERR "WaveFront: sample slot %d "
+					"write protected\n",
+					header->number);
+				return -EACCES;
+			}
+		}
+
+		wavefront_delete_sample (hw, header->number);
+	}
+
+	if (header->size) {
+		hw->freemem = wavefront_freemem (hw);
+
+		if (hw->freemem < header->size) {
+			printk (KERN_ERR
+				"WaveFront: insufficient memory to "
+				"load %d byte sample.\n",
+				header->size);
+			return -ENOMEM;
+		}
+	
+	}
+
+	skip = WF_GET_CHANNEL(&header->hdr.s);
+
+	if (skip > 0) {
+		switch (header->hdr.s.SampleResolution) {
+		case LINEAR_16BIT:
+			break;
+		default:
+			printk (KERN_ERR
+				"WaveFront: channel selection only possible "
+				"on 16-bit samples");
+			return -EINVAL;
+		}
+	}
+
+	switch (skip) {
+	case 0:
+		initial_skip = 0;
+		skip = 1;
+		break;
+	case 1:
+		initial_skip = 0;
+		skip = 2;
+		break;
+	case 2:
+		initial_skip = 1;
+		skip = 2;
+		break;
+	case 3:
+		initial_skip = 2;
+		skip = 3;
+		break;
+	case 4:
+		initial_skip = 3;
+		skip = 4;
+		break;
+	case 5:
+		initial_skip = 4;
+		skip = 5;
+		break;
+	case 6:
+		initial_skip = 5;
+		skip = 6;
+		break;
+	}
+
+	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
+		printk (KERN_DEBUG "WaveFront: channel selection: %d => "
+			"initial skip = %d, skip = %d\n",
+			WF_GET_CHANNEL (&header->hdr.s), initial_skip, skip);
+	}
+    
+	/* Be safe, and zero the "Unused" bits ... */
+
+	WF_SET_CHANNEL(&header->hdr.s, 0);
+
+	/* adjust size for 16 bit samples by dividing by two.  We always
+	   send 16 bits per write, even for 8 bit samples, so the length
+	   is always half the size of the sample data in bytes.
+	*/
+
+	length = header->size / 2;
+
+	/* the data we're sent has not been munged, and in fact, the
+	   header we have to send isn't just a munged copy either.
+	   so, build the sample header right here.
+	*/
+
+	shptr = &sample_hdr[0];
+
+	shptr = munge_int32 (header->number, shptr, 2);
+
+	if (header->size) {
+		shptr = munge_int32 (length, shptr, 4);
+	}
+
+	/* Yes, a 4 byte result doesn't contain all of the offset bits,
+	   but the offset only uses 24 bits.
+	*/
+
+	shptr = munge_int32 (*((UINT32 *) &header->hdr.s.sampleStartOffset),
+			     shptr, 4);
+	shptr = munge_int32 (*((UINT32 *) &header->hdr.s.loopStartOffset),
+			     shptr, 4);
+	shptr = munge_int32 (*((UINT32 *) &header->hdr.s.loopEndOffset),
+			     shptr, 4);
+	shptr = munge_int32 (*((UINT32 *) &header->hdr.s.sampleEndOffset),
+			     shptr, 4);
+	
+	/* This one is truly wierd. What kind of wierdo decided that in
+	   a system dominated by 16 and 32 bit integers, they would use
+	   a 12 bit transfer size ?
+	*/
+	
+	shptr = munge_int32 (header->hdr.s.FrequencyBias, shptr, 3);
+	
+	/* Why is this nybblified, when the MSB is *always* zero ? 
+	   Anyway, we can't take address of bitfield, so make a
+	   good-faith guess at where it starts.
+	*/
+	
+	shptr = munge_int32 (*(&header->hdr.s.FrequencyBias+1),
+			     shptr, 2);
+
+	if (wavefront_cmd (hw, header->size ?
+			   WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER,
+			   0, sample_hdr)) {
+		printk (KERN_WARNING "WaveFront: sample %sdownload refused.\n",
+			header->size ? "" : "header ");
+		return -EIO;
+	}
+
+	if (header->size == 0) {
+		goto sent; /* Sorry. Just had to have one somewhere */
+	}
+    
+	data_end = dataptr + length;
+
+	/* Do any initial skip over an unused channel's data */
+
+	dataptr += initial_skip;
+    
+	for (written = 0, blocknum = 0;
+	     written < length; written += max_blksize, blocknum++) {
+	
+		if ((length - written) > max_blksize) {
+			blocksize = max_blksize;
+		} else {
+			/* round to nearest 16-byte value */
+			blocksize = ((length-written+7)&~0x7);
+		}
+
+		if (wavefront_cmd (hw, WFC_DOWNLOAD_BLOCK, 0, 0)) {
+			printk (KERN_WARNING "WaveFront: download block "
+				"request refused.\n");
+			return -EIO;
+		}
+
+		for (i = 0; i < blocksize; i++) {
+
+			if (dataptr < data_end) {
+		
+				get_user (sample_short, dataptr);
+				dataptr += skip;
+		
+				if (data_is_unsigned) {
+
+					if (WF_SAMPLE_IS_8BIT(&header->hdr.s)) {
+			
+						/* 8 bit sample
+						 resolution, sign
+						 extend both bytes.
+						*/
+			
+						((unsigned char*)
+						 &sample_short)[0] += 0x7f;
+						((unsigned char*)
+						 &sample_short)[1] += 0x7f;
+			
+					} else {
+			
+						/* 16 bit sample
+						 resolution, sign
+						 extend the MSB.
+						*/
+			
+						sample_short += 0x7fff;
+					}
+				}
+
+			} else {
+
+				/* In padding section of final block:
+
+				   Don't fetch unsupplied data from
+				   user space, just continue with
+				   whatever the final value was.
+				*/
+			}
+	    
+			if (i < blocksize - 1) {
+				outw (sample_short, hw->block_port);
+			} else {
+				outw (sample_short, hw->last_block_port);
+			}
+		}
+
+		/* Get "DMA page acknowledge" */
+	
+		if ((dma_ack = wavefront_read (hw)) != WF_DMA_ACK) {
+			if (dma_ack == -1) {
+				printk (KERN_ERR "WaveFront: upload sample "
+					"DMA ack timeout\n");
+				return -EIO;
+			} else {
+				printk (KERN_ERR "WaveFront: upload sample "
+					"DMA ack error 0x%x\n",
+					dma_ack);
+				return -EIO;
+			}
+		}
+	}
+
+	hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_SAMPLE);
+
+	/* Note, label is here because sending the sample header shouldn't
+	   alter the sample_status info at all.
+	*/
+
+ sent:
+	return 0;
+}
+
+static int
+wavefront_send_alias (struct wf_config *hw, 
+		      wavefront_patch_info *header)
+
+{
+	unsigned char alias_hdr[WF_ALIAS_BYTES];
+
+	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
+		printk (KERN_DEBUG "WaveFront: download alias, %d is "
+			"alias for %d\n",
+			header->number,
+			header->hdr.a.OriginalSample);
+	}
+    
+	munge_int32 (header->number, &alias_hdr[0], 2);
+	munge_int32 (header->hdr.a.OriginalSample, &alias_hdr[2], 2);
+	munge_int32 (*((unsigned int *)&header->hdr.a.sampleStartOffset),
+		     &alias_hdr[4], 4);
+	munge_int32 (*((unsigned int *)&header->hdr.a.loopStartOffset),
+		     &alias_hdr[8], 4);
+	munge_int32 (*((unsigned int *)&header->hdr.a.loopEndOffset),
+		     &alias_hdr[12], 4);
+	munge_int32 (*((unsigned int *)&header->hdr.a.sampleEndOffset),
+		     &alias_hdr[16], 4);
+	munge_int32 (header->hdr.a.FrequencyBias, &alias_hdr[20], 3);
+	munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2);
+
+	if (wavefront_cmd (hw, WFC_DOWNLOAD_SAMPLE_ALIAS, 0, alias_hdr)) {
+		printk (KERN_ERR "WaveFront: download alias failed.\n");
+		return -EIO;
+	}
+
+	hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS);
+
+	return 0;
+}
+
+static int
+wavefront_send_multisample (struct wf_config *hw,
+			    wavefront_patch_info *header)
+{
+	int i;
+	int num_samples;
+	unsigned char msample_hdr[WF_MSAMPLE_BYTES];
+
+	munge_int32 (header->number, &msample_hdr[0], 2);
+
+	/* You'll recall at this point that the "number of samples" value
+	   in a wavefront_multisample struct is actually the log2 of the
+	   real number of samples.
+	*/
+
+	num_samples = (1<<(header->hdr.ms.NumberOfSamples&7));
+	msample_hdr[2] = (unsigned char) header->hdr.ms.NumberOfSamples;
+
+	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
+		printk (KERN_DEBUG "WaveFront: multi %d with %d=%d samples\n",
+			header->number, header->hdr.ms.NumberOfSamples, num_samples);
+	}
+
+	for (i = 0; i < num_samples; i++) {
+		if ((hw->debug & (WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA)) ==
+		    (WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA)) {
+			printk (KERN_DEBUG "WaveFront: sample[%d] = %d\n",
+				i, header->hdr.ms.SampleNumber[i]);
+		}
+		munge_int32 (header->hdr.ms.SampleNumber[i],
+			     &msample_hdr[3+(i*2)], 2);
+	}
+    
+	/* Need a hack here to pass in the number of bytes
+	   to be written to the synth. This is ugly, and perhaps
+	   one day, I'll fix it.
+	*/
+
+	if (wavefront_cmd (hw, WFC_DOWNLOAD_MULTISAMPLE, 
+			   (unsigned char *) ((num_samples*2)+3),
+			   msample_hdr)) {
+		printk (KERN_ERR "WaveFront: download of multisample failed.\n");
+		return -EIO;
+	}
+
+	hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);
+
+	return 0;
+}
+
+static int
+wavefront_fetch_multisample (struct wf_config *hw,
+			     wavefront_patch_info *header)
+{
+	int i;
+	unsigned char log_ns[1];
+	unsigned char number[2];
+	int num_samples;
+
+	munge_int32 (header->number, number, 2);
+    
+	if (wavefront_cmd (hw, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {
+		printk (KERN_ERR "WaveFront: upload multisample failed.\n");
+		return -EIO;
+	}
+    
+	if (hw->debug & WF_DEBUG_DATA) {
+		printk (KERN_DEBUG "WaveFront: msample %d has %d samples\n",
+			header->number, log_ns[0]);
+	}
+
+	header->hdr.ms.NumberOfSamples = log_ns[0];
+
+	/* get the number of samples ... */
+
+	num_samples = (1 << log_ns[0]);
+    
+	for (i = 0; i < num_samples; i++) {
+		char d[2];
+	
+		if ((d[0] = wavefront_read (hw)) == -1) {
+			printk (KERN_ERR "WaveFront: upload multisample failed "
+				"during sample loop.\n");
+			return -EIO;
+		}
+
+		if ((d[1] = wavefront_read (hw)) == -1) {
+			printk (KERN_ERR "WaveFront: upload multisample failed "
+				"during sample loop.\n");
+			return -EIO;
+		}
+	
+		header->hdr.ms.SampleNumber[i] =
+			demunge_int32 ((unsigned char *) d, 2);
+	
+		if (hw->debug & WF_DEBUG_DATA) {
+			printk (KERN_DEBUG "WaveFront: msample "
+				"sample[%d] = %d\n",
+				i, header->hdr.ms.SampleNumber[i]);
+		}
+	}
+
+	return 0;
+}
+
+
+static int
+wavefront_send_drum (struct wf_config *hw, wavefront_patch_info *header)
+
+{
+	unsigned char drumbuf[WF_DRUM_BYTES];
+	wavefront_drum *drum = &header->hdr.d;
+	int i;
+
+	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
+		printk (KERN_DEBUG
+			"WaveFront: downloading edrum for MIDI "
+			"note %d, patch = %d\n", 
+			header->number, drum->PatchNumber);
+	}
+
+	drumbuf[0] = header->number & 0x7f;
+
+	for (i = 0; i < 4; i++) {
+		munge_int32 (((unsigned char *)drum)[i], &drumbuf[1+(i*2)], 2);
+	}
+
+	if (wavefront_cmd (hw, WFC_DOWNLOAD_EDRUM_PROGRAM, 0, drumbuf)) {
+		printk (KERN_ERR "WaveFront: download drum failed.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int 
+wavefront_find_free_sample (struct wf_config *hw)
+
+{
+	int i;
+
+	for (i = 0; i < WF_MAX_SAMPLE; i++) {
+		if (!(hw->sample_status[i] & WF_SLOT_FILLED)) {
+			return i;
+		}
+	}
+	printk (KERN_WARNING "WaveFront: no free sample slots!\n");
+	return -1;
+}
+
+static int 
+wavefront_find_free_patch (struct wf_config *hw)
+
+{
+	int i;
+
+	for (i = 0; i < WF_MAX_SAMPLE; i++) {
+		if (!(hw->patch_status[i] & WF_SLOT_FILLED)) {
+			return i;
+		}
+	}
+	printk (KERN_WARNING "WaveFront: no free patch slots!\n");
+	return -1;
+}
+
+static int 
+log2_2048(int n)
+
+{
+	int tbl[]={0, 0, 2048, 3246, 4096, 4755, 5294, 5749, 6143,
+		   6492, 6803, 7084, 7342, 7578, 7797, 8001, 8192,
+		   8371, 8540, 8699, 8851, 8995, 9132, 9264, 9390,
+		   9510, 9626, 9738, 9845, 9949, 10049, 10146};
+	int i;
+
+	/* Returns 2048*log2(n) */
+
+	/* FIXME: this is like doing integer math
+	   on quantum particles (RuN) */
+
+	i=0;
+	while(n>=32*256) {
+		n>>=8;
+		i+=2048*8;
+	}
+	while(n>=32) {
+		n>>=1;
+		i+=2048;
+	}
+	i+=tbl[n];
+	return(i);
+}
+
+static int
+wavefront_load_gus_patch (struct wf_config *hw,
+			  int dev, int format, const char *addr,
+			  int offs, int count, int pmgr_flag)
+{
+	struct patch_info guspatch;
+	wavefront_patch_info samp, pat, prog;
+	wavefront_patch *patp;
+	wavefront_sample *sampp;
+	wavefront_program *progp;
+
+	int i,base_note;
+	long sizeof_patch;
+
+	/* Copy in the header of the GUS patch */
+
+	sizeof_patch = (long) &guspatch.data[0] - (long) &guspatch; 
+	COPY_FROM_USER (&((char *) &guspatch)[offs],
+			&(addr)[offs], sizeof_patch - offs);
+
+	if ((i = wavefront_find_free_patch (hw)) == -1) {
+		return -EBUSY;
+	}
+	pat.number = i;
+	pat.subkey = WF_ST_PATCH;
+	patp = &pat.hdr.p;
+
+	if ((i = wavefront_find_free_sample (hw)) == -1) {
+		return -EBUSY;
+	}
+	samp.number = i;
+	samp.subkey = WF_ST_SAMPLE;
+	samp.size = guspatch.len;
+	sampp = &samp.hdr.s;
+
+	prog.number = guspatch.instr_no;
+	progp = &prog.hdr.pr;
+
+	/* Setup the patch structure */
+
+	patp->amplitude_bias=guspatch.volume;
+	patp->portamento=0;
+	patp->sample_number= samp.number & 0xff;
+	patp->sample_msb= samp.number>>8;
+	patp->pitch_bend= /*12*/ 0;
+	patp->mono=1;
+	patp->retrigger=1;
+	patp->nohold=(guspatch.mode & WAVE_SUSTAIN_ON) ? 0:1;
+	patp->frequency_bias=0;
+	patp->restart=0;
+	patp->reuse=0;
+	patp->reset_lfo=1;
+	patp->fm_src2=0;
+	patp->fm_src1=WF_MOD_MOD_WHEEL;
+	patp->am_src=WF_MOD_PRESSURE;
+	patp->am_amount=127;
+	patp->fc1_mod_amount=0;
+	patp->fc2_mod_amount=0; 
+	patp->fm_amount1=0;
+	patp->fm_amount2=0;
+	patp->envelope1.attack_level=127;
+	patp->envelope1.decay1_level=127;
+	patp->envelope1.decay2_level=127;
+	patp->envelope1.sustain_level=127;
+	patp->envelope1.release_level=0;
+	patp->envelope2.attack_velocity=127;
+	patp->envelope2.attack_level=127;
+	patp->envelope2.decay1_level=127;
+	patp->envelope2.decay2_level=127;
+	patp->envelope2.sustain_level=127;
+	patp->envelope2.release_level=0;
+	patp->envelope2.attack_velocity=127;
+	patp->randomizer=0;
+
+	/* Program for this patch */
+
+	progp->layer[0].patch_number= pat.number; /* XXX is this right ? */
+	progp->layer[0].mute=1;
+	progp->layer[0].pan_or_mod=1;
+	progp->layer[0].pan=7;
+	progp->layer[0].mix_level=127  /* guspatch.volume */;
+	progp->layer[0].split_type=0;
+	progp->layer[0].split_point=0;
+	progp->layer[0].updown=0;
+
+	for (i = 1; i < 4; i++) {
+		progp->layer[i].mute=0;
+	}
+
+	/* Sample data */
+
+	sampp->SampleResolution=((~guspatch.mode & WAVE_16_BITS)<<1);
+
+	for (base_note=0;
+	     note_to_freq (base_note) < guspatch.base_note;
+	     base_note++);
+
+	if ((guspatch.base_note-note_to_freq(base_note))
+	    >(note_to_freq(base_note)-guspatch.base_note))
+		base_note++;
+
+	printk(KERN_DEBUG "ref freq=%d,base note=%d\n",
+	       guspatch.base_freq,
+	       base_note);
+
+	sampp->FrequencyBias = (29550 - log2_2048(guspatch.base_freq)
+				+ base_note*171);
+	printk(KERN_DEBUG "Freq Bias is %d\n", sampp->FrequencyBias);
+	sampp->Loop=(guspatch.mode & WAVE_LOOPING) ? 1:0;
+	sampp->sampleStartOffset.Fraction=0;
+	sampp->sampleStartOffset.Integer=0;
+	sampp->loopStartOffset.Fraction=0;
+	sampp->loopStartOffset.Integer=guspatch.loop_start
+		>>((guspatch.mode&WAVE_16_BITS) ? 1:0);
+	sampp->loopEndOffset.Fraction=0;
+	sampp->loopEndOffset.Integer=guspatch.loop_end
+		>>((guspatch.mode&WAVE_16_BITS) ? 1:0);
+	sampp->sampleEndOffset.Fraction=0;
+	sampp->sampleEndOffset.Integer=guspatch.len >> (guspatch.mode&1);
+	sampp->Bidirectional=(guspatch.mode&WAVE_BIDIR_LOOP) ? 1:0;
+	sampp->Reverse=(guspatch.mode&WAVE_LOOP_BACK) ? 1:0;
+
+	/* Now ship it down */
+
+	wavefront_send_sample (hw, &samp, 
+			       (unsigned short *) &(addr)[sizeof_patch],
+			       (guspatch.mode & WAVE_UNSIGNED) ? 1:0);
+	wavefront_send_patch (hw, &pat);
+	wavefront_send_program (hw, &prog);
+
+	/* Now pan as best we can ... use the slave/internal MIDI device
+	   number if it exists (since it talks to the WaveFront), or the
+	   master otherwise.
+	*/
+
+#ifdef CONFIG_MIDI
+	if (hw->mididev > 0) {
+		midi_synth_controller (hw->mididev, guspatch.instr_no, 10,
+				       ((guspatch.panning << 4) > 127) ?
+				       127 : (guspatch.panning << 4));
+	}
+#endif CONFIG_MIDI
+
+	return(0);
+}
+
+int
+wavefront_load_patch (int dev, int format, const char *addr,
+		      int offs, int count, int pmgr_flag)
+{
+
+	struct wf_config *hw;
+	wavefront_patch_info header;
+
+	if ((hw = hw_from_dev (dev)) == 0) {
+		return -EINVAL;
+	}
+
+	if (format == SYSEX_PATCH) {	/* Handled by midi_synth.c */
+		if (midi_load_patch == NULL) {
+			printk (KERN_ERR
+				"WaveFront: SYSEX not loadable: "
+				"no midi patch loader!\n");
+			return -EINVAL;
+		}
+		return midi_load_patch (dev, format, addr,
+					offs, count, pmgr_flag);
+
+	} else if (format == GUS_PATCH) {
+		return wavefront_load_gus_patch (hw, dev, format,
+						 addr, offs, count, pmgr_flag);
+
+	} else if (format != WAVEFRONT_PATCH) {
+		printk (KERN_ERR "WaveFront: unknown patch format %d\n", format);
+		return -EINVAL;
+	}
+
+	if (count < sizeof (wavefront_patch_info)) {
+		printk (KERN_ERR "WaveFront: sample header too short\n");
+		return -EINVAL;
+	}
+
+	/* copied in so far: `offs' bytes from `addr'. We shouldn't copy
+	   them in again, and they correspond to header->key and header->devno.
+	   So now, copy the rest of the wavefront_patch_info struct, except
+	   for the 'hdr' field, since this is handled via indirection
+	   through the 'hdrptr' field.
+	*/
+
+	COPY_FROM_USER (&((char *) &header)[offs], &(addr)[offs],
+			sizeof(wavefront_patch_info) -
+			sizeof(wavefront_any) - offs);
+
+	if (hw->debug & WF_DEBUG_LOAD_PATCH) {
+		printk (KERN_DEBUG "WaveFront: download "
+			"Sample type: %d "
+			"Sample number: %d "
+			"Sample size: %d\n",
+			header.subkey,
+			header.number,
+			header.size);
+	}
+
+	switch (header.subkey) {
+	case WF_ST_SAMPLE:  /* sample or sample_header, based on patch->size */
+
+		COPY_FROM_USER ((unsigned char *) &header.hdr.s,
+				(unsigned char *) header.hdrptr,
+				sizeof (wavefront_sample));
+
+		return wavefront_send_sample (hw, &header, header.dataptr, 0);
+
+	case WF_ST_MULTISAMPLE:
+
+		COPY_FROM_USER ((unsigned char *) &header.hdr.s,
+				(unsigned char *) header.hdrptr,
+				sizeof (wavefront_multisample));
+
+		return wavefront_send_multisample (hw, &header);
+
+
+	case WF_ST_ALIAS:
+
+		COPY_FROM_USER ((unsigned char *) &header.hdr.a,
+				(unsigned char *) header.hdrptr,
+				sizeof (wavefront_alias));
+
+		return wavefront_send_alias (hw, &header);
+
+	case WF_ST_DRUM:
+		COPY_FROM_USER ((unsigned char *) &header.hdr.d, 
+				(unsigned char *) header.hdrptr,
+				sizeof (wavefront_drum));
+
+		return wavefront_send_drum (hw, &header);
+
+	case WF_ST_PATCH:
+		COPY_FROM_USER ((unsigned char *) &header.hdr.p, 
+				(unsigned char *) header.hdrptr,
+				sizeof (wavefront_patch));
+
+		return wavefront_send_patch (hw, &header);
+
+	case WF_ST_PROGRAM:
+		COPY_FROM_USER ((unsigned char *) &header.hdr.pr, 
+				(unsigned char *) header.hdrptr,
+				sizeof (wavefront_program));
+
+		return wavefront_send_program (hw, &header);
+
+	default:
+		printk (KERN_ERR "WaveFront: unknown patch type %d.\n",
+			header.subkey);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/***********************************************************************
+WaveFront: /dev/sequencer{,2} and other hardware-dependent interfaces
+***********************************************************************/
+
+static void
+process_sample_hdr (UCHAR8 *buf)
+
+{
+	wavefront_sample s;
+	UCHAR8 *ptr;
+
+	ptr = buf;
+
+	/* The board doesn't send us an exact copy of a "wavefront_sample"
+	   in response to an Upload Sample Header command. Instead, we 
+	   have to convert the data format back into our data structure,
+	   just as in the Download Sample command, where we have to do
+	   something very similar in the reverse direction.
+	*/
+
+	*((UINT32 *) &s.sampleStartOffset) = demunge_int32 (ptr, 4); ptr += 4;
+	*((UINT32 *) &s.loopStartOffset) = demunge_int32 (ptr, 4); ptr += 4;
+	*((UINT32 *) &s.loopEndOffset) = demunge_int32 (ptr, 4); ptr += 4;
+	*((UINT32 *) &s.sampleEndOffset) = demunge_int32 (ptr, 4); ptr += 4;
+	*((UINT32 *) &s.FrequencyBias) = demunge_int32 (ptr, 3); ptr += 3;
+
+	s.SampleResolution = *ptr & 0x3;
+	s.Loop = *ptr & 0x8;
+	s.Bidirectional = *ptr & 0x10;
+	s.Reverse = *ptr & 0x40;
+
+	/* Now copy it back to where it came from */
+
+	memcpy (buf, (unsigned char *) &s, sizeof (wavefront_sample));
+}
+
+static int
+wavefront_synth_control (int dev, int cmd, caddr_t arg)
+
+{
+	struct wf_config *hw;
+	wavefront_control wc;
+	unsigned char patchnumbuf[2];
+	int i;
+
+	if ((hw = hw_from_dev (dev)) == 0) {
+		printk (KERN_ERR
+			"WaveFront: synth_control with unknown "
+			"device number %d\n", dev);
+		return -EINVAL;
+	}
+
+	COPY_FROM_USER (&wc, arg, sizeof (wc));
+
+	if (hw->debug & WF_DEBUG_CMD) {
+		printk (KERN_DEBUG "WaveFront: synth control with "
+			"cmd 0x%x\n", wc.cmd);
+	}
+
+	/* special case handling of or for various commands */
+
+	switch (wc.cmd) {
+	case WFC_DISABLE_INTERRUPTS:
+		printk (KERN_INFO "WaveFront: interrupts disabled.\n");
+		outb (0x80|0x20, hw->control_port);
+		hw->interrupts_on = 0;
+		return 0;
+
+	case WFC_ENABLE_INTERRUPTS:
+		printk (KERN_INFO "WaveFront: interrupts enabled.\n");
+		outb (0x80|0x20|0x40, hw->control_port);
+		hw->interrupts_on = 1;
+		return 0;
+
+	case WFC_INTERRUPT_STATUS:
+		wc.rbuf[0] = hw->interrupts_on;
+		return 0;
+
+	case WFC_ROMSAMPLES_RDONLY:
+		hw->rom_samples_rdonly = wc.wbuf[0];
+		wc.status = 0;
+		return 0;
+
+	case WFC_IDENTIFY_SLOT_TYPE:
+		i = wc.wbuf[0] | (wc.wbuf[1] << 7);
+		if (i <0 || i >= WF_MAX_SAMPLE) {
+			printk (KERN_WARNING "WaveFront: invalid slot ID %d\n",
+				i);
+			wc.status = EINVAL;
+			return 0;
+		}
+		wc.rbuf[0] = hw->sample_status[i];
+		wc.status = 0;
+		return 0;
+
+	case WFC_DEBUG_DRIVER:
+		hw->debug = wc.wbuf[0];
+		printk (KERN_INFO "WaveFront: debug = 0x%x\n", hw->debug);
+		return 0;
+
+	case WFC_FX_IOCTL:
+		wffx_ioctl (hw, (wavefront_fx_info *) &wc.wbuf[0]);
+		return 0;
+
+	case WFC_UPLOAD_PATCH:
+		munge_int32 (*((UINT32 *) wc.wbuf), patchnumbuf, 2);
+		memcpy (wc.wbuf, patchnumbuf, 2);
+		break;
+
+	case WFC_UPLOAD_MULTISAMPLE:
+	case WFC_UPLOAD_SAMPLE_ALIAS:
+		printk (KERN_INFO "WaveFront: support for various uploads "
+			"being considered.\n");
+		wc.status = EINVAL;
+		return -EINVAL;
+	}
+
+	wc.status = wavefront_cmd (hw, wc.cmd, wc.rbuf, wc.wbuf);
+
+	/* Special case handling of certain commands.
+
+	   In particular, if the command was an upload, demunge the data
+	   so that the user-level doesn't have to think about it.
+	*/
+
+	if (wc.status == 0) {
+		switch (wc.cmd) {
+			/* intercept any freemem requests so that we know
+			   we are always current with the user-level view
+			   of things.
+			*/
+
+		case WFC_REPORT_FREE_MEMORY:
+			hw->freemem = demunge_int32 (wc.rbuf, 4);
+			break;
+
+		case WFC_UPLOAD_PATCH:
+			demunge_buf (wc.rbuf, wc.rbuf, WF_PATCH_BYTES);
+			break;
+
+		case WFC_UPLOAD_PROGRAM:
+			demunge_buf (wc.rbuf, wc.rbuf, WF_PROGRAM_BYTES);
+			break;
+
+		case WFC_UPLOAD_EDRUM_PROGRAM:
+			demunge_buf (wc.rbuf, wc.rbuf, WF_DRUM_BYTES - 1);
+			break;
+
+		case WFC_UPLOAD_SAMPLE_HEADER:
+			process_sample_hdr (wc.rbuf);
+			break;
+
+		case WFC_UPLOAD_MULTISAMPLE:
+		case WFC_UPLOAD_SAMPLE_ALIAS:
+			printk (KERN_INFO "WaveFront: support for "
+				"various uploads "
+				"being considered.\n");
+			break;
+
+		case WFC_VMIDI_OFF:
+			virtual_midi_disable (hw->mididev);
+			break;
+
+		case WFC_VMIDI_ON:
+			virtual_midi_enable (hw->mididev, 0);
+			break;
+
+			break;
+		}
+	}
+
+	/* XXX It would be nice to avoid a complete copy of the whole
+	   struct sometimes. But I think its fast enough that this
+	   is a low priority fix.
+	*/
+
+	COPY_TO_USER (arg, &wc, sizeof (wc));
+	return 0;
+}
+
+
+/***********************************************************************
+WaveFront: MIDI synth interface
+***********************************************************************/
+
+
+static int
+wavefront_ioctl (int dev, unsigned int cmd, caddr_t arg)
+{
+	wf_config *hw;
+	unsigned char rbuf[4];
+
+	if ((hw = hw_from_dev (dev)) == 0) {
+		return -EINVAL;
+	}
+
+	switch (cmd) {
+	case SNDCTL_SYNTH_INFO:
+		memcpy (&((char *) arg)[0], &wavefront_info,
+			sizeof (wavefront_info));
+		return 0;
+		break;
+
+	case SNDCTL_SEQ_RESETSAMPLES:
+		printk (KERN_WARNING
+			"WaveFront: cannot reset sample status in kernel.\n");
+		return 0; /* don't force an error */
+		break;
+
+	case SNDCTL_SEQ_PERCMODE:
+		/* XXX does this correspond to anything obvious ?*/
+		return 0; /* don't force an error */
+		break;
+
+	case SNDCTL_SYNTH_MEMAVL:
+		if (wavefront_cmd (hw, WFC_REPORT_FREE_MEMORY, rbuf, 0) != 0) {
+			printk (KERN_ERR
+				"WaveFront: cannot get free memory size\n");
+			return 0;
+		} else {
+			hw->freemem = demunge_int32 (rbuf, 4);
+			return hw->freemem;
+		}
+
+	case SNDCTL_SYNTH_CONTROL:
+		return wavefront_synth_control (dev, cmd, arg);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int
+wavefront_open (int dev, int mode)
+
+{
+	struct wf_config *hw;
+
+	if ((hw = hw_from_dev (dev)) == 0) {
+		return -EINVAL;
+	}
+
+	if (hw->opened) {
+		printk (KERN_ERR "WaveFront: warning: device in use\n");
+	}
+
+	hw->opened = mode;
+	return 0;
+}
+
+static void
+wavefront_close (int dev)
+
+{
+	struct wf_config *hw;
+
+	if ((hw = hw_from_dev (dev)) == 0) {
+		printk (KERN_ERR
+			"WaveFront: close() called on non-existent dev %d", dev);
+		return;
+	}
+
+	hw->opened = 0;
+	hw->debug = 0;
+
+	return;
+}
+
+static void
+wavefront_aftertouch (int dev, int channel, int pressure)
+{
+	struct wf_config *hw = hw_from_dev (dev);
+	if (!hw) return;
+	midi_synth_aftertouch (hw->mididev,channel,pressure);
+};
+
+static void
+wavefront_bender (int dev, int chn, int value)
+{
+	struct wf_config *hw = hw_from_dev (dev);
+	if (!hw) return;
+	midi_synth_bender (hw->mididev, chn, value);
+};
+
+static void
+wavefront_controller (int dev, int channel, int ctrl_num, int value)
+{
+	struct wf_config *hw = hw_from_dev (dev);
+	if (!hw) return;
+	if(ctrl_num==CTRL_PITCH_BENDER) wavefront_bender(0,channel,value);
+	midi_synth_controller (hw->mididev, channel,ctrl_num,value);
+};
+
+static void
+wavefront_panning(int dev, int channel, int pressure)
+{
+	struct wf_config *hw = hw_from_dev (dev);
+	if (!hw) return;
+	midi_synth_controller(hw->mididev,channel,CTL_PAN,pressure);
+};
+
+static int
+wavefront_set_instr (int dev, int channel, int instr_no)
+{
+	struct wf_config *hw = hw_from_dev (dev);
+	if (!hw) return 1;
+	return(midi_synth_set_instr(hw->mididev,channel,instr_no));
+};
+
+static int
+wavefront_kill_note (int dev, int channel, int note, int volume)
+{
+	struct wf_config *hw = hw_from_dev (dev);
+	if (!hw) return 1;
+	if (note==255)
+		return(midi_synth_start_note(hw->mididev, channel, 0, 0));
+	return(midi_synth_kill_note(hw->mididev, channel, note, volume));
+};
+
+static int
+wavefront_start_note (int dev, int channel, int note, int volume)
+{
+	struct wf_config *hw = hw_from_dev (dev);
+	if (!hw) return 1;
+
+	if (note==255) {
+		/*midi_synth_controller(hw->mididev,channel,7,volume);*/
+		midi_synth_aftertouch(hw->mididev,channel,volume); 
+		return(0);
+	};
+	if (volume==0) {
+		volume=127;
+		midi_synth_aftertouch(hw->mididev,channel,0);
+	};
+	midi_synth_start_note (hw->mididev, channel, note, volume);
+	return(0);
+};
+
+static void
+wavefront_setup_voice (int dev, int voice, int chn)
+{
+};
+
+static void wavefront_reset (int dev)
+
+{
+	int i;
+	for(i=0;i<16;i++) {
+		midi_synth_kill_note (dev,i,0,0);
+	};
+};
+
+static struct synth_operations wavefront_operations =
+{
+	"WaveFront",
+	&wavefront_info,
+	0,
+	SYNTH_TYPE_SAMPLE,
+	SAMPLE_TYPE_WAVEFRONT,
+	wavefront_open,
+	wavefront_close,
+	wavefront_ioctl,
+	wavefront_kill_note,
+	wavefront_start_note,
+	wavefront_set_instr,
+	wavefront_reset,
+	NULL,
+	wavefront_load_patch,
+	wavefront_aftertouch,
+	wavefront_controller,
+	wavefront_panning,
+	NULL,
+	wavefront_bender,
+	NULL,
+	wavefront_setup_voice
+};
+
+
+/***********************************************************************
+WaveFront: OSS/Free and/or Linux kernel installation interface
+***********************************************************************/
+
+void
+wavefrontintr (int irq, void *dev_id, struct pt_regs *dummy)
+{
+	int i;
+
+	if (irq < 0 || irq > 16) {
+		printk (KERN_WARNING "WaveFront: bogus interrupt %d recv'd\n",
+			irq);
+	} else if ((i = irq2hw[irq]) == -1) {
+		printk (KERN_ALERT
+			"WaveFront: interrupt from unknown hw (irq=%d).\n", irq);
+	} else {
+		wfs[i].irq_ok = 1;
+	}
+}
+
+/* STATUS REGISTER 
+
+0 Host Rx Interrupt Enable (1=Enabled)
+1 Host Rx Register Full (1=Full)
+2 Host Rx Interrupt Pending (1=Interrupt)
+3 Unused
+4 Host Tx Interrupt (1=Enabled)
+5 Host Tx Register empty (1=Empty)
+6 Host Tx Interrupt Pending (1=Interrupt)
+7 Unused
+
+*/
+
+/* CONTROL REGISTER
+0 Host Rx Interrupt Enable (1=Enabled)      0x1
+1 Unused                                    0x2
+2 Unused                                    0x4
+3 Unused                                    0x8
+4 Host Tx Interrupt Enable                 0x10
+5 Mute (0=Mute; 1=Play)                    0x20
+6 Master Interrupt Enable (1=Enabled)      0x40
+7 Master Reset (0=Reset; 1=Run)            0x80
+*/
+
+int
+probe_wavefront (struct address_info *hw_config)
+
+{
+	int             i;
+	int             tmp1, tmp2;
+	unsigned char   bits;
+	unsigned char   rbuf[32], wbuf[32];
+	wf_config       *hw;
+
+	if (hw_config->irq < 0 || hw_config->irq > 16) {
+	    printk (KERN_WARNING "WaveFront: impossible IRQ suggested(%d)\n", 
+		    hw_config->irq);
+	    return 0;
+	}
+  
+	/* Yeah yeah, TB docs say 8, but the FX device on the Tropez Plus
+	   takes up another 8 ...
+	*/
+
+	if (check_region (hw_config->io_base, 16)) {
+		printk (KERN_ERR "WaveFront: IO address range 0x%x - 0x%x "
+			"already in use - ignored\n", hw_config->io_base,
+			hw_config->io_base+15);
+		return 0;
+	}
+  
+	for (i = 0; i < WAVEFRONT_MAX_DEVICES; i++) {
+		if (!wfs[i].installed) {
+			wfs[i].installed = 1;
+			break;
+		}
+	}
+
+	if (i == WAVEFRONT_MAX_DEVICES) {
+		printk (KERN_WARNING "WaveFront: no device slots available (max = %d).\n",
+			WAVEFRONT_MAX_DEVICES);
+		return 0;
+	}
+  
+	hw = &wfs[i];
+
+	hw->irq = hw_config->irq;
+	hw->base = hw_config->io_base;
+
+	hw->israw = 0;
+	hw->debug = wf_debug_default;
+	hw->interrupts_on = 0;
+	hw->rom_samples_rdonly = 1; /* XXX default lock on ROM sample slots */
+
+	hw_config->slots[WF_SYNTH_SLOT] = hw->synthdev = -1;
+	hw_config->slots[WF_INTERNAL_MIDI_SLOT] = hw->mididev = -1;
+	hw_config->slots[WF_EXTERNAL_MIDI_SLOT] = hw->ext_mididev = -1;
+
+	irq2hw[hw_config->irq] = i;
+  
+	if (wavefront_cmd (hw, WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) {
+		hw->fw_version[0] = rbuf[0];
+		hw->fw_version[1] = rbuf[1];
+		printk (KERN_INFO "WaveFront: firmware %d.%d already loaded.\n",
+			rbuf[0], rbuf[1]);
+      
+		if (wavefront_cmd (hw, WFC_HARDWARE_VERSION, rbuf, wbuf) == 0) {
+			hw->hw_version[0] = rbuf[0];
+			hw->hw_version[1] = rbuf[1];
+		} else {
+			printk (KERN_INFO "WaveFront: not raw, but no hardware version!\n");
+			return 0;
+		}
+		if (!wf_raw) {
+			return 1;
+		}
+	} else {
+		hw->israw = 1;
+		printk (KERN_INFO
+			"WaveFront: no response to firmware probe, "
+			"assume raw.\n");
+	}
+
+	if (request_irq (hw_config->irq, wavefrontintr,
+			 0, "WaveFront", NULL) < 0) {
+		printk (KERN_WARNING "WaveFront: IRQ %d not available!\n",
+			hw_config->irq);
+		return 0;
+	}
+
+	switch (hw_config->irq) {
+	case 9:
+		bits = 0x00;
+		break;
+	case 5:
+		bits = 0x08;
+		break;
+	case 12:
+		bits = 0x10;
+		break;
+	case 15:
+		bits = 0x18;
+		break;
+	
+	default:
+		printk (KERN_WARNING "WaveFront: invalid IRQ %d\n",
+			hw_config->irq);
+		return 0;
+	}
+  
+	/* try reset of port */
+      
+	outb (0x0, hw->control_port); 
+  
+	/* At this point, the board is in reset, and the H/W initialization
+	   register is accessed at the same address as the data port.
+     
+	   Bit 7 - Enable IRQ Driver	
+	   0 - Tri-state the Wave-Board drivers for the PC Bus IRQs
+	   1 - Enable IRQ selected by bits 5:3 to be driven onto the PC Bus.
+     
+	   Bit 6 - MIDI Interface Select
+
+	   XXX PBD: I think this documentation is backwards. I leave bit
+	   6 unset, and get MIDI data from the 9 pin D connector.
+
+	   0 - Use the MIDI Input from the 26-pin WaveBlaster
+	   compatible header as the serial MIDI source
+	   1 - Use the MIDI Input from the 9-pin D connector as the serial MIDI 
+	   source.
+     
+	   Bits 5:3 - IRQ Selection
+	   0 0 0 - IRQ 2/9
+	   0 0 1 - IRQ 5
+	   0 1 0 - IRQ 12
+	   0 1 1 - IRQ 15
+	   1 0 0 - Reserved
+	   1 0 1 - Reserved
+	   1 1 0 - Reserved
+	   1 1 1 - Reserved
+     
+	   Bits 2:1 - Reserved
+	   Bit 0 - Disable Boot ROM
+	   0 - memory accesses to 03FC30-03FFFFH utilize the internal Boot ROM
+	   1 - memory accesses to 03FC30-03FFFFH are directed to external 
+	   storage.
+     
+	*/
+
+	/* configure hardware: IRQ, plus external MIDI interface selected */
+  
+	outb (bits | 0x80, hw->data_port);	
+  
+	/* take us out of reset, unmute, master + TX + RX interrupts on */
+  
+	outb (0x80|0x20|0x40|0x10|0x1, hw->control_port);
+  
+	for (i = 0; i < 1000000 && !hw->irq_ok; i++);
+  
+	/* Data port is now the data port, not the h/w initialization port 
+     
+	   The boot ROM will check the OSRAM, and will then
+	   wait for the either the "download OS" or
+	   "report h/w version" commands.
+
+	   Any other command will supposedly be ignored.
+	*/
+  
+	if (!hw->irq_ok) {
+		printk (KERN_WARNING
+			"WaveFront: intr not received after h/w un-reset.\n");
+		free_irq (hw_config->irq, NULL);
+		return 0;
+	} else {
+		hw->irq_ok = 0;
+	}
+
+	hw->interrupts_on = 1;
+
+	/* WaveFront SDK says:
+     
+	   "When the Master Reset is set to zero (0), the audio board is held
+	   in reset, which is the power-up condition. Setting Master Reset to one
+	   (1) allows the on-board processor to run. It takes approximately two
+	   to four seconds, depending on the memory configuration, for the
+	   on-board processor to complete it's initialization routine before it
+	   will respond to commands after a reset."
+
+	   Actually, it seems that most of the time, even with 8MB of RAM,
+	   its actually ready immediately.
+	*/
+
+	if (!wavefront_wait (hw, STAT_CAN_WRITE)) {
+		if (!wavefront_wait (hw, STAT_CAN_WRITE)) {
+			if (!wavefront_wait (hw, STAT_CAN_WRITE)) {
+				printk (KERN_WARNING
+					"WaveFront: OS not ready after "
+					"memory check.\n");
+				free_irq (hw_config->irq, NULL);
+				return 0;
+			}
+		}
+	}
+
+	/* get H/W version, and check we get an interrupt */
+  
+	outb (WFC_HARDWARE_VERSION, hw->data_port);
+  
+	for (i = 0; i < 1000000 && !hw->irq_ok; i++);
+  
+	/* We don't need the IRQ anymore for the WaveFront code,
+	   and to allow an MPU-401 driver to attach to it later, lets
+	   give it back ....
+
+	   DO NOT alter irq2hw[], since we'll still use this to lookup
+	   the config struct from an address_info struct.
+	*/
+
+	free_irq (hw_config->irq, NULL);
+
+	if (!hw->irq_ok) {
+		printk (KERN_WARNING
+			"WaveFront: interrupt not received after "
+			"h/w version cmd.\n");
+		return 0;
+	} else {
+		hw->irq_ok = 0;
+	}
+  
+	if ((tmp1 = wavefront_read(hw)) == -1) {
+		printk (KERN_WARNING
+			"WaveFront @ 0x%x not ready, ignoring\n", hw->base);
+		return 0;
+	}
+  
+	if ((tmp2 = wavefront_read(hw)) == -1) {
+		printk (KERN_WARNING
+			"WaveFront @ 0x%x not responding correctly, ignoring\n",
+			hw->base);
+		return 0;
+	}
+  
+	printk (KERN_INFO "WaveFront: hardware version %d.%d\n", tmp1, tmp2);
+  
+	return 1;
+}
+
+#include "os.h"
+#define __KERNEL_SYSCALLS__
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/unistd.h>
+#include <asm/uaccess.h>
+
+static int errno; 
+
+static int
+wavefront_download_firmware (wf_config *hw, char *path)
+
+{
+	unsigned char section[WF_SECTION_MAX];
+	char section_length; /* yes, just a char; max value is WF_SECTION_MAX */
+	int section_cnt_downloaded = 0;
+	int fd;
+	int c;
+	int i;
+	mm_segment_t fs;
+
+	/* This tries to be a bit cleverer than the stuff Alan Cox did for
+	   the generic sound firmware, in that it actually knows
+	   something about the structure of the Motorola firmware. In
+	   particular, it uses a version that has been stripped of the
+	   20K of useless header information, and had section lengths
+	   added, making it possible to load the entire OS without any
+	   [kv]malloc() activity, since the longest entity we ever read is
+	   42 bytes (well, WF_SECTION_MAX) long.
+	*/
+
+	fs = get_fs();
+	set_fs (get_ds());
+
+	if ((fd = open (path, 0, 0)) < 0) {
+		printk (KERN_WARNING "WaveFront: Unable to load \"%s\".\n", path);
+		return 1;
+	}
+
+	while (1) {
+		int x;
+
+		if ((x = read (fd, &section_length, sizeof (section_length))) !=
+		    sizeof (section_length)) {
+			printk (KERN_ERR "WaveFront: firmware read error.\n");
+			goto failure;
+		}
+
+		if (section_length == 0) {
+			break;
+		}
+
+		if (read (fd, section, section_length) != section_length) {
+			printk (KERN_ERR "WaveFront: firmware section "
+				"read error.\n");
+			goto failure;
+		}
+
+		/* Send command */
+	
+		if (!wavefront_write (hw, WFC_DOWNLOAD_OS)) {
+			goto failure;
+		}
+	
+		for (i = 0; i < section_length; i++) {
+			if (!wavefront_write (hw, section[i])) {
+				goto failure;
+			}
+		}
+	
+		/* get ACK */
+	
+		if (wavefront_wait (hw, STAT_CAN_READ)) {
+
+			if ((c = inb (hw->data_port)) != WF_ACK) {
+
+				printk (KERN_ERR "WaveFront: download "
+					"of section #%d not "
+					"acknowledged, ack = 0x%x\n",
+					section_cnt_downloaded + 1, c);
+				goto failure;
+		
+			} else if ((hw->debug & WF_DEBUG_IO) &&
+				   !(++section_cnt_downloaded % 10)) {
+				printk (KERN_DEBUG ".");
+			}
+
+		} else {
+			printk (KERN_ERR "WaveFront: timed out "
+				"for download ACK.\n");
+		}
+
+	}
+
+	close (fd);
+	set_fs (fs);
+	if (hw->debug & WF_DEBUG_IO) {
+		printk (KERN_DEBUG "\n");
+	}
+	return 0;
+
+ failure:
+	close (fd);
+	set_fs (fs);
+	printk (KERN_ERR "\nWaveFront: firmware download failed!!!\n");
+	return 1;
+}
+
+static int
+wavefront_config_midi (wf_config *hw, struct address_info *hw_config)
+
+{
+	unsigned char rbuf[4], wbuf[4];
+    
+	if (!probe_wf_mpu (hw_config)) {
+		printk (KERN_WARNING "WaveFront: could not install "
+			"MPU-401 device.\n");
+		return 1;
+	} 
+
+	/* Attach an modified MPU-401 driver to the master MIDI interface */
+
+	hw_config->name = "WaveFront Internal MIDI";
+	attach_wf_mpu (hw_config);
+
+	if (hw_config->slots[WF_INTERNAL_MIDI_SLOT] == -1) {
+		printk (KERN_WARNING "WaveFront: MPU-401 not configured.\n");
+		return 1;
+	}
+
+	hw->mididev = hw_config->slots[WF_INTERNAL_MIDI_SLOT];
+
+	/* Route external MIDI to WaveFront synth (by default) */
+    
+	if (wavefront_cmd (hw, WFC_MISYNTH_ON, rbuf, wbuf)) {
+		printk (KERN_WARNING
+			"WaveFront: cannot enable MIDI-IN to synth routing.\n");
+		/* XXX error ? */
+	}
+
+	/* Get the regular MIDI patch loading function, so we can
+	   use it if we ever get handed a SYSEX patch. This is
+	   unlikely, because its so damn slow, but we may as well
+	   leave this functionality from maui.c behind, since it
+	   could be useful for sequencer applications that can
+	   only use MIDI to do patch loading.
+	*/
+
+	if (midi_devs[hw->mididev]->converter != NULL) {
+		midi_load_patch = midi_devs[hw->mididev]->converter->load_patch;
+		midi_devs[hw->mididev]->converter->load_patch =
+		    &wavefront_load_patch;
+	}
+
+	/* Turn on Virtual MIDI, but first *always* turn it off,
+	   since otherwise consectutive reloads of the driver will
+	   never cause the hardware to generate the initial "internal" or 
+	   "external" source bytes in the MIDI data stream. This
+	   is pretty important, since the internal hardware generally will
+	   be used to generate none or very little MIDI output, and
+	   thus the only source of MIDI data is actually external. Without
+	   the switch bytes, the driver will think it all comes from
+	   the internal interface. Duh.
+	*/
+
+	if (wavefront_cmd (hw, WFC_VMIDI_OFF, rbuf, wbuf)) { 
+		printk (KERN_WARNING "WaveFront: cannot disable "
+			"virtual MIDI mode\n");
+		/* XXX go ahead and try anyway ? */
+	}
+
+	hw_config->name = "WaveFront External MIDI";
+    
+	if (virtual_midi_enable (hw->mididev, hw_config)) {
+		printk (KERN_WARNING "WaveFront: no virtual MIDI access.\n");
+	} else {
+		hw->ext_mididev = hw_config->slots[WF_EXTERNAL_MIDI_SLOT];
+		if (wavefront_cmd (hw, WFC_VMIDI_ON, rbuf, wbuf)) {
+			printk (KERN_WARNING
+				"WaveFront: cannot enable virtual MIDI mode.\n");
+			virtual_midi_disable (hw->mididev);
+		} 
+	}
+    
+	return 0;
+}
+
+static int
+wavefront_init (wf_config *hw, struct address_info *hw_config)
+
+{
+	int samples_are_from_rom = 0;
+
+	/* XXX what state does the board need to be in before
+	   I can download the firmware ? I think any state
+	   after it acknowledges a hardware version command
+	   post-booting.
+	*/
+
+	if (hw->israw || wf_raw) {
+		samples_are_from_rom = 1;
+
+		if (wavefront_download_firmware (hw, wf_ospath)) {
+			return 1;
+		}
+    
+		/* enter normal operation:
+		   bit 7: (on) reset  0x80
+		   bit 6: interrupts enabled 0x40
+		   bit 5: (on) mute (i.e. in play mode) 0x20
+		   bits 4-0: zero
+	   
+		   note: tx and rx interrupts turned off
+		*/
+	
+		outb (0x80|0x40|0x20, hw->control_port);
+	
+		/* Set up MPU-401 emulation mode.  For some reason, this always
+		   fails the first time, and generates no ACK, so we'll
+		   treat it as a special case by sleeping for a while, and then
+		   trying again.
+		*/
+	
+		wavefront_write (hw, 0xf0);
+		wavefront_write (hw, 1);
+		wavefront_sleep (hw, (HZ/wf_sleep_interval) * wf_sleep_tries);
+		wavefront_write (hw, 0xf0);
+		wavefront_write (hw, 1);
+		if (wavefront_read (hw) != 0x80) {
+			printk (KERN_ERR
+				"WaveFront: set MPU emulation mode "
+				"command failed.\n");
+			return (1);
+		}
+	}
+
+	hw->freemem = wavefront_freemem (hw);
+	printk (KERN_INFO "WaveFront: available DRAM %dk\n", hw->freemem / 1024);
+    
+	wavefront_get_sample_status (hw, samples_are_from_rom);
+	wavefront_get_program_status (hw);
+	wavefront_get_patch_status (hw);
+
+	if (fx_raw) {
+		wffx_init (hw);
+	}
+    
+	return 0;
+}
+
+void
+attach_wavefront (struct address_info *hw_config)
+{
+	int i;
+	struct wf_config *hw;
+
+	if ((i = irq2hw[hw_config->irq]) == -1) {
+		printk (KERN_ERR "WaveFront: cannot attach unknown irq 0x%x.\n",
+			hw_config->irq);
+		return;
+	}
+
+	hw = &wfs[i];
+
+	if ((i = sound_alloc_synthdev()) == -1) {
+		printk (KERN_ERR "WaveFront: Too many synthesizers\n");
+		return;
+	} else {
+		hw_config->slots[WF_SYNTH_SLOT] = i;
+		hw->synthdev = i;
+		dev2hw[hw->synthdev] = i;
+		synth_devs[hw->synthdev] = &wavefront_operations;
+	}
+
+	if (wavefront_init (hw, hw_config)) {
+		printk (KERN_WARNING "WaveFront: board could not "
+			"be initialized.\n");
+		sound_unload_synthdev (i);
+		hw->installed = 0;
+		return;
+	}
+    
+	request_region (hw_config->io_base+2, 6, "WaveFront synth");
+	request_region (hw_config->io_base+8, 8, "WaveFront FX");
+
+	conf_printf2 ("WaveFront Synth", hw_config->io_base, 0, -1, -1);
+
+#if defined(CONFIG_MIDI)    
+	if (wavefront_config_midi (hw, hw_config)) {
+		printk (KERN_WARNING "WaveFront: could not initialize MIDI.\n");
+	}
+#else
+	printk (KERN_WARNING
+		"WaveFront: MIDI not configured at kernel-config time.\n");
+#endif CONFIG_MIDI
+
+	return;
+}
+void
+unload_wavefront (struct address_info *hw_config)
+{
+	struct wf_config *hw;
+	int i;
+
+	if ((i = irq2hw[hw_config->irq]) == -1) {
+	    printk (KERN_ERR "WaveFront: unloading unrecognized device!\n");
+	    return;
+	}
+	hw = &wfs[i];
+
+	/* the first two are freed by the wf_mpu code */
+	release_region (hw_config->io_base+2, 6);
+	release_region (hw_config->io_base+8, 8);
+	sound_unload_synthdev (hw->synthdev);
+#if defined(CONFIG_MIDI)
+	unload_wf_mpu (hw_config);
+#endif
+}
+
+/***********************************************************************/
+/*   WaveFront FX control                                              */
+/***********************************************************************/
+
+#include "yss225.h"
+
+/* Control bits for the Load Control Register
+ */
+
+#define FX_LSB_TRANSFER 0x01    /* transfer after DSP LSB byte written */
+#define FX_MSB_TRANSFER 0x02    /* transfer after DSP MSB byte written */
+#define FX_AUTO_INCR    0x04    /* auto-increment DSP address after transfer */
+
+static int
+wffx_idle (struct wf_config *hw) 
+    
+{
+	int i;
+	unsigned int x = 0x80;
+    
+	for (i = 0; i < 1000; i++) {
+		x = inb (hw->fx_status);
+		if ((x & 0x80) == 0) {
+			break;
+		}
+	}
+    
+	if (x & 0x80) {
+		printk (KERN_ERR "WaveFront: FX device never idle.\n");
+		return 0;
+	}
+    
+	return (1);
+}
+
+static void
+wffx_mute (struct wf_config *hw, int onoff)
+    
+{
+	if (!wffx_idle(hw)) {
+		return;
+	}
+    
+	outb (onoff ? 0x02 : 0x00, hw->fx_op);
+}
+
+static int
+wffx_memset (struct wf_config *hw, int page,
+	     int addr, int cnt, unsigned short *data)
+{
+	if (page < 0 || page > 7) {
+		printk (KERN_ERR "WaveFront: FX memset: "
+			"page must be >= 0 and <= 7\n");
+		return -EINVAL;
+	}
+
+	if (addr < 0 || addr > 0x7f) {
+		printk (KERN_ERR "WaveFront: FX memset: "
+			"addr must be >= 0 and <= 7f\n");
+		return -EINVAL;
+	}
+
+	if (cnt == 1) {
+
+		outb (FX_LSB_TRANSFER, hw->fx_lcr);
+		outb (page, hw->fx_dsp_page);
+		outb (addr, hw->fx_dsp_addr);
+		outb ((data[0] >> 8), hw->fx_dsp_msb);
+		outb ((data[0] & 0xff), hw->fx_dsp_lsb);
+
+		printk (KERN_INFO "WaveFront: FX: addr %d:%x set to 0x%x\n",
+			page, addr, data[0]);
+	
+	} else {
+		int i;
+
+		outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+		outb (page, hw->fx_dsp_page);
+		outb (addr, hw->fx_dsp_addr);
+
+		for (i = 0; i < cnt; i++) {
+			outb ((data[i] >> 8), hw->fx_dsp_msb);
+			outb ((data[i] & 0xff), hw->fx_dsp_lsb);
+			if (!wffx_idle (hw)) {
+				break;
+			}
+		}
+
+		if (i != cnt) {
+			printk (KERN_WARNING
+				"WaveFront: FX memset "
+				"(0x%x, 0x%x, 0x%x, %d) incomplete\n",
+				page, addr, (int) data, cnt);
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+static int
+wffx_ioctl (struct wf_config *hw, wavefront_fx_info *r)
+
+{
+	unsigned short page_data[256];
+	unsigned short *pd;
+
+	switch (r->request) {
+	case WFFX_MUTE:
+		wffx_mute (hw, r->data[0]);
+		return 0;
+
+	case WFFX_MEMSET:
+
+		if (r->data[2] <= 0) {
+			printk (KERN_ERR "WaveFront: cannot write "
+				"<= 0 bytes to FX\n");
+			return -EINVAL;
+		} else if (r->data[2] == 1) {
+			pd = (unsigned short *) &r->data[3];
+		} else {
+			if (r->data[2] > sizeof (page_data)) {
+				printk (KERN_ERR
+					"WaveFront: cannot write "
+					"> 255 bytes to FX\n");
+				return -EINVAL;
+			}
+			COPY_FROM_USER(page_data, (unsigned char *) r->data[3],
+				       r->data[2]);
+			pd = page_data;
+		}
+
+		return wffx_memset (hw,
+				    r->data[0], /* page */
+				    r->data[1], /* addr */
+				    r->data[2], /* cnt */
+				    pd);
+
+	default:
+		printk (KERN_WARNING
+			"WaveFront: FX: ioctl %d not yet supported\n",
+			r->request);
+		return -EINVAL;
+	}
+}
+
+/* YSS225 initialization.
+
+   This code was developed using DOSEMU. The Turtle Beach SETUPSND
+   utility was run with I/O tracing in DOSEMU enabled, and a reconstruction
+   of the port I/O done, using the Yamaha faxback document as a guide
+   to add more logic to the code. Its really pretty wierd.
+
+   There was an alternative approach of just dumping the whole I/O
+   sequence as a series of port/value pairs and a simple loop
+   that output it. However, I hope that eventually I'll get more
+   control over what this code does, and so I tried to stick with
+   a somewhat "algorithmic" approach.
+*/
+
+static int
+wffx_init (struct wf_config *hw)
+
+{
+	int i;
+	int j;
+
+	/* Set all bits for all channels on the MOD unit to zero */
+	/* XXX But why do this twice ? */
+
+	for (j = 0; j < 2; j++) {
+		for (i = 0x10; i <= 0xff; i++) {
+	    
+			if (!wffx_idle (hw)) {
+				return (-1);
+			}
+	    
+			outb (i, hw->fx_mod_addr);
+			outb (0x0, hw->fx_mod_data);
+		}
+	}
+
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x02, hw->fx_op);                        /* mute on */
+
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x44, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x42, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x43, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x7c, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x7e, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x46, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x49, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x47, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x4a, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+
+	/* either because of stupidity by TB's programmers, or because it
+	   actually does something, rezero the MOD page.
+	*/
+	for (i = 0x10; i <= 0xff; i++) {
+	
+		if (!wffx_idle (hw)) {
+			return (-1);
+		}
+	
+		outb (i, hw->fx_mod_addr);
+		outb (0x0, hw->fx_mod_data);
+	}
+	/* load page zero */
+
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x00, hw->fx_dsp_page);
+	outb (0x00, hw->fx_dsp_addr);
+
+	for (i = 0; i < sizeof (page_zero); i += 2) {
+		outb (page_zero[i], hw->fx_dsp_msb);
+		outb (page_zero[i+1], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	/* Now load page one */
+
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x01, hw->fx_dsp_page);
+	outb (0x00, hw->fx_dsp_addr);
+
+	for (i = 0; i < sizeof (page_one); i += 2) {
+		outb (page_one[i], hw->fx_dsp_msb);
+		outb (page_one[i+1], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+    
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x02, hw->fx_dsp_page);
+	outb (0x00, hw->fx_dsp_addr);
+
+	for (i = 0; i < sizeof (page_two); i++) {
+		outb (page_two[i], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+    
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x03, hw->fx_dsp_page);
+	outb (0x00, hw->fx_dsp_addr);
+
+	for (i = 0; i < sizeof (page_three); i++) {
+		outb (page_three[i], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+    
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x04, hw->fx_dsp_page);
+	outb (0x00, hw->fx_dsp_addr);
+
+	for (i = 0; i < sizeof (page_four); i++) {
+		outb (page_four[i], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	/* Load memory area (page six) */
+    
+	outb (FX_LSB_TRANSFER, hw->fx_lcr); 
+	outb (0x06, hw->fx_dsp_page); 
+
+	for (i = 0; i < sizeof (page_six); i += 3) {
+		outb (page_six[i], hw->fx_dsp_addr);
+		outb (page_six[i+1], hw->fx_dsp_msb);
+		outb (page_six[i+2], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+    
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x00, hw->fx_dsp_addr);
+
+	for (i = 0; i < sizeof (page_seven); i += 2) {
+		outb (page_seven[i], hw->fx_dsp_msb);
+		outb (page_seven[i+1], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	/* Now setup the MOD area. We do this algorithmically in order to
+	   save a little data space. It could be done in the same fashion
+	   as the "pages".
+	*/
+
+	for (i = 0x00; i <= 0x0f; i++) {
+		outb (0x01, hw->fx_mod_addr);
+		outb (i, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+		outb (0x02, hw->fx_mod_addr);
+		outb (0x00, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	for (i = 0xb0; i <= 0xbf; i++) {
+		outb (i, hw->fx_mod_addr);
+		outb (0x20, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	for (i = 0xf0; i <= 0xff; i++) {
+		outb (i, hw->fx_mod_addr);
+		outb (0x20, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	for (i = 0x10; i <= 0x1d; i++) {
+		outb (i, hw->fx_mod_addr);
+		outb (0xff, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	outb (0x1e, hw->fx_mod_addr);
+	outb (0x40, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+
+	for (i = 0x1f; i <= 0x2d; i++) {
+		outb (i, hw->fx_mod_addr);
+		outb (0xff, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	outb (0x2e, hw->fx_mod_addr);
+	outb (0x00, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+
+	for (i = 0x2f; i <= 0x3e; i++) {
+		outb (i, hw->fx_mod_addr);
+		outb (0x00, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	outb (0x3f, hw->fx_mod_addr);
+	outb (0x20, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+
+	for (i = 0x40; i <= 0x4d; i++) {
+		outb (i, hw->fx_mod_addr);
+		outb (0x00, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	outb (0x4e, hw->fx_mod_addr);
+	outb (0x0e, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x4f, hw->fx_mod_addr);
+	outb (0x0e, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+
+
+	for (i = 0x50; i <= 0x6b; i++) {
+		outb (i, hw->fx_mod_addr);
+		outb (0x00, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	outb (0x6c, hw->fx_mod_addr);
+	outb (0x40, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+
+	outb (0x6d, hw->fx_mod_addr);
+	outb (0x00, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+
+	outb (0x6e, hw->fx_mod_addr);
+	outb (0x40, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+
+	outb (0x6f, hw->fx_mod_addr);
+	outb (0x40, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+
+	for (i = 0x70; i <= 0x7f; i++) {
+		outb (i, hw->fx_mod_addr);
+		outb (0xc0, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+    
+	for (i = 0x80; i <= 0xaf; i++) {
+		outb (i, hw->fx_mod_addr);
+		outb (0x00, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	for (i = 0xc0; i <= 0xdd; i++) {
+		outb (i, hw->fx_mod_addr);
+		outb (0x00, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	outb (0xde, hw->fx_mod_addr);
+	outb (0x10, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0xdf, hw->fx_mod_addr);
+	outb (0x10, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+
+	for (i = 0xe0; i <= 0xef; i++) {
+		outb (i, hw->fx_mod_addr);
+		outb (0x00, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	for (i = 0x00; i <= 0x0f; i++) {
+		outb (0x01, hw->fx_mod_addr);
+		outb (i, hw->fx_mod_data);
+		outb (0x02, hw->fx_mod_addr);
+		outb (0x01, hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	outb (0x02, hw->fx_op); /* mute on */
+
+	/* Now set the coefficients and so forth for the programs above */
+
+	for (i = 0; i < sizeof (coefficients); i += 4) {
+		outb (coefficients[i], hw->fx_dsp_page);
+		outb (coefficients[i+1], hw->fx_dsp_addr);
+		outb (coefficients[i+2], hw->fx_dsp_msb);
+		outb (coefficients[i+3], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	/* Some settings (?) that are too small to bundle into loops */
+
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x1e, hw->fx_mod_addr);
+	outb (0x14, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0xde, hw->fx_mod_addr);
+	outb (0x20, hw->fx_mod_data);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0xdf, hw->fx_mod_addr);
+	outb (0x20, hw->fx_mod_data);
+    
+	/* some more coefficients */
+
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x06, hw->fx_dsp_page);
+	outb (0x78, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x40, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x03, hw->fx_dsp_addr);
+	outb (0x0f, hw->fx_dsp_msb);
+	outb (0xff, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x0b, hw->fx_dsp_addr);
+	outb (0x0f, hw->fx_dsp_msb);
+	outb (0xff, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x02, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x0a, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x46, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+	if (!wffx_idle(hw)) return (-1);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x49, hw->fx_dsp_addr);
+	outb (0x00, hw->fx_dsp_msb);
+	outb (0x00, hw->fx_dsp_lsb);
+    
+	/* Now, for some strange reason, lets reload every page
+	   and all the coefficients over again. I have *NO* idea
+	   why this is done. I do know that no sound is produced
+	   is this phase is omitted.
+	*/
+
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x00, hw->fx_dsp_page);  
+	outb (0x10, hw->fx_dsp_addr);
+
+	for (i = 0; i < sizeof (page_zero_v2); i += 2) {
+		outb (page_zero_v2[i], hw->fx_dsp_msb);
+		outb (page_zero_v2[i+1], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+    
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x01, hw->fx_dsp_page);
+	outb (0x10, hw->fx_dsp_addr);
+
+	for (i = 0; i < sizeof (page_one_v2); i += 2) {
+		outb (page_one_v2[i], hw->fx_dsp_msb);
+		outb (page_one_v2[i+1], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+    
+	if (!wffx_idle(hw)) return (-1);
+	if (!wffx_idle(hw)) return (-1);
+    
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x02, hw->fx_dsp_page);
+	outb (0x10, hw->fx_dsp_addr);
+
+	for (i = 0; i < sizeof (page_two_v2); i++) {
+		outb (page_two_v2[i], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x03, hw->fx_dsp_page);
+	outb (0x10, hw->fx_dsp_addr);
+
+	for (i = 0; i < sizeof (page_three_v2); i++) {
+		outb (page_three_v2[i], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+    
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x04, hw->fx_dsp_page);
+	outb (0x10, hw->fx_dsp_addr);
+
+	for (i = 0; i < sizeof (page_four_v2); i++) {
+		outb (page_four_v2[i], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+    
+	outb (FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x06, hw->fx_dsp_page);
+
+	/* Page six v.2 is algorithmic */
+    
+	for (i = 0x10; i <= 0x3e; i += 2) {
+		outb (i, hw->fx_dsp_addr);
+		outb (0x00, hw->fx_dsp_msb);
+		outb (0x00, hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
+	outb (0x07, hw->fx_dsp_page);
+	outb (0x10, hw->fx_dsp_addr);
+
+	for (i = 0; i < sizeof (page_seven_v2); i += 2) {
+		outb (page_seven_v2[i], hw->fx_dsp_msb);
+		outb (page_seven_v2[i+1], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	for (i = 0x00; i < sizeof(mod_v2); i += 2) {
+		outb (mod_v2[i], hw->fx_mod_addr);
+		outb (mod_v2[i+1], hw->fx_mod_data);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	for (i = 0; i < sizeof (coefficients2); i += 4) {
+		outb (coefficients2[i], hw->fx_dsp_page);
+		outb (coefficients2[i+1], hw->fx_dsp_addr);
+		outb (coefficients2[i+2], hw->fx_dsp_msb);
+		outb (coefficients2[i+3], hw->fx_dsp_lsb);
+		if (!wffx_idle(hw)) return (-1);
+	}
+
+	outb (0x00, hw->fx_op);
+	if (!wffx_idle(hw)) return (-1);
+    
+	for (i = 0; i < sizeof (coefficients3); i += 2) {
+		int x;
+
+		outb (0x07, hw->fx_dsp_page);
+		x = (i % 4) ? 0x4e : 0x4c;
+		outb (x, hw->fx_dsp_addr);
+		outb (coefficients3[i], hw->fx_dsp_msb);
+		outb (coefficients3[i+1], hw->fx_dsp_lsb);
+	}
+
+	outb (0x00, hw->fx_op); /* mute off */
+
+	return 0;
+}
+
+EXPORT_NO_SYMBOLS;
+struct address_info cfg;
+
+int io = -1;
+int irq = -1;
+
+MODULE_PARM(io,"i");
+MODULE_PARM(irq,"i");
+
+int init_module (void)
+
+{
+	printk ("Turtle Beach WaveFront Driver\n"
+		"Copyright (C) by Hannu Solvainen, "
+		"Paul Barton-Davis 1993-1998.\n");
+
+	if (io == -1 || irq == -1) {
+		printk (KERN_INFO "WaveFront: irq and io "
+			"options must be set.\n");
+		return -EINVAL;
+	}
+	cfg.io_base = io;
+	cfg.irq = irq;
+
+	if (probe_wavefront (&cfg) == 0) {
+		return -ENODEV;
+	} 
+	attach_wavefront (&cfg);
+	SOUND_LOCK;
+	return 0;
+}
+
+void cleanup_module (void)
+
+{
+	unload_wavefront (&cfg);
+	SOUND_LOCK_END;
+}
+
+#endif MODULE   
+#endif CONFIG_SOUND_WAVEFRONT 
+
+
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/wf_midi.c linux/drivers/sound/wf_midi.c
--- v2.1.109/linux/drivers/sound/wf_midi.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/wf_midi.c	Sat Jul 18 14:11:41 1998
@@ -0,0 +1,984 @@
+/*
+ * sound/wf_midi.c
+ *
+ * The low level driver for the WaveFront ICS2115 MIDI interface(s)
+ * Note that there is also an MPU-401 emulation (actually, a UART-401
+ * emulation) on the CS4232 on the Tropez Plus. This code has nothing
+ * to do with that interface at all.
+ *
+ * The interface is essentially just a UART-401, but is has the
+ * interesting property of supporting what Turtle Beach called
+ * "Virtual MIDI" mode. In this mode, there are effectively *two*
+ * MIDI buses accessible via the interface, one that is routed
+ * solely to/from the external WaveFront synthesizer and the other
+ * corresponding to the pin/socket connector used to link external
+ * MIDI devices to the board.
+ *
+ * This driver fully supports this mode, allowing two distinct
+ * midi devices (/dev/midiNN and /dev/midiNN+1) to be used
+ * completely independently, giving 32 channels of MIDI routing,
+ * 16 to the WaveFront synth and 16 to the external MIDI bus.
+ *
+ * Switching between the two is accomplished externally by the driver
+ * using the two otherwise unused MIDI bytes. See the code for more details.
+ *
+ * NOTE: VIRTUAL MIDI MODE IS ON BY DEFAULT (see wavefront.c)
+ *
+ * The main reason to turn off Virtual MIDI mode is when you want to
+ * tightly couple the WaveFront synth with an external MIDI
+ * device. You won't be able to distinguish the source of any MIDI
+ * data except via SysEx ID, but thats probably OK, since for the most
+ * part, the WaveFront won't be sending any MIDI data at all.
+ *  
+ * The main reason to turn on Virtual MIDI Mode is to provide two
+ * completely independent 16-channel MIDI buses, one to the
+ * WaveFront and one to any external MIDI devices. Given the 32
+ * voice nature of the WaveFront, its pretty easy to find a use
+ * for all 16 channels driving just that synth.
+ *
+ */
+
+/*
+ * Copyright (C) by Paul Barton-Davis 1998
+ * Substantial portions of this file are derived from work that is:
+ *
+ *    Copyright (C) by Hannu Savolainen 1993-1996
+ *
+ * USS/Lite 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.
+ */
+
+#include <linux/config.h>
+#include "sound_config.h"
+#include "soundmodule.h"
+
+#include <linux/wavefront.h>
+
+#if (defined(CONFIG_WAVEFRONT) && defined(CONFIG_MIDI)) || defined(MODULE)
+
+struct wf_mpu_config {
+	int             base;	/* I/O base */
+	int             irq;
+	int             opened;	/* Open mode */
+	int             devno;
+	int             synthno;
+	int             mode;
+#define MODE_MIDI	1
+#define MODE_SYNTH	2
+
+	void            (*inputintr) (int dev, unsigned char data);
+    
+	/* Virtual MIDI support */
+    
+	char configured_for_virtual;   /* setup for virtual completed */
+	char isvirtual;                /* do virtual I/O stuff */
+	char isexternal;               /* i am an external interface */
+	int internal;                  /* external interface midi_devno */
+	int external;                  /* external interface midi_devno */
+};
+
+#define	DATAPORT(base)   (base)
+#define	COMDPORT(base)   (base+1)
+#define	STATPORT(base)   (base+1)
+
+static void     start_uart_mode (struct wf_mpu_config *devc);
+
+static int 
+wf_mpu_status (struct wf_mpu_config *devc)
+{
+	return inb (STATPORT (devc->base));
+}
+
+static void 
+wf_mpu_cmd (struct wf_mpu_config *devc, unsigned char cmd)
+{
+	outb ((cmd), COMDPORT(devc->base));
+}
+
+#define input_avail(devc)		(!(wf_mpu_status(devc)&INPUT_AVAIL))
+#define output_ready(devc)		(!(wf_mpu_status(devc)&OUTPUT_READY))
+
+static int 
+read_data (struct wf_mpu_config *devc)
+{
+	return inb (DATAPORT (devc->base));
+}
+
+static void 
+write_data (struct wf_mpu_config *devc, unsigned char byte)
+{
+	outb (byte, DATAPORT (devc->base));
+}
+
+#define	OUTPUT_READY	0x40
+#define	INPUT_AVAIL	0x80
+#define	MPU_ACK		0xFE
+#define	MPU_RESET	0xFF
+#define	UART_MODE_ON	0x3F
+
+static struct wf_mpu_config dev_conf[MAX_MIDI_DEV] =
+{
+	{0}
+};
+
+static volatile int irq2dev[17] =
+{-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1};
+
+static struct synth_info wf_mpu_synth_info_proto =
+{"WaveFront MPU-401 interface", 0,
+ SYNTH_TYPE_MIDI, MIDI_TYPE_MPU401, 0, 128, 0, 128, SYNTH_CAP_INPUT};
+
+static struct synth_info wf_mpu_synth_info[MAX_MIDI_DEV];
+
+/*
+ * States for the input scanner (should be in dev_table.h)
+ */
+
+#define MST_SYSMSG		100	/* System message (sysx etc). */
+#define MST_MTC			102	/* Midi Time Code (MTC) qframe msg */
+#define MST_SONGSEL		103	/* Song select */
+#define MST_SONGPOS		104	/* Song position pointer */
+#define MST_TIMED		105	/* Leading timing byte rcvd */
+
+/* buffer space check for input scanner */
+
+#define BUFTEST(mi) if (mi->m_ptr >= MI_MAX || mi->m_ptr < 0) \
+{printk(KERN_ERR "WF-MPU: Invalid buffer pointer %d/%d, s=%d\n", \
+	mi->m_ptr, mi->m_left, mi->m_state);mi->m_ptr--;}
+
+static unsigned char len_tab[] =	/* # of data bytes following a status
+					 */
+{
+	2,				/* 8x */
+	2,				/* 9x */
+	2,				/* Ax */
+	2,				/* Bx */
+	1,				/* Cx */
+	1,				/* Dx */
+	2,				/* Ex */
+	0				/* Fx */
+};
+
+static int
+wf_mpu_input_scanner (struct wf_mpu_config *devc, unsigned char midic)
+{
+	struct midi_input_info *mi;
+
+	mi = &midi_devs[devc->devno]->in_info;
+
+	switch (mi->m_state) {
+	case MST_INIT:
+		switch (midic) {
+		case 0xf8:
+			/* Timer overflow */
+			break;
+		
+		case 0xfc:
+			break;
+		
+		case 0xfd:
+			/* XXX do something useful with this. If there is
+			   an external MIDI timer (e.g. a hardware sequencer,
+			   a useful timer can be derived ...
+		   
+			   For now, no timer support.
+			*/
+			break;
+		
+		case 0xfe:
+			return MPU_ACK;
+			break;
+		
+		case 0xf0:
+		case 0xf1:
+		case 0xf2:
+		case 0xf3:
+		case 0xf4:
+		case 0xf5:
+		case 0xf6:
+		case 0xf7:
+			break;
+		
+		case 0xf9:
+			break;
+		
+		case 0xff:
+			mi->m_state = MST_SYSMSG;
+			break;
+		
+		default:
+			if (midic <= 0xef) {
+				mi->m_state = MST_TIMED;
+			}
+			else
+				printk (KERN_ERR "<MPU: Unknown event %02x> ",
+					midic);
+		}
+		break;
+	  
+	case MST_TIMED:
+	{
+		int             msg = ((int) (midic & 0xf0) >> 4);
+	  
+		mi->m_state = MST_DATA;
+	  
+		if (msg < 8) {	/* Data byte */
+	      
+			msg = ((int) (mi->m_prev_status & 0xf0) >> 4);
+			msg -= 8;
+			mi->m_left = len_tab[msg] - 1;
+	      
+			mi->m_ptr = 2;
+			mi->m_buf[0] = mi->m_prev_status;
+			mi->m_buf[1] = midic;
+
+			if (mi->m_left <= 0) {
+				mi->m_state = MST_INIT;
+				do_midi_msg (devc->synthno, mi->m_buf,
+					     mi->m_ptr);
+				mi->m_ptr = 0;
+			}
+		} else if (msg == 0xf) {	/* MPU MARK */
+	      
+			mi->m_state = MST_INIT;
+
+			switch (midic) {
+			case 0xf8:
+				break;
+		    
+			case 0xf9:
+				break;
+		    
+			case 0xfc:
+				break;
+		    
+			default:
+			}
+		} else {
+			mi->m_prev_status = midic;
+			msg -= 8;
+			mi->m_left = len_tab[msg];
+	      
+			mi->m_ptr = 1;
+			mi->m_buf[0] = midic;
+	      
+			if (mi->m_left <= 0) {
+				mi->m_state = MST_INIT;
+				do_midi_msg (devc->synthno, mi->m_buf,
+					     mi->m_ptr);
+				mi->m_ptr = 0;
+			}
+		}
+	}
+	break;
+
+	case MST_SYSMSG:
+		switch (midic) {
+		case 0xf0:
+			mi->m_state = MST_SYSEX;
+			break;
+	    
+		case 0xf1:
+			mi->m_state = MST_MTC;
+			break;
+
+		case 0xf2:
+			mi->m_state = MST_SONGPOS;
+			mi->m_ptr = 0;
+			break;
+	    
+		case 0xf3:
+			mi->m_state = MST_SONGSEL;
+			break;
+	    
+		case 0xf6:
+			mi->m_state = MST_INIT;
+	    
+			/*
+			 *    Real time messages
+			 */
+		case 0xf8:
+			/* midi clock */
+			mi->m_state = MST_INIT;
+			/* XXX need ext MIDI timer support */
+			break;
+	    
+		case 0xfA:
+			mi->m_state = MST_INIT;
+			/* XXX need ext MIDI timer support */
+			break;
+	    
+		case 0xFB:
+			mi->m_state = MST_INIT;
+			/* XXX need ext MIDI timer support */
+			break;
+	    
+		case 0xFC:
+			mi->m_state = MST_INIT;
+			/* XXX need ext MIDI timer support */
+			break;
+	    
+		case 0xFE:
+			/* active sensing */
+			mi->m_state = MST_INIT;
+			break;
+	    
+		case 0xff:
+			mi->m_state = MST_INIT;
+			break;
+
+		default:
+			printk (KERN_ERR "unknown MIDI sysmsg %0x\n", midic);
+			mi->m_state = MST_INIT;
+		}
+		break;
+
+	case MST_MTC:
+		mi->m_state = MST_INIT;
+		break;
+
+	case MST_SYSEX:
+		if (midic == 0xf7) {
+			mi->m_state = MST_INIT;
+		} else {
+			/* XXX fix me */
+		}
+		break;
+
+	case MST_SONGPOS:
+		BUFTEST (mi);
+		mi->m_buf[mi->m_ptr++] = midic;
+		if (mi->m_ptr == 2) {
+			mi->m_state = MST_INIT;
+			mi->m_ptr = 0;
+			/* XXX need ext MIDI timer support */
+		}
+		break;
+
+	case MST_DATA:
+		BUFTEST (mi);
+		mi->m_buf[mi->m_ptr++] = midic;
+		if ((--mi->m_left) <= 0) {
+			mi->m_state = MST_INIT;
+			do_midi_msg (devc->synthno, mi->m_buf, mi->m_ptr);
+			mi->m_ptr = 0;
+		}
+		break;
+
+	default:
+		printk (KERN_ERR "Bad state %d ", mi->m_state);
+		mi->m_state = MST_INIT;
+	}
+
+	return 1;
+}
+
+void
+wf_mpuintr (int irq, void *dev_id, struct pt_regs *dummy)
+{
+	struct wf_mpu_config *devc;
+	int             dev;
+	static struct wf_mpu_config *isrc = 0;
+	int             n;
+	struct midi_input_info *mi;
+	static int cnt = 0;
+
+	if (irq < 0 || irq > 15) {
+		printk (KERN_ERR "WF-MPU: bogus interrupt #%d", irq);
+		return;
+	}
+	dev = irq2dev[irq];
+	mi = &midi_devs[dev]->in_info;
+	if (mi->m_busy) return;
+	mi->m_busy = 1;
+	sti (); 
+
+	n = 50;
+
+	/* guarantee that we're working with the "real" (internal)
+	   interface before doing anything physical.
+	*/
+
+	devc = &dev_conf[dev];
+	devc = &dev_conf[devc->internal];
+
+	if (isrc == 0) {
+      
+		/* This is just an initial setting. If Virtual MIDI mode is
+		   enabled on the ICS2115, we'll get a switch char before
+		   anything else, and if it isn't, then the guess will be
+		   correct for our purposes.
+		*/
+      
+		isrc = &dev_conf[devc->internal];
+	}
+  
+	while (input_avail (devc) && n-- > 0) {
+		unsigned char c = read_data (devc);
+      
+		if (devc->isvirtual) {
+			if (c == WF_EXTERNAL_SWITCH) {
+				isrc = &dev_conf[devc->external];
+				continue;
+			} else if (c == WF_INTERNAL_SWITCH) { 
+				isrc = &dev_conf[devc->internal];
+				continue;
+			} /* else just leave it as it is */
+		} else {
+			isrc = &dev_conf[devc->internal];
+		}
+
+		if (isrc->mode == MODE_SYNTH) {
+	  
+			wf_mpu_input_scanner (isrc, c);
+	  
+		} else if (isrc->opened & OPEN_READ) {
+	  
+			if (isrc->inputintr) {
+				isrc->inputintr (isrc->devno, c);
+			} 
+		}
+	}
+
+	mi->m_busy = 0;
+}
+
+static int
+wf_mpu_open (int dev, int mode,
+	     void            (*input) (int dev, unsigned char data),
+	     void            (*output) (int dev)
+	)
+{
+	struct wf_mpu_config *devc;
+
+	if (dev < 0 || dev >= num_midis || midi_devs[dev]==NULL)
+		return -ENXIO;
+
+	devc = &dev_conf[dev];
+
+	if (devc->opened) {
+		return -EBUSY;
+	}
+
+	devc->mode = MODE_MIDI;
+	devc->opened = mode;
+	devc->synthno = 0;
+
+	devc->inputintr = input;
+	return 0;
+}
+ 
+static void
+wf_mpu_close (int dev)
+{
+	struct wf_mpu_config *devc;
+
+	devc = &dev_conf[dev];
+	devc->mode = 0;
+	devc->inputintr = NULL;
+	devc->opened = 0;
+}
+
+static int
+wf_mpu_out (int dev, unsigned char midi_byte)
+{
+	int             timeout;
+	unsigned long   flags;
+	static int lastoutdev = -1;
+
+	struct wf_mpu_config *devc;
+	unsigned char switchch;
+
+	/* The actual output has to occur using the "internal" config info
+	 */
+  
+	devc = &dev_conf[dev_conf[dev].internal];
+  
+	if (devc->isvirtual && lastoutdev != dev) {
+      
+		if (dev == devc->internal) { 
+			switchch = WF_INTERNAL_SWITCH;
+		} else if (dev == devc->external) { 
+			switchch = WF_EXTERNAL_SWITCH;
+		} else {
+			printk (KERN_ERR "WF-MPU: bad device number %d", dev);
+			return (0);
+		}
+      
+		for (timeout = 30000; timeout > 0 && !output_ready (devc);
+		     timeout--);
+      
+		save_flags (flags);
+		cli ();
+      
+		if (!output_ready (devc)) {
+			printk (KERN_WARNING "WF-MPU: Send switch "
+				"byte timeout\n");
+			restore_flags (flags);
+			return 0;
+		}
+      
+		write_data (devc, switchch);
+		restore_flags (flags);
+	} 
+
+	lastoutdev = dev;
+
+	/*
+	 * Sometimes it takes about 30000 loops before the output becomes ready
+	 * (After reset). Normally it takes just about 10 loops.
+	 */
+
+	for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--);
+
+	save_flags (flags);
+	cli ();
+	if (!output_ready (devc)) {
+		printk (KERN_WARNING "WF-MPU: Send data timeout\n");
+		restore_flags (flags);
+		return 0;
+	}
+
+	write_data (devc, midi_byte);
+	restore_flags (flags);
+
+	return 1;
+}
+
+static int
+wf_mpu_start_read (int dev)
+{
+	return 0;
+}
+
+static int
+wf_mpu_end_read (int dev)
+{
+	return 0;
+}
+
+static int
+wf_mpu_ioctl (int dev, unsigned cmd, caddr_t arg)
+{
+	printk (KERN_WARNING
+		"WF-MPU: Intelligent mode not supported by hardware.\n");
+	return -(EINVAL);
+}
+
+static void
+wf_mpu_kick (int dev)
+{
+}
+
+static int
+wf_mpu_buffer_status (int dev)
+{
+	return 0;			/*
+					 * No data in buffers
+					 */
+}
+
+static int
+wf_mpu_synth_ioctl (int dev,
+		    unsigned int cmd, caddr_t arg)
+{
+	int             midi_dev;
+
+	midi_dev = synth_devs[dev]->midi_dev;
+
+	if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev]==NULL)
+		return -(ENXIO);
+
+	switch (cmd) {
+
+	case SNDCTL_SYNTH_INFO:
+		copy_to_user (&((char *) arg)[0],
+			      &wf_mpu_synth_info[midi_dev],
+			      sizeof (struct synth_info));
+	
+		return 0;
+		break;
+	
+	case SNDCTL_SYNTH_MEMAVL:
+		return 0x7fffffff;
+		break;
+	
+	default:
+		return -(EINVAL);
+	}
+}
+
+static int
+wf_mpu_synth_open (int dev, int mode)
+{
+	int             midi_dev;
+	struct wf_mpu_config *devc;
+
+	midi_dev = synth_devs[dev]->midi_dev;
+
+	if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev]==NULL) {
+		return -(ENXIO);
+	}
+  
+	devc = &dev_conf[midi_dev];
+	if (devc->opened) {
+		return -(EBUSY);
+	}
+  
+	devc->mode = MODE_SYNTH;
+	devc->synthno = dev;
+	devc->opened = mode;
+	devc->inputintr = NULL;
+	return 0;
+}
+
+static void
+wf_mpu_synth_close (int dev)
+{
+	int             midi_dev;
+	struct wf_mpu_config *devc;
+
+	midi_dev = synth_devs[dev]->midi_dev;
+
+	devc = &dev_conf[midi_dev];
+	devc->inputintr = NULL;
+	devc->opened = 0;
+	devc->mode = 0;
+}
+
+#define MIDI_SYNTH_NAME	"WaveFront (MIDI)"
+#define MIDI_SYNTH_CAPS	SYNTH_CAP_INPUT
+#include "midi_synth.h"
+
+static struct synth_operations wf_mpu_synth_proto =
+{
+	"WaveFront (ICS2115)",
+	NULL,  /* info field, filled in during configuration */
+	0,     /* MIDI dev XXX should this be -1 ? */
+	SYNTH_TYPE_MIDI,
+	SAMPLE_TYPE_WAVEFRONT,
+	wf_mpu_synth_open,
+	wf_mpu_synth_close,
+	wf_mpu_synth_ioctl,
+	midi_synth_kill_note,
+	midi_synth_start_note,
+	midi_synth_set_instr,
+	midi_synth_reset,
+	midi_synth_hw_control,
+	midi_synth_load_patch,
+	midi_synth_aftertouch,
+	midi_synth_controller,
+	midi_synth_panning,
+	NULL,
+	midi_synth_bender,
+	NULL,				/* alloc */
+	midi_synth_setup_voice,
+	midi_synth_send_sysex
+};
+
+static struct synth_operations wf_mpu_synth_operations[WAVEFRONT_MAX_DEVICES*2];
+static struct midi_operations  wf_mpu_midi_operations[WAVEFRONT_MAX_DEVICES*2];
+static int wfmpu_cnt = 0;
+
+static struct midi_operations wf_mpu_midi_proto =
+{
+	{"WF-MPU MIDI", 0, MIDI_CAP_MPU401, SNDCARD_MPU401},
+	NULL,  /*converter*/
+	{0},   /* in_info */
+	wf_mpu_open,
+	wf_mpu_close,
+	wf_mpu_ioctl,
+	wf_mpu_out,
+	wf_mpu_start_read,
+	wf_mpu_end_read,
+	wf_mpu_kick,
+	NULL,
+	wf_mpu_buffer_status,
+	NULL
+};
+
+
+static int
+config_wf_mpu (int dev, struct address_info *hw_config)
+
+{
+	struct wf_mpu_config *devc;
+	int                internal;
+
+	if (wfmpu_cnt >= WAVEFRONT_MAX_DEVICES * 2) {
+		printk (KERN_ERR "WF-MPU: eh ? more MPU devices "
+			"than cards ?!!\n");
+		return (-1);
+	}
+  
+	/* There is no synth available on the external interface,
+	   so do the synth stuff to the internal interface only.
+	*/
+
+	internal = dev_conf[dev].internal;
+	devc = &dev_conf[internal];
+
+	if (!dev_conf[dev].isexternal) {
+		memcpy ((char *) &wf_mpu_synth_operations[wfmpu_cnt],
+			(char *) &wf_mpu_synth_proto,
+			sizeof (struct synth_operations));
+	}
+
+	memcpy ((char *) &wf_mpu_midi_operations[wfmpu_cnt],
+		(char *) &wf_mpu_midi_proto,
+		sizeof (struct midi_operations));
+  
+	if (dev_conf[dev].isexternal) {
+		wf_mpu_midi_operations[wfmpu_cnt].converter = NULL;
+	} else {
+		wf_mpu_midi_operations[wfmpu_cnt].converter =
+			&wf_mpu_synth_operations[wfmpu_cnt];
+	}
+
+	memcpy ((char *) &wf_mpu_synth_info[dev],
+		(char *) &wf_mpu_synth_info_proto,
+		sizeof (struct synth_info));
+
+	strcpy (wf_mpu_synth_info[dev].name, hw_config->name);
+	strcpy (wf_mpu_midi_operations[wfmpu_cnt].info.name, hw_config->name);
+
+	conf_printf (hw_config->name, hw_config);
+
+	if (!dev_conf[dev].isexternal) {
+		wf_mpu_synth_operations[wfmpu_cnt].midi_dev = dev;
+	}
+	wf_mpu_synth_operations[wfmpu_cnt].info = &wf_mpu_synth_info[dev];
+
+	midi_devs[dev] = &wf_mpu_midi_operations[wfmpu_cnt];
+
+	dev_conf[dev].opened = 0;
+	dev_conf[dev].mode = 0;
+	dev_conf[dev].configured_for_virtual = 0;
+	dev_conf[dev].devno = dev;
+
+	midi_devs[dev]->in_info.m_busy = 0;
+	midi_devs[dev]->in_info.m_state = MST_INIT;
+	midi_devs[dev]->in_info.m_ptr = 0;
+	midi_devs[dev]->in_info.m_left = 0;
+	midi_devs[dev]->in_info.m_prev_status = 0;
+
+	wfmpu_cnt++;
+
+	return (0);
+}
+
+int
+virtual_midi_enable (int dev, struct address_info *hw_config)
+
+{
+	int idev;
+	int edev;
+	struct wf_mpu_config *devc;
+
+	devc = &dev_conf[dev];
+	
+	if (devc->configured_for_virtual) {
+
+		idev = devc->internal;
+		edev = devc->external;
+
+	} else {
+
+		if (hw_config == NULL) {
+			printk (KERN_ERR
+				"WF-MPU: virtual midi first "
+				"enabled without hw_config!\n");
+			return -EINVAL;
+		}
+
+		idev = devc->internal;
+
+		if ((edev = sound_alloc_mididev()) == -1) {
+			printk (KERN_ERR
+				"WF-MPU: too many midi devices detected\n");
+			return -1;
+		}
+
+		hw_config->slots[WF_EXTERNAL_MIDI_SLOT] = edev;
+	}
+
+	dev_conf[edev].isvirtual = 1;
+	dev_conf[idev].isvirtual = 1;
+    
+	if (dev_conf[idev].configured_for_virtual) {
+		return 0;
+	} 
+
+	/* Configure external interface struct */
+
+	devc = &dev_conf[edev];
+	devc->internal = idev;
+	devc->external = edev;
+	devc->isexternal = 1;
+
+	/* Configure external interface struct 
+	   (devc->isexternal and devc->internal set in attach_wf_mpu())
+	*/
+
+	devc = &dev_conf[idev];
+	devc->external = edev;
+
+	/* Configure the tables for the external */
+
+	if (config_wf_mpu (edev, hw_config)) {
+		printk (KERN_WARNING "WF-MPU: configuration for MIDI "
+			"device %d failed\n", edev);
+		return (-1);
+	}
+
+	/* Don't bother to do this again if we are toggled back and
+	   forth between virtual MIDI mode and "normal" operation.
+	*/
+
+	dev_conf[edev].configured_for_virtual = 1;
+	dev_conf[idev].configured_for_virtual = 1;
+
+	return 0;
+}
+
+void
+virtual_midi_disable (int dev)
+
+{
+	struct wf_mpu_config *devc;
+	unsigned long flags;
+
+	save_flags (flags);
+	cli();
+
+	/* Assumes for logical purposes that the caller has taken
+	   care of fiddling with WaveFront hardware commands to
+	   turn off Virtual MIDI mode. 
+	*/
+    
+	devc = &dev_conf[dev];
+
+	devc = &dev_conf[devc->internal];
+	devc->isvirtual = 0;
+
+	devc = &dev_conf[devc->external];
+	devc->isvirtual = 0;
+
+	restore_flags (flags);
+}
+
+void
+attach_wf_mpu (struct address_info *hw_config)
+{
+	int m;
+	struct wf_mpu_config *devc;
+
+	if (request_irq (hw_config->irq, wf_mpuintr,
+			 0, "WaveFront MIDI", NULL) < 0) {
+		printk (KERN_ERR "WF-MPU: Failed to allocate IRQ%d\n",
+			hw_config->irq);
+		return;
+	}
+
+	if ((m = sound_alloc_mididev()) == -1){
+		printk (KERN_ERR "WF-MPU: Too many MIDI devices detected.\n");
+		free_irq (hw_config->irq, NULL);
+		release_region (hw_config->io_base, 2);
+		return;
+	}
+
+	request_region (hw_config->io_base, 2, "WaveFront MPU");
+
+	hw_config->slots[WF_INTERNAL_MIDI_SLOT] = m;
+	devc = &dev_conf[m];
+	devc->base = hw_config->io_base;
+	devc->irq = hw_config->irq;
+	devc->isexternal = 0;
+	devc->internal = m;
+	devc->external = -1;
+	devc->isvirtual = 0;
+
+	irq2dev[devc->irq] = m;
+
+	if (config_wf_mpu (m, hw_config)) {
+		printk (KERN_WARNING
+			"WF-MPU: configuration for MIDI device %d failed\n", m);
+		sound_unload_mididev (m);
+	}
+
+	/* This being a WaveFront (ICS-2115) emulated MPU-401, we have
+	   to switch it into UART (dumb) mode, because otherwise, it
+	   won't do anything at all.
+	*/
+  
+	start_uart_mode (devc);
+
+}
+
+int
+probe_wf_mpu (struct address_info *hw_config)
+
+{
+	if (hw_config->irq < 0 || hw_config->irq > 16) {
+		printk (KERN_WARNING "WF-MPU: bogus IRQ value requested (%d)\n",
+			hw_config->irq);
+		return 0;
+	}
+
+	if (check_region (hw_config->io_base, 2)) {
+		printk (KERN_WARNING "WF-MPU: I/O port %x already in use\n\n",
+			hw_config->io_base);
+		return 0;
+	}
+
+	if (inb (hw_config->io_base + 1) == 0xff) { /* Just bus float? */
+		printk ("WF-MPU: Port %x looks dead.\n", hw_config->io_base);
+		return 0;
+	}
+
+	return 1;
+}
+
+void
+unload_wf_mpu (struct address_info *hw_config)
+{
+
+	release_region (hw_config->io_base, 2); 
+	sound_unload_mididev (hw_config->slots[WF_INTERNAL_MIDI_SLOT]);
+	if (hw_config->irq > 0) {
+		free_irq (hw_config->irq, NULL);
+	}
+	if (hw_config->slots[WF_EXTERNAL_MIDI_SLOT] > 0) {
+		sound_unload_mididev (hw_config->slots[WF_EXTERNAL_MIDI_SLOT]);
+	}
+}
+
+static void
+start_uart_mode (struct wf_mpu_config *devc)
+{
+	int             ok, timeout;
+	unsigned long   flags;
+
+	save_flags (flags);
+	cli ();
+
+	for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--);
+
+	wf_mpu_cmd (devc, UART_MODE_ON);
+
+	for (ok = 0, timeout = 50000; timeout > 0 && !ok; timeout--) {
+		if (input_avail (devc)) {
+			if (read_data (devc) == MPU_ACK) {
+				ok = 1;
+			}
+		}
+	}
+
+	restore_flags (flags);
+}
+
+#endif
+
+
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/yss225.c linux/drivers/sound/yss225.c
--- v2.1.109/linux/drivers/sound/yss225.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/yss225.c	Sat Jul 18 14:11:41 1998
@@ -0,0 +1,317 @@
+unsigned char page_zero[] = {
+0x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00,
+0x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00,
+0x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x19,
+0x01, 0x1a, 0x01, 0x20, 0x01, 0x40, 0x01, 0x17, 0x00, 0x00, 0x01,
+0x80, 0x01, 0x20, 0x00, 0x10, 0x01, 0xa0, 0x03, 0xd1, 0x00, 0x00,
+0x01, 0xf2, 0x02, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf4, 0x02,
+0xe0, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17,
+0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x00, 0x00,
+0x40, 0x00, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x60, 0x00, 0x00,
+0x00, 0x92, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb3, 0x02,
+0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x40,
+0x00, 0x80, 0x00, 0xf5, 0x00, 0x20, 0x00, 0x70, 0x00, 0xa0, 0x02,
+0x11, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+0x02, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x17, 0x00, 0x1b, 0x00,
+0x1d, 0x02, 0xdf
+};    
+
+unsigned char page_one[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00,
+0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00,
+0x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01,
+0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x02, 0x60,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x80, 0x00,
+0x00, 0x02, 0xfb, 0x02, 0xa0, 0x00, 0x00, 0x00, 0x1b, 0x02, 0xd7,
+0x00, 0x00, 0x02, 0xf7, 0x03, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00,
+0x1c, 0x03, 0x3c, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x00, 0x03, 0xc0,
+0x00, 0x00, 0x03, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5d, 0x00,
+0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x03, 0xc0,
+0x00, 0x00, 0x03, 0x9e, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03,
+0xbe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+0xdb, 0x00, 0x00, 0x02, 0xdb, 0x00, 0x00, 0x02, 0xe0, 0x00, 0x00,
+0x02, 0xfb, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x40, 0x02, 0xfb, 0x02,
+0x60, 0x00, 0x1b
+};
+
+unsigned char page_two[] = {
+0xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4,
+0x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x07,
+0x05, 0x05, 0x05, 0x04, 0x07, 0x05, 0x04, 0x07, 0x05, 0x44, 0x46,
+0x44, 0x46, 0x46, 0x07, 0x05, 0x44, 0x46, 0x05, 0x46, 0x05, 0x46,
+0x05, 0x46, 0x05, 0x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07,
+0x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07, 0x44, 0x05, 0x05,
+0x05, 0x44, 0x05, 0x05, 0x05, 0x46, 0x05, 0x46, 0x05, 0x46, 0x05,
+0x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44
+};
+
+unsigned char page_three[] = {
+0x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06,
+0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0xc0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00,
+0x60, 0x00, 0x70, 0x00, 0x40, 0x00, 0x40, 0x00, 0x42, 0x00, 0x40,
+0x00, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+0x00, 0x42, 0x00, 0x40, 0x00, 0x42, 0x00, 0x02, 0x00, 0x02, 0x00,
+0x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40
+};
+
+unsigned char page_four[] = {
+0x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
+0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x60, 0x00,
+0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60,
+0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00,
+0x20, 0x00, 0x22, 0x02, 0x22, 0x02, 0x20, 0x00, 0x60, 0x00, 0x22,
+0x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01
+};
+
+unsigned char page_six[] = {
+0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00,
+0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e,
+0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00,
+0x16, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1c, 0x00,
+0x00, 0x1e, 0x00, 0x00, 0x20, 0x00, 0x00, 0x22, 0x00, 0x00, 0x24,
+0x00, 0x00, 0x26, 0x00, 0x00, 0x28, 0x00, 0x00, 0x2a, 0x00, 0x00,
+0x2c, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x30, 0x00, 0x00, 0x32, 0x00,
+0x00, 0x34, 0x00, 0x00, 0x36, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3a,
+0x00, 0x00, 0x3c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x40, 0x00, 0x00,
+0x42, 0x03, 0x00, 0x44, 0x01, 0x00, 0x46, 0x0a, 0x21, 0x48, 0x0d,
+0x23, 0x4a, 0x23, 0x1b, 0x4c, 0x37, 0x8f, 0x4e, 0x45, 0x77, 0x50,
+0x52, 0xe2, 0x52, 0x1c, 0x92, 0x54, 0x1c, 0x52, 0x56, 0x07, 0x00,
+0x58, 0x2f, 0xc6, 0x5a, 0x0b, 0x00, 0x5c, 0x30, 0x06, 0x5e, 0x17,
+0x00, 0x60, 0x3d, 0xda, 0x62, 0x29, 0x00, 0x64, 0x3e, 0x41, 0x66,
+0x39, 0x00, 0x68, 0x4c, 0x48, 0x6a, 0x49, 0x00, 0x6c, 0x4c, 0x6c,
+0x6e, 0x11, 0xd2, 0x70, 0x16, 0x0c, 0x72, 0x00, 0x00, 0x74, 0x00,
+0x80, 0x76, 0x0f, 0x00, 0x78, 0x00, 0x80, 0x7a, 0x13, 0x00, 0x7c,
+0x80, 0x00, 0x7e, 0x80, 0x80
+};
+
+unsigned char page_seven[] = {
+0x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+0x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f,
+0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff,
+0x0f, 0xff, 0x0f, 0xff, 0x02, 0xe9, 0x06, 0x8c, 0x06, 0x8c, 0x0f,
+0xff, 0x1a, 0x75, 0x0d, 0x8b, 0x04, 0xe9, 0x0b, 0x16, 0x1a, 0x38,
+0x0d, 0xc8, 0x04, 0x6f, 0x0b, 0x91, 0x0f, 0xff, 0x06, 0x40, 0x06,
+0x40, 0x02, 0x8f, 0x0f, 0xff, 0x06, 0x62, 0x06, 0x62, 0x02, 0x7b,
+0x0f, 0xff, 0x06, 0x97, 0x06, 0x97, 0x02, 0x52, 0x0f, 0xff, 0x06,
+0xf6, 0x06, 0xf6, 0x02, 0x19, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55,
+0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x14,
+0xda, 0x0d, 0x93, 0x04, 0xda, 0x05, 0x93, 0x14, 0xda, 0x0d, 0x93,
+0x04, 0xda, 0x05, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x00
+};
+
+unsigned char page_zero_v2[] = {
+0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+unsigned char page_one_v2[] = {
+0x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+unsigned char page_two_v2[] = {
+0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00
+};
+unsigned char page_three_v2[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00
+};
+unsigned char page_four_v2[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00
+};
+
+unsigned char page_seven_v2[] = {
+0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+unsigned char mod_v2[] = {
+0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02,
+0x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05,
+0x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0,
+0x20, 0xb1, 0x20, 0xb2, 0x20, 0xb3, 0x20, 0xb4, 0x20, 0xb5, 0x20,
+0xb6, 0x20, 0xb7, 0x20, 0xf0, 0x20, 0xf1, 0x20, 0xf2, 0x20, 0xf3,
+0x20, 0xf4, 0x20, 0xf5, 0x20, 0xf6, 0x20, 0xf7, 0x20, 0x10, 0xff,
+0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x14, 0xff, 0x15, 0xff, 0x16,
+0xff, 0x17, 0xff, 0x20, 0xff, 0x21, 0xff, 0x22, 0xff, 0x23, 0xff,
+0x24, 0xff, 0x25, 0xff, 0x26, 0xff, 0x27, 0xff, 0x30, 0x00, 0x31,
+0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00,
+0x37, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44,
+0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x50, 0x00, 0x51, 0x00,
+0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57,
+0x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00,
+0x65, 0x00, 0x66, 0x00, 0x67, 0x00, 0x70, 0xc0, 0x71, 0xc0, 0x72,
+0xc0, 0x73, 0xc0, 0x74, 0xc0, 0x75, 0xc0, 0x76, 0xc0, 0x77, 0xc0,
+0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85,
+0x00, 0x86, 0x00, 0x87, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00,
+0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0xa0,
+0x00, 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa5, 0x00,
+0xa6, 0x00, 0xa7, 0x00, 0xc0, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
+0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xd0, 0x00,
+0xd1, 0x00, 0xd2, 0x00, 0xd3, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0xd6,
+0x00, 0xd7, 0x00, 0xe0, 0x00, 0xe1, 0x00, 0xe2, 0x00, 0xe3, 0x00,
+0xe4, 0x00, 0xe5, 0x00, 0xe6, 0x00, 0xe7, 0x00, 0x01, 0x00, 0x02,
+0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03,
+0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01,
+0x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01
+};
+unsigned char coefficients[] = {
+0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03,
+0x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49,
+0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01,
+0x40, 0x02, 0x40, 0x01, 0x41, 0x02, 0x60, 0x07, 0x40, 0x00, 0x00,
+0x07, 0x41, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00, 0x07, 0x4a, 0x00,
+0x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x4a, 0x01, 0x20, 0x07, 0x47,
+0x00, 0x00, 0x07, 0x4a, 0x00, 0x00, 0x07, 0x7c, 0x00, 0x00, 0x07,
+0x7e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x07, 0x7c, 0x00, 0x00,
+0x07, 0x7e, 0x00, 0x00, 0x07, 0x44, 0x00, 0x00, 0x00, 0x44, 0x01,
+0x00, 0x07, 0x44, 0x00, 0x00, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43,
+0x00, 0x00, 0x00, 0x42, 0x01, 0x1a, 0x00, 0x43, 0x01, 0x20, 0x07,
+0x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00,
+0x07, 0x41, 0x00, 0x00, 0x01, 0x40, 0x02, 0x40, 0x01, 0x41, 0x02,
+0x60, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x44,
+0x0f, 0xff, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07,
+0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x51, 0x06, 0x40,
+0x07, 0x50, 0x06, 0x40, 0x07, 0x4f, 0x03, 0x81, 0x07, 0x53, 0x1a,
+0x76, 0x07, 0x54, 0x0d, 0x8b, 0x07, 0x55, 0x04, 0xe9, 0x07, 0x56,
+0x0b, 0x17, 0x07, 0x57, 0x1a, 0x38, 0x07, 0x58, 0x0d, 0xc9, 0x07,
+0x59, 0x04, 0x6f, 0x07, 0x5a, 0x0b, 0x91, 0x07, 0x73, 0x14, 0xda,
+0x07, 0x74, 0x0d, 0x93, 0x07, 0x75, 0x04, 0xd9, 0x07, 0x76, 0x05,
+0x93, 0x07, 0x77, 0x14, 0xda, 0x07, 0x78, 0x0d, 0x93, 0x07, 0x79,
+0x04, 0xd9, 0x07, 0x7a, 0x05, 0x93, 0x07, 0x5e, 0x03, 0x68, 0x07,
+0x5c, 0x04, 0x31, 0x07, 0x5d, 0x04, 0x31, 0x07, 0x62, 0x03, 0x52,
+0x07, 0x60, 0x04, 0x76, 0x07, 0x61, 0x04, 0x76, 0x07, 0x66, 0x03,
+0x2e, 0x07, 0x64, 0x04, 0xda, 0x07, 0x65, 0x04, 0xda, 0x07, 0x6a,
+0x02, 0xf6, 0x07, 0x68, 0x05, 0x62, 0x07, 0x69, 0x05, 0x62, 0x06,
+0x46, 0x0a, 0x22, 0x06, 0x48, 0x0d, 0x24, 0x06, 0x6e, 0x11, 0xd3,
+0x06, 0x70, 0x15, 0xcb, 0x06, 0x52, 0x20, 0x93, 0x06, 0x54, 0x20,
+0x54, 0x06, 0x4a, 0x27, 0x1d, 0x06, 0x58, 0x2f, 0xc8, 0x06, 0x5c,
+0x30, 0x07, 0x06, 0x4c, 0x37, 0x90, 0x06, 0x60, 0x3d, 0xdb, 0x06,
+0x64, 0x3e, 0x42, 0x06, 0x4e, 0x45, 0x78, 0x06, 0x68, 0x4c, 0x48,
+0x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02,
+0xba
+};
+unsigned char coefficients2[] = {
+0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f,
+0xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d,
+0x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07,
+0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00,
+0x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00
+};
+unsigned char coefficients3[] = { 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00,
+0x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc,
+0x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01,
+0x47, 0x01, 0x47, 0x01, 0x70, 0x01, 0x70, 0x01, 0x99, 0x01, 0x99,
+0x01, 0xc2, 0x01, 0xc2, 0x01, 0xeb, 0x01, 0xeb, 0x02, 0x14, 0x02,
+0x14, 0x02, 0x3d, 0x02, 0x3d, 0x02, 0x66, 0x02, 0x66, 0x02, 0x8f,
+0x02, 0x8f, 0x02, 0xb8, 0x02, 0xb8, 0x02, 0xe1, 0x02, 0xe1, 0x03,
+0x0a, 0x03, 0x0a, 0x03, 0x33, 0x03, 0x33, 0x03, 0x5c, 0x03, 0x5c,
+0x03, 0x85, 0x03, 0x85, 0x03, 0xae, 0x03, 0xae, 0x03, 0xd7, 0x03,
+0xd7, 0x04, 0x00, 0x04, 0x00, 0x04, 0x28, 0x04, 0x28, 0x04, 0x51,
+0x04, 0x51, 0x04, 0x7a, 0x04, 0x7a, 0x04, 0xa3, 0x04, 0xa3, 0x04,
+0xcc, 0x04, 0xcc, 0x04, 0xf5, 0x04, 0xf5, 0x05, 0x1e, 0x05, 0x1e,
+0x05, 0x47, 0x05, 0x47, 0x05, 0x70, 0x05, 0x70, 0x05, 0x99, 0x05,
+0x99, 0x05, 0xc2, 0x05, 0xc2, 0x05, 0xeb, 0x05, 0xeb, 0x06, 0x14,
+0x06, 0x14, 0x06, 0x3d, 0x06, 0x3d, 0x06, 0x66, 0x06, 0x66, 0x06,
+0x8f, 0x06, 0x8f, 0x06, 0xb8, 0x06, 0xb8, 0x06, 0xe1, 0x06, 0xe1,
+0x07, 0x0a, 0x07, 0x0a, 0x07, 0x33, 0x07, 0x33, 0x07, 0x5c, 0x07,
+0x5c, 0x07, 0x85, 0x07, 0x85, 0x07, 0xae, 0x07, 0xae, 0x07, 0xd7,
+0x07, 0xd7, 0x08, 0x00, 0x08, 0x00, 0x08, 0x28, 0x08, 0x28, 0x08,
+0x51, 0x08, 0x51, 0x08, 0x7a, 0x08, 0x7a, 0x08, 0xa3, 0x08, 0xa3,
+0x08, 0xcc, 0x08, 0xcc, 0x08, 0xf5, 0x08, 0xf5, 0x09, 0x1e, 0x09,
+0x1e, 0x09, 0x47, 0x09, 0x47, 0x09, 0x70, 0x09, 0x70, 0x09, 0x99,
+0x09, 0x99, 0x09, 0xc2, 0x09, 0xc2, 0x09, 0xeb, 0x09, 0xeb, 0x0a,
+0x14, 0x0a, 0x14, 0x0a, 0x3d, 0x0a, 0x3d, 0x0a, 0x66, 0x0a, 0x66,
+0x0a, 0x8f, 0x0a, 0x8f, 0x0a, 0xb8, 0x0a, 0xb8, 0x0a, 0xe1, 0x0a,
+0xe1, 0x0b, 0x0a, 0x0b, 0x0a, 0x0b, 0x33, 0x0b, 0x33, 0x0b, 0x5c,
+0x0b, 0x5c, 0x0b, 0x85, 0x0b, 0x85, 0x0b, 0xae, 0x0b, 0xae, 0x0b,
+0xd7, 0x0b, 0xd7, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x28, 0x0c, 0x28,
+0x0c, 0x51, 0x0c, 0x51, 0x0c, 0x7a, 0x0c, 0x7a, 0x0c, 0xa3, 0x0c,
+0xa3, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xf5, 0x0c, 0xf5, 0x0d, 0x1e,
+0x0d, 0x1e, 0x0d, 0x47, 0x0d, 0x47, 0x0d, 0x70, 0x0d, 0x70, 0x0d,
+0x99, 0x0d, 0x99, 0x0d, 0xc2, 0x0d, 0xc2, 0x0d, 0xeb, 0x0d, 0xeb,
+0x0e, 0x14, 0x0e, 0x14, 0x0e, 0x3d, 0x0e, 0x3d, 0x0e, 0x66, 0x0e,
+0x66, 0x0e, 0x8f, 0x0e, 0x8f, 0x0e, 0xb8, 0x0e, 0xb8, 0x0e, 0xe1,
+0x0e, 0xe1, 0x0f, 0x0a, 0x0f, 0x0a, 0x0f, 0x33, 0x0f, 0x33, 0x0f,
+0x5c, 0x0f, 0x5c, 0x0f, 0x85, 0x0f, 0x85, 0x0f, 0xae, 0x0f, 0xae,
+0x0f, 0xd7, 0x0f, 0xd7, 0x0f, 0xff, 0x0f, 0xff
+};
+
diff -u --recursive --new-file v2.1.109/linux/drivers/sound/yss225.h linux/drivers/sound/yss225.h
--- v2.1.109/linux/drivers/sound/yss225.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/yss225.h	Sat Jul 18 14:11:41 1998
@@ -0,0 +1,24 @@
+#ifndef __yss255_h__
+#define __yss255_h__
+
+extern unsigned char page_zero[256];
+extern unsigned char page_one[256];
+extern unsigned char page_two[128];
+extern unsigned char page_three[128];
+extern unsigned char page_four[128];
+extern unsigned char page_six[192];
+extern unsigned char page_seven[256];
+extern unsigned char page_zero_v2[96];
+extern unsigned char page_one_v2[96];
+extern unsigned char page_two_v2[48];
+extern unsigned char page_three_v2[48];
+extern unsigned char page_four_v2[48];
+extern unsigned char page_seven_v2[96];
+extern unsigned char mod_v2[304];
+extern unsigned char coefficients[364];
+extern unsigned char coefficients2[56];
+extern unsigned char coefficients3[404];
+
+
+#endif __ys225_h__
+
diff -u --recursive --new-file v2.1.109/linux/drivers/video/Config.in linux/drivers/video/Config.in
--- v2.1.109/linux/drivers/video/Config.in	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/Config.in	Sat Jul 18 13:55:45 1998
@@ -31,15 +31,14 @@
   fi
   if [ "$CONFIG_PPC" = "y" ]; then
     bool 'Open Firmware frame buffer device support' CONFIG_FB_OF
-    bool 'S3 Trio frame buffer device support' CONFIG_FB_S3TRIO
     if [ "$CONFIG_FB_OF" = "y" ]; then
 #     bool 'Apple "control" display support' CONFIG_FB_CONTROL
 #     bool 'Apple "platinum" display support' CONFIG_FB_PLATINUM
 #     bool 'Apple "valkyrie" display support' CONFIG_FB_VALKYRIE
       bool 'ATI Mach64 display support' CONFIG_FB_ATY
 #     bool 'IMS Twin Turbo display support' CONFIG_FB_IMSTT
-#     bool 'Chips 65550 display support' CONFIG_FB_CT65550
-#     bool 'S3 Trio display support' CONFIG_FB_S3TRIO
+      bool 'Chips 65550 display support' CONFIG_FB_CT65550
+      bool 'S3 Trio display support' CONFIG_FB_S3TRIO
     fi
   fi
   if [ "$CONFIG_MAC" = "y" ]; then
@@ -58,20 +57,23 @@
     tristate 'TGA framebuffer support' CONFIG_FB_TGA
   fi
   if [ "$ARCH" = "i386" ]; then
-    if [ "$CONFIG_VGA_CONSOLE" != "y" ]; then
-      bool 'VESA VGA graphics console' CONFIG_FB_VESA
-      define_bool CONFIG_VIDEO_SELECT y
-    fi
+    bool 'VESA VGA graphics console' CONFIG_FB_VESA
+    define_bool CONFIG_VIDEO_SELECT y
     tristate 'MDA dual-headed support' CONFIG_FB_MDA
   fi
   if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
-    bool 'PROM framebuffer' CONFIG_FB_PROM
     bool 'SBUS and UPA framebuffers' CONFIG_FB_SBUS
     if [ "$CONFIG_FB_SBUS" != "n" ]; then
       if [ "$ARCH" = "sparc64" ]; then
-	bool 'Creator/Creator3D support' CONFIG_FB_CREATOR
+	bool '  Creator/Creator3D support' CONFIG_FB_CREATOR
+      fi
+      bool '  CGsix (GX,GXplus) support' CONFIG_FB_CGSIX
+    fi
+    if [ "$CONFIG_PCI" != "n" ]; then
+      bool 'PCI framebuffers' CONFIG_FB_PCI
+      if [ "$CONFIG_FB_PCI" != "n" ]; then
+        bool '  ATI Mach64 display support' CONFIG_FB_ATY
       fi
-      bool 'CGsix (GX,GXplus) support' CONFIG_FB_CGSIX
     fi
   fi
   tristate 'Virtual Frame Buffer support (ONLY FOR TESTING!)' CONFIG_FB_VIRTUAL
@@ -143,10 +145,10 @@
 	define_bool CONFIG_FBCON_CFB16 m
       fi
     fi
-    if [ "$CONFIG_FB_VIRTUAL" = "y" ]; then
+    if [ "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" ]; then
       define_bool CONFIG_FBCON_CFB24 y
     else
-      if [ "$CONFIG_FB_VIRTUAL" = "m" ]; then
+      if [ "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then
 	define_bool CONFIG_FBCON_CFB24 m
       fi
     fi
diff -u --recursive --new-file v2.1.109/linux/drivers/video/Makefile linux/drivers/video/Makefile
--- v2.1.109/linux/drivers/video/Makefile	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/Makefile	Sat Jul 18 13:55:45 1998
@@ -29,9 +29,14 @@
   L_OBJS += dummycon.o
 endif
 
+ifeq ($(CONFIG_PROM_CONSOLE),y)
+  L_OBJS += promcon.o
+endif
+
 ifeq ($(CONFIG_FB),y)
-  L_OBJS += fonts.o font_8x8.o font_8x16.o pearl_8x8.o font_6x11.o font_sun8x16.o
-  OX_OBJS += fbcon.o fbcmap.o fbgen.o
+  L_OBJS += fonts.o font_8x8.o font_8x16.o pearl_8x8.o font_6x11.o font_sun8x16.o font_sun12x22.o
+  OX_OBJS += fbcon.o fbcmap.o
+# fbgen is not compiled by default since nobody uses it yet
 endif
 
 # Frame Buffer Devices
@@ -60,6 +65,10 @@
 L_OBJS += atyfb.o
 endif
 
+ifeq ($(CONFIG_FB_CT65550),y)
+L_OBJS += chipsfb.o
+endif
+
 ifeq ($(CONFIG_FB_CYBER),y)
 L_OBJS += cyberfb.o
 else
@@ -77,7 +86,7 @@
 endif
 
 ifeq ($(CONFIG_FB_OF),y)
-L_OBJS += offb.o
+L_OBJS += offb.o macmodes.o
 endif
 
 ifeq ($(CONFIG_FB_RETINAZ3),y)
@@ -132,14 +141,6 @@
   endif
 endif
 
-ifeq ($(CONFIG_FB_PROM),y)
-L_OBJS += promfb.o
-else
-  ifeq ($(CONFIG_FB_PROM),m)
-  M_OBJS += promfb.o
-  endif
-endif
-
 ifeq ($(CONFIG_FB_SBUS),y)
 L_OBJS += sbusfb.o
   ifeq ($(CONFIG_FB_CREATOR),y)
@@ -316,12 +317,6 @@
 
 ifdef CONFIG_VGA_CONSOLE
 L_OBJS += vgacon.o
-endif
-
-# Console Wrapper
-
-ifdef CONFIG_ABSCON_COMPAT
-L_OBJS += compatcon.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.109/linux/drivers/video/S3triofb.c linux/drivers/video/S3triofb.c
--- v2.1.109/linux/drivers/video/S3triofb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/S3triofb.c	Sat Jul 18 13:55:46 1998
@@ -94,14 +94,6 @@
 static int s3trio_ioctl(struct inode *inode, struct file *file, u_int cmd,
 			u_long arg, int con, struct fb_info *info);
 
-#ifdef CONFIG_FB_COMPAT_XPMAC
-extern struct vc_mode display_info;
-extern struct fb_info *console_fb_info;
-extern int (*console_setmode_ptr)(struct vc_mode *, int);
-extern int (*console_set_cmap_ptr)(struct fb_cmap *, int, int,
-				   struct fb_info *);
-static int s3trio_console_setmode(struct vc_mode *mode, int doit);
-#endif /* CONFIG_FB_COMPAT_XPMAC */
 
     /*
      *  Interface to the low level console driver
@@ -616,8 +608,6 @@
 	display_info.cmap_adr_address = address + 0x1008000 + 0x3c8;
 	display_info.cmap_data_address = address + 0x1008000 + 0x3c9;
 	console_fb_info = &fb_info;
-	console_setmode_ptr = s3trio_console_setmode;
-	console_set_cmap_ptr = s3trio_set_cmap;
     }
 #endif /* CONFIG_FB_COMPAT_XPMAC) */
 
@@ -730,51 +720,6 @@
 		    &fb_display[con].var, 1, s3trio_setcolreg, &fb_info);
 }
 
-#ifdef CONFIG_FB_COMPAT_XPMAC
-
-    /*
-     *  Backward compatibility mode for Xpmac
-     */
-
-static int s3trio_console_setmode(struct vc_mode *mode, int doit)
-{
-#if 1
-    return -EINVAL;
-#else
-    int err;
-    struct fb_var_screeninfo var;
-    struct s3trio_par par;
-
-    if (mode->mode <= 0 || mode->mode > VMODE_MAX )
-        return -EINVAL;
-    par.video_mode = mode->mode;
-
-    switch (mode->depth) {
-        case 24:
-        case 32:
-            par.color_mode = CMODE_32;
-            break;
-        case 16:
-            par.color_mode = CMODE_16;
-            break;
-        case 8:
-        case 0:			/* (default) */
-            par.color_mode = CMODE_8;
-            break;
-        default:
-            return -EINVAL;
-    }
-    encode_var(&var, &par);
-    if ((err = decode_var(&var, &par)))
-        return err;
-    if (doit)
-        s3trio_set_var(&var, currcon, 0);
-    return 0;
-#endif
-}
-
-#endif /* CONFIG_FB_COMPAT_XPMAC */
-
 void s3triofb_setup(char *options, int *ints) {
 
         return;
@@ -933,6 +878,6 @@
 
 static struct display_switch fbcon_trio8 = {
    fbcon_cfb8_setup, fbcon_trio8_bmove, fbcon_trio8_clear, fbcon_trio8_putc,
-   fbcon_trio8_putcs, fbcon_trio8_revc, NULL
+   fbcon_trio8_putcs, fbcon_trio8_revc, NULL, NULL, FONTWIDTH(8)
 };
 #endif
diff -u --recursive --new-file v2.1.109/linux/drivers/video/atafb.c linux/drivers/video/atafb.c
--- v2.1.109/linux/drivers/video/atafb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/atafb.c	Sat Jul 18 13:55:46 1998
@@ -2671,7 +2671,7 @@
 			sprintf(default_name,"default%d",i);
 			default_par=get_video_mode(default_name);
 			if (! default_par)
-				panic("can't set default video mode\n");
+				panic("can't set default video mode");
 			var=atafb_predefined[default_par-1];
 			var.activate = FB_ACTIVATE_TEST;
 			if (! do_fb_set_var(&var,1))
@@ -2768,7 +2768,7 @@
 #else /* ATAFB_STE */
 		/* no default driver included */
 		/* Nobody will ever see this message :-) */
-		panic("Cannot initialize video hardware\n");
+		panic("Cannot initialize video hardware");
 #endif
 	} while (0);
 
@@ -2791,6 +2791,8 @@
 		mem_req = ((mem_req + PAGE_SIZE - 1) & PAGE_MASK) + PAGE_SIZE;
 		screen_base = (unsigned long)atari_stram_alloc(mem_req, NULL,
 							       "atafb");
+		if (!screen_base)
+			panic("Cannot allocate screen memory");
 		memset((char *) screen_base, 0, mem_req);
 		pad = ((screen_base + PAGE_SIZE-1) & PAGE_MASK) - screen_base;
 		screen_base+=pad;
diff -u --recursive --new-file v2.1.109/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.1.109/linux/drivers/video/atyfb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/atyfb.c	Sat Jul 18 13:55:46 1998
@@ -53,6 +53,9 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #endif
+#ifdef __sparc__
+#include <asm/pbm.h>
+#endif
 
 #include "aty.h"
 #include "fbcon.h"
@@ -239,12 +242,21 @@
     u32 h_sync_neg, v_sync_neg;
 };
 
+struct pci_mmap_map {
+    unsigned long voff;
+    unsigned long poff;
+    unsigned long size;
+    unsigned long prot_flag;
+    unsigned long prot_mask;
+};
+
 struct fb_info_aty {
     struct fb_info fb_info;
     unsigned long ati_regbase_phys;
     unsigned long ati_regbase;
     unsigned long frame_buffer_phys;
     unsigned long frame_buffer;
+    struct pci_mmap_map *mmap_map;
     u8 chip_class;
     u8 pixclock_lim_8;	/* ps, <= 8 bpp */
     u8 pixclock_lim_hi;	/* ps, > 8 bpp */
@@ -387,6 +399,10 @@
 			  struct fb_info *info);
 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
 		       u_long arg, int con, struct fb_info *info);
+#ifdef __sparc__
+static int atyfb_mmap(struct fb_info *info, struct file *file,
+		      struct vm_area_struct *vma);
+#endif
 
 
     /*
@@ -428,7 +444,7 @@
      */
 
 static int aty_init(struct fb_info_aty *info, const char *name);
-#ifndef CONFIG_FB_OF
+#ifdef CONFIG_ATARI
 static int store_video_par(char *videopar, unsigned char m64_num);
 static char *strtoke(char *s, const char *ct);
 #endif
@@ -442,7 +458,12 @@
 
 static struct fb_ops atyfb_ops = {
     atyfb_open, atyfb_release, atyfb_get_fix, atyfb_get_var, atyfb_set_var,
-    atyfb_get_cmap, atyfb_set_cmap, atyfb_pan_display, atyfb_ioctl
+    atyfb_get_cmap, atyfb_set_cmap, atyfb_pan_display, atyfb_ioctl,
+#ifdef __sparc__
+    atyfb_mmap
+#else
+    NULL
+#endif
 };
 
 
@@ -785,7 +806,7 @@
 
 static void atyfb_set_par(struct atyfb_par *par, struct fb_info_aty *info)
 {
-    int i, j, hres;
+    int i, j = 0, hres;
     struct aty_regvals *init = get_aty_struct(par->hw.gx.vmode, info);
     int vram_type = aty_ld_le32(CONFIG_STAT0, info) & 7;
 
@@ -911,8 +932,22 @@
 	    j = 0x47052100;
 	    break;
 
-	case CLASS_CT:
 	case CLASS_VT:
+	    if (vram_type == 4) {
+		/*
+		 * What to do here? - The contents of MEM_CNTL do not
+		 * seem to match my documentation, and touching this
+		 * register makes the output unusable.
+		 * (green bars across the screen and similar effects).
+		 *
+		 * Eddie C. Dost  (ecd@skynet.be)
+		 */
+		j = 0x87010184;
+		break;
+	     }
+	     /* fallthrough */
+
+	case CLASS_CT:
 	    aty_st_le32(BUS_CNTL, 0x680000f9, info);
 	    switch (info->total_vram) {
 		case 0x00100000:
@@ -1208,7 +1243,7 @@
     u_int h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
     u_int v_total, v_disp;
     u_int v_sync_strt, v_sync_wid, v_sync_pol;
-    u_int xtalin, vclk;
+    u_int xtalin, vclk = 0;
     u8 pll_ref_div, vclk_fb_div, vclk_post_div, pll_ext_cntl;
 
     memset(var, 0, sizeof(struct fb_var_screeninfo));
@@ -1476,6 +1511,7 @@
 		    display->dispsw = NULL;
 		    break;
 	    }
+	    display->scrollmode = accel ? 0 : SCROLL_YREDRAW;
 	    if (info->changevar)
 		(*info->changevar)(con);
 	}
@@ -1564,6 +1600,112 @@
     return -EINVAL;
 }
 
+#ifdef __sparc__
+static int atyfb_mmap(struct fb_info *info, struct file *file,
+		      struct vm_area_struct *vma)
+{
+	struct fb_info_aty *fb = (struct fb_info_aty *)info;
+	unsigned int size, page, map_size = 0;
+	unsigned long map_offset = 0;
+	int i;
+
+	if (!fb->mmap_map)
+		return -ENXIO;
+
+	size = vma->vm_end - vma->vm_start;
+	if (vma->vm_offset & ~PAGE_MASK)
+		return -ENXIO;
+
+	/* To stop the swapper from even considering these pages. */
+	vma->vm_flags |= (VM_SHM | VM_LOCKED);
+
+#ifdef __sparc_v9__
+	/* Align it as much as desirable */
+	{
+		int j, max = -1, align;
+		
+		map_offset = vma->vm_offset+size;
+		for (i = 0; fb->mmap_map[i].size; i++) {
+			if (fb->mmap_map[i].voff < vma->vm_offset)
+				continue;
+			if (fb->mmap_map[i].voff >= map_offset)
+				break;
+			if (max < 0 ||
+			    fb->mmap_map[i].size > fb->mmap_map[max].size)
+				max = i;
+		}
+		if (max >= 0) {
+			j = fb->mmap_map[max].size;
+			if (fb->mmap_map[max].voff + j > map_offset)
+				j = map_offset - fb->mmap_map[max].voff;
+			for (align = 0x400000; align > PAGE_SIZE; align >>= 3)
+				if (j >= align &&
+				    !(fb->mmap_map[max].poff & (align - 1)))
+					break;
+			if (align > PAGE_SIZE) {
+				j = align;
+				align = j - ((vma->vm_start
+					      + fb->mmap_map[max].voff
+					      - vma->vm_offset) & (j - 1));
+				if (align != j) {
+					struct vm_area_struct *vmm;
+
+					vmm = find_vma(current->mm,
+						       vma->vm_start);
+					if (!vmm || vmm->vm_start
+						    >= vma->vm_end + align) {
+						vma->vm_start += align;
+						vma->vm_end += align;
+					}
+				}
+			}
+		}
+	}
+#endif	
+
+	/* Each page, see which map applies */
+	for (page = 0; page < size; ) {
+		map_size = 0;
+		for (i = 0; fb->mmap_map[i].size; i++) {
+			unsigned long start = fb->mmap_map[i].voff;
+			unsigned long end = start + fb->mmap_map[i].size;
+			unsigned long offset = vma->vm_offset + page;
+
+			if (start > offset)
+				continue;
+			if (offset > end)
+				continue;
+
+			map_size = fb->mmap_map[i].size - (offset - start);
+			map_offset = fb->mmap_map[i].poff + (offset - start);
+			break;
+		}
+		if (!map_size) {
+			page += PAGE_SIZE;
+			continue;
+		}
+		if (page + map_size > size)
+			map_size = size - page;
+
+		pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
+		pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
+
+		if (remap_page_range(vma->vm_start + page, map_offset,
+				     map_size, vma->vm_page_prot))
+			return -EAGAIN;
+
+		page += map_size;
+	}
+
+	if (!map_size)
+		return -EINVAL;
+
+	vma->vm_file = file;
+	file->f_count++;
+	vma->vm_flags |= VM_IO;
+	return 0;
+}
+#endif /* __sparc__ */
 
     /*
      *  Initialisation
@@ -1667,7 +1809,9 @@
 #endif
 
     sense = read_aty_sense(info);
+#if 0
     printk("monitor sense = %x\n", sense);
+#endif
 #if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
     if (default_vmode == VMODE_NVRAM) {
 	default_vmode = nvram_read_byte(NV_VMODE);
@@ -1774,7 +1918,204 @@
     /* We don't want to be called like this. */
     /* We rely on Open Firmware (offb) instead. */
 #elif defined(CONFIG_PCI)
-    /* Anyone who wants to do a PCI probe for an ATI chip? */
+    struct pci_dev *pdev;
+    struct fb_info_aty *info;
+    unsigned long addr;
+    int i, j;
+    u16 tmp;
+
+    for (pdev = pci_devices; pdev; pdev = pdev->next) {
+	if (((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
+	    (pdev->vendor == PCI_VENDOR_ID_ATI)) {
+
+	    info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
+	    if (!info) {
+		printk("atyfb_init: can't alloc fb_info_aty\n");
+		return;
+	    }
+
+	    addr = pdev->base_address[0];
+	    if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+		addr = pdev->base_address[1];
+	    if (!addr)
+		continue;
+
+#ifdef __sparc__
+	    /*
+	     * Map memory-mapped registers.
+	     */
+	    info->ati_regbase = addr + 0x7ffc00;
+	    info->ati_regbase_phys = __pa(addr + 0x7ffc00);
+
+	    /*
+	     * Map in big-endian aperture.
+	     */
+	    info->frame_buffer = (unsigned long)(addr + 0x800000);
+	    info->frame_buffer_phys = __pa(addr + 0x800000);
+
+	    /*
+	     * Figure mmap addresses from PCI config space.
+	     * Split Framebuffer in big- and little-endian halfs.
+	     */
+	    for (i = 0; i < 6 && pdev->base_address[i]; i++)
+		/* nothing */;
+	    j = i + 1;
+
+            info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC);
+	    if (!info->mmap_map) {
+		printk("atyfb_init: can't alloc mmap_map\n");
+		kfree(info);
+	    }
+
+	    memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
+	    for (i = j = 0; i < 6 && pdev->base_address[i]; i++) {
+		int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
+		unsigned long base;
+		u32 size, pbase;
+
+		base = pdev->base_address[i];
+
+		io = (base & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO;
+
+		pci_read_config_dword(pdev, breg, &pbase);
+		pci_write_config_dword(pdev, breg, 0xffffffff);
+		pci_read_config_dword(pdev, breg, &size);
+		pci_write_config_dword(pdev, breg, pbase);
+
+		if (io)
+			size &= ~1;
+		size = ~(size) + 1;
+
+		if (base == addr) {
+			info->mmap_map[j].voff = (pbase + 0x800000)
+								& PAGE_MASK;
+			info->mmap_map[j].poff = __pa((base + 0x800000)
+								& PAGE_MASK);
+			info->mmap_map[j].size = 0x800000;
+			info->mmap_map[j].prot_mask = _PAGE_CACHE;
+			info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE;
+			size -= 0x800000;
+			j++;
+		}
+
+		info->mmap_map[j].voff = pbase & PAGE_MASK;
+		info->mmap_map[j].poff = __pa(base & PAGE_MASK);
+		info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
+		info->mmap_map[j].prot_mask = _PAGE_CACHE;
+		info->mmap_map[j].prot_flag = _PAGE_E;
+		j++;
+	    }
+
+	    /*
+	     * Fix PROMs idea of MEM_CNTL settings...
+	     */
+	    tmp = aty_ld_le32(CONFIG_CHIP_ID, info) & CFG_CHIP_TYPE;
+	    if (tmp == MACH64_VT_ID) {
+		u32 mem = aty_ld_le32(MEM_CNTL, info);
+		switch (mem & 0x0f) {
+		    case 3:
+			mem = (mem & ~(0x0f)) | 2;
+			break;
+		    case 7:
+			mem = (mem & ~(0x0f)) | 3;
+			break;
+		    case 9:
+			mem = (mem & ~(0x0f)) | 4;
+			break;
+		    case 11:
+			mem = (mem & ~(0x0f)) | 5;
+			break;
+		    default:
+			break;
+		}
+		mem &= ~(0x00f00000);
+		aty_st_le32(MEM_CNTL, mem, info);
+	    }
+
+	    /*
+	     * Set default vmode and cmode from PROM properties.
+	     */
+	    {
+		struct pcidev_cookie *cookie = pdev->sysdata;
+		int node = cookie->prom_node;
+		int width = prom_getintdefault(node, "width", 1024);
+		int height = prom_getintdefault(node, "height", 768);
+		int depth = prom_getintdefault(node, "depth", 8);
+
+		switch (depth) {
+		    case 8:
+			default_cmode = CMODE_8;
+			break;
+		    case 16:
+			default_cmode = CMODE_16;
+			break;
+		    case 32:
+			default_cmode = CMODE_32;
+			break;
+		    default:
+			break;
+		}
+
+		switch (width) {
+		    case 1024:
+			if (height == 768)
+			    default_vmode = VMODE_1024_768_75;
+			break;
+		    case 1152:
+			if (height == 870)
+			    default_vmode = VMODE_1152_870_75;
+			break;
+		    case 1280:
+			if (height == 960)
+			    default_vmode = VMODE_1280_960_75;
+			else if (height == 1024)
+			    default_vmode = VMODE_1280_1024_75;
+			break;
+		    default:
+			break;
+		}
+	    }
+
+#else /* __sparc__ */
+
+	    info->ati_regbase = (unsigned long)
+				ioremap(0x7ff000 + addr, 0x1000) + 0xc00;
+
+	    info->ati_regbase_phys = 0x7ff000 + addr;
+	    info->ati_regbase = (unsigned long)
+				ioremap(info->ati_regbase_phys, 0x1000);
+
+	    info->ati_regbase_phys += 0xc00;
+	    info->ati_regbase += 0xc00;
+
+	    /*
+	     * Enable memory-space accesses using config-space
+	     * command register.
+	     */
+	    pci_read_config_word(pdev, PCI_COMMAND, &tmp);
+	    if (!(tmp & PCI_COMMAND_MEMORY)) {
+		tmp |= PCI_COMMAND_MEMORY;
+		pci_write_config_word(pdev, PCI_COMMAND, tmp);
+	    }
+
+#ifdef __BIG_ENDIAN
+	    /* Use the big-endian aperture */
+	    addr += 0x800000;
+#endif
+
+	    /* Map in frame buffer */
+	    info->frame_buffer_phys = addr;
+	    info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
+
+#endif /* __sparc__ */
+
+	    if (!aty_init(info, "PCI")) {
+		if (info->mmap_map)
+		    kfree(info->mmap_map);
+	        kfree(info);
+	    }
+	}
+    }
 #elif defined(CONFIG_ATARI)
     int m64_num;
     struct fb_info_aty *info;
@@ -1979,7 +2320,7 @@
     ssave = send;
     return sbegin;
 }
-#endif /* !CONFIG_FB_OF */
+#endif /* CONFIG_ATARI */
 
 static int atyfbcon_switch(int con, struct fb_info *info)
 {
@@ -2021,14 +2362,20 @@
     u8 gen_cntl;
 
     gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info2);
+#ifndef __sparc__
     if (blank & VESA_VSYNC_SUSPEND)
 	    gen_cntl |= 0x8;
     if (blank & VESA_HSYNC_SUSPEND)
 	    gen_cntl |= 0x4;
     if ((blank & VESA_POWERDOWN) == VESA_POWERDOWN)
 	    gen_cntl |= 0x40;
+#endif
     if (blank == VESA_NO_BLANKING)
 	    gen_cntl &= ~(0x4c);
+#ifdef __sparc__
+    else
+	    gen_cntl |= 0x40;
+#endif
     aty_st_8(CRTC_GEN_CNTL, gen_cntl, info2);
 }
 
@@ -2237,7 +2584,7 @@
 
 static struct display_switch fbcon_aty8 = {
     fbcon_cfb8_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty8_putc,
-    fbcon_aty8_putcs, fbcon_cfb8_revc, NULL
+    fbcon_aty8_putcs, fbcon_cfb8_revc, NULL, NULL, FONTWIDTH(8)
 };
 #endif
 
@@ -2258,7 +2605,7 @@
 
 static struct display_switch fbcon_aty16 = {
     fbcon_cfb16_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty16_putc,
-    fbcon_aty16_putcs, fbcon_cfb16_revc, NULL
+    fbcon_aty16_putcs, fbcon_cfb16_revc, NULL, FONTWIDTH(8)
 };
 #endif
 
@@ -2279,7 +2626,7 @@
 
 static struct display_switch fbcon_aty32 = {
     fbcon_cfb32_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty32_putc,
-    fbcon_aty32_putcs, fbcon_cfb32_revc, NULL
+    fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, FONTWIDTH(8)
 };
 #endif
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/cgsixfb.c linux/drivers/video/cgsixfb.c
--- v2.1.109/linux/drivers/video/cgsixfb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/cgsixfb.c	Sat Jul 18 13:55:46 1998
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.1 1998/07/06 15:51:09 jj Exp $
+/* $Id: cgsixfb.c,v 1.2 1998/07/13 12:47:14 jj Exp $
  * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -226,37 +226,6 @@
 	p->next_plane = 0;
 }
 
-static void cg6_bmove(struct display *p, int sy, int sx, int dy, int dx,
-			   int height, int width)
-{
-#if 0
-	int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
-	u8 *src, *dst;
-
-	if (sx == 0 && dx == 0 && width * 32 == bytes)
-		mymemmove(p->screen_base + dy * linesize,
-				  p->screen_base + sy * linesize,
-				  height * linesize);
-	else if (dy < sy || (dy == sy && dx < sx)) {
-		src = p->screen_base + sy * linesize + sx * 32;
-		dst = p->screen_base + dy * linesize + dx * 32;
-		for (rows = height * p->fontheight ; rows-- ;) {
-			mymemmove(dst, src, width * 32);
-			src += bytes;
-			dst += bytes;
-		}
-	} else {
-		src = p->screen_base + (sy+height) * linesize + sx * 32 - bytes;
-		dst = p->screen_base + (dy+height) * linesize + dx * 32 - bytes;
-		for (rows = height * p->fontheight ; rows-- ;) {
-			mymemmove(dst, src, width * 32);
-			src -= bytes;
-			dst -= bytes;
-		}
-	}
-#endif	
-}
-
 static void cg6_clear(struct vc_data *conp, struct display *p, int sy, int sx,
 		      int height, int width)
 {
@@ -310,113 +279,160 @@
 
 static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
 {
-#if 0
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct cg6_fbc *fbc = fb->s.cg6.fbc;
-	int i, xy;
+	int i, x, y;
 	u8 *fd;
 
-	if (p->fontheight == 16) {
-		xy = (yy << (16 + 4));
-		fd = p->fontdata + ((c & 0xff) << 4);
+	if (p->fontheightlog) {
+		y = fb->y_margin + (yy << p->fontheightlog);
+		i = ((c & 0xff) << p->fontheightlog);
 	} else {
-		xy = ((yy * p->fontheight) << 16);
-		fd = p->fontdata + (c & 0xff) * p->fontheight;
+		y = fb->y_margin + (yy * p->fontheight);
+		i = (c & 0xff) * p->fontheight;
+	}
+	if (p->fontwidth <= 8)
+		fd = p->fontdata + i;
+	else
+		fd = p->fontdata + (i << 1);
+	if (p->fontwidthlog)
+		x = fb->x_margin + (xx << p->fontwidthlog);
+	else
+		x = fb->x_margin + (xx * p->fontwidth);
+	do {
+		i = fbc->s;
+	} while (i & 0x10000000);
+	fbc->fg = attr_fg_col(c);
+	fbc->bg = attr_bg_col(c);
+	fbc->mode = 0x140000;
+	fbc->alu = 0xe880fc30;
+	fbc->pixelm = ~(0);
+	fbc->s = 0;
+	fbc->clip = 0;
+	fbc->pm = 0xff;
+	fbc->incx = 0;
+	fbc->incy = 1;
+	fbc->x0 = x;
+	fbc->x1 = x + p->fontwidth - 1;
+	fbc->y0 = y;
+	if (p->fontwidth <= 8) {
+		for (i = 0; i < p->fontheight; i++)
+			fbc->font = *fd++ << 24;
+	} else {
+		for (i = 0; i < p->fontheight; i++) {
+			fbc->font = *(u16 *)fd << 16;
+			fd += 2;
+		}
 	}
-	xy += (xx << 3) + fb->s.cg6.xy_margin;
-	fbc->ppc = 0x203;
-	fbc->fg = cg6_cmap[attr_fg_col(c)];
-	fbc->fbc = 0x2000707f;
-	fbc->rop = 0x83;
-	fbc->pmask = 0xffffffff;
-	fbc->bg = cg6_cmap[attr_bg_col(c)];
-	fbc->fontw = 8;
-	fbc->fontinc = 0x10000;
-	fbc->fontxy = xy;
-	for (i = 0; i < p->fontheight; i++)
-		fbc->font = *fd++ << 24;
-#endif		
 }
 
 static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
 		      int count, int yy, int xx)
 {
-#if 0
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct cg6_fbc *fbc = fb->s.cg6.fbc;
-	int i, xy;
+	int i, x, y;
 	u8 *fd1, *fd2, *fd3, *fd4;
 
-	fbc->ppc = 0x203;
-	fbc->fg = cg6_cmap[attr_fg_col(*s)];
-	fbc->fbc = 0x2000707f;
-	fbc->rop = 0x83;
-	fbc->pmask = 0xffffffff;
-	fbc->bg = cg6_cmap[attr_bg_col(*s)];
-	if (p->fontheight == 16) {
-		xy = (yy << (16 + 4)) + (xx << 3) + fb->s.cg6.xy_margin;
+	do {
+		i = fbc->s;
+	} while (i & 0x10000000);
+	fbc->fg = attr_fg_col(*s);
+	fbc->bg = attr_bg_col(*s);
+	fbc->mode = 0x140000;
+	fbc->alu = 0xe880fc30;
+	fbc->pixelm = ~(0);
+	fbc->s = 0;
+	fbc->clip = 0;
+	fbc->pm = 0xff;
+	x = fb->x_margin;
+	y = fb->y_margin;
+	if (p->fontwidthlog)
+		x += (xx << p->fontwidthlog);
+	else
+		x += xx * p->fontwidth;
+	if (p->fontheightlog)
+		y += (yy << p->fontheightlog);
+	else
+		y += (yy * p->fontheight);
+	if (p->fontwidth <= 8) {
 		while (count >= 4) {
 			count -= 4;
-			fbc->fontw = 32;
-			fbc->fontinc = 0x10000;
-			fbc->fontxy = xy;
-			fd1 = p->fontdata + ((*s++ & 0xff) << 4);
-			fd2 = p->fontdata + ((*s++ & 0xff) << 4);
-			fd3 = p->fontdata + ((*s++ & 0xff) << 4);
-			fd4 = p->fontdata + ((*s++ & 0xff) << 4);
-			for (i = 0; i < 16; i++)
-				fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << 8)) << 8)) << 8);
-			xy += 32;
-		}
-		while (count) {
-			count--;
-			fbc->fontw = 8;
-			fbc->fontinc = 0x10000;
-			fbc->fontxy = xy;
-			fd1 = p->fontdata + ((*s++ & 0xff) << 4);
-			for (i = 0; i < 16; i++)
-				fbc->font = *fd1++ << 24;
-			xy += 8;
+			fbc->incx = 0;
+			fbc->incy = 1;
+			fbc->x0 = x;
+			fbc->x1 = (x += 4 * p->fontwidth) - 1;
+			fbc->y0 = y;
+			if (p->fontheightlog) {
+				fd1 = p->fontdata + ((*s++ & 0xff) << p->fontheightlog);
+				fd2 = p->fontdata + ((*s++ & 0xff) << p->fontheightlog);
+				fd3 = p->fontdata + ((*s++ & 0xff) << p->fontheightlog);
+				fd4 = p->fontdata + ((*s++ & 0xff) << p->fontheightlog);
+			} else {
+				fd1 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
+				fd2 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
+				fd3 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
+				fd4 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
+			}
+			if (p->fontwidth == 8) {
+				for (i = 0; i < p->fontheight; i++)
+					fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
+						<< 8)) << 8)) << 8);
+			} else {
+				for (i = 0; i < p->fontheight; i++)
+					fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
+						<< p->fontwidth)) << p->fontwidth)) << p->fontwidth)) << (24 - 3 * p->fontwidth);
+			}
 		}
 	} else {
-		xy = ((yy * p->fontheight) << 16) + (xx << 3) + fb->s.cg6.xy_margin;
-		while (count >= 4) {
-			count -= 4;
-			fbc->fontw = 32;
-			fbc->fontinc = 0x10000;
-			fbc->fontxy = xy;
-			fd1 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
-			fd2 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
-			fd3 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
-			fd4 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
-			for (i = 0; i < p->fontheight; i++)
-				fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << 8)) << 8)) << 8);
-			xy += 32;
+		while (count >= 2) {
+			count -= 2;
+			fbc->incx = 0;
+			fbc->incy = 1;
+			fbc->x0 = x;
+			fbc->x1 = (x += 2 * p->fontwidth) - 1;
+			fbc->y0 = y;
+			if (p->fontheightlog) {
+				fd1 = p->fontdata + ((*s++ & 0xff) << (p->fontheightlog + 1));
+				fd2 = p->fontdata + ((*s++ & 0xff) << (p->fontheightlog + 1));
+			} else {
+				fd1 = p->fontdata + (((*s++ & 0xff) * p->fontheight) << 1);
+				fd2 = p->fontdata + (((*s++ & 0xff) * p->fontheight) << 1);
+			}
+			for (i = 0; i < p->fontheight; i++) {
+				fbc->font = ((((u32)*(u16 *)fd1) << p->fontwidth) | ((u32)*(u16 *)fd2)) << (16 - p->fontwidth);
+				fd1 += 2; fd2 += 2;
+			}
 		}
-		while (count) {
-			count--;
-			fbc->fontw = 8;
-			fbc->fontinc = 0x10000;
-			fbc->fontxy = xy;
-			fd1 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
-			for (i = 0; i < 16; i++)
+	}
+	while (count) {
+		count--;
+		fbc->incx = 0;
+		fbc->incy = 1;
+		fbc->x0 = x;
+		fbc->x1 = (x += p->fontwidth) - 1;
+		fbc->y0 = y;
+		if (p->fontheightlog)
+			i = ((*s++ & 0xff) << p->fontheightlog);
+		else
+			i = ((*s++ & 0xff) * p->fontheight);
+		if (p->fontwidth <= 8) {
+			fd1 = p->fontdata + i;
+			for (i = 0; i < p->fontheight; i++)
 				fbc->font = *fd1++ << 24;
-			xy += 8;
+		} else {
+			fd1 = p->fontdata + (i << 1);
+			for (i = 0; i < p->fontheight; i++) {
+				fbc->font = *(u16 *)fd1 << 16;
+				fd1 += 2;
+			}
 		}
 	}
-#endif
 }
 
 static void cg6_revc(struct display *p, int xx, int yy)
 {
-	u8 *dest;
-	int bytes=p->next_line, rows;
-        
-	dest = p->screen_base + yy * p->fontheight * bytes + xx * 8;
-	for (rows = p->fontheight ; rows-- ; dest += bytes) {
-		((u32 *)dest)[0] ^= 0x0f0f0f0f;
-		((u32 *)dest)[1] ^= 0x0f0f0f0f;
-	}
+	/* Not used if hw cursor */
 }
 
 static void cg6_loadcmap (struct fb_info_sbusfb *fb, int index, int count)
@@ -433,7 +449,8 @@
 }
 
 static struct display_switch cg6_dispsw __initdata = {
-	cg6_setup, cg6_bmove, cg6_clear, cg6_putc, cg6_putcs, cg6_revc, NULL
+	cg6_setup, fbcon_redraw_bmove, cg6_clear, cg6_putc, cg6_putcs, cg6_revc, 
+	NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
 };
 
 static void cg6_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
@@ -477,6 +494,63 @@
 	fb->s.cg6.thc->thc_cursxy = v;
 }
 
+static void cg6_blank (struct fb_info_sbusfb *fb)
+{
+	fb->s.cg6.thc->thc_misc &= ~CG6_THC_MISC_VIDEO;
+}
+
+static void cg6_unblank (struct fb_info_sbusfb *fb)
+{
+	fb->s.cg6.thc->thc_misc |= CG6_THC_MISC_VIDEO;
+}
+
+static void cg6_reset (struct fb_info_sbusfb *fb)
+{
+	unsigned int rev, conf;
+	
+	/* Turn off stuff in the Transform Engine. */
+	fb->s.cg6.tec->tec_matrix = 0;
+	fb->s.cg6.tec->tec_clip = 0;
+	fb->s.cg6.tec->tec_vdc = 0;
+
+	/* Take care of bugs in old revisions. */
+	rev = (*(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;
+	if (rev < 5) {
+		conf = (*(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) |
+			CG6_FHC_CPU_68020 | CG6_FHC_TEST |
+			(11 << CG6_FHC_TEST_X_SHIFT) |
+			(11 << CG6_FHC_TEST_Y_SHIFT);
+		if (rev < 2)
+			conf |= CG6_FHC_DST_DISABLE;
+		*(fb->s.cg6.fhc) = conf;
+	}
+
+	/* Set things in the FBC. */
+	fb->s.cg6.fbc->mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
+			    CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
+			    CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
+			    CG6_FBC_BDISP_MASK);
+	fb->s.cg6.fbc->mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
+			   CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
+			   CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
+			   CG6_FBC_BDISP_0);
+	fb->s.cg6.fbc->clip = 0;
+	fb->s.cg6.fbc->offx = 0;
+	fb->s.cg6.fbc->offy = 0;
+	fb->s.cg6.fbc->clipminx = 0;
+	fb->s.cg6.fbc->clipminy = 0;
+	fb->s.cg6.fbc->clipmaxx = fb->type.fb_width - 1;
+	fb->s.cg6.fbc->clipmaxy = fb->type.fb_height - 1;
+	/* Enable cursor in Brooktree DAC. */
+	fb->s.cg6.bt->addr = 0x06 << 24;
+	fb->s.cg6.bt->control |= 0x03 << 24;
+}
+
+static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
+{
+	p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin);
+}
+
 static char idstring[60] __initdata = { 0 };
 
 __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb))
@@ -504,8 +578,10 @@
 		disp->screen_base = (char *)sparc_alloc_io(phys + CG6_RAM_OFFSET, 0, 
 			type->fb_size, "cgsix_ram", fb->iospace, 0);
 	disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
-	fb->s.cg6.fbc = (struct cg6_fbc *)(char *)sparc_alloc_io(phys + CG6_FBC_OFFSET, 0, 
+	fb->s.cg6.fbc = (struct cg6_fbc *)sparc_alloc_io(phys + CG6_FBC_OFFSET, 0, 
 			4096, "cgsix_fbc", fb->iospace, 0);
+	fb->s.cg6.tec = (struct cg6_tec *)sparc_alloc_io(phys + CG6_TEC_OFFSET, 0, 
+			sizeof(struct cg6_tec), "cgsix_tec", fb->iospace, 0);
 	fb->s.cg6.thc = (struct cg6_thc *)sparc_alloc_io(phys + CG6_THC_OFFSET, 0, 
 				sizeof(struct cg6_thc), "cgsix_thc", fb->iospace, 0);
 	fb->s.cg6.bt = (struct bt_regs *)sparc_alloc_io(phys + CG6_BROOKTREE_OFFSET, 0, 
@@ -514,11 +590,15 @@
 				sizeof(u32), "cgsix_fhc", fb->iospace, 0);
 	fb->dispsw = cg6_dispsw;
 
+	fb->margins = cg6_margins;
 	fb->loadcmap = cg6_loadcmap;
 	fb->setcursor = cg6_setcursor;
 	fb->setcursormap = cg6_setcursormap;
 	fb->setcurshape = cg6_setcurshape;
 	fb->fill = cg6_fill;
+	fb->blank = cg6_blank;
+	fb->unblank = cg6_unblank;
+	fb->reset = cg6_reset;
 	
 	fb->physbase = phys;
 	fb->mmap_map = cg6_mmap_map;
@@ -543,6 +623,8 @@
 	sprintf(idstring, "cgsix at %02x.%08lx TEC Rev %x CPU %s Rev %x", fb->iospace, phys, 
 		    (fb->s.cg6.thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK,
 		    p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK);
+		    
+	cg6_reset(fb);
 		    
 	return idstring;
 }
diff -u --recursive --new-file v2.1.109/linux/drivers/video/chipsfb.c linux/drivers/video/chipsfb.c
--- v2.1.109/linux/drivers/video/chipsfb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/chipsfb.c	Sat Jul 18 13:55:46 1998
@@ -0,0 +1,556 @@
+/*
+ *  drivers/video/chipsfb.c -- frame buffer device for
+ *  Chips & Technologies 65550 chip.
+ *
+ *  Copyright (C) 1998 Paul Mackerras
+ *
+ *  This file is derived from the Powermac "chips" driver:
+ *  Copyright (C) 1997 Fabio Riccardi.
+ *  And from the frame buffer device for Open Firmware-initialized devices:
+ *  Copyright (C) 1997 Geert Uytterhoeven.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/selection.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#ifdef CONFIG_FB_COMPAT_XPMAC
+#include <asm/vc_ioctl.h>
+#endif
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/adb.h>
+#include <asm/pmu.h>
+
+#include "fbcon.h"
+#include "fbcon-cfb8.h"
+#include "fbcon-cfb16.h"
+
+static int currcon = 0;
+
+struct fb_info_chips {
+	struct fb_info info;
+	struct fb_fix_screeninfo fix;
+	struct fb_var_screeninfo var;
+	struct display disp;
+	struct {
+		__u8 red, green, blue;
+	} palette[256];
+	__u8 *frame_buffer;
+	__u8 *blitter_regs;
+	__u8 *io_base;
+	unsigned long chips_base_phys;
+	unsigned long chips_io_phys;
+	struct fb_info_chips *next;
+#ifdef CONFIG_PMAC_PBOOK
+	unsigned char *save_framebuffer;
+#endif
+};
+
+#define write_xr(num,val)	{ out_8(p->io_base + 0x3D6, num); out_8(p->io_base + 0x3D7, val); }
+#define read_xr(num,var)	{ out_8(p->io_base + 0x3D6, num); var = in_8(p->io_base + 0x3D7); }
+#define write_fr(num,val)	{ out_8(p->io_base + 0x3D0, num); out_8(p->io_base + 0x3D1, val); }
+#define read_fr(num,var)	{ out_8(p->io_base + 0x3D0, num); var = in_8(p->io_base + 0x3D1); }
+#define write_cr(num,val)	{ out_8(p->io_base + 0x3D4, num); out_8(p->io_base + 0x3D5, val); }
+#define read_cr(num,var)	{ out_8(p->io_base + 0x3D4, num); var = in_8(p->io_base + 0x3D5); }
+
+
+static struct fb_info_chips *all_chips;
+
+#ifdef CONFIG_PMAC_PBOOK
+int chips_sleep_notify(struct notifier_block *, unsigned long, void *);
+static struct notifier_block chips_sleep_notifier = {
+	chips_sleep_notify, NULL, 0
+};
+#endif
+
+/*
+ * Exported functions
+ */
+void chips_init(void);
+void chips_of_init(struct device_node *dp);
+
+static int chips_open(struct fb_info *info, int user);
+static int chips_release(struct fb_info *info, int user);
+static int chips_get_fix(struct fb_fix_screeninfo *fix, int con,
+			 struct fb_info *info);
+static int chips_get_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info);
+static int chips_set_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info);
+static int chips_pan_display(struct fb_var_screeninfo *var, int con,
+			     struct fb_info *info);
+static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info);
+static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info);
+static int chips_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		       u_long arg, int con, struct fb_info *info);
+
+static struct fb_ops chipsfb_ops = {
+	chips_open,
+	chips_release,
+	chips_get_fix,
+	chips_get_var,
+	chips_set_var,
+	chips_get_cmap,
+	chips_set_cmap,
+	chips_pan_display,
+	chips_ioctl
+};
+
+static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green,
+			     u_int *blue, u_int *transp, struct fb_info *info);
+static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *info);
+static void do_install_cmap(int con, struct fb_info *info);
+static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, int con, int bpp);
+
+
+static int chips_open(struct fb_info *info, int user)
+{
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int chips_release(struct fb_info *info, int user)
+{
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int chips_get_fix(struct fb_fix_screeninfo *fix, int con,
+			 struct fb_info *info)
+{
+	struct fb_info_chips *cp = (struct fb_info_chips *) info;
+
+	*fix = cp->fix;
+	return 0;
+}
+
+static int chips_get_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info)
+{
+	struct fb_info_chips *cp = (struct fb_info_chips *) info;
+
+	*var = cp->var;
+	return 0;
+}
+
+static int chips_set_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info)
+{
+	struct fb_info_chips *cp = (struct fb_info_chips *) info;
+	struct display *disp = (con >= 0)? &fb_display[con]: &cp->disp;
+
+	if (var->xres > 800 || var->yres > 600
+	    || var->xres_virtual > 800 || var->yres_virtual > 600
+	    || (var->bits_per_pixel != 8 && var->bits_per_pixel != 16)
+	    || var->nonstd
+	    || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+		return -EINVAL;
+
+	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW &&
+		var->bits_per_pixel != disp->var.bits_per_pixel) {
+		chips_set_bitdepth(cp, disp, con, var->bits_per_pixel);
+	}
+
+	return 0;
+}
+
+static int chips_pan_display(struct fb_var_screeninfo *var, int con,
+			     struct fb_info *info)
+{
+	if (var->xoffset != 0 || var->yoffset != 0)
+		return -EINVAL;
+	return 0;
+}
+
+static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info)
+{
+	if (con == currcon)		/* current console? */
+		return fb_get_cmap(cmap, &fb_display[con].var, kspc,
+				   chipsfb_getcolreg, info);
+	if (fb_display[con].cmap.len)	/* non default colormap? */
+		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2);
+	else
+		fb_copy_cmap(fb_default_cmap(256), cmap, kspc? 0: 2);
+	return 0;
+}
+
+static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			 struct fb_info *info)
+{
+	struct display *disp = &fb_display[con];
+	int err;
+
+	if (disp->cmap.len == 0) {
+		err = fb_alloc_cmap(&disp->cmap, 256, 0);
+		if (err)
+			return err;
+	}
+
+	if (con == currcon)
+		return fb_set_cmap(cmap, &disp->var, kspc, chipsfb_setcolreg,
+				   info);
+	fb_copy_cmap(cmap, &disp->cmap, kspc==0);
+	return 0;
+}
+
+static int chips_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		       u_long arg, int con, struct fb_info *info)
+{
+	return -EINVAL;
+}
+
+static int chipsfb_switch(int con, struct fb_info *info)
+{
+	struct fb_info_chips *p = (struct fb_info_chips *) info;
+	struct display* old_disp = &fb_display[currcon];
+	struct display* new_disp = &fb_display[con];
+	int	bit_depth;
+
+	if (fb_display[currcon].cmap.len)
+		fb_get_cmap(&old_disp->cmap,
+			    &old_disp->var, 1, chipsfb_getcolreg,
+			    info);
+
+	bit_depth = new_disp->var.bits_per_pixel;
+	if (old_disp->var.bits_per_pixel != bit_depth)
+	{
+	  currcon = con;
+	  chips_set_bitdepth(p, new_disp, con, bit_depth);
+	}
+	else
+	  currcon = con;
+	
+	do_install_cmap(con, info);
+	return 0;
+}
+
+static int chipsfb_updatevar(int con, struct fb_info *info)
+{
+	return 0;
+}
+
+static void chipsfb_blank(int blank, struct fb_info *info)
+{
+	struct fb_info_chips *p = (struct fb_info_chips *) info;
+	int i;
+
+	if (blank > 1) {
+		pmu_enable_backlight(0);
+	} else if (blank) {
+		for (i = 0; i < 256; ++i) {
+			out_8(p->io_base + 0x3c8, i);
+			udelay(1);
+			out_8(p->io_base + 0x3c9, 0);
+			out_8(p->io_base + 0x3c9, 0);
+			out_8(p->io_base + 0x3c9, 0);
+		}
+	} else {
+		pmu_enable_backlight(1);
+		do_install_cmap(currcon, info);
+	}
+}
+
+static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green,
+			     u_int *blue, u_int *transp, struct fb_info *info)
+{
+	struct fb_info_chips *p = (struct fb_info_chips *) info;
+
+	if (regno > 255)
+		return 1;
+	*red = p->palette[regno].red;
+	*green = p->palette[regno].green;
+	*blue = p->palette[regno].blue;
+	return 0;
+}
+
+static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *info)
+{
+	struct fb_info_chips *p = (struct fb_info_chips *) info;
+
+	if (regno > 255)
+		return 1;
+	p->palette[regno].red = red;
+	p->palette[regno].green = green;
+	p->palette[regno].blue = blue;
+	out_8(p->io_base + 0x3c8, regno);
+	udelay(1);
+	out_8(p->io_base + 0x3c9, red);
+	out_8(p->io_base + 0x3c9, green);
+	out_8(p->io_base + 0x3c9, blue);
+
+#ifdef CONFIG_FBCON_CFB16
+    if (regno < 16)
+		fbcon_cfb16_cmap[regno] = (red << 10) | (green << 5) | blue;		
+#endif
+
+    return 0;
+}
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+	if (con != currcon)
+		return;
+	if (fb_display[con].cmap.len)
+		fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
+			    chipsfb_setcolreg, info);
+	else
+		fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), &fb_display[con].var, 1,
+			    chipsfb_setcolreg, info);
+}
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+/* from drivers/macintosh/pmac-cons.h */
+#define VMODE_800_600_60	10	/* 800x600, 60Hz */
+#endif /* CONFIG_FB_COMPAT_XPMAC */
+
+static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, int con, int bpp)
+{
+	int err;
+	struct fb_fix_screeninfo* fix = &p->fix;
+	struct fb_var_screeninfo* var = &p->var;
+	
+	if (bpp == 16) {
+		if (con == currcon) {
+			write_cr(0x13, 200);		// 16 bit display width (decimal)
+			write_xr(0x81, 0x14);		// 15 bit (TrueColor) color mode
+			write_xr(0x82, 0x00);		// disable palettes
+			write_xr(0x20, 0x10);		// 16 bit blitter mode
+		}
+
+		fix->line_length = 800*2;
+		fix->visual = FB_VISUAL_TRUECOLOR;
+
+		var->red.offset = 10;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 5;
+		
+		disp->dispsw = &fbcon_cfb16;
+    } else if (bpp == 8) {
+		if (con == currcon) {
+			write_cr(0x13, 100);		// 8 bit display width (decimal)
+			write_xr(0x81, 0x12);		// 8 bit color mode
+			write_xr(0x82, 0x08);		// Graphics gamma enable
+			write_xr(0x20, 0x00);		// 8 bit blitter mode
+		}
+
+		fix->line_length = 800;
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;		
+
+ 		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 8;
+		
+		disp->dispsw = &fbcon_cfb8;
+	}
+
+	var->bits_per_pixel = bpp;
+	disp->line_length = p->fix.line_length;
+	disp->visual = fix->visual;
+	disp->var = *var;
+
+#ifdef CONFIG_PMAC_PBOOK
+	display_info.depth = bpp;
+	display_info.pitch = fix->line_length;
+#endif
+	
+	if (p->info.changevar)
+		(*p->info.changevar)(con);
+
+	if ((err = fb_alloc_cmap(&disp->cmap, 0, 0)))
+		return;
+	do_install_cmap(con, (struct fb_info *)p);
+}
+
+__initfunc(static void init_chips(struct fb_info_chips *p))
+{
+	int i;
+
+	memset(&p->fix, 0, sizeof(p->fix));
+	strcpy(p->fix.id, "C&T 65550");
+	p->fix.smem_start = (char *) p->chips_base_phys;
+	p->fix.smem_len = 800 * 600;
+	p->fix.mmio_start = (char *) p->chips_io_phys;
+	p->fix.type = FB_TYPE_PACKED_PIXELS;
+	p->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	p->fix.line_length = 800;
+
+	memset(&p->var, 0, sizeof(p->var));
+	p->var.xres = 800;
+	p->var.yres = 600;
+	p->var.xres_virtual = 800;
+	p->var.yres_virtual = 600;
+	p->var.bits_per_pixel = 8;
+	p->var.red.length = p->var.green.length = p->var.blue.length = 8;
+	p->var.height = p->var.width = -1;
+	p->var.vmode = FB_VMODE_NONINTERLACED;
+	p->var.pixclock = 10000;
+	p->var.left_margin = p->var.right_margin = 16;
+	p->var.upper_margin = p->var.lower_margin = 16;
+	p->var.hsync_len = p->var.vsync_len = 8;
+
+	memset(&p->disp, 0, sizeof(p->disp));
+	p->disp.var = p->var;
+	p->disp.cmap.red = NULL;
+	p->disp.cmap.green = NULL;
+	p->disp.cmap.blue = NULL;
+	p->disp.cmap.transp = NULL;
+	p->disp.screen_base = (char *) p->frame_buffer;
+	p->disp.visual = p->fix.visual;
+	p->disp.type = p->fix.type;
+	p->disp.type_aux = p->fix.type_aux;
+	p->disp.line_length = p->fix.line_length;
+	p->disp.can_soft_blank = 1;
+	p->disp.dispsw = &fbcon_cfb8;
+	p->disp.scrollmode = SCROLL_YREDRAW;
+
+	strcpy(p->info.modename, p->fix.id);
+	p->info.node = -1;
+	p->info.fbops = &chipsfb_ops;
+	p->info.disp = &p->disp;
+	p->info.fontname[0] = 0;
+	p->info.changevar = NULL;
+	p->info.switch_con = &chipsfb_switch;
+	p->info.updatevar = &chipsfb_updatevar;
+	p->info.blank = &chipsfb_blank;
+
+	for (i = 0; i < 16; ++i) {
+		int j = color_table[i];
+		p->palette[i].red = default_red[j];
+		p->palette[i].green = default_grn[j];
+		p->palette[i].blue = default_blu[j];
+	}
+
+	if (register_framebuffer(&p->info) < 0) {
+		kfree(p);
+		return;
+	}
+
+	printk("fb%d: Chips 65550 frame buffer\n", GET_FB_IDX(p->info.node));
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+	if (!console_fb_info) {
+		display_info.height = p->var.yres;
+		display_info.width = p->var.xres;
+		display_info.depth = 8;
+		display_info.pitch = p->fix.line_length;
+		display_info.mode = VMODE_800_600_60;
+		strncpy(display_info.name, "chips65550",
+			sizeof(display_info.name));
+		display_info.fb_address = p->chips_base_phys + 0x800000;
+		display_info.cmap_adr_address = p->chips_io_phys + 0x3c8;
+		display_info.cmap_data_address = p->chips_io_phys + 0x3c9;
+		display_info.disp_reg_address = p->chips_base_phys + 0xc00000;
+		console_fb_info = &p->info;
+	}
+#endif /* CONFIG_FB_COMPAT_XPMAC */
+
+#ifdef CONFIG_PMAC_PBOOK
+	if (all_chips == NULL)
+		notifier_chain_register(&sleep_notifier_list,
+					&chips_sleep_notifier);
+#endif /* CONFIG_PMAC_PBOOK */
+	p->next = all_chips;
+	all_chips = p;
+}
+
+__initfunc(void chips_init(void))
+{
+#ifndef CONFIG_FB_OF
+	struct device_node *dp;
+
+	dp = find_devices("chips65550");
+	if (dp != 0)
+		chips_of_init(dp);
+#endif /* CONFIG_FB_OF */
+}
+
+__initfunc(void chips_of_init(struct device_node *dp))
+{
+	struct fb_info_chips *p;
+	unsigned long addr;
+	unsigned char bus, devfn;
+	unsigned short cmd;
+
+	if (dp->n_addrs == 0)
+		return;
+	p = kmalloc(sizeof(*p), GFP_ATOMIC);
+	if (p == 0)
+		return;
+	addr = dp->addrs[0].address;
+	p->chips_base_phys = addr;
+	p->frame_buffer = __ioremap(addr+0x800000, 0x100000, _PAGE_NO_CACHE);
+	p->blitter_regs = ioremap(addr + 0xC00000, 0x1000);
+
+	if (pci_device_loc(dp, &bus, &devfn) == 0) {
+		pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
+		cmd |= 3;	/* enable memory and IO space */
+		pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
+		p->io_base = (unsigned char *) pci_io_base(bus);
+		/* XXX really want the physical address here */
+		p->chips_io_phys = (unsigned long) pci_io_base(bus);
+	}
+
+	/* Clear the entire framebuffer */
+	memset(p->frame_buffer, 0, 0x100000);
+
+	/* turn on the backlight */
+	pmu_enable_backlight(1);
+
+	init_chips(p);
+}
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * Save the contents of the frame buffer when we go to sleep,
+ * and restore it when we wake up again.
+ */
+int
+chips_sleep_notify(struct notifier_block *this, unsigned long code, void *x)
+{
+	struct fb_info_chips *p;
+
+	for (p = all_chips; p != NULL; p = p->next) {
+		int nb = p->var.yres * p->fix.line_length;
+
+		switch (code) {
+		case PBOOK_SLEEP:
+			p->save_framebuffer = vmalloc(nb);
+			if (p->save_framebuffer)
+				memcpy(p->save_framebuffer,
+				       p->frame_buffer, nb);
+			break;
+		case PBOOK_WAKE:
+			if (p->save_framebuffer) {
+				memcpy(p->frame_buffer,
+				       p->save_framebuffer, nb);
+				vfree(p->save_framebuffer);
+				p->save_framebuffer = 0;
+			}
+			break;
+		}
+	}
+	return NOTIFY_DONE;
+}
+#endif /* CONFIG_PMAC_PBOOK */
diff -u --recursive --new-file v2.1.109/linux/drivers/video/compatcon.c linux/drivers/video/compatcon.c
--- v2.1.109/linux/drivers/video/compatcon.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/compatcon.c	Wed Dec 31 16:00:00 1969
@@ -1,332 +0,0 @@
-/*
- *  linux/drivers/video/compatcon.c -- Console wrapper
- *
- *	Created 26 Apr 1998 by Geert Uytterhoeven
- *
- *  This will be removed once there are frame buffer devices for all supported
- *  graphics hardware
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-#include <linux/console.h>
-#include <linux/console_struct.h>
-#include <linux/string.h>
-#include <linux/kd.h>
-#include <linux/malloc.h>
-#include <linux/vt_kern.h>
-#include <linux/selection.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/linux_logo.h>
-
-#include <linux/console_compat.h>
-
-
-    /*
-     *  Interface used by the world
-     */
-
-static const char *compatcon_startup(void);
-static void compatcon_init(struct vc_data *conp);
-static void compatcon_deinit(struct vc_data *conp);
-static void compatcon_clear(struct vc_data *conp, int sy, int sx, int height,
-			    int width);
-static void compatcon_putc(struct vc_data *conp, int c, int ypos, int xpos);
-static void compatcon_putcs(struct vc_data *conp, const unsigned short *s, int count,
-			    int ypos, int xpos);
-static void compatcon_cursor(struct vc_data *conp, int mode);
-static int compatcon_scroll(struct vc_data *conp, int t, int b, int dir,
-			    int count);
-static void compatcon_bmove(struct vc_data *conp, int sy, int sx, int dy,
-			    int dx, int height, int width);
-static int compatcon_switch(struct vc_data *conp);
-static int compatcon_blank(int blank);
-static int compatcon_get_font(struct vc_data *conp, int *w, int *h, char *data);
-static int compatcon_set_font(struct vc_data *conp, int w, int h, char *data);
-static int compatcon_set_palette(struct vc_data *conp, unsigned char *table);
-static int compatcon_scrolldelta(struct vc_data *conp, int lines);
-
-
-    /*
-     *  Internal routines
-     */
-
-unsigned long video_num_columns;
-unsigned long video_num_lines;
-unsigned long video_size_row;
-unsigned char video_type;
-unsigned long video_mem_base;
-unsigned long video_mem_term;
-unsigned long video_screen_size;
-int can_do_color;
-
-extern void set_cursor(int currcons);
-extern void hide_cursor(void);
-extern int set_get_cmap(unsigned char *arg, int set);
-extern void set_palette(void);
-extern int set_get_font(unsigned char *arg, int set, int ch512);
-extern void set_vesa_blanking(unsigned long arg);
-extern void vesa_blank(void);
-extern void vesa_powerdown(void);
-extern int con_adjust_height(unsigned long fontheight);
-extern void con_type_init(const char **);
-extern void con_type_init_finish(void);
-
-#define BLANK	0x0020
-
-
-__initfunc(static const char *compatcon_startup(void))
-{
-    const char *display_desc = "????";
-
-    video_num_lines = ORIG_VIDEO_LINES;
-    video_num_columns = ORIG_VIDEO_COLS;
-    video_size_row = 2*video_num_columns;
-    video_screen_size = video_num_lines*video_size_row;
-
-    con_type_init(&display_desc);
-    return display_desc;
-}
-
-
-static void compatcon_init(struct vc_data *conp)
-{
-    static int first = 1;
-
-    conp->vc_cols = video_num_columns;
-    conp->vc_rows = video_num_lines;
-    conp->vc_can_do_color = can_do_color;
-    if (first) {
-	con_type_init_finish();
-	first = 0;
-    }
-}
-
-static void compatcon_deinit(struct vc_data *conp)
-{
-}
-
-
-static void compatcon_clear(struct vc_data *conp, int sy, int sx, int height,
-			    int width)
-{
-    int rows;
-    unsigned long dest;
-
-    if (console_blanked)
-	return;
-
-    dest = video_mem_base+sy*video_size_row+sx*2;
-    if (sx == 0 && width == video_num_columns)      
-	memsetw((void *)dest, conp->vc_video_erase_char, height*video_size_row);
-    else
-	for (rows = height; rows-- ; dest += video_size_row)
-	    memsetw((void *)dest, conp->vc_video_erase_char, width*2);
-}
-
-
-static void compatcon_putc(struct vc_data *conp, int c, int ypos, int xpos)
-{
-    u16 *p;
-
-    if (console_blanked)
-	return;
-
-    p = (u16 *)(video_mem_base+ypos*video_size_row+xpos*2);
-    scr_writew(c, p);
-}
-
-
-static void compatcon_putcs(struct vc_data *conp, const unsigned short *s, int count,
-			    int ypos, int xpos)
-{
-    u16 *p;
-    u16 sattr;
-
-    if (console_blanked)
-	return;
-
-    p = (u16 *)(video_mem_base+ypos*video_size_row+xpos*2);
-    while (count--)
-	scr_writew(*s++, p++);
-}
-
-
-static void compatcon_cursor(struct vc_data *conp, int mode)
-{
-    switch (mode) {
-	case CM_ERASE:
-	    hide_cursor();
-	    break;
-
-	case CM_MOVE:
-	case CM_DRAW:
-	    set_cursor(conp->vc_num);
-	    break;
-    }
-}
-
-
-static int compatcon_scroll(struct vc_data *conp, int t, int b, int dir,
-			    int count)
-{
-    if (console_blanked)
-	return 0;
-
-    compatcon_cursor(conp, CM_ERASE);
-
-    switch (dir) {
-	case SM_UP:
-	    if (count > conp->vc_rows)	/* Maximum realistic size */
-		count = conp->vc_rows;
-	    compatcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols);
-	    compatcon_clear(conp, b-count, 0, count, conp->vc_cols);
-	    break;
-
-	case SM_DOWN:
-	    if (count > conp->vc_rows)	/* Maximum realistic size */
-		count = conp->vc_rows;
-	    /*
-	     *  Fixed bmove() should end Arno's frustration with copying?
-	     *  Confucius says:
-	     *	Man who copies in wrong direction, end up with trashed
-	     *	data
-	     */
-	    compatcon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols);
-	    compatcon_clear(conp, t, 0, count, conp->vc_cols);
-	    break;
-
-	case SM_LEFT:
-	    compatcon_bmove(conp, 0, t+count, 0, t, conp->vc_rows, b-t-count);
-	    compatcon_clear(conp, 0, b-count, conp->vc_rows, count);
-	    break;
-
-	case SM_RIGHT:
-	    compatcon_bmove(conp, 0, t, 0, t+count, conp->vc_rows, b-t-count);
-	    compatcon_clear(conp, 0, t, conp->vc_rows, count);
-	    break;
-    }
-    return 0;
-}
-
-
-static inline void memmovew(u16 *to, u16 *from, unsigned int count)
-{
-    if ((unsigned long)to < (unsigned long)from)
-	memcpyw(to, from, count);
-    else {
-	count /= 2;
-	to += count;
-	from += count;
-	while (count) {
-	    count--;
-	    scr_writew(scr_readw(--from), --to);
-	}
-    }
-}
-
-static void compatcon_bmove(struct vc_data *conp, int sy, int sx, int dy,
-			    int dx, int height, int width)
-{
-    unsigned long src, dst;
-    int rows;
-
-    if (console_blanked)
-	return;
-
-    if (sx == 0 && dx == 0 && width == video_num_columns) {
-	src = video_mem_base+sy*video_size_row;
-	dst = video_mem_base+dy*video_size_row;
-	memmovew((u16 *)dst, (u16 *)src, height*video_size_row);
-    } else if (dy < sy || (dy == sy && dx < sx)) {
-	src = video_mem_base+sy*video_size_row+sx*2;
-	dst = video_mem_base+dy*video_size_row+dx*2;
-	for (rows = height; rows-- ;) {
-	    memmovew((u16 *)dst, (u16 *)src, width*2);
-	    src += video_size_row;
-	    dst += video_size_row;
-	}
-    } else {
-	src = video_mem_base+(sy+height-1)*video_size_row+sx*2;
-	dst = video_mem_base+(dy+height-1)*video_size_row+dx*2;
-	for (rows = height; rows-- ;) {
-	    memmovew((u16 *)dst, (u16 *)src, width*2);
-	    src -= video_size_row;
-	    dst -= video_size_row;
-	}
-    }
-}
-
-
-static int compatcon_switch(struct vc_data *conp)
-{
-    return 1;
-}
-
-
-static int compatcon_blank(int blank)
-{
-    if (blank) {
-	set_vesa_blanking(blank-1);
-	if (blank-1 == 0)
-	    vesa_blank();
-	else
-	    vesa_powerdown();
-	return 0;
-    } else {
-	/* Tell console.c that it has to restore the screen itself */
-	return 1;
-    }
-    return 0;
-}
-
-
-static int compatcon_get_font(struct vc_data *conp, int *w, int *h, char *data)
-{
-    /* this is not supported: data already points to a kernel space copy */
-    return -ENOSYS;
-}
-
-
-static int compatcon_set_font(struct vc_data *conp, int w, int h, char *data)
-{
-    /* this is not supported: data already points to a kernel space copy */
-    return -ENOSYS;
-}
-
-static int compatcon_set_palette(struct vc_data *conp, unsigned char *table)
-{
-    if (console_blanked || vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
-	return -EINVAL;
-    set_palette();
-    return 0;
-}
-
-static int compatcon_scrolldelta(struct vc_data *conp, int lines)
-{
-    /* TODO */
-    return -ENOSYS;
-}
-
-    /*
-     *  The console `switch' structure for the console wrapper
-     */
-
-struct consw compat_con = {
-    compatcon_startup, compatcon_init, compatcon_deinit, compatcon_clear,
-    compatcon_putc, compatcon_putcs, compatcon_cursor, compatcon_scroll,
-    compatcon_bmove, compatcon_switch, compatcon_blank, compatcon_get_font,
-    compatcon_set_font, compatcon_set_palette, compatcon_scrolldelta,
-    NULL, NULL
-};
diff -u --recursive --new-file v2.1.109/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c
--- v2.1.109/linux/drivers/video/creatorfb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/creatorfb.c	Sat Jul 18 13:55:46 1998
@@ -1,4 +1,4 @@
-/* $Id: creatorfb.c,v 1.4 1998/07/06 15:51:10 jj Exp $
+/* $Id: creatorfb.c,v 1.5 1998/07/13 12:47:12 jj Exp $
  * creatorfb.c: Creator/Creator3D frame buffer driver
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -177,35 +177,6 @@
 	p->next_plane = 0;
 }
 
-static void ffb_bmove(struct display *p, int sy, int sx, int dy, int dx,
-			   int height, int width)
-{
-	int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
-	u8 *src, *dst;
-
-	if (sx == 0 && dx == 0 && width * 32 == bytes)
-		mymemmove(p->screen_base + dy * linesize,
-				  p->screen_base + sy * linesize,
-				  height * linesize);
-	else if (dy < sy || (dy == sy && dx < sx)) {
-		src = p->screen_base + sy * linesize + sx * 32;
-		dst = p->screen_base + dy * linesize + dx * 32;
-		for (rows = height * p->fontheight ; rows-- ;) {
-			mymemmove(dst, src, width * 32);
-			src += bytes;
-			dst += bytes;
-		}
-	} else {
-		src = p->screen_base + (sy+height) * linesize + sx * 32 - bytes;
-		dst = p->screen_base + (dy+height) * linesize + dx * 32 - bytes;
-		for (rows = height * p->fontheight ; rows-- ;) {
-			mymemmove(dst, src, width * 32);
-			src -= bytes;
-			dst -= bytes;
-		}
-	}
-}
-
 static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
 		      int height, int width)
 {
@@ -221,12 +192,16 @@
 	fbc->unk2 = 8;
 
 	/* FIXME: Optimize this by allowing 8/16 fontheigh only and introduce p->fontheightlog */
-	if (p->fontheight == 16) {
-		y = sy << 4; h = height << 4;
+	if (p->fontheightlog) {
+		y = sy << p->fontheightlog; h = height << p->fontheightlog;
 	} else {
 		y = sy * p->fontheight; h = height * p->fontheight;
 	}
-	x = sx << 3; w = width << 3;
+	if (p->fontwidthlog) {
+		x = sx << p->fontwidthlog; w = width << p->fontwidthlog;
+	} else {
+		x = sx * p->fontwidth; w = width * p->fontwidth;
+	}
 	fbc->by = y + fb->y_margin;
 	fbc->bx = x + fb->x_margin;
 	fbc->bh = h;
@@ -260,25 +235,39 @@
 	int i, xy;
 	u8 *fd;
 
-	if (p->fontheight == 16) {
-		xy = (yy << (16 + 4));
-		fd = p->fontdata + ((c & 0xff) << 4);
+	if (p->fontheightlog) {
+		xy = (yy << (16 + p->fontheightlog));
+		i = ((c & 0xff) << p->fontheightlog);
 	} else {
 		xy = ((yy * p->fontheight) << 16);
-		fd = p->fontdata + (c & 0xff) * p->fontheight;
+		i = (c & 0xff) * p->fontheight;
 	}
-	xy += (xx << 3) + fb->s.ffb.xy_margin;
+	if (p->fontwidth <= 8)
+		fd = p->fontdata + i;
+	else
+		fd = p->fontdata + (i << 1);
+	if (p->fontwidthlog)
+		xy += (xx << p->fontwidthlog) + fb->s.ffb.xy_margin;
+	else
+		xy += (xx * p->fontwidth) + fb->s.ffb.xy_margin;
 	fbc->ppc = 0x203;
 	fbc->fg = ffb_cmap[attr_fg_col(c)];
 	fbc->fbc = 0x2000707f;
 	fbc->rop = 0x83;
 	fbc->pmask = 0xffffffff;
 	fbc->bg = ffb_cmap[attr_bg_col(c)];
-	fbc->fontw = 8;
+	fbc->fontw = p->fontwidth;
 	fbc->fontinc = 0x10000;
 	fbc->fontxy = xy;
-	for (i = 0; i < p->fontheight; i++)
-		fbc->font = *fd++ << 24;
+	if (p->fontwidth <= 8) {
+		for (i = 0; i < p->fontheight; i++)
+			fbc->font = *fd++ << 24;
+	} else {
+		for (i = 0; i < p->fontheight; i++) {
+			fbc->font = *(u16 *)fd << 16;
+			fd += 2;
+		}
+	}
 }
 
 static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
@@ -295,75 +284,91 @@
 	fbc->rop = 0x83;
 	fbc->pmask = 0xffffffff;
 	fbc->bg = ffb_cmap[attr_bg_col(*s)];
-	if (p->fontheight == 16) {
-		xy = (yy << (16 + 4)) + (xx << 3) + fb->s.ffb.xy_margin;
+	xy = fb->s.ffb.xy_margin;
+	if (p->fontwidthlog)
+		xy += (xx << p->fontwidthlog);
+	else
+		xy += xx * p->fontwidth;
+	if (p->fontheightlog)
+		xy += (yy << (16 + p->fontheightlog));
+	else
+		xy += ((yy * p->fontheight) << 16);
+	if (p->fontwidth <= 8) {
 		while (count >= 4) {
 			count -= 4;
-			fbc->fontw = 32;
+			fbc->fontw = 4 * p->fontwidth;
 			fbc->fontinc = 0x10000;
 			fbc->fontxy = xy;
-			fd1 = p->fontdata + ((*s++ & 0xff) << 4);
-			fd2 = p->fontdata + ((*s++ & 0xff) << 4);
-			fd3 = p->fontdata + ((*s++ & 0xff) << 4);
-			fd4 = p->fontdata + ((*s++ & 0xff) << 4);
-			for (i = 0; i < 16; i++)
-				fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << 8)) << 8)) << 8);
-			xy += 32;
-		}
-		while (count) {
-			count--;
-			fbc->fontw = 8;
-			fbc->fontinc = 0x10000;
-			fbc->fontxy = xy;
-			fd1 = p->fontdata + ((*s++ & 0xff) << 4);
-			for (i = 0; i < 16; i++)
-				fbc->font = *fd1++ << 24;
-			xy += 8;
+			if (p->fontheightlog) {
+				fd1 = p->fontdata + ((*s++ & 0xff) << p->fontheightlog);
+				fd2 = p->fontdata + ((*s++ & 0xff) << p->fontheightlog);
+				fd3 = p->fontdata + ((*s++ & 0xff) << p->fontheightlog);
+				fd4 = p->fontdata + ((*s++ & 0xff) << p->fontheightlog);
+			} else {
+				fd1 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
+				fd2 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
+				fd3 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
+				fd4 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
+			}
+			if (p->fontwidth == 8) {
+				for (i = 0; i < p->fontheight; i++)
+					fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
+						<< 8)) << 8)) << 8);
+				xy += 32;
+			} else {
+				for (i = 0; i < p->fontheight; i++)
+					fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
+						<< p->fontwidth)) << p->fontwidth)) << p->fontwidth)) << (24 - 3 * p->fontwidth);
+				xy += 4 * p->fontwidth;
+			}
 		}
 	} else {
-		xy = ((yy * p->fontheight) << 16) + (xx << 3) + fb->s.ffb.xy_margin;
-		while (count >= 4) {
-			count -= 4;
-			fbc->fontw = 32;
+		while (count >= 2) {
+			count -= 2;
+			fbc->fontw = 2 * p->fontwidth;
 			fbc->fontinc = 0x10000;
 			fbc->fontxy = xy;
-			fd1 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
-			fd2 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
-			fd3 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
-			fd4 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
-			for (i = 0; i < p->fontheight; i++)
-				fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << 8)) << 8)) << 8);
-			xy += 32;
+			if (p->fontheightlog) {
+				fd1 = p->fontdata + ((*s++ & 0xff) << (p->fontheightlog + 1));
+				fd2 = p->fontdata + ((*s++ & 0xff) << (p->fontheightlog + 1));
+			} else {
+				fd1 = p->fontdata + (((*s++ & 0xff) * p->fontheight) << 1);
+				fd2 = p->fontdata + (((*s++ & 0xff) * p->fontheight) << 1);
+			}
+			for (i = 0; i < p->fontheight; i++) {
+				fbc->font = ((((u32)*(u16 *)fd1) << p->fontwidth) | ((u32)*(u16 *)fd2)) << (16 - p->fontwidth);
+				fd1 += 2; fd2 += 2;
+			}
+			xy += 2 * p->fontwidth;
 		}
-		while (count) {
-			count--;
-			fbc->fontw = 8;
-			fbc->fontinc = 0x10000;
-			fbc->fontxy = xy;
-			fd1 = p->fontdata + ((*s++ & 0xff) * p->fontheight);
-			for (i = 0; i < 16; i++)
+	}
+	while (count) {
+		count--;
+		fbc->fontw = p->fontwidth;
+		fbc->fontinc = 0x10000;
+		fbc->fontxy = xy;
+		if (p->fontheightlog)
+			i = ((*s++ & 0xff) << p->fontheightlog);
+		else
+			i = ((*s++ & 0xff) * p->fontheight);
+		if (p->fontwidth <= 8) {
+			fd1 = p->fontdata + i;
+			for (i = 0; i < p->fontheight; i++)
 				fbc->font = *fd1++ << 24;
-			xy += 8;
+		} else {
+			fd1 = p->fontdata + (i << 1);
+			for (i = 0; i < p->fontheight; i++) {
+				fbc->font = *(u16 *)fd1 << 16;
+				fd1 += 2;
+			}
 		}
+		xy += p->fontwidth;
 	}
 }
 
 static void ffb_revc(struct display *p, int xx, int yy)
 {
-	u8 *dest;
-	int bytes = p->next_line, rows;
-
-	dest = p->screen_base + yy * p->fontheight * bytes + xx * 32;
-	for (rows = p->fontheight ; rows-- ; dest += bytes) {
-		((u32 *)dest)[0] ^= 0xffffffff;
-		((u32 *)dest)[1] ^= 0xffffffff;
-		((u32 *)dest)[2] ^= 0xffffffff;
-		((u32 *)dest)[3] ^= 0xffffffff;
-		((u32 *)dest)[4] ^= 0xffffffff;
-		((u32 *)dest)[5] ^= 0xffffffff;
-		((u32 *)dest)[6] ^= 0xffffffff;
-		((u32 *)dest)[7] ^= 0xffffffff;
-	}
+	/* Not used if hw cursor */
 }
 
 static void ffb_loadcmap (struct fb_info_sbusfb *fb, int index, int count)
@@ -384,9 +389,16 @@
 }
 
 static struct display_switch ffb_dispsw __initdata = {
-	ffb_setup, ffb_bmove, ffb_clear, ffb_putc, ffb_putcs, ffb_revc, NULL
+	ffb_setup, fbcon_redraw_bmove, ffb_clear, ffb_putc, ffb_putcs, ffb_revc, 
+	NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
 };
 
+static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
+{
+	fb->s.ffb.xy_margin = (y_margin << 16) + x_margin;
+	p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
+}
+
 static inline void ffb_curs_enable (struct fb_info_sbusfb *fb, int enable)
 {
 	struct ffb_dac *dac = fb->s.ffb.dac;
@@ -478,6 +490,7 @@
 	fb->s.ffb.dac = (struct ffb_dac *)((char *)__va(regs[0].phys_addr) + FFB_DAC_POFF);
 	fb->dispsw = ffb_dispsw;
 
+	fb->margins = ffb_margins;
 	fb->loadcmap = ffb_loadcmap;
 	fb->setcursor = ffb_setcursor;
 	fb->setcursormap = ffb_setcursormap;
diff -u --recursive --new-file v2.1.109/linux/drivers/video/cyberfb.c linux/drivers/video/cyberfb.c
--- v2.1.109/linux/drivers/video/cyberfb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/cyberfb.c	Sat Jul 18 13:55:46 1998
@@ -1174,7 +1174,7 @@
 
 static struct display_switch fbcon_cyber8 = {
    fbcon_cfb8_setup, fbcon_cyber8_bmove, fbcon_cyber8_clear, fbcon_cyber8_putc,
-   fbcon_cyber8_putcs, fbcon_cyber8_revc, NULL
+   fbcon_cyber8_putcs, fbcon_cyber8_revc, NULL, NULL, FONTWIDTH(8)
 };
 #endif
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-afb.c linux/drivers/video/fbcon-afb.c
--- v2.1.109/linux/drivers/video/fbcon-afb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-afb.c	Sat Jul 18 13:55:46 1998
@@ -412,7 +412,7 @@
 
 struct display_switch fbcon_afb = {
     fbcon_afb_setup, fbcon_afb_bmove, fbcon_afb_clear, fbcon_afb_putc,
-    fbcon_afb_putcs, fbcon_afb_revc, NULL
+    fbcon_afb_putcs, fbcon_afb_revc, NULL, NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-cfb16.c linux/drivers/video/fbcon-cfb16.c
--- v2.1.109/linux/drivers/video/fbcon-cfb16.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-cfb16.c	Sat Jul 18 13:55:46 1998
@@ -179,7 +179,7 @@
 
 struct display_switch fbcon_cfb16 = {
     fbcon_cfb16_setup, fbcon_cfb16_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc,
-    fbcon_cfb16_putcs, fbcon_cfb16_revc, NULL
+    fbcon_cfb16_putcs, fbcon_cfb16_revc, NULL, NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-cfb2.c linux/drivers/video/fbcon-cfb2.c
--- v2.1.109/linux/drivers/video/fbcon-cfb2.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-cfb2.c	Sat Jul 18 13:55:46 1998
@@ -185,7 +185,7 @@
 
 struct display_switch fbcon_cfb2 = {
     fbcon_cfb2_setup, fbcon_cfb2_bmove, fbcon_cfb2_clear, fbcon_cfb2_putc,
-    fbcon_cfb2_putcs, fbcon_cfb2_revc, NULL
+    fbcon_cfb2_putcs, fbcon_cfb2_revc, NULL, NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-cfb24.c linux/drivers/video/fbcon-cfb24.c
--- v2.1.109/linux/drivers/video/fbcon-cfb24.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-cfb24.c	Sat Jul 18 13:55:46 1998
@@ -199,7 +199,7 @@
 
 struct display_switch fbcon_cfb24 = {
     fbcon_cfb24_setup, fbcon_cfb24_bmove, fbcon_cfb24_clear, fbcon_cfb24_putc,
-    fbcon_cfb24_putcs, fbcon_cfb24_revc, NULL
+    fbcon_cfb24_putcs, fbcon_cfb24_revc, NULL, NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-cfb32.c linux/drivers/video/fbcon-cfb32.c
--- v2.1.109/linux/drivers/video/fbcon-cfb32.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-cfb32.c	Sat Jul 18 13:55:46 1998
@@ -184,7 +184,7 @@
 
 struct display_switch fbcon_cfb32 = {
     fbcon_cfb32_setup, fbcon_cfb32_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc,
-    fbcon_cfb32_putcs, fbcon_cfb32_revc, NULL
+    fbcon_cfb32_putcs, fbcon_cfb32_revc, NULL, NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-cfb4.c linux/drivers/video/fbcon-cfb4.c
--- v2.1.109/linux/drivers/video/fbcon-cfb4.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-cfb4.c	Sat Jul 18 13:55:46 1998
@@ -188,7 +188,7 @@
 
 struct display_switch fbcon_cfb4 = {
     fbcon_cfb4_setup, fbcon_cfb4_bmove, fbcon_cfb4_clear, fbcon_cfb4_putc,
-    fbcon_cfb4_putcs, fbcon_cfb4_revc, NULL
+    fbcon_cfb4_putcs, fbcon_cfb4_revc, NULL, NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-cfb8.c linux/drivers/video/fbcon-cfb8.c
--- v2.1.109/linux/drivers/video/fbcon-cfb8.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-cfb8.c	Sat Jul 18 13:55:46 1998
@@ -51,23 +51,30 @@
     int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
     u8 *src,*dst;
 
-    if (sx == 0 && dx == 0 && width * 8 == bytes)
+    if (sx == 0 && dx == 0 && width * p->fontwidth == bytes) {
 	mymemmove(p->screen_base + dy * linesize,
 		  p->screen_base + sy * linesize,
 		  height * linesize);
-    else if (dy < sy || (dy == sy && dx < sx)) {
-	src = p->screen_base + sy * linesize + sx * 8;
-	dst = p->screen_base + dy * linesize + dx * 8;
+	return;
+    }
+    if (p->fontwidthlog) {
+    	sx <<= p->fontwidthlog; dx <<= p->fontwidthlog; width <<= p->fontwidthlog;
+    } else {
+    	sx *= p->fontwidth; dx *= p->fontwidth; width *= p->fontwidth;
+    }
+    if (dy < sy || (dy == sy && dx < sx)) {
+	src = p->screen_base + sy * linesize + sx;
+	dst = p->screen_base + dy * linesize + dx;
 	for (rows = height * p->fontheight ; rows-- ;) {
-	    mymemmove(dst, src, width * 8);
+	    mymemmove(dst, src, width);
 	    src += bytes;
 	    dst += bytes;
 	}
     } else {
-	src = p->screen_base + (sy+height) * linesize + sx * 8 - bytes;
-	dst = p->screen_base + (dy+height) * linesize + dx * 8 - bytes;
+	src = p->screen_base + (sy+height) * linesize + sx - bytes;
+	dst = p->screen_base + (dy+height) * linesize + dx - bytes;
 	for (rows = height * p->fontheight ; rows-- ;) {
-	    mymemmove(dst, src, width * 8);
+	    mymemmove(dst, src, width);
 	    src -= bytes;
 	    dst -= bytes;
 	}
@@ -77,32 +84,20 @@
 void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy, int sx,
 		      int height, int width)
 {
-    u8 *dest0,*dest;
-    int bytes=p->next_line,lines=height * p->fontheight, rows, i;
-    u32 bgx;
+    u8 *dest;
+    int bytes=p->next_line,lines=height * p->fontheight, rows;
+    u8 bgx;
 
-    dest = p->screen_base + sy * p->fontheight * bytes + sx * 8;
+    dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth;
 
     bgx=attr_bgcol_ec(p,conp);
-    bgx |= (bgx << 8);
-    bgx |= (bgx << 16);
 
-    if (sx == 0 && width * 8 == bytes)
-	for (i = 0 ; i < lines * width ; i++) {
-	    ((u32 *)dest)[0]=bgx;
-	    ((u32 *)dest)[1]=bgx;
-	    dest+=8;
-	}
+    if (sx == 0 && p->fontwidth == 8 && width * 8 == bytes)
+        memset(dest, bgx, lines * width * p->fontwidth);
     else {
-	dest0=dest;
-	for (rows = lines; rows-- ; dest0 += bytes) {
-	    dest=dest0;
-	    for (i = 0 ; i < width ; i++) {
-		((u32 *)dest)[0]=bgx;
-		((u32 *)dest)[1]=bgx;
-		dest+=8;
-	    }
-	}
+    	width *= p->fontwidth;
+	for (rows = lines; rows-- ; dest += bytes)
+	    memset(dest, bgx, width);
     }
 }
 
@@ -114,7 +109,10 @@
     u32 eorx,fgx,bgx;
 
     dest = p->screen_base + yy * p->fontheight * bytes + xx * 8;
-    cdat = p->fontdata + (c & 0xff) * p->fontheight;
+    if (p->fontwidth <= 8)
+	cdat = p->fontdata + (c & 0xff) * p->fontheight;
+    else
+	cdat = p->fontdata + ((c & 0xff) * p->fontheight << 1);
 
     fgx=attr_fgcol(p,c);
     bgx=attr_bgcol(p,c);
@@ -124,9 +122,28 @@
     bgx |= (bgx << 16);
     eorx = fgx ^ bgx;
 
-    for (rows = p->fontheight ; rows-- ; dest += bytes) {
-	((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx;
-	((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx;
+    switch (p->fontwidth) {
+    case 4:
+	for (rows = p->fontheight ; rows-- ; dest += bytes)
+	    ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx;
+        break;
+    case 8:
+	for (rows = p->fontheight ; rows-- ; dest += bytes) {
+	    ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx;
+	    ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx;
+        }
+        break;
+    case 12:
+    case 16:
+	for (rows = p->fontheight ; rows-- ; dest += bytes) {
+	    ((u32 *)dest)[0]= (nibbletab_cfb8[*(u16 *)cdat >> 12] & eorx) ^ bgx;
+	    ((u32 *)dest)[1]= (nibbletab_cfb8[(*(u16 *)cdat >> 8) & 0xf] & eorx) ^ bgx;
+	    ((u32 *)dest)[2]= (nibbletab_cfb8[(*(u16 *)cdat >> 4) & 0xf] & eorx) ^ bgx;
+	    if (p->fontwidth == 16)
+	        ((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx;
+	    cdat += 2;
+        }
+        break;
     }
 }
 
@@ -145,15 +162,46 @@
     bgx |= (bgx << 8);
     bgx |= (bgx << 16);
     eorx = fgx ^ bgx;
-    while (count--) {
-	c = *s++;
-	cdat = p->fontdata + c * p->fontheight;
-
-	for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
-	    ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx;
-	    ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx;
-	}
-	dest0+=8;
+    switch (p->fontwidth) {
+    case 4:
+	while (count--) {
+	    c = *s++;
+	    cdat = p->fontdata + c * p->fontheight;
+
+	    for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes)
+		((u32 *)dest)[0]= (nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx;
+	    dest0+=4;
+        }
+        break;
+    case 8:
+	while (count--) {
+	    c = *s++;
+	    cdat = p->fontdata + c * p->fontheight;
+
+	    for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+		((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx;
+		((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx;
+	    }
+	    dest0+=8;
+        }
+        break;
+    case 12:
+    case 16:
+	while (count--) {
+	    c = *s++;
+	    cdat = p->fontdata + (c * p->fontheight << 1);
+
+	    for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+		((u32 *)dest)[0]= (nibbletab_cfb8[*(u16 *)cdat >> 12] & eorx) ^ bgx;
+		((u32 *)dest)[1]= (nibbletab_cfb8[(*(u16 *)cdat >> 8) & 0xf] & eorx) ^ bgx;
+		((u32 *)dest)[2]= (nibbletab_cfb8[(*(u16 *)cdat >> 4) & 0xf] & eorx) ^ bgx;
+		if (p->fontwidth == 16)
+		    ((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx;
+		cdat += 2;
+	    }
+	    dest0+=p->fontwidth;
+        }
+        break;
     }
 }
 
@@ -162,10 +210,15 @@
     u8 *dest;
     int bytes=p->next_line, rows;
 
-    dest = p->screen_base + yy * p->fontheight * bytes + xx * 8;
+    dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth;
     for (rows = p->fontheight ; rows-- ; dest += bytes) {
-	((u32 *)dest)[0] ^= 0x0f0f0f0f;
-	((u32 *)dest)[1] ^= 0x0f0f0f0f;
+    	switch (p->fontwidth) {
+    	case 16: ((u32 *)dest)[3] ^= 0x0f0f0f0f; /* FALL THROUGH */
+    	case 12: ((u32 *)dest)[2] ^= 0x0f0f0f0f; /* FALL THROUGH */
+    	case 8: ((u32 *)dest)[1] ^= 0x0f0f0f0f;  /* FALL THROUGH */
+    	case 4: ((u32 *)dest)[0] ^= 0x0f0f0f0f;  /* FALL THROUGH */
+    	default: break;
+    	}
     }
 }
 
@@ -176,7 +229,8 @@
 
 struct display_switch fbcon_cfb8 = {
     fbcon_cfb8_setup, fbcon_cfb8_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc,
-    fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL
+    fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, 
+    FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-ilbm.c linux/drivers/video/fbcon-ilbm.c
--- v2.1.109/linux/drivers/video/fbcon-ilbm.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-ilbm.c	Sat Jul 18 13:55:46 1998
@@ -260,7 +260,7 @@
 
 struct display_switch fbcon_ilbm = {
     fbcon_ilbm_setup, fbcon_ilbm_bmove, fbcon_ilbm_clear, fbcon_ilbm_putc,
-    fbcon_ilbm_putcs, fbcon_ilbm_revc, NULL
+    fbcon_ilbm_putcs, fbcon_ilbm_revc, NULL, NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-iplan2p2.c linux/drivers/video/fbcon-iplan2p2.c
--- v2.1.109/linux/drivers/video/fbcon-iplan2p2.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-iplan2p2.c	Sat Jul 18 13:55:46 1998
@@ -374,7 +374,8 @@
 
 struct display_switch fbcon_iplan2p2 = {
     fbcon_iplan2p2_setup, fbcon_iplan2p2_bmove, fbcon_iplan2p2_clear,
-    fbcon_iplan2p2_putc, fbcon_iplan2p2_putcs, fbcon_iplan2p2_revc, NULL
+    fbcon_iplan2p2_putc, fbcon_iplan2p2_putcs, fbcon_iplan2p2_revc, NULL,
+    NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-iplan2p4.c linux/drivers/video/fbcon-iplan2p4.c
--- v2.1.109/linux/drivers/video/fbcon-iplan2p4.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-iplan2p4.c	Sat Jul 18 13:55:46 1998
@@ -394,7 +394,8 @@
 
 struct display_switch fbcon_iplan2p4 = {
     fbcon_iplan2p4_setup, fbcon_iplan2p4_bmove, fbcon_iplan2p4_clear,
-    fbcon_iplan2p4_putc, fbcon_iplan2p4_putcs, fbcon_iplan2p4_revc, NULL
+    fbcon_iplan2p4_putc, fbcon_iplan2p4_putcs, fbcon_iplan2p4_revc, NULL,
+    NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-iplan2p8.c linux/drivers/video/fbcon-iplan2p8.c
--- v2.1.109/linux/drivers/video/fbcon-iplan2p8.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-iplan2p8.c	Sat Jul 18 13:55:46 1998
@@ -431,7 +431,8 @@
 
 struct display_switch fbcon_iplan2p8 = {
     fbcon_iplan2p8_setup, fbcon_iplan2p8_bmove, fbcon_iplan2p8_clear,
-    fbcon_iplan2p8_putc, fbcon_iplan2p8_putcs, fbcon_iplan2p8_revc, NULL
+    fbcon_iplan2p8_putc, fbcon_iplan2p8_putcs, fbcon_iplan2p8_revc, NULL,
+    NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-mac.c linux/drivers/video/fbcon-mac.c
--- v2.1.109/linux/drivers/video/fbcon-mac.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-mac.c	Sat Jul 18 13:55:46 1998
@@ -497,7 +497,7 @@
 
 struct display_switch fbcon_mac = {
     fbcon_mac_setup, fbcon_mac_bmove, fbcon_mac_clear, fbcon_mac_putc,
-    fbcon_mac_putcs, fbcon_mac_revc, NULL
+    fbcon_mac_putcs, fbcon_mac_revc, NULL, NULL, FONTWIDTHRANGE(1,8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-mfb.c linux/drivers/video/fbcon-mfb.c
--- v2.1.109/linux/drivers/video/fbcon-mfb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-mfb.c	Sat Jul 18 13:55:46 1998
@@ -153,7 +153,7 @@
 
 struct display_switch fbcon_mfb = {
     fbcon_mfb_setup, fbcon_mfb_bmove, fbcon_mfb_clear, fbcon_mfb_putc,
-    fbcon_mfb_putcs, fbcon_mfb_revc, NULL
+    fbcon_mfb_putcs, fbcon_mfb_revc, NULL, NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon-vga.c linux/drivers/video/fbcon-vga.c
--- v2.1.109/linux/drivers/video/fbcon-vga.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon-vga.c	Sat Jul 18 13:55:46 1998
@@ -178,7 +178,7 @@
 
 struct display_switch fbcon_vga = {
     fbcon_vga_setup, fbcon_vga_bmove, fbcon_vga_clear, fbcon_vga_putc,
-    fbcon_vga_putcs, fbcon_vga_revc, NULL
+    fbcon_vga_putcs, fbcon_vga_revc, NULL, NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- v2.1.109/linux/drivers/video/fbcon.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon.c	Sat Jul 18 13:55:46 1998
@@ -25,7 +25,8 @@
  *			   Andreas Schwab
  *
  *  Hardware cursor support added by Emmanuel Marty (core@ggi-project.org)
- *  Smart redraw scrolling added by Jakub Jelinek (jj@ultra.linux.cz)
+ *  Smart redraw scrolling, arbitrary font width support added by 
+ *                         Jakub Jelinek (jj@ultra.linux.cz)
  *
  *
  *  The low level operations for the various display memory organizations are
@@ -132,13 +133,10 @@
 static int cursor_on = 0;
 static int cursor_blink_rate;
 
-static __inline__ int CURSOR_UNDRAWN(void)
+static __inline__ void CURSOR_UNDRAWN(void)
 {
-    int cursor_was_drawn;
     vbl_cursor_cnt = 0;
-    cursor_was_drawn = cursor_drawn;
     cursor_drawn = 0;
-    return cursor_was_drawn;
 }
 #endif
 
@@ -168,7 +166,7 @@
 static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
 			int height, int width);
 static int fbcon_switch(struct vc_data *conp);
-static int fbcon_blank(int blank);
+static int fbcon_blank(struct vc_data *conp, int blank);
 static int fbcon_get_font(struct vc_data *conp, int *w, int *h, char *data);
 static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data);
 static int fbcon_set_palette(struct vc_data *conp, unsigned char *table);
@@ -330,6 +328,9 @@
     info = registered_fb[(int)con2fb_map[unit]];
 
     info->changevar = &fbcon_changevar;
+    conp->vc_display_fg = &info->display_fg;
+    if (!info->display_fg)
+        info->display_fg = conp;
     fb_display[unit] = *(info->disp);	/* copy from default */
     DPRINTK("mode:   %s\n",info->modename);
     DPRINTK("visual: %d\n",fb_display[unit].visual);
@@ -374,6 +375,20 @@
 	p->scrollmode = SCROLL_YMOVE;
 }
 
+static void fbcon_font_widths(struct display *p)
+{
+    int i;
+    p->fontwidthlog = 0;
+    for (i = 2; i <= 6; i++)
+    	if (p->fontwidth == (1 << i))
+	    p->fontwidthlog = i;
+    p->fontheightlog = 0;
+    for (i = 2; i <= 6; i++)
+    	if (p->fontheight == (1 << i))
+	    p->fontheightlog = i;
+}
+
+#define fontwidthvalid(p,w) ((p)->dispsw->fontwidthmask & FONTWIDTH(w))
 
 static void fbcon_setup(int con, int init, int logo)
 {
@@ -381,6 +396,8 @@
     struct vc_data *conp = p->conp;
     int nr_rows, nr_cols;
     int old_rows, old_cols;
+    unsigned short *save = NULL, *r, *q;
+    int logo_lines = 0;
     /* Only if not module */
     extern int initmem_freed;
     
@@ -391,10 +408,12 @@
 
     if (!p->fb_info->fontname[0] ||
 	!findsoftfont(p->fb_info->fontname, &p->fontwidth, &p->fontheight,
-		      &p->fontdata) || p->fontwidth != 8)
+		      &p->fontdata) || !fontwidthvalid(p,p->fontwidth))
 	getdefaultfont(p->var.xres, p->var.yres, NULL, &p->fontwidth,
 		       &p->fontheight, &p->fontdata);
-    if (p->fontwidth != 8) {
+
+    fbcon_font_widths(p);
+    if (!fontwidthvalid(p,p->fontwidth)) {
 #ifdef CONFIG_MAC
 	if (MACH_IS_MAC)
 	    /* ++Geert: hack to make 6x11 fonts work on mac */
@@ -403,44 +422,58 @@
 #endif
 	{
 	    /* ++Geert: changed from panic() to `correct and continue' */
-	    printk(KERN_ERR "fbcon_setup: No support for fontwidth != 8");
+	    printk(KERN_ERR "fbcon_setup: No support for fontwidth %d\n", p->fontwidth);
 	    p->dispsw = &fbcon_dummy;
 	}
     }
+    if (p->dispsw->set_font)
+    	p->dispsw->set_font(p, p->fontwidth, p->fontheight);
     updatescrollmode(p);
     
+    old_cols = conp->vc_cols;
+    old_rows = conp->vc_rows;
+    
+    nr_cols = p->var.xres/p->fontwidth;
+    nr_rows = p->var.yres/p->fontheight;
+    
     if (logo) {
     	/* Need to make room for the logo */
-    	int logo_lines = (LOGO_H + p->fontheight - 1) / p->fontheight;
-    	unsigned short *q = (unsigned short *)(conp->vc_origin + 
-    				conp->vc_size_row * conp->vc_rows);
-	unsigned short *r;
+	int cnt;
+	int step;
     
-    	for (r = q - logo_lines * conp->vc_cols; r < q; r++)
+    	logo_lines = (LOGO_H + p->fontheight - 1) / p->fontheight;
+    	q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows);
+    	step = logo_lines * old_cols;
+    	for (r = q - logo_lines * old_cols; r < q; r++)
     	    if (*r != conp->vc_video_erase_char)
     	    	break;
+	if (r != q && nr_rows >= old_rows + logo_lines) {
+    	    save = kmalloc(logo_lines * nr_cols * 2, GFP_KERNEL);
+    	    if (save) {
+    	        int i = old_cols < nr_cols ? old_cols : nr_cols;
+    	    	scr_memsetw(save, conp->vc_video_erase_char, logo_lines * nr_cols * 2);
+    	    	r = q - step;
+    	    	for (cnt = 0; cnt < logo_lines; cnt++, r += i)
+    	    		scr_memcpyw(save + cnt * nr_cols, r, 2 * i);
+    	    	r = q;
+    	    }
+    	}
     	if (r == q) {
     	    /* We can scroll screen down */
-    	    int cnt;
-    	    int step = logo_lines * conp->vc_cols;
-
-	    r = q - step - conp->vc_cols;
-    	    for (cnt = conp->vc_rows - logo_lines; cnt > 0; cnt--) {
+	    r = q - step - old_cols;
+    	    for (cnt = old_rows - logo_lines; cnt > 0; cnt--) {
     	    	scr_memcpyw(r + step, r, conp->vc_size_row);
-    	    	r -= conp->vc_cols;
+    	    	r -= old_cols;
+    	    }
+    	    if (!save) {
+	    	conp->vc_y += logo_lines;
+    		conp->vc_pos += logo_lines * conp->vc_size_row;
     	    }
-    	    conp->vc_y += logo_lines;
-    	    conp->vc_pos += logo_lines * conp->vc_size_row;
     	}
     	scr_memsetw((unsigned short *)conp->vc_origin, conp->vc_video_erase_char, 
     		conp->vc_size_row * logo_lines);
     }
     
-    old_cols = conp->vc_cols;
-    old_rows = conp->vc_rows;
-    
-    nr_cols = p->var.xres/p->fontwidth;
-    nr_rows = p->var.yres/p->fontheight;
     /*
      *  ++guenther: console.c:vc_allocate() relies on initializing
      *  vc_{cols,rows}, but we must not set those if we are only
@@ -465,8 +498,14 @@
 
     if (!init) {
 	vc_resize_con(nr_rows, nr_cols, con);
-	if (con == fg_console &&
-	    old_rows == nr_rows && old_cols == nr_cols)
+	if (save) {
+    	    q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows);
+	    scr_memcpyw(q, save, logo_lines * nr_cols * 2);
+	    conp->vc_y += logo_lines;
+    	    conp->vc_pos += logo_lines * conp->vc_size_row;
+    	    kfree(save);
+	}
+	if (con == fg_console)
 	    update_screen(con); /* So that we set origin correctly */
     }
 	
@@ -515,6 +554,7 @@
     int unit = conp->vc_num;
     struct display *p = &fb_display[unit];
     u_int y_break;
+    int redraw_cursor = 0;
 
     if (!p->can_soft_blank && console_blanked)
 	return;
@@ -523,8 +563,10 @@
 	return;
 
     if ((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
-	(sx <= p->cursor_x) && (p->cursor_x < sx+width))
+	(sx <= p->cursor_x) && (p->cursor_x < sx+width)) {
 	CURSOR_UNDRAWN();
+	redraw_cursor = 1;
+    }
 
     /* Split blits that cross physical y_wrap boundary */
 
@@ -535,6 +577,9 @@
 	p->dispsw->clear(conp, p, real_y(p, sy+b), sx, height-b, width);
     } else
 	p->dispsw->clear(conp, p, real_y(p, sy), sx, height, width);
+
+    if (redraw_cursor)
+	vbl_cursor_cnt = CURSOR_DRAW_DELAY;
 }
 
 
@@ -542,14 +587,20 @@
 {
     int unit = conp->vc_num;
     struct display *p = &fb_display[unit];
+    int redraw_cursor = 0;
 
     if (!p->can_soft_blank && console_blanked)
 	    return;
 
-    if ((p->cursor_x == xpos) && (p->cursor_y == ypos))
+    if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) {
 	    CURSOR_UNDRAWN();
+	    redraw_cursor = 1;
+    }
 
     p->dispsw->putc(conp, p, c, real_y(p, ypos), xpos);
+
+    if (redraw_cursor)
+	    vbl_cursor_cnt = CURSOR_DRAW_DELAY;
 }
 
 
@@ -558,14 +609,19 @@
 {
     int unit = conp->vc_num;
     struct display *p = &fb_display[unit];
+    int redraw_cursor = 0;
 
     if (!p->can_soft_blank && console_blanked)
 	    return;
 
     if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) &&
-	(p->cursor_x < (xpos + count)))
+	(p->cursor_x < (xpos + count))) {
 	    CURSOR_UNDRAWN();
+	    redraw_cursor = 1;
+    }
     p->dispsw->putcs(conp, p, s, count, real_y(p, ypos), xpos);
+    if (redraw_cursor)
+	    vbl_cursor_cnt = CURSOR_DRAW_DELAY;
 }
 
 
@@ -613,19 +669,16 @@
 static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp)
 {
     struct display *p;
-    static int _vbl_cursor_cnt = 1, _vbl_cursor_drawn;
 
-    if (!--_vbl_cursor_cnt) {
-	_vbl_cursor_cnt = cursor_blink_rate;
-	_vbl_cursor_drawn = !_vbl_cursor_drawn;
-    }
+    if (!cursor_on)
+	return;
 
-    if (cursor_on && vbl_cursor_cnt) {
-	if (cursor_drawn != _vbl_cursor_drawn) {
-	    p = &fb_display[fg_console];
-	    p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y));
-	}
-	cursor_drawn = _vbl_cursor_drawn;
+    if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) {
+	p = &fb_display[fg_console];
+	if (p->dispsw->revc)
+		p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y));
+	cursor_drawn ^= 1;
+	vbl_cursor_cnt = cursor_blink_rate;
     }
 }
 #endif
@@ -759,6 +812,53 @@
     }
 }
 
+/* This cannot be used together with ypan or ywrap */
+void fbcon_redraw_bmove(struct display *p, int sy, int sx, int dy, int dx, int h, int w)
+{
+    if (sy != dy)
+    	panic("fbcon_redraw_bmove width sy != dy");
+    /* h will be always 1, but it does not matter if we are more generic */
+    while (h-- > 0) {
+	struct vc_data *conp = p->conp;
+	unsigned short *d = (unsigned short *)
+		(conp->vc_origin + conp->vc_size_row * dy + dx * 2);
+	unsigned short *s = d + (dx - sx);
+	unsigned short *start = d;
+	unsigned short *ls = d;
+	unsigned short *le = d + w;
+	unsigned short c;
+	int x = dx;
+	unsigned short attr = 1;
+
+	do {
+	    c = scr_readw(d);
+	    if (attr != (c & 0xff00)) {
+		attr = c & 0xff00;
+		if (d > start) {
+		    p->dispsw->putcs(conp, p, start, d - start, dy, x);
+		    x += d - start;
+		    start = d;
+		}
+	    }
+	    if (s >= ls && s < le && c == scr_readw(s)) {
+		if (d > start) {
+		    p->dispsw->putcs(conp, p, start, d - start, dy, x);
+		    x += d - start + 1;
+		    start = d + 1;
+		} else {
+		    x++;
+		    start++;
+		}
+	    }
+	    s++;
+	    d++;
+	} while (d < le);
+	if (d > start)
+	    p->dispsw->putcs(conp, p, start, d - start, dy, x);
+	sy++;
+	dy++;
+    }
+}
 
 static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
 			int count)
@@ -1007,11 +1107,14 @@
 }
 
 
-static int fbcon_blank(int blank)
+static int fbcon_blank(struct vc_data *conp, int blank)
 {
-    struct display *p = &fb_display[fg_console];
+    struct display *p = &fb_display[conp->vc_num];
     struct fb_info *info = p->fb_info;
 
+    if (blank < 0)	/* Entering graphics mode */
+	return 0;
+
     fbcon_cursor(p->conp, blank ? CM_ERASE : CM_DRAW);
 
     if (!p->can_soft_blank) {
@@ -1030,7 +1133,7 @@
 			     p->var.xres_virtual*p->var.yres_virtual*
 			     p->var.bits_per_pixel>>3);
 	     } else
-		 p->dispsw->clear(p->conp, p, 0, 0, p->conp->vc_rows, p->conp->vc_cols);
+		 p->dispsw->clear(conp, p, 0, 0, p->conp->vc_rows, p->conp->vc_cols);
 	    return 0;
 	} else {
 	    /* Tell console.c that it has to restore the screen itself */
@@ -1065,6 +1168,7 @@
 
 
 #define REFCOUNT(fd)	(((int *)(fd))[-1])
+#define FNTSIZE(fd)	(((int *)(fd))[-2])
 
 static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data)
 {
@@ -1080,15 +1184,12 @@
 
     if (w == 0) {
 	/* engage predefined font, name in 'data' */
-	char name[MAX_FONT_NAME+1];
-
-	if ((i = verify_area( VERIFY_READ, (void *)data, MAX_FONT_NAME )))
-	    return i;
-	copy_from_user( name, data, MAX_FONT_NAME );
-	name[sizeof(name)-1] = 0;
+	unsigned short width, height;
+	data[MAX_FONT_NAME] = 0;
 
-	if (!findsoftfont( name, &w, &h, (u8 **)&data ))
+	if (!findsoftfont( data, &width, &height, (u8 **)&data ))
 	    return -ENOENT;
+	w = width; h = height;
 	userspace = 0;
     } else if (w == 1) {
 	/* copy font from some other console in 'h'*/
@@ -1109,12 +1210,14 @@
 	p->fontdata = op->fontdata;
 	w = p->fontwidth = op->fontwidth;
 	h = p->fontheight = op->fontheight;
+	p->fontwidthlog = op->fontwidthlog;
+	p->fontheightlog = op->fontheightlog;
 	if ((p->userfont = op->userfont))
 	    REFCOUNT(p->fontdata)++;	/* increment usage counter */
 	goto activate;
     }
 
-    if (w != 8)
+    if (!fontwidthvalid(p,w))
 	/* Currently only fontwidth == 8 supported */
 	return -ENXIO;
 
@@ -1125,9 +1228,10 @@
 	old_data = p->fontdata;
 
     if (userspace) {
-	if (!(new_data = kmalloc( sizeof(int)+size, GFP_USER )))
+	if (!(new_data = kmalloc( 2*sizeof(int)+size, GFP_USER )))
 	    return -ENOMEM;
-	new_data += sizeof(int);
+	new_data += 2*sizeof(int);
+	FNTSIZE(new_data) = size;
 	REFCOUNT(new_data) = 1; /* usage counter */
 
 	for (i = 0; i < 256; i++)
@@ -1142,13 +1246,17 @@
     }
     p->fontwidth = w;
     p->fontheight = h;
+    fbcon_font_widths(p);
 
 activate:
     if (resize) {
 	/* reset wrap/pan */
 	p->var.xoffset = p->var.yoffset = p->yscroll = 0;
-	/* Adjust the virtual screen-size to fontheight*rows */
-	p->var.yres_virtual = (p->var.yres/h)*h;
+	if (!p->dispsw->set_font || 
+	    !p->dispsw->set_font(p, p->fontwidth, p->fontheight)) {
+	    /* Adjust the virtual screen-size to fontheight*rows */
+	    p->var.yres_virtual = (p->var.yres/h)*h;
+	}
 	p->vrows = p->var.yres_virtual/h;
 	updatescrollmode(p);
 	vc_resize_con( p->var.yres/h, p->var.xres/w, unit );
@@ -1156,7 +1264,7 @@
 	update_screen( unit );
 
     if (old_data && (--REFCOUNT(old_data) == 0))
-	kfree( old_data - sizeof(int) );
+	kfree( old_data - 2*sizeof(int) );
 
     return 0;
 }
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fbcon.h linux/drivers/video/fbcon.h
--- v2.1.109/linux/drivers/video/fbcon.h	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fbcon.h	Sat Jul 18 13:55:46 1998
@@ -30,8 +30,15 @@
 		  int count, int yy, int xx);     
     void (*revc)(struct display *p, int xx, int yy);
     void (*cursor)(struct display *p, int mode, int xx, int yy);
+    int  (*set_font)(struct display *p, int width, int height);
+    unsigned int fontwidthmask;      /* 1 at (1 << (width - 1)) if width is supported */
 }; 
 
+/* fontwidth w is supported by dispsw */
+#define FONTWIDTH(w)	(1 << ((w) - 1))
+/* fontwidths w1-w2 inclusive are supported by dispsw */
+#define FONTWIDTHRANGE(w1,w2)	(FONTWIDTH(w2+1) - FONTWIDTH(w1))
+
 
     /*
      *  Attribute Decoding
@@ -63,6 +70,8 @@
 #define SCROLL_YPAN	(1)
 #define SCROLL_YMOVE	(2)
 #define SCROLL_YREDRAW	(3)
+
+extern void fbcon_redraw_bmove(struct display *, int, int, int, int, int, int);
 
 
 /* ================================================================= */
diff -u --recursive --new-file v2.1.109/linux/drivers/video/font.h linux/drivers/video/font.h
--- v2.1.109/linux/drivers/video/font.h	Mon Nov 24 01:18:57 1997
+++ linux/drivers/video/font.h	Sat Jul 18 13:55:46 1998
@@ -18,15 +18,15 @@
     *    Find a font with a specific name
     */
 
-extern int findsoftfont(char *name, int *width, int *height, u_char *data[]);
+extern int findsoftfont(char *name, unsigned short *width, unsigned short *height, u_char *data[]);
 
 
    /*
     *    Get the default font for a specific screen size
     */
 
-extern void getdefaultfont(int xres, int yres, char *name[], int *width,
-                           int *height, u_char *data[]);
+extern void getdefaultfont(int xres, int yres, char *name[], unsigned short *width,
+                           unsigned short *height, u_char *data[]);
 
 
 /* Max. length for the name of a predefined font */
diff -u --recursive --new-file v2.1.109/linux/drivers/video/font_sun12x22.c linux/drivers/video/font_sun12x22.c
--- v2.1.109/linux/drivers/video/font_sun12x22.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/font_sun12x22.c	Sat Jul 18 13:55:46 1998
@@ -0,0 +1,6210 @@
+#define FONTDATAMAX 5632
+
+char fontname_sun12x22[] = "SUN12x22";
+
+int  fontheight_sun12x22 = 22;
+int  fontwidth_sun12x22  = 12;
+
+unsigned short fontdata_sun12x22[FONTDATAMAX] = {
+
+	/* 0 0x00 '^@' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 1 0x01 '^A' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 2 0x02 '^B' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 3 0x03 '^C' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 4 0x04 '^D' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 5 0x05 '^E' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 6 0x06 '^F' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 7 0x07 '^G' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 8 0x08 '^H' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 9 0x09 '^I' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 10 0x0a '^J' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 11 0x0b '^K' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 12 0x0c '^L' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 13 0x0d '^M' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 14 0x0e '^N' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 15 0x0f '^O' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 16 0x10 '^P' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 17 0x11 '^Q' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 18 0x12 '^R' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 19 0x13 '^S' */
+	0x0000, /* 000000000000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 20 0x14 '^T' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1ff0, /* 000111111111 */
+	0x3cc0, /* 001111001100 */
+	0x7cc0, /* 011111001100 */
+	0x7cc0, /* 011111001100 */
+	0x7cc0, /* 011111001100 */
+	0x3cc0, /* 001111001100 */
+	0x1cc0, /* 000111001100 */
+	0x0cc0, /* 000011001100 */
+	0x0cc0, /* 000011001100 */
+	0x0cc0, /* 000011001100 */
+	0x0cc0, /* 000011001100 */
+	0x0cc0, /* 000011001100 */
+	0x0cc0, /* 000011001100 */
+	0x1ce0, /* 000111001110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 21 0x15 '^U' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1f00, /* 000111110000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x1f00, /* 000111110000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x1f00, /* 000111110000 */
+	0x0180, /* 000000011000 */
+	0x0180, /* 000000011000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x1f00, /* 000111110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 22 0x16 '^V' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 23 0x17 '^W' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 24 0x18 '^X' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 25 0x19 '^Y' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 26 0x1a '^Z' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 27 0x1b '^[' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 28 0x1c '^\' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 29 0x1d '^]' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 30 0x1e '^^' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 31 0x1f '^_' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 32 0x20 ' ' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 33 0x21 '!' */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 34 0x22 '"' */
+	0x0000, /* 000000000000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 35 0x23 '#' */
+	0x0000, /* 000000000000 */
+	0x0330, /* 000000110011 */
+	0x0330, /* 000000110011 */
+	0x0330, /* 000000110011 */
+	0x0660, /* 000001100110 */
+	0x1ff0, /* 000111111111 */
+	0x1ff0, /* 000111111111 */
+	0x0cc0, /* 000011001100 */
+	0x0cc0, /* 000011001100 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x7fc0, /* 011111111100 */
+	0x7fc0, /* 011111111100 */
+	0x3300, /* 001100110000 */
+	0x6600, /* 011001100000 */
+	0x6600, /* 011001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 36 0x24 '$' */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x1f80, /* 000111111000 */
+	0x3fc0, /* 001111111100 */
+	0x66e0, /* 011001101110 */
+	0x6660, /* 011001100110 */
+	0x6600, /* 011001100000 */
+	0x3e00, /* 001111100000 */
+	0x1f80, /* 000111111000 */
+	0x07c0, /* 000001111100 */
+	0x0660, /* 000001100110 */
+	0x0660, /* 000001100110 */
+	0x6660, /* 011001100110 */
+	0x7fc0, /* 011111111100 */
+	0x3f80, /* 001111111000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 37 0x25 '%' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x38c0, /* 001110001100 */
+	0x4cc0, /* 010011001100 */
+	0x4580, /* 010001011000 */
+	0x6580, /* 011001011000 */
+	0x3b00, /* 001110110000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x0dc0, /* 000011011100 */
+	0x1a60, /* 000110100110 */
+	0x1a20, /* 000110100010 */
+	0x3320, /* 001100110010 */
+	0x31c0, /* 001100011100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 38 0x26 '&' */
+	0x0000, /* 000000000000 */
+	0x0700, /* 000001110000 */
+	0x0f80, /* 000011111000 */
+	0x18c0, /* 000110001100 */
+	0x18c0, /* 000110001100 */
+	0x18c0, /* 000110001100 */
+	0x0f80, /* 000011111000 */
+	0x1e00, /* 000111100000 */
+	0x3e00, /* 001111100000 */
+	0x7700, /* 011101110000 */
+	0x6360, /* 011000110110 */
+	0x61e0, /* 011000011110 */
+	0x61c0, /* 011000011100 */
+	0x6180, /* 011000011000 */
+	0x3fe0, /* 001111111110 */
+	0x1e60, /* 000111100110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 39 0x27 ''' */
+	0x0000, /* 000000000000 */
+	0x0c00, /* 000011000000 */
+	0x1e00, /* 000111100000 */
+	0x1e00, /* 000111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x1800, /* 000110000000 */
+	0x1000, /* 000100000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 40 0x28 '(' */
+	0x0000, /* 000000000000 */
+	0x0180, /* 000000011000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0300, /* 000000110000 */
+	0x0180, /* 000000011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 41 0x29 ')' */
+	0x0000, /* 000000000000 */
+	0x1800, /* 000110000000 */
+	0x0c00, /* 000011000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x1800, /* 000110000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 42 0x2a '*' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x0600, /* 000001100000 */
+	0x6660, /* 011001100110 */
+	0x76e0, /* 011101101110 */
+	0x1980, /* 000110011000 */
+	0x0000, /* 000000000000 */
+	0x1980, /* 000110011000 */
+	0x76e0, /* 011101101110 */
+	0x6660, /* 011001100110 */
+	0x0600, /* 000001100000 */
+	0x0f00, /* 000011110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 43 0x2b '+' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x7fe0, /* 011111111110 */
+	0x7fe0, /* 011111111110 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 44 0x2c ',' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0c00, /* 000011000000 */
+	0x1e00, /* 000111100000 */
+	0x1e00, /* 000111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x1800, /* 000110000000 */
+	0x1000, /* 000100000000 */
+	0x0000, /* 000000000000 */
+
+	/* 45 0x2d '-' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x7fe0, /* 011111111110 */
+	0x7fe0, /* 011111111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 46 0x2e '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0c00, /* 000011000000 */
+	0x1e00, /* 000111100000 */
+	0x1e00, /* 000111100000 */
+	0x0c00, /* 000011000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 47 0x2f '/' */
+	0x0000, /* 000000000000 */
+	0x0060, /* 000000000110 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x0180, /* 000000011000 */
+	0x0180, /* 000000011000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x1800, /* 000110000000 */
+	0x1800, /* 000110000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x6000, /* 011000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 48 0x30 '0' */
+	0x0000, /* 000000000000 */
+	0x0700, /* 000001110000 */
+	0x0f80, /* 000011111000 */
+	0x1180, /* 000100011000 */
+	0x10c0, /* 000100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x3080, /* 001100001000 */
+	0x1880, /* 000110001000 */
+	0x1f00, /* 000111110000 */
+	0x0e00, /* 000011100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 49 0x31 '1' */
+	0x0000, /* 000000000000 */
+	0x0200, /* 000000100000 */
+	0x0600, /* 000001100000 */
+	0x0e00, /* 000011100000 */
+	0x1e00, /* 000111100000 */
+	0x3600, /* 001101100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 50 0x32 '2' */
+	0x0000, /* 000000000000 */
+	0x1f00, /* 000111110000 */
+	0x3f80, /* 001111111000 */
+	0x61c0, /* 011000011100 */
+	0x40c0, /* 010000001100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x0180, /* 000000011000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x1800, /* 000110000000 */
+	0x3020, /* 001100000010 */
+	0x7fe0, /* 011111111110 */
+	0x7fe0, /* 011111111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 51 0x33 '3' */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x1fc0, /* 000111111100 */
+	0x20e0, /* 001000001110 */
+	0x4060, /* 010000000110 */
+	0x0060, /* 000000000110 */
+	0x00e0, /* 000000001110 */
+	0x07c0, /* 000001111100 */
+	0x0fc0, /* 000011111100 */
+	0x00e0, /* 000000001110 */
+	0x0060, /* 000000000110 */
+	0x0060, /* 000000000110 */
+	0x4060, /* 010000000110 */
+	0x6040, /* 011000000100 */
+	0x3f80, /* 001111111000 */
+	0x1f00, /* 000111110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 52 0x34 '4' */
+	0x0000, /* 000000000000 */
+	0x0180, /* 000000011000 */
+	0x0380, /* 000000111000 */
+	0x0380, /* 000000111000 */
+	0x0580, /* 000001011000 */
+	0x0580, /* 000001011000 */
+	0x0980, /* 000010011000 */
+	0x0980, /* 000010011000 */
+	0x1180, /* 000100011000 */
+	0x1180, /* 000100011000 */
+	0x2180, /* 001000011000 */
+	0x3fe0, /* 001111111110 */
+	0x7fe0, /* 011111111110 */
+	0x0180, /* 000000011000 */
+	0x0180, /* 000000011000 */
+	0x0180, /* 000000011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 53 0x35 '5' */
+	0x0000, /* 000000000000 */
+	0x0fc0, /* 000011111100 */
+	0x0fc0, /* 000011111100 */
+	0x1000, /* 000100000000 */
+	0x1000, /* 000100000000 */
+	0x2000, /* 001000000000 */
+	0x3f80, /* 001111111000 */
+	0x31c0, /* 001100011100 */
+	0x00e0, /* 000000001110 */
+	0x0060, /* 000000000110 */
+	0x0060, /* 000000000110 */
+	0x0060, /* 000000000110 */
+	0x4060, /* 010000000110 */
+	0x6060, /* 011000000110 */
+	0x30c0, /* 001100001100 */
+	0x1f80, /* 000111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 54 0x36 '6' */
+	0x0000, /* 000000000000 */
+	0x0700, /* 000001110000 */
+	0x0c00, /* 000011000000 */
+	0x1800, /* 000110000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x6000, /* 011000000000 */
+	0x6780, /* 011001111000 */
+	0x6fc0, /* 011011111100 */
+	0x70e0, /* 011100001110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7040, /* 011100000100 */
+	0x3f80, /* 001111111000 */
+	0x1f00, /* 000111110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 55 0x37 '7' */
+	0x0000, /* 000000000000 */
+	0x1fe0, /* 000111111110 */
+	0x3fe0, /* 001111111110 */
+	0x6040, /* 011000000100 */
+	0x0040, /* 000000000100 */
+	0x00c0, /* 000000001100 */
+	0x0080, /* 000000001000 */
+	0x0080, /* 000000001000 */
+	0x0180, /* 000000011000 */
+	0x0100, /* 000000010000 */
+	0x0100, /* 000000010000 */
+	0x0300, /* 000000110000 */
+	0x0200, /* 000000100000 */
+	0x0200, /* 000000100000 */
+	0x0600, /* 000001100000 */
+	0x0400, /* 000001000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 56 0x38 '8' */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x1180, /* 000100011000 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x1880, /* 000110001000 */
+	0x0d00, /* 000011010000 */
+	0x0600, /* 000001100000 */
+	0x0b00, /* 000010110000 */
+	0x1180, /* 000100011000 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x1880, /* 000110001000 */
+	0x0f00, /* 000011110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 57 0x39 '9' */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x11c0, /* 000100011100 */
+	0x20e0, /* 001000001110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x70e0, /* 011100001110 */
+	0x3f60, /* 001111110110 */
+	0x1e60, /* 000111100110 */
+	0x0060, /* 000000000110 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x0180, /* 000000011000 */
+	0x0700, /* 000001110000 */
+	0x3c00, /* 001111000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 58 0x3a ':' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0c00, /* 000011000000 */
+	0x1e00, /* 000111100000 */
+	0x1e00, /* 000111100000 */
+	0x0c00, /* 000011000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0c00, /* 000011000000 */
+	0x1e00, /* 000111100000 */
+	0x1e00, /* 000111100000 */
+	0x0c00, /* 000011000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 59 0x3b ';' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0c00, /* 000011000000 */
+	0x1e00, /* 000111100000 */
+	0x1e00, /* 000111100000 */
+	0x0c00, /* 000011000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0c00, /* 000011000000 */
+	0x1e00, /* 000111100000 */
+	0x1e00, /* 000111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x1800, /* 000110000000 */
+	0x1000, /* 000100000000 */
+	0x0000, /* 000000000000 */
+
+	/* 60 0x3c '<' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0060, /* 000000000110 */
+	0x01c0, /* 000000011100 */
+	0x0700, /* 000001110000 */
+	0x1c00, /* 000111000000 */
+	0x7000, /* 011100000000 */
+	0x7000, /* 011100000000 */
+	0x1c00, /* 000111000000 */
+	0x0700, /* 000001110000 */
+	0x01c0, /* 000000011100 */
+	0x0060, /* 000000000110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 61 0x3d '=' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x7fe0, /* 011111111110 */
+	0x7fe0, /* 011111111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x7fe0, /* 011111111110 */
+	0x7fe0, /* 011111111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 62 0x3e '>' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x6000, /* 011000000000 */
+	0x3800, /* 001110000000 */
+	0x0e00, /* 000011100000 */
+	0x0380, /* 000000111000 */
+	0x00e0, /* 000000001110 */
+	0x00e0, /* 000000001110 */
+	0x0380, /* 000000111000 */
+	0x0e00, /* 000011100000 */
+	0x3800, /* 001110000000 */
+	0x6000, /* 011000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 63 0x3f '?' */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x1f80, /* 000111111000 */
+	0x39c0, /* 001110011100 */
+	0x20c0, /* 001000001100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x0180, /* 000000011000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 64 0x40 '@' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x3fc0, /* 001111111100 */
+	0x3060, /* 001100000110 */
+	0x6060, /* 011000000110 */
+	0x6720, /* 011001110010 */
+	0x6fa0, /* 011011111010 */
+	0x6ca0, /* 011011001010 */
+	0x6ca0, /* 011011001010 */
+	0x67e0, /* 011001111110 */
+	0x6000, /* 011000000000 */
+	0x3000, /* 001100000000 */
+	0x3fe0, /* 001111111110 */
+	0x0fe0, /* 000011111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 65 0x41 'A' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0b00, /* 000010110000 */
+	0x0b00, /* 000010110000 */
+	0x0900, /* 000010010000 */
+	0x1180, /* 000100011000 */
+	0x1180, /* 000100011000 */
+	0x1080, /* 000100001000 */
+	0x3fc0, /* 001111111100 */
+	0x20c0, /* 001000001100 */
+	0x2040, /* 001000000100 */
+	0x4060, /* 010000000110 */
+	0x4060, /* 010000000110 */
+	0xe0f0, /* 111000001111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 66 0x42 'B' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xff00, /* 111111110000 */
+	0x6080, /* 011000001000 */
+	0x60c0, /* 011000001100 */
+	0x60c0, /* 011000001100 */
+	0x60c0, /* 011000001100 */
+	0x6180, /* 011000011000 */
+	0x7f80, /* 011111111000 */
+	0x60c0, /* 011000001100 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x60c0, /* 011000001100 */
+	0xff80, /* 111111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 67 0x43 'C' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0fc0, /* 000011111100 */
+	0x1060, /* 000100000110 */
+	0x2020, /* 001000000010 */
+	0x2000, /* 001000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x2000, /* 001000000000 */
+	0x3020, /* 001100000010 */
+	0x1840, /* 000110000100 */
+	0x0f80, /* 000011111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 68 0x44 'D' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xff00, /* 111111110000 */
+	0x61c0, /* 011000011100 */
+	0x60c0, /* 011000001100 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6040, /* 011000000100 */
+	0x6180, /* 011000011000 */
+	0xfe00, /* 111111100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 69 0x45 'E' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x7fc0, /* 011111111100 */
+	0x3040, /* 001100000100 */
+	0x3040, /* 001100000100 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3080, /* 001100001000 */
+	0x3f80, /* 001111111000 */
+	0x3080, /* 001100001000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3020, /* 001100000010 */
+	0x3020, /* 001100000010 */
+	0x7fe0, /* 011111111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 70 0x46 'F' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x7fc0, /* 011111111100 */
+	0x3040, /* 001100000100 */
+	0x3040, /* 001100000100 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3080, /* 001100001000 */
+	0x3f80, /* 001111111000 */
+	0x3080, /* 001100001000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x7800, /* 011110000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 71 0x47 'G' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0fc0, /* 000011111100 */
+	0x1060, /* 000100000110 */
+	0x2020, /* 001000000010 */
+	0x2000, /* 001000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x61f0, /* 011000011111 */
+	0x6060, /* 011000000110 */
+	0x2060, /* 001000000110 */
+	0x3060, /* 001100000110 */
+	0x1860, /* 000110000110 */
+	0x0f80, /* 000011111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 72 0x48 'H' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xf0f0, /* 111100001111 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7fe0, /* 011111111110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0xf0f0, /* 111100001111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 73 0x49 'I' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1f80, /* 000111111000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x1f80, /* 000111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 74 0x4a 'J' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1f80, /* 000111111000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0400, /* 000001000000 */
+	0x3800, /* 001110000000 */
+	0x3000, /* 001100000000 */
+	0x0000, /* 000000000000 */
+
+	/* 75 0x4b 'K' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xf0e0, /* 111100001110 */
+	0x6180, /* 011000011000 */
+	0x6300, /* 011000110000 */
+	0x6600, /* 011001100000 */
+	0x6c00, /* 011011000000 */
+	0x7800, /* 011110000000 */
+	0x7800, /* 011110000000 */
+	0x7c00, /* 011111000000 */
+	0x6e00, /* 011011100000 */
+	0x6700, /* 011001110000 */
+	0x6380, /* 011000111000 */
+	0x61c0, /* 011000011100 */
+	0x60e0, /* 011000001110 */
+	0xf070, /* 111100000111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 76 0x4c 'L' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x7800, /* 011110000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3020, /* 001100000010 */
+	0x3020, /* 001100000010 */
+	0x7fe0, /* 011111111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 77 0x4d 'M' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xe070, /* 111000000111 */
+	0x60e0, /* 011000001110 */
+	0x70e0, /* 011100001110 */
+	0x70e0, /* 011100001110 */
+	0x70e0, /* 011100001110 */
+	0x5960, /* 010110010110 */
+	0x5960, /* 010110010110 */
+	0x5960, /* 010110010110 */
+	0x4d60, /* 010011010110 */
+	0x4e60, /* 010011100110 */
+	0x4e60, /* 010011100110 */
+	0x4460, /* 010001000110 */
+	0x4460, /* 010001000110 */
+	0xe4f0, /* 111001001111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 78 0x4e 'N' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xc070, /* 110000000111 */
+	0x6020, /* 011000000010 */
+	0x7020, /* 011100000010 */
+	0x7820, /* 011110000010 */
+	0x5820, /* 010110000010 */
+	0x4c20, /* 010011000010 */
+	0x4620, /* 010001100010 */
+	0x4720, /* 010001110010 */
+	0x4320, /* 010000110010 */
+	0x41a0, /* 010000011010 */
+	0x40e0, /* 010000001110 */
+	0x40e0, /* 010000001110 */
+	0x4060, /* 010000000110 */
+	0xe030, /* 111000000011 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 79 0x4f 'O' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x11c0, /* 000100011100 */
+	0x20c0, /* 001000001100 */
+	0x2060, /* 001000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x2040, /* 001000000100 */
+	0x3040, /* 001100000100 */
+	0x1880, /* 000110001000 */
+	0x0f00, /* 000011110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 80 0x50 'P' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x7f80, /* 011111111000 */
+	0x30c0, /* 001100001100 */
+	0x3060, /* 001100000110 */
+	0x3060, /* 001100000110 */
+	0x3060, /* 001100000110 */
+	0x30c0, /* 001100001100 */
+	0x3780, /* 001101111000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x7800, /* 011110000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 81 0x51 'Q' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x11c0, /* 000100011100 */
+	0x20c0, /* 001000001100 */
+	0x2060, /* 001000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x3040, /* 001100000100 */
+	0x3840, /* 001110000100 */
+	0x1f80, /* 000111111000 */
+	0x0e00, /* 000011100000 */
+	0x1f00, /* 000111110000 */
+	0x2390, /* 001000111001 */
+	0x01e0, /* 000000011110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 82 0x52 'R' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xff00, /* 111111110000 */
+	0x6180, /* 011000011000 */
+	0x60c0, /* 011000001100 */
+	0x60c0, /* 011000001100 */
+	0x60c0, /* 011000001100 */
+	0x6080, /* 011000001000 */
+	0x7f00, /* 011111110000 */
+	0x7c00, /* 011111000000 */
+	0x6e00, /* 011011100000 */
+	0x6700, /* 011001110000 */
+	0x6380, /* 011000111000 */
+	0x61c0, /* 011000011100 */
+	0x60e0, /* 011000001110 */
+	0xf070, /* 111100000111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 83 0x53 'S' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1fe0, /* 000111111110 */
+	0x3060, /* 001100000110 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x7000, /* 011100000000 */
+	0x3c00, /* 001111000000 */
+	0x1e00, /* 000111100000 */
+	0x0780, /* 000001111000 */
+	0x01c0, /* 000000011100 */
+	0x00e0, /* 000000001110 */
+	0x4060, /* 010000000110 */
+	0x4060, /* 010000000110 */
+	0x60c0, /* 011000001100 */
+	0x7f80, /* 011111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 84 0x54 'T' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x7fe0, /* 011111111110 */
+	0x4620, /* 010001100010 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x1f80, /* 000111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 85 0x55 'U' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xf070, /* 111100000111 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x7040, /* 011100000100 */
+	0x3fc0, /* 001111111100 */
+	0x1f80, /* 000111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 86 0x56 'V' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xe0e0, /* 111000001110 */
+	0x6040, /* 011000000100 */
+	0x3080, /* 001100001000 */
+	0x3080, /* 001100001000 */
+	0x3080, /* 001100001000 */
+	0x1900, /* 000110010000 */
+	0x1900, /* 000110010000 */
+	0x1900, /* 000110010000 */
+	0x0a00, /* 000010100000 */
+	0x0e00, /* 000011100000 */
+	0x0e00, /* 000011100000 */
+	0x0400, /* 000001000000 */
+	0x0400, /* 000001000000 */
+	0x0400, /* 000001000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 87 0x57 'W' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xfef0, /* 111111101111 */
+	0x6620, /* 011001100010 */
+	0x6620, /* 011001100010 */
+	0x6620, /* 011001100010 */
+	0x7620, /* 011101100010 */
+	0x7740, /* 011101110100 */
+	0x3340, /* 001100110100 */
+	0x3740, /* 001101110100 */
+	0x3bc0, /* 001110111100 */
+	0x3b80, /* 001110111000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 88 0x58 'X' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xf070, /* 111100000111 */
+	0x6020, /* 011000000010 */
+	0x3040, /* 001100000100 */
+	0x3880, /* 001110001000 */
+	0x1880, /* 000110001000 */
+	0x0d00, /* 000011010000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0b00, /* 000010110000 */
+	0x1180, /* 000100011000 */
+	0x11c0, /* 000100011100 */
+	0x20c0, /* 001000001100 */
+	0x4060, /* 010000000110 */
+	0xe0f0, /* 111000001111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 89 0x59 'Y' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xf070, /* 111100000111 */
+	0x6020, /* 011000000010 */
+	0x3040, /* 001100000100 */
+	0x1880, /* 000110001000 */
+	0x1880, /* 000110001000 */
+	0x0d00, /* 000011010000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0f00, /* 000011110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 90 0x5a 'Z' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fe0, /* 001111111110 */
+	0x20c0, /* 001000001100 */
+	0x00c0, /* 000000001100 */
+	0x0180, /* 000000011000 */
+	0x0180, /* 000000011000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x1800, /* 000110000000 */
+	0x1820, /* 000110000010 */
+	0x3fe0, /* 001111111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 91 0x5b '[' */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x0f80, /* 000011111000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0f80, /* 000011111000 */
+	0x0f80, /* 000011111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 92 0x5c '\' */
+	0x0000, /* 000000000000 */
+	0x6000, /* 011000000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x1800, /* 000110000000 */
+	0x1800, /* 000110000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0180, /* 000000011000 */
+	0x0180, /* 000000011000 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x0060, /* 000000000110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 93 0x5d ']' */
+	0x0000, /* 000000000000 */
+	0x1f00, /* 000111110000 */
+	0x1f00, /* 000111110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x1f00, /* 000111110000 */
+	0x1f00, /* 000111110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 94 0x5e '^' */
+	0x0000, /* 000000000000 */
+	0x0400, /* 000001000000 */
+	0x0e00, /* 000011100000 */
+	0x1b00, /* 000110110000 */
+	0x3180, /* 001100011000 */
+	0x60c0, /* 011000001100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 95 0x5f '_' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 96 0x60 '`' */
+	0x0000, /* 000000000000 */
+	0x0100, /* 000000010000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0780, /* 000001111000 */
+	0x0780, /* 000001111000 */
+	0x0300, /* 000000110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 97 0x61 'a' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x18c0, /* 000110001100 */
+	0x10c0, /* 000100001100 */
+	0x03c0, /* 000000111100 */
+	0x1cc0, /* 000111001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x39c0, /* 001110011100 */
+	0x1ee0, /* 000111101110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 98 0x62 'b' */
+	0x0000, /* 000000000000 */
+	0x2000, /* 001000000000 */
+	0x6000, /* 011000000000 */
+	0xe000, /* 111000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6780, /* 011001111000 */
+	0x6fc0, /* 011011111100 */
+	0x70e0, /* 011100001110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7060, /* 011100000110 */
+	0x78c0, /* 011110001100 */
+	0x4f80, /* 010011111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 99 0x63 'c' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1f80, /* 000111111000 */
+	0x31c0, /* 001100011100 */
+	0x20c0, /* 001000001100 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x7040, /* 011100000100 */
+	0x30c0, /* 001100001100 */
+	0x1f80, /* 000111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 100 0x64 'd' */
+	0x0000, /* 000000000000 */
+	0x0060, /* 000000000110 */
+	0x00e0, /* 000000001110 */
+	0x0060, /* 000000000110 */
+	0x0060, /* 000000000110 */
+	0x0060, /* 000000000110 */
+	0x0f60, /* 000011110110 */
+	0x31e0, /* 001100011110 */
+	0x20e0, /* 001000001110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x70e0, /* 011100001110 */
+	0x3960, /* 001110010110 */
+	0x1e70, /* 000111100111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 101 0x65 'e' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x30c0, /* 001100001100 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7fe0, /* 011111111110 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x3000, /* 001100000000 */
+	0x1860, /* 000110000110 */
+	0x0f80, /* 000011111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 102 0x66 'f' */
+	0x0000, /* 000000000000 */
+	0x0380, /* 000000111000 */
+	0x04c0, /* 000001001100 */
+	0x04c0, /* 000001001100 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x3f80, /* 001111111000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x1e00, /* 000111100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 103 0x67 'g' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1f20, /* 000111110010 */
+	0x31e0, /* 001100011110 */
+	0x60c0, /* 011000001100 */
+	0x60c0, /* 011000001100 */
+	0x60c0, /* 011000001100 */
+	0x3180, /* 001100011000 */
+	0x3f00, /* 001111110000 */
+	0x6000, /* 011000000000 */
+	0x7fc0, /* 011111111100 */
+	0x3fe0, /* 001111111110 */
+	0x2060, /* 001000000110 */
+	0x4020, /* 010000000010 */
+	0x4020, /* 010000000010 */
+	0x7fc0, /* 011111111100 */
+	0x3f80, /* 001111111000 */
+	0x0000, /* 000000000000 */
+
+	/* 104 0x68 'h' */
+	0x0000, /* 000000000000 */
+	0x1000, /* 000100000000 */
+	0x3000, /* 001100000000 */
+	0x7000, /* 011100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3780, /* 001101111000 */
+	0x39c0, /* 001110011100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x79e0, /* 011110011110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 105 0x69 'i' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1e00, /* 000111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x1f80, /* 000111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 106 0x6a 'j' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x03c0, /* 000000111100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x20c0, /* 001000001100 */
+	0x30c0, /* 001100001100 */
+	0x3880, /* 001110001000 */
+	0x1f00, /* 000111110000 */
+	0x0e00, /* 000011100000 */
+	0x0000, /* 000000000000 */
+
+	/* 107 0x6b 'k' */
+	0x0000, /* 000000000000 */
+	0x6000, /* 011000000000 */
+	0xe000, /* 111000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x61c0, /* 011000011100 */
+	0x6300, /* 011000110000 */
+	0x6600, /* 011001100000 */
+	0x7c00, /* 011111000000 */
+	0x7800, /* 011110000000 */
+	0x7c00, /* 011111000000 */
+	0x6e00, /* 011011100000 */
+	0x6700, /* 011001110000 */
+	0x6380, /* 011000111000 */
+	0xf1e0, /* 111100011110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 108 0x6c 'l' */
+	0x0000, /* 000000000000 */
+	0x1e00, /* 000111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x1f80, /* 000111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 109 0x6d 'm' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xddc0, /* 110111011100 */
+	0x6ee0, /* 011011101110 */
+	0x6660, /* 011001100110 */
+	0x6660, /* 011001100110 */
+	0x6660, /* 011001100110 */
+	0x6660, /* 011001100110 */
+	0x6660, /* 011001100110 */
+	0x6660, /* 011001100110 */
+	0x6660, /* 011001100110 */
+	0xef70, /* 111011110111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 110 0x6e 'n' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x2780, /* 001001111000 */
+	0x79c0, /* 011110011100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x79e0, /* 011110011110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 111 0x6f 'o' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x11c0, /* 000100011100 */
+	0x20e0, /* 001000001110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7040, /* 011100000100 */
+	0x3880, /* 001110001000 */
+	0x1f00, /* 000111110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 112 0x70 'p' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xef80, /* 111011111000 */
+	0x71c0, /* 011100011100 */
+	0x60e0, /* 011000001110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6040, /* 011000000100 */
+	0x7080, /* 011100001000 */
+	0x7f00, /* 011111110000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0xf000, /* 111100000000 */
+	0x0000, /* 000000000000 */
+
+	/* 113 0x71 'q' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f20, /* 000011110010 */
+	0x11e0, /* 000100011110 */
+	0x20e0, /* 001000001110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7060, /* 011100000110 */
+	0x38e0, /* 001110001110 */
+	0x1fe0, /* 000111111110 */
+	0x0060, /* 000000000110 */
+	0x0060, /* 000000000110 */
+	0x0060, /* 000000000110 */
+	0x0060, /* 000000000110 */
+	0x00f0, /* 000000001111 */
+	0x0000, /* 000000000000 */
+
+	/* 114 0x72 'r' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x7380, /* 011100111000 */
+	0x34c0, /* 001101001100 */
+	0x38c0, /* 001110001100 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x7800, /* 011110000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 115 0x73 's' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1fc0, /* 000111111100 */
+	0x30c0, /* 001100001100 */
+	0x3040, /* 001100000100 */
+	0x3800, /* 001110000000 */
+	0x1e00, /* 000111100000 */
+	0x0780, /* 000001111000 */
+	0x01c0, /* 000000011100 */
+	0x20c0, /* 001000001100 */
+	0x30c0, /* 001100001100 */
+	0x3f80, /* 001111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 116 0x74 't' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0400, /* 000001000000 */
+	0x0400, /* 000001000000 */
+	0x0c00, /* 000011000000 */
+	0x7fc0, /* 011111111100 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c00, /* 000011000000 */
+	0x0c20, /* 000011000010 */
+	0x0e40, /* 000011100100 */
+	0x0780, /* 000001111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 117 0x75 'u' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x79e0, /* 011110011110 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x39c0, /* 001110011100 */
+	0x1e60, /* 000111100110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 118 0x76 'v' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xf070, /* 111100000111 */
+	0x6020, /* 011000000010 */
+	0x3040, /* 001100000100 */
+	0x3040, /* 001100000100 */
+	0x1880, /* 000110001000 */
+	0x1880, /* 000110001000 */
+	0x0d00, /* 000011010000 */
+	0x0d00, /* 000011010000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 119 0x77 'w' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xff70, /* 111111110111 */
+	0x6620, /* 011001100010 */
+	0x6620, /* 011001100010 */
+	0x6620, /* 011001100010 */
+	0x3740, /* 001101110100 */
+	0x3b40, /* 001110110100 */
+	0x3b40, /* 001110110100 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 120 0x78 'x' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xf8f0, /* 111110001111 */
+	0x7040, /* 011100000100 */
+	0x3880, /* 001110001000 */
+	0x1d00, /* 000111010000 */
+	0x0e00, /* 000011100000 */
+	0x0700, /* 000001110000 */
+	0x0b80, /* 000010111000 */
+	0x11c0, /* 000100011100 */
+	0x20e0, /* 001000001110 */
+	0xf1f0, /* 111100011111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 121 0x79 'y' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xf0f0, /* 111100001111 */
+	0x6020, /* 011000000010 */
+	0x3040, /* 001100000100 */
+	0x3040, /* 001100000100 */
+	0x1880, /* 000110001000 */
+	0x1880, /* 000110001000 */
+	0x0d00, /* 000011010000 */
+	0x0d00, /* 000011010000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0400, /* 000001000000 */
+	0x0c00, /* 000011000000 */
+	0x0800, /* 000010000000 */
+	0x7800, /* 011110000000 */
+	0x7000, /* 011100000000 */
+	0x0000, /* 000000000000 */
+
+	/* 122 0x7a 'z' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x7fe0, /* 011111111110 */
+	0x60e0, /* 011000001110 */
+	0x41c0, /* 010000011100 */
+	0x0380, /* 000000111000 */
+	0x0700, /* 000001110000 */
+	0x0e00, /* 000011100000 */
+	0x1c00, /* 000111000000 */
+	0x3820, /* 001110000010 */
+	0x7060, /* 011100000110 */
+	0x7fe0, /* 011111111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 123 0x7b '{' */
+	0x0000, /* 000000000000 */
+	0x0380, /* 000000111000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x3800, /* 001110000000 */
+	0x0c00, /* 000011000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0380, /* 000000111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 124 0x7c '|' */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+
+	/* 125 0x7d '}' */
+	0x0000, /* 000000000000 */
+	0x1c00, /* 000111000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0300, /* 000000110000 */
+	0x01c0, /* 000000011100 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x1c00, /* 000111000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 126 0x7e '~' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1c20, /* 000111000010 */
+	0x3e60, /* 001111100110 */
+	0x67c0, /* 011001111100 */
+	0x4380, /* 010000111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 127 0x7f '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 128 0x80 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0fc0, /* 000011111100 */
+	0x1060, /* 000100000110 */
+	0x2020, /* 001000000010 */
+	0x2000, /* 001000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x2000, /* 001000000000 */
+	0x3020, /* 001100000010 */
+	0x1840, /* 000110000100 */
+	0x0f80, /* 000011111000 */
+	0x0600, /* 000001100000 */
+	0x0300, /* 000000110000 */
+	0x0180, /* 000000011000 */
+	0x0f00, /* 000011110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 129 0x81 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x79e0, /* 011110011110 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x39c0, /* 001110011100 */
+	0x1e60, /* 000111100110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 130 0x82 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0180, /* 000000011000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x30c0, /* 001100001100 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7fe0, /* 011111111110 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x3000, /* 001100000000 */
+	0x1860, /* 000110000110 */
+	0x0f80, /* 000011111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 131 0x83 '.' */
+	0x0000, /* 000000000000 */
+	0x0200, /* 000000100000 */
+	0x0700, /* 000001110000 */
+	0x0d80, /* 000011011000 */
+	0x18c0, /* 000110001100 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x18c0, /* 000110001100 */
+	0x10c0, /* 000100001100 */
+	0x03c0, /* 000000111100 */
+	0x1cc0, /* 000111001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x39c0, /* 001110011100 */
+	0x1ee0, /* 000111101110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 132 0x84 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x18c0, /* 000110001100 */
+	0x10c0, /* 000100001100 */
+	0x03c0, /* 000000111100 */
+	0x1cc0, /* 000111001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x39c0, /* 001110011100 */
+	0x1ee0, /* 000111101110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 133 0x85 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0c00, /* 000011000000 */
+	0x0600, /* 000001100000 */
+	0x0300, /* 000000110000 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x18c0, /* 000110001100 */
+	0x10c0, /* 000100001100 */
+	0x03c0, /* 000000111100 */
+	0x1cc0, /* 000111001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x39c0, /* 001110011100 */
+	0x1ee0, /* 000111101110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 134 0x86 '.' */
+	0x0000, /* 000000000000 */
+	0x0700, /* 000001110000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0700, /* 000001110000 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x18c0, /* 000110001100 */
+	0x10c0, /* 000100001100 */
+	0x03c0, /* 000000111100 */
+	0x1cc0, /* 000111001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x39c0, /* 001110011100 */
+	0x1ee0, /* 000111101110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 135 0x87 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1f80, /* 000111111000 */
+	0x31c0, /* 001100011100 */
+	0x20c0, /* 001000001100 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x7040, /* 011100000100 */
+	0x30c0, /* 001100001100 */
+	0x1f80, /* 000111111000 */
+	0x0600, /* 000001100000 */
+	0x0300, /* 000000110000 */
+	0x0180, /* 000000011000 */
+	0x0f00, /* 000011110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 136 0x88 '.' */
+	0x0000, /* 000000000000 */
+	0x0200, /* 000000100000 */
+	0x0700, /* 000001110000 */
+	0x0d80, /* 000011011000 */
+	0x18c0, /* 000110001100 */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x30c0, /* 001100001100 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7fe0, /* 011111111110 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x3000, /* 001100000000 */
+	0x1860, /* 000110000110 */
+	0x0f80, /* 000011111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 137 0x89 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x30c0, /* 001100001100 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7fe0, /* 011111111110 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x3000, /* 001100000000 */
+	0x1860, /* 000110000110 */
+	0x0f80, /* 000011111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 138 0x8a '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0c00, /* 000011000000 */
+	0x0600, /* 000001100000 */
+	0x0300, /* 000000110000 */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x30c0, /* 001100001100 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7fe0, /* 011111111110 */
+	0x6000, /* 011000000000 */
+	0x6000, /* 011000000000 */
+	0x3000, /* 001100000000 */
+	0x1860, /* 000110000110 */
+	0x0f80, /* 000011111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 139 0x8b '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1e00, /* 000111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x1f80, /* 000111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 140 0x8c '.' */
+	0x0000, /* 000000000000 */
+	0x0400, /* 000001000000 */
+	0x0e00, /* 000011100000 */
+	0x1b00, /* 000110110000 */
+	0x3180, /* 001100011000 */
+	0x0000, /* 000000000000 */
+	0x1e00, /* 000111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x1f80, /* 000111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 141 0x8d '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1800, /* 000110000000 */
+	0x0c00, /* 000011000000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x1e00, /* 000111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x1f80, /* 000111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 142 0x8e '.' */
+	0x0000, /* 000000000000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0000, /* 000000000000 */
+	0x0400, /* 000001000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0b00, /* 000010110000 */
+	0x0b00, /* 000010110000 */
+	0x1980, /* 000110011000 */
+	0x1180, /* 000100011000 */
+	0x3fc0, /* 001111111100 */
+	0x20c0, /* 001000001100 */
+	0x6060, /* 011000000110 */
+	0x4060, /* 010000000110 */
+	0xe0f0, /* 111000001111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 143 0x8f '.' */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x1980, /* 000110011000 */
+	0x0f00, /* 000011110000 */
+	0x0400, /* 000001000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0b00, /* 000010110000 */
+	0x0b00, /* 000010110000 */
+	0x1980, /* 000110011000 */
+	0x1180, /* 000100011000 */
+	0x3fc0, /* 001111111100 */
+	0x20c0, /* 001000001100 */
+	0x6060, /* 011000000110 */
+	0x4060, /* 010000000110 */
+	0xe0f0, /* 111000001111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 144 0x90 '.' */
+	0x0000, /* 000000000000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0800, /* 000010000000 */
+	0x7fe0, /* 011111111110 */
+	0x3020, /* 001100000010 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3080, /* 001100001000 */
+	0x3f80, /* 001111111000 */
+	0x3080, /* 001100001000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3020, /* 001100000010 */
+	0x3020, /* 001100000010 */
+	0x7fe0, /* 011111111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 145 0x91 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3de0, /* 001111011110 */
+	0x6630, /* 011001100011 */
+	0x4630, /* 010001100011 */
+	0x0630, /* 000001100011 */
+	0x3ff0, /* 001111111111 */
+	0x6600, /* 011001100000 */
+	0xc600, /* 110001100000 */
+	0xc600, /* 110001100000 */
+	0xe730, /* 111001110011 */
+	0x7de0, /* 011111011110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 146 0x92 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x03f0, /* 000000111111 */
+	0x0710, /* 000001110001 */
+	0x0710, /* 000001110001 */
+	0x0b00, /* 000010110000 */
+	0x0b00, /* 000010110000 */
+	0x0b20, /* 000010110010 */
+	0x13e0, /* 000100111110 */
+	0x1320, /* 000100110010 */
+	0x3f00, /* 001111110000 */
+	0x2300, /* 001000110000 */
+	0x2300, /* 001000110000 */
+	0x4310, /* 010000110001 */
+	0x4310, /* 010000110001 */
+	0xe7f0, /* 111001111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 147 0x93 '.' */
+	0x0000, /* 000000000000 */
+	0x0200, /* 000000100000 */
+	0x0700, /* 000001110000 */
+	0x0d80, /* 000011011000 */
+	0x18c0, /* 000110001100 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x11c0, /* 000100011100 */
+	0x20e0, /* 001000001110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7040, /* 011100000100 */
+	0x3880, /* 001110001000 */
+	0x1f00, /* 000111110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 148 0x94 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x11c0, /* 000100011100 */
+	0x20e0, /* 001000001110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7040, /* 011100000100 */
+	0x3880, /* 001110001000 */
+	0x1f00, /* 000111110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 149 0x95 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0c00, /* 000011000000 */
+	0x0600, /* 000001100000 */
+	0x0300, /* 000000110000 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x11c0, /* 000100011100 */
+	0x20e0, /* 001000001110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7040, /* 011100000100 */
+	0x3880, /* 001110001000 */
+	0x1f00, /* 000111110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 150 0x96 '.' */
+	0x0000, /* 000000000000 */
+	0x0200, /* 000000100000 */
+	0x0700, /* 000001110000 */
+	0x0d80, /* 000011011000 */
+	0x18c0, /* 000110001100 */
+	0x0000, /* 000000000000 */
+	0x79e0, /* 011110011110 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x39c0, /* 001110011100 */
+	0x1e60, /* 000111100110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 151 0x97 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1800, /* 000110000000 */
+	0x0c00, /* 000011000000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x79e0, /* 011110011110 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x39c0, /* 001110011100 */
+	0x1e60, /* 000111100110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 152 0x98 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xf0f0, /* 111100001111 */
+	0x6020, /* 011000000010 */
+	0x3040, /* 001100000100 */
+	0x3040, /* 001100000100 */
+	0x1880, /* 000110001000 */
+	0x1880, /* 000110001000 */
+	0x0d00, /* 000011010000 */
+	0x0d00, /* 000011010000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0400, /* 000001000000 */
+	0x0c00, /* 000011000000 */
+	0x0800, /* 000010000000 */
+	0x7800, /* 011110000000 */
+	0x7000, /* 011100000000 */
+	0x0000, /* 000000000000 */
+
+	/* 153 0x99 '.' */
+	0x0000, /* 000000000000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x11c0, /* 000100011100 */
+	0x20c0, /* 001000001100 */
+	0x2060, /* 001000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x2040, /* 001000000100 */
+	0x3040, /* 001100000100 */
+	0x1880, /* 000110001000 */
+	0x0f00, /* 000011110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 154 0x9a '.' */
+	0x0000, /* 000000000000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0xe030, /* 111000000011 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x6020, /* 011000000010 */
+	0x7040, /* 011100000100 */
+	0x3fc0, /* 001111111100 */
+	0x1f80, /* 000111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 155 0x9b '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x1f80, /* 000111111000 */
+	0x36c0, /* 001101101100 */
+	0x26c0, /* 001001101100 */
+	0x6600, /* 011001100000 */
+	0x6600, /* 011001100000 */
+	0x6600, /* 011001100000 */
+	0x6600, /* 011001100000 */
+	0x7640, /* 011101100100 */
+	0x36c0, /* 001101101100 */
+	0x1f80, /* 000111111000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 156 0x9c '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x1cc0, /* 000111001100 */
+	0x18c0, /* 000110001100 */
+	0x1800, /* 000110000000 */
+	0x1800, /* 000110000000 */
+	0x1800, /* 000110000000 */
+	0x7e00, /* 011111100000 */
+	0x7e00, /* 011111100000 */
+	0x1800, /* 000110000000 */
+	0x1800, /* 000110000000 */
+	0x1800, /* 000110000000 */
+	0x1800, /* 000110000000 */
+	0x3e20, /* 001111100010 */
+	0x7fe0, /* 011111111110 */
+	0x61c0, /* 011000011100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 157 0x9d '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x30c0, /* 001100001100 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0f00, /* 000011110000 */
+	0x0600, /* 000001100000 */
+	0x1f80, /* 000111111000 */
+	0x0600, /* 000001100000 */
+	0x1f80, /* 000111111000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 158 0x9e '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 159 0x9f '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 160 0xa0 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0180, /* 000000011000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x18c0, /* 000110001100 */
+	0x10c0, /* 000100001100 */
+	0x03c0, /* 000000111100 */
+	0x1cc0, /* 000111001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x39c0, /* 001110011100 */
+	0x1ee0, /* 000111101110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 161 0xa1 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0180, /* 000000011000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x1e00, /* 000111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x1f80, /* 000111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 162 0xa2 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0180, /* 000000011000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0f80, /* 000011111000 */
+	0x11c0, /* 000100011100 */
+	0x20e0, /* 001000001110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x6060, /* 011000000110 */
+	0x7040, /* 011100000100 */
+	0x3880, /* 001110001000 */
+	0x1f00, /* 000111110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 163 0xa3 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0180, /* 000000011000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x79e0, /* 011110011110 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x39c0, /* 001110011100 */
+	0x1e60, /* 000111100110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 164 0xa4 '.' */
+	0x0000, /* 000000000000 */
+	0x1c40, /* 000111000100 */
+	0x3fc0, /* 001111111100 */
+	0x2380, /* 001000111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x2780, /* 001001111000 */
+	0x79c0, /* 011110011100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x79e0, /* 011110011110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 165 0xa5 '.' */
+	0x0000, /* 000000000000 */
+	0x1c40, /* 000111000100 */
+	0x3fc0, /* 001111111100 */
+	0x2380, /* 001000111000 */
+	0xc070, /* 110000000111 */
+	0x6020, /* 011000000010 */
+	0x7020, /* 011100000010 */
+	0x7820, /* 011110000010 */
+	0x5c20, /* 010111000010 */
+	0x4e20, /* 010011100010 */
+	0x4720, /* 010001110010 */
+	0x43a0, /* 010000111010 */
+	0x41e0, /* 010000011110 */
+	0x40e0, /* 010000001110 */
+	0x4060, /* 010000000110 */
+	0xe030, /* 111000000011 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 166 0xa6 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1f00, /* 000111110000 */
+	0x3180, /* 001100011000 */
+	0x0180, /* 000000011000 */
+	0x0780, /* 000001111000 */
+	0x1980, /* 000110011000 */
+	0x3180, /* 001100011000 */
+	0x3180, /* 001100011000 */
+	0x3380, /* 001100111000 */
+	0x1dc0, /* 000111011100 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 167 0xa7 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0700, /* 000001110000 */
+	0x1980, /* 000110011000 */
+	0x10c0, /* 000100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x3080, /* 001100001000 */
+	0x1980, /* 000110011000 */
+	0x0e00, /* 000011100000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 168 0xa8 '.' */
+	0x0000, /* 000000000000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0300, /* 000000110000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x1800, /* 000110000000 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x3040, /* 001100000100 */
+	0x39c0, /* 001110011100 */
+	0x1f80, /* 000111111000 */
+	0x0f00, /* 000011110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 169 0xa9 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 170 0xaa '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x00c0, /* 000000001100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 171 0xab '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1000, /* 000100000000 */
+	0x3000, /* 001100000000 */
+	0x1000, /* 000100000000 */
+	0x1040, /* 000100000100 */
+	0x1080, /* 000100001000 */
+	0x1100, /* 000100010000 */
+	0x3a00, /* 001110100000 */
+	0x05c0, /* 000001011100 */
+	0x0a20, /* 000010100010 */
+	0x1020, /* 000100000010 */
+	0x20c0, /* 001000001100 */
+	0x4100, /* 010000010000 */
+	0x0200, /* 000000100000 */
+	0x03e0, /* 000000111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 172 0xac '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x1000, /* 000100000000 */
+	0x3000, /* 001100000000 */
+	0x1000, /* 000100000000 */
+	0x1040, /* 000100000100 */
+	0x1080, /* 000100001000 */
+	0x1100, /* 000100010000 */
+	0x3a40, /* 001110100100 */
+	0x04c0, /* 000001001100 */
+	0x0940, /* 000010010100 */
+	0x1240, /* 000100100100 */
+	0x2440, /* 001001000100 */
+	0x47e0, /* 010001111110 */
+	0x0040, /* 000000000100 */
+	0x0040, /* 000000000100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 173 0xad '.' */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 174 0xae '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0660, /* 000001100110 */
+	0x0cc0, /* 000011001100 */
+	0x1980, /* 000110011000 */
+	0x3300, /* 001100110000 */
+	0x6600, /* 011001100000 */
+	0x3300, /* 001100110000 */
+	0x1980, /* 000110011000 */
+	0x0cc0, /* 000011001100 */
+	0x0660, /* 000001100110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 175 0xaf '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x6600, /* 011001100000 */
+	0x3300, /* 001100110000 */
+	0x1980, /* 000110011000 */
+	0x0cc0, /* 000011001100 */
+	0x0660, /* 000001100110 */
+	0x0cc0, /* 000011001100 */
+	0x1980, /* 000110011000 */
+	0x3300, /* 001100110000 */
+	0x6600, /* 011001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 176 0xb0 '.' */
+	0x0c30, /* 000011000011 */
+	0x0820, /* 000010000010 */
+	0x6180, /* 011000011000 */
+	0x2080, /* 001000001000 */
+	0x0c30, /* 000011000011 */
+	0x0820, /* 000010000010 */
+	0x6180, /* 011000011000 */
+	0x2080, /* 001000001000 */
+	0x0c30, /* 000011000011 */
+	0x0820, /* 000010000010 */
+	0x6180, /* 011000011000 */
+	0x2080, /* 001000001000 */
+	0x0c30, /* 000011000011 */
+	0x0820, /* 000010000010 */
+	0x6180, /* 011000011000 */
+	0x2080, /* 001000001000 */
+	0x0c30, /* 000011000011 */
+	0x0820, /* 000010000010 */
+	0x6180, /* 011000011000 */
+	0x2080, /* 001000001000 */
+	0x0c30, /* 000011000011 */
+	0x0820, /* 000010000010 */
+
+	/* 177 0xb1 '.' */
+	0x7770, /* 011101110111 */
+	0x2220, /* 001000100010 */
+	0x8880, /* 100010001000 */
+	0xddd0, /* 110111011101 */
+	0x8880, /* 100010001000 */
+	0x2220, /* 001000100010 */
+	0x7770, /* 011101110111 */
+	0x2220, /* 001000100010 */
+	0x8880, /* 100010001000 */
+	0xddd0, /* 110111011101 */
+	0x8880, /* 100010001000 */
+	0x2220, /* 001000100010 */
+	0x7770, /* 011101110111 */
+	0x2220, /* 001000100010 */
+	0x8880, /* 100010001000 */
+	0xddd0, /* 110111011101 */
+	0x8880, /* 100010001000 */
+	0x2220, /* 001000100010 */
+	0x7770, /* 011101110111 */
+	0x2220, /* 001000100010 */
+	0x8880, /* 100010001000 */
+	0xddd0, /* 110111011101 */
+
+	/* 178 0xb2 '.' */
+	0xf3c0, /* 111100111100 */
+	0xf7d0, /* 111101111101 */
+	0x9e70, /* 100111100111 */
+	0xdf70, /* 110111110111 */
+	0xf3c0, /* 111100111100 */
+	0xf7d0, /* 111101111101 */
+	0x9e70, /* 100111100111 */
+	0xdf70, /* 110111110111 */
+	0xf3c0, /* 111100111100 */
+	0xf7d0, /* 111101111101 */
+	0x9e70, /* 100111100111 */
+	0xdf70, /* 110111110111 */
+	0xf3c0, /* 111100111100 */
+	0xf7d0, /* 111101111101 */
+	0x9e70, /* 100111100111 */
+	0xdf70, /* 110111110111 */
+	0xf3c0, /* 111100111100 */
+	0xf7d0, /* 111101111101 */
+	0x9e70, /* 100111100111 */
+	0xdf70, /* 110111110111 */
+	0xf3c0, /* 111100111100 */
+	0xf7d0, /* 111101111101 */
+
+	/* 179 0xb3 '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 180 0xb4 '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0xfe00, /* 111111100000 */
+	0xfe00, /* 111111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 181 0xb5 '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0xfe00, /* 111111100000 */
+	0xfe00, /* 111111100000 */
+	0x0600, /* 000001100000 */
+	0xfe00, /* 111111100000 */
+	0xfe00, /* 111111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 182 0xb6 '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0xfd80, /* 111111011000 */
+	0xfd80, /* 111111011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 183 0xb7 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xff80, /* 111111111000 */
+	0xff80, /* 111111111000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 184 0xb8 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xfe00, /* 111111100000 */
+	0xfe00, /* 111111100000 */
+	0x0600, /* 000001100000 */
+	0xfe00, /* 111111100000 */
+	0xfe00, /* 111111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 185 0xb9 '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0xfd80, /* 111111011000 */
+	0xfd80, /* 111111011000 */
+	0x0180, /* 000000011000 */
+	0xfd80, /* 111111011000 */
+	0xfd80, /* 111111011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 186 0xba '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 187 0xbb '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xff80, /* 111111111000 */
+	0xff80, /* 111111111000 */
+	0x0180, /* 000000011000 */
+	0xfd80, /* 111111011000 */
+	0xfd80, /* 111111011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 188 0xbc '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0xfd80, /* 111111011000 */
+	0xfd80, /* 111111011000 */
+	0x0180, /* 000000011000 */
+	0xff80, /* 111111111000 */
+	0xff80, /* 111111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 189 0xbd '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0xff80, /* 111111111000 */
+	0xff80, /* 111111111000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 190 0xbe '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0xfe00, /* 111111100000 */
+	0xfe00, /* 111111100000 */
+	0x0600, /* 000001100000 */
+	0xfe00, /* 111111100000 */
+	0xfe00, /* 111111100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 191 0xbf '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xfe00, /* 111111100000 */
+	0xfe00, /* 111111100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 192 0xc0 '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x07f0, /* 000001111111 */
+	0x07f0, /* 000001111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 193 0xc1 '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 194 0xc2 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 195 0xc3 '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x07f0, /* 000001111111 */
+	0x07f0, /* 000001111111 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 196 0xc4 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 197 0xc5 '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 198 0xc6 '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x07f0, /* 000001111111 */
+	0x07f0, /* 000001111111 */
+	0x0600, /* 000001100000 */
+	0x07f0, /* 000001111111 */
+	0x07f0, /* 000001111111 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 199 0xc7 '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0df0, /* 000011011111 */
+	0x0df0, /* 000011011111 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 200 0xc8 '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0df0, /* 000011011111 */
+	0x0df0, /* 000011011111 */
+	0x0c00, /* 000011000000 */
+	0x0ff0, /* 000011111111 */
+	0x0ff0, /* 000011111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 201 0xc9 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0ff0, /* 000011111111 */
+	0x0ff0, /* 000011111111 */
+	0x0c00, /* 000011000000 */
+	0x0df0, /* 000011011111 */
+	0x0df0, /* 000011011111 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 202 0xca '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0xfdf0, /* 111111011111 */
+	0xfdf0, /* 111111011111 */
+	0x0000, /* 000000000000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 203 0xcb '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0000, /* 000000000000 */
+	0xfdf0, /* 111111011111 */
+	0xfdf0, /* 111111011111 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 204 0xcc '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0df0, /* 000011011111 */
+	0x0df0, /* 000011011111 */
+	0x0c00, /* 000011000000 */
+	0x0df0, /* 000011011111 */
+	0x0df0, /* 000011011111 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 205 0xcd '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0000, /* 000000000000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 206 0xce '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0xfdf0, /* 111111011111 */
+	0xfdf0, /* 111111011111 */
+	0x0000, /* 000000000000 */
+	0xfdf0, /* 111111011111 */
+	0xfdf0, /* 111111011111 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 207 0xcf '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0000, /* 000000000000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 208 0xd0 '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 209 0xd1 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0000, /* 000000000000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 210 0xd2 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 211 0xd3 '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0ff0, /* 000011111111 */
+	0x0ff0, /* 000011111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 212 0xd4 '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x07f0, /* 000001111111 */
+	0x07f0, /* 000001111111 */
+	0x0600, /* 000001100000 */
+	0x07f0, /* 000001111111 */
+	0x07f0, /* 000001111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 213 0xd5 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x07f0, /* 000001111111 */
+	0x07f0, /* 000001111111 */
+	0x0600, /* 000001100000 */
+	0x07f0, /* 000001111111 */
+	0x07f0, /* 000001111111 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 214 0xd6 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0ff0, /* 000011111111 */
+	0x0ff0, /* 000011111111 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 215 0xd7 '.' */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+	0x0d80, /* 000011011000 */
+
+	/* 216 0xd8 '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0600, /* 000001100000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 217 0xd9 '.' */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0xfe00, /* 111111100000 */
+	0xfe00, /* 111111100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 218 0xda '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x07f0, /* 000001111111 */
+	0x07f0, /* 000001111111 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+
+	/* 219 0xdb '.' */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+
+	/* 220 0xdc '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+
+	/* 221 0xdd '.' */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+	0xfc00, /* 111111000000 */
+
+	/* 222 0xde '.' */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+	0x03f0, /* 000000111111 */
+
+	/* 223 0xdf '.' */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0xfff0, /* 111111111111 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 224 0xe0 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 225 0xe1 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x1980, /* 000110011000 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x3180, /* 001100011000 */
+	0x3780, /* 001101111000 */
+	0x3180, /* 001100011000 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x3180, /* 001100011000 */
+	0x7700, /* 011101110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 226 0xe2 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 227 0xe3 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 228 0xe4 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 229 0xe5 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 230 0xe6 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x30c0, /* 001100001100 */
+	0x39c0, /* 001110011100 */
+	0x36e0, /* 001101101110 */
+	0x3000, /* 001100000000 */
+	0x3000, /* 001100000000 */
+	0x6000, /* 011000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 231 0xe7 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 232 0xe8 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 233 0xe9 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 234 0xea '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 235 0xeb '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 236 0xec '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 237 0xed '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 238 0xee '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 239 0xef '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 240 0xf0 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 241 0xf1 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x7fe0, /* 011111111110 */
+	0x7fe0, /* 011111111110 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x7fe0, /* 011111111110 */
+	0x7fe0, /* 011111111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 242 0xf2 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 243 0xf3 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 244 0xf4 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 245 0xf5 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 246 0xf6 '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x7fe0, /* 011111111110 */
+	0x7fe0, /* 011111111110 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 247 0xf7 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 248 0xf8 '.' */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x1980, /* 000110011000 */
+	0x0f00, /* 000011110000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 249 0xf9 '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 250 0xfa '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0600, /* 000001100000 */
+	0x0f00, /* 000011110000 */
+	0x0f00, /* 000011110000 */
+	0x0600, /* 000001100000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 251 0xfb '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 252 0xfc '.' */
+	/* FIXME */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 253 0xfd '.' */
+	0x0000, /* 000000000000 */
+	0x0f00, /* 000011110000 */
+	0x1f80, /* 000111111000 */
+	0x3180, /* 001100011000 */
+	0x2180, /* 001000011000 */
+	0x0300, /* 000000110000 */
+	0x0600, /* 000001100000 */
+	0x0c00, /* 000011000000 */
+	0x1840, /* 000110000100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 254 0xfe '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x3fc0, /* 001111111100 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+	/* 255 0xff '.' */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+	0x0000, /* 000000000000 */
+
+};
+
diff -u --recursive --new-file v2.1.109/linux/drivers/video/fonts.c linux/drivers/video/fonts.c
--- v2.1.109/linux/drivers/video/fonts.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/fonts.c	Sat Jul 18 13:55:46 1998
@@ -47,6 +47,11 @@
 extern int fontwidth_sun8x16, fontheight_sun8x16;
 extern u8 fontdata_sun8x16[];
 
+/* SUN12x22 */
+extern char fontname_sun12x22[];
+extern int fontwidth_sun12x22, fontheight_sun12x22;
+extern u8 fontdata_sun12x22[];
+
 
 
    /*
@@ -66,6 +71,7 @@
 #define PEARL8x8_IDX	2
 #define VGA6x11_IDX	3
 #define SUN8x16_IDX	4
+#define SUN12x22_IDX	5
 
 static struct softfontdesc softfonts[] = {
    { VGA8x8_IDX, fontname_8x8, &fontwidth_8x8, &fontheight_8x8, fontdata_8x8 },
@@ -77,6 +83,8 @@
 #else
    { SUN8x16_IDX, fontname_sun8x16, &fontwidth_sun8x16, &fontheight_sun8x16, 
      fontdata_sun8x16 },
+   { SUN12x22_IDX, fontname_sun12x22, &fontwidth_sun12x22, &fontheight_sun12x22, 
+     fontdata_sun12x22 },
 #endif
 };
 
@@ -87,7 +95,7 @@
     *    Find a font with a specific name
     */
 
-int findsoftfont(char *name, int *width, int *height, u8 *data[])
+int findsoftfont(char *name, unsigned short *width, unsigned short *height, u8 *data[])
 {
    unsigned int i;
 
@@ -109,7 +117,7 @@
     *    Get the default font for a specific screen size
     */
 
-void getdefaultfont(int xres, int yres, char *name[], int *width, int *height,
+void getdefaultfont(int xres, int yres, char *name[], unsigned short *width, unsigned short *height,
                     u8 *data[])
 {
     int i, j;
diff -u --recursive --new-file v2.1.109/linux/drivers/video/macfb.c linux/drivers/video/macfb.c
--- v2.1.109/linux/drivers/video/macfb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/macfb.c	Sat Jul 18 14:11:18 1998
@@ -43,7 +43,7 @@
 	{0,0,0},	/* transparency */
 	0,		/* standard pixel format */
 	FB_ACTIVATE_NOW,
-	274,195,	/* 14" monitor *Mikael Nykvist's anyway* */
+	274,195,	/* 14" monitor - the late Mikael Nykvist's anyway */
 	0,		/* The only way to accelerate a mac is .. */
 	0L,0L,0L,0L,0L,
 	0L,0L,0,	/* No sync info */
diff -u --recursive --new-file v2.1.109/linux/drivers/video/macmodes.c linux/drivers/video/macmodes.c
--- v2.1.109/linux/drivers/video/macmodes.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/macmodes.c	Sun Jul 19 20:45:45 1998
@@ -0,0 +1,424 @@
+/*
+ *  linux/drivers/video/macmodes.c -- Standard MacOS video modes
+ *
+ *	Copyright (C) 1998 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+
+#include <linux/tty.h>
+#include <linux/fb.h>
+#include <linux/string.h>
+#include <asm/vc_ioctl.h>
+
+
+    /*
+     *  Video mode values.
+     *  These are supposed to be the same as the values that Apple uses in
+     *  MacOS.
+     */
+
+#define VMODE_512_384_60I	1	/* 512x384, 60Hz interlaced (NTSC) */
+#define VMODE_512_384_60	2	/* 512x384, 60Hz */
+#define VMODE_640_480_50I	3	/* 640x480, 50Hz interlaced (PAL) */
+#define VMODE_640_480_60I	4	/* 640x480, 60Hz interlaced (NTSC) */
+#define VMODE_640_480_60	5	/* 640x480, 60Hz (VGA) */
+#define VMODE_640_480_67	6	/* 640x480, 67Hz */
+#define VMODE_640_870_75P	7	/* 640x870, 75Hz (portrait) */
+#define VMODE_768_576_50I	8	/* 768x576, 50Hz (PAL full frame) */
+#define VMODE_800_600_56	9	/* 800x600, 56Hz */
+#define VMODE_800_600_60	10	/* 800x600, 60Hz */
+#define VMODE_800_600_72	11	/* 800x600, 72Hz */
+#define VMODE_800_600_75	12	/* 800x600, 75Hz */
+#define VMODE_832_624_75	13	/* 832x624, 75Hz */
+#define VMODE_1024_768_60	14	/* 1024x768, 60Hz */
+#define VMODE_1024_768_70	15	/* 1024x768, 70Hz (or 72Hz?) */
+#define VMODE_1024_768_75V	16	/* 1024x768, 75Hz (VESA) */
+#define VMODE_1024_768_75	17	/* 1024x768, 75Hz */
+#define VMODE_1152_870_75	18	/* 1152x870, 75Hz */
+#define VMODE_1280_960_75	19	/* 1280x960, 75Hz */
+#define VMODE_1280_1024_75	20	/* 1280x1024, 75Hz */
+
+#define CMODE_8			0	/* 8 bits/pixel */
+#define CMODE_16		1	/* 16 (actually 15) bits/pixel */
+#define CMODE_32		2	/* 32 (actually 24) bits/pixel */
+
+
+struct mac_mode {
+    int number;
+    u32 xres;
+    u32 yres;
+    u32 pixclock;
+    u32 left_margin;
+    u32 right_margin;
+    u32 upper_margin;
+    u32 lower_margin;
+    u32 hsync_len;
+    u32 vsync_len;
+    u32 sync;
+    u32 vmode;
+};
+
+
+    /* 512x384, 60Hz, Interlaced (NTSC) */
+
+#if 0
+static const struct mac_mode mac_mode_1 = {
+    VMODE_512_384_60I, 512, 384,
+    pixclock, left, right, upper, lower, hslen, vslen,
+    sync, FB_VMODE_INTERLACED
+};
+#endif
+
+    /* 512x384, 60Hz, Non-Interlaced */
+
+#if 0
+static const struct mac_mode mac_mode_2 = {
+    VMODE_512_384_60, 512, 384,
+    pixclock, left, right, upper, lower, hslen, vslen,
+    sync, FB_VMODE_NONINTERLACED
+};
+#endif
+
+    /* 640x480, 50Hz, Interlaced (PAL) */
+
+#if 0
+static const struct mac_mode mac_mode_3 = {
+    VMODE_640_480_50I, 640, 480,
+    pixclock, left, right, upper, lower, hslen, vslen,
+    sync, FB_VMODE_INTERLACED
+};
+#endif
+
+    /* 640x480, 60Hz, Interlaced (NTSC) */
+
+#if 0
+static const struct mac_mode mac_mode_4 = {
+    VMODE_640_480_60I, 640, 480,
+    pixclock, left, right, upper, lower, hslen, vslen,
+    sync, FB_VMODE_INTERLACED
+};
+#endif
+
+    /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+
+static const struct mac_mode mac_mode_5 = {
+    VMODE_640_480_60, 640, 480,
+    39722, 32, 32, 33, 10, 96, 2,
+    0, FB_VMODE_NONINTERLACED
+};
+
+    /* 640x480, 67Hz, Non-Interlaced (30.0 MHz dotclock) */
+
+static const struct mac_mode mac_mode_6 = {
+    VMODE_640_480_67, 640, 480,
+    33334, 80, 80, 39, 3, 64, 3,
+    0, FB_VMODE_NONINTERLACED
+};
+
+    /* 640x870, 75Hz (portrait), Non-Interlaced */
+
+#if 0
+static const struct mac_mode mac_mode_7 = {
+    VMODE_640_870_75P, 640, 870,
+    pixclock, left, right, upper, lower, hslen, vslen,
+    sync, FB_VMODE_NONINTERLACED
+};
+#endif
+
+    /* 768x576, 50Hz (PAL full frame), Interlaced */
+
+#if 0
+static const struct mac_mode mac_mode_8 = {
+    VMODE_768_576_50I, 768, 576,
+    pixclock, left, right, upper, lower, hslen, vslen,
+    sync, FB_VMODE_INTERLACED
+};
+#endif
+
+    /* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */
+
+static const struct mac_mode mac_mode_9 = {
+    VMODE_800_600_56, 800, 600,
+    27778, 112, 40, 22, 1, 72, 2,
+    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+    /* 800x600, 60 Hz, Non-Interlaced (40.00 MHz dotclock) */
+
+static const struct mac_mode mac_mode_10 = {
+    VMODE_800_600_60, 800, 600,
+    25000, 72, 56, 23, 1, 128, 4,
+    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+    /* 800x600, 72 Hz, Non-Interlaced (50.00 MHz dotclock) */
+
+static const struct mac_mode mac_mode_11 = {
+    VMODE_800_600_72, 800, 600,
+    20000, 48, 72, 23, 37, 120, 6,
+    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+    /* 800x600, 75 Hz, Non-Interlaced (49.50 MHz dotclock) */
+
+static const struct mac_mode mac_mode_12 = {
+    VMODE_800_600_75, 800, 600,
+    20203, 144, 32, 21, 1, 80, 3,
+    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+    /* 832x624, 75Hz, Non-Interlaced (57.6 MHz */
+
+static const struct mac_mode mac_mode_13 = {
+    VMODE_832_624_75, 832, 624,
+    17362, 208, 48, 39, 1, 64, 3,
+    0, FB_VMODE_NONINTERLACED
+};
+
+    /* 1024x768, 60 Hz, Non-Interlaced (65.00 MHz dotclock) */
+
+static const struct mac_mode mac_mode_14 = {
+    VMODE_1024_768_60, 1024, 768,
+    15385, 144, 40, 29, 3, 136, 6,
+    0, FB_VMODE_NONINTERLACED
+};
+
+    /* 1024x768, 72 Hz, Non-Interlaced (75.00 MHz dotclock) */
+
+static const struct mac_mode mac_mode_15 = {
+    VMODE_1024_768_70, 1024, 768,
+    13334, 128, 40, 29, 3, 136, 6,
+    0, FB_VMODE_NONINTERLACED
+};
+
+    /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
+
+static const struct mac_mode mac_mode_16 = {
+    VMODE_1024_768_75V, 1024, 768,
+    12699, 176, 16, 28, 1, 96, 3,
+    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+    /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
+
+static const struct mac_mode mac_mode_17 = {
+    VMODE_1024_768_75, 1024, 768,
+    12699, 160, 32, 28, 1, 96, 3,
+    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+    /* 1152x870, 75 Hz, Non-Interlaced (100.0 MHz dotclock) */
+
+static const struct mac_mode mac_mode_18 = {
+    VMODE_1152_870_75, 1152, 870,
+    10000, 128, 48, 39, 3, 128, 3,
+    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+    /* 1280x960, 75 Hz, Non-Interlaced (126.00 MHz dotclock) */
+
+static const struct mac_mode mac_mode_19 = {
+    VMODE_1280_960_75, 1280, 960,
+    7937, 224, 32, 36, 1, 144, 3,
+    0, FB_VMODE_NONINTERLACED
+};
+
+    /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
+
+static const struct mac_mode mac_mode_20 = {
+    VMODE_1280_1024_75, 1280, 1024,
+    7408, 232, 64, 38, 1, 112, 3,
+    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+
+static const struct mac_mode *mac_modes[20] = {
+    NULL,		/* 512x384, 60Hz interlaced (NTSC) */
+    NULL,		/* 512x384, 60Hz */
+    NULL,		/* 640x480, 50Hz interlaced (PAL) */
+    NULL,		/* 640x480, 60Hz interlaced (NTSC) */
+    &mac_mode_5,	/* 640x480, 60Hz (VGA) */
+    &mac_mode_6,	/* 640x480, 67Hz */
+    NULL,		/* 640x870, 75Hz (portrait) */
+    NULL,		/* 768x576, 50Hz (PAL full frame) */
+    &mac_mode_9,	/* 800x600, 56Hz */
+    &mac_mode_10,	/* 800x600, 60Hz */
+    &mac_mode_11,	/* 800x600, 72Hz */
+    &mac_mode_12,	/* 800x600, 75Hz */
+    &mac_mode_13,	/* 832x624, 75Hz */
+    &mac_mode_14,	/* 1024x768, 60Hz */
+    &mac_mode_15,	/* 1024x768, 70Hz (or 72Hz?) */
+    &mac_mode_16,	/* 1024x768, 75Hz (VESA) */
+    &mac_mode_17,	/* 1024x768, 75Hz */
+    &mac_mode_18,	/* 1152x870, 75Hz */
+    &mac_mode_19,	/* 1280x960, 75Hz */
+    &mac_mode_20,	/* 1280x1024, 75Hz */
+};
+
+static const struct mac_mode *mac_modes_inv[] = {
+    &mac_mode_6,	/* 640x480, 67Hz */
+    &mac_mode_5,	/* 640x480, 60Hz (VGA) */
+    &mac_mode_12,	/* 800x600, 75Hz */
+    &mac_mode_11,	/* 800x600, 72Hz */
+    &mac_mode_10,	/* 800x600, 60Hz */
+    &mac_mode_9,	/* 800x600, 56Hz */
+    &mac_mode_13,	/* 832x624, 75Hz */
+    &mac_mode_17,	/* 1024x768, 75Hz */
+    &mac_mode_16,	/* 1024x768, 75Hz (VESA) */
+    &mac_mode_15,	/* 1024x768, 70Hz (or 72Hz?) */
+    &mac_mode_14,	/* 1024x768, 60Hz */
+    &mac_mode_18,	/* 1152x870, 75Hz */
+    &mac_mode_19,	/* 1280x960, 75Hz */
+    &mac_mode_20,	/* 1280x1024, 75Hz */
+};
+
+
+static struct mon_map {
+    int sense;
+    int vmode;
+} monitor_map[] = {
+    { 0x000, VMODE_1280_1024_75 },	/* 21" RGB */
+    { 0x114, VMODE_640_870_75P },	/* Portrait Monochrome */
+    { 0x221, VMODE_512_384_60 },	/* 12" RGB*/
+    { 0x331, VMODE_1280_1024_75 },	/* 21" RGB (Radius) */
+    { 0x334, VMODE_1280_1024_75 },	/* 21" mono (Radius) */
+    { 0x335, VMODE_1280_1024_75 },	/* 21" mono */
+    { 0x40A, VMODE_640_480_60I },	/* NTSC */
+    { 0x51E, VMODE_640_870_75P },	/* Portrait RGB */
+    { 0x603, VMODE_832_624_75 },	/* 12"-16" multiscan */
+    { 0x60b, VMODE_1024_768_70 },	/* 13"-19" multiscan */
+    { 0x623, VMODE_1152_870_75 },	/* 13"-21" multiscan */
+    { 0x62b, VMODE_640_480_67 },	/* 13"/14" RGB */
+    { 0x700, VMODE_640_480_50I },	/* PAL */
+    { 0x714, VMODE_640_480_60I },	/* NTSC */
+    { 0x717, VMODE_800_600_75 },	/* VGA */
+    { 0x72d, VMODE_832_624_75 },	/* 16" RGB (Goldfish) */
+    { 0x730, VMODE_768_576_50I },	/* PAL (Alternate) */
+    { 0x73a, VMODE_1152_870_75 },	/* 3rd party 19" */
+    { 0x73f, VMODE_640_480_67 },	/* no sense lines connected at all */
+    { -1,    VMODE_640_480_60 },	/* catch-all, must be last */
+};
+
+
+    /*
+     *  Convert a MacOS vmode/cmode pair to a frame buffer video mode structure
+     */
+
+int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var)
+{
+    const struct mac_mode *mode = NULL;
+
+    if (vmode > 0 && vmode <= VMODE_MAX)
+	mode = mac_modes[vmode-1];
+
+    if (!mode)
+	return -EINVAL;
+
+    memset(var, 0, sizeof(struct fb_var_screeninfo));
+    switch (cmode) {
+	case CMODE_8:
+	    var->bits_per_pixel = 8;
+	    var->red.offset = 0;
+	    var->red.length = 8;   
+	    var->green.offset = 0;
+	    var->green.length = 8;
+	    var->blue.offset = 0;
+	    var->blue.length = 8;
+	    break;
+
+	case CMODE_16:
+	    var->bits_per_pixel = 16;
+	    var->red.offset = 10;
+	    var->red.length = 5;
+	    var->green.offset = 5;
+	    var->green.length = 5;
+	    var->blue.offset = 0;
+	    var->blue.length = 5;
+	    break;
+
+	case CMODE_32:
+	    var->bits_per_pixel = 32;
+	    var->red.offset = 16;
+	    var->red.length = 8;
+	    var->green.offset = 8;
+	    var->green.length = 8;
+	    var->blue.offset = 0;
+	    var->blue.length = 8;
+	    var->transp.offset = 24;
+	    var->transp.length = 8;
+	    break;
+
+	default:
+	    return -EINVAL;
+    }
+    var->xres = mode->xres;
+    var->yres = mode->yres;
+    var->xres_virtual = mode->xres;
+    var->yres_virtual = mode->yres;
+    var->height = -1;
+    var->width = -1;
+    var->pixclock = mode->pixclock;
+    var->left_margin = mode->left_margin;
+    var->right_margin = mode->right_margin;
+    var->upper_margin = mode->upper_margin;
+    var->lower_margin = mode->lower_margin;
+    var->hsync_len = mode->hsync_len;
+    var->vsync_len = mode->vsync_len;
+    var->sync = mode->sync;
+    var->vmode = mode->vmode;
+    return 0;
+}
+
+
+    /*
+     *  Convert a frame buffer video mode structure to a MacOS vmode/cmode pair
+     */
+
+int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
+		     int *cmode)
+{
+    int i = 0;
+
+    if (var->bits_per_pixel <= 8)
+	*cmode = CMODE_8;
+    else if (var->bits_per_pixel <= 16)
+	*cmode = CMODE_16;
+    else if (var->bits_per_pixel <= 32)
+	*cmode = CMODE_32;
+    else
+	return -EINVAL;
+
+    for (i = 0; i < sizeof(mac_modes_inv)/sizeof(*mac_modes_inv); i++) {
+	const struct mac_mode *mode = mac_modes_inv[i];
+	if (var->xres > mode->xres || var->yres > mode->yres)
+	    continue;
+	if (var->xres_virtual > mode->xres || var->yres_virtual > mode->yres)
+	    continue;
+	if (var->pixclock > mode->pixclock)
+	    continue;
+	if (var->vmode != mode->vmode)
+	    continue;
+	*vmode = mode->number;
+	return 0;
+    }
+    return -EINVAL;
+}
+
+
+    /*
+     *  Convert a Mac monitor sense number to a MacOS vmode number
+     */
+
+int mac_map_monitor_sense(int sense)
+{
+    struct mon_map *map;
+
+    for (map = monitor_map; map->sense >= 0; ++map)
+	if (map->sense == sense)
+	    break;
+    return map->vmode;
+}
diff -u --recursive --new-file v2.1.109/linux/drivers/video/mdafb.c linux/drivers/video/mdafb.c
--- v2.1.109/linux/drivers/video/mdafb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/mdafb.c	Sat Jul 18 13:55:46 1998
@@ -286,7 +286,7 @@
 
 static struct display_switch fbcon_mdafb = {
     fbcon_vga_setup, fbcon_vga_bmove, fbcon_vga_clear, fbcon_vga_putc,
-    fbcon_vga_putcs, fbcon_vga_revc, fbcon_mdafb_cursor
+    fbcon_vga_putcs, fbcon_vga_revc, fbcon_mdafb_cursor, NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/offb.c linux/drivers/video/offb.c
--- v2.1.109/linux/drivers/video/offb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/offb.c	Sat Jul 18 13:55:46 1998
@@ -32,6 +32,7 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 
+#include "fbcon.h"
 #include "fbcon-cfb8.h"
 
 
@@ -86,9 +87,6 @@
 int console_setcmap(int, unsigned char *, unsigned char *, unsigned char *);
 int console_powermode(int);
 struct fb_info *console_fb_info = NULL;
-int (*console_setmode_ptr)(struct vc_mode *, int) = NULL;
-int (*console_set_cmap_ptr)(struct fb_cmap *, int, int, struct fb_info *)
-    = NULL;
 struct vc_mode display_info;
 #endif /* CONFIG_FB_COMPAT_XPMAC */
 
@@ -276,17 +274,13 @@
 
 #ifdef CONFIG_FB_ATY
 extern void atyfb_of_init(struct device_node *dp);
-
-static const char *aty_names[] = {
-    "ATY,mach64", "ATY,XCLAIM", "ATY,264VT", "ATY,mach64ii", "ATY,264GT-B", 
-    "ATY,mach64_3D_pcc", "ATY,XCLAIM3D", "ATY,XCLAIMVR", "ATY,RAGEII_M",
-    "ATY,XCLAIMVRPro", "ATY,mach64_3DU", "ATY,XCLAIM3DPro"
-};
 #endif /* CONFIG_FB_ATY */
 #ifdef CONFIG_FB_S3TRIO
 extern void s3triofb_init_of(struct device_node *dp);
 #endif /* CONFIG_FB_S3TRIO */
-
+#ifdef CONFIG_FB_CT65550
+extern void chips_of_init(struct device_node *dp);
+#endif /* CONFIG_FB_CT65550 */
 
     /*
      *  Initialisation
@@ -308,10 +302,7 @@
 
 	if (!ofonly) {
 #ifdef CONFIG_FB_ATY
-	    for (i = 0; i < sizeof(aty_names)/sizeof(*aty_names); i++)
-		if (!strcmp(dp->name, aty_names[i]))
-		    break;
-	    if (i < sizeof(aty_names)/sizeof(*aty_names)) {
+	    if (!strncmp(dp->name, "ATY", 3)) {
 		atyfb_of_init(dp);
 		continue;
 	    }
@@ -320,6 +311,12 @@
             if (s3triofb_init_of(dp))
                 continue;
 #endif /* CONFIG_FB_S3TRIO */
+#ifdef CONFIG_FB_CT65550
+	    if (!strcmp(dp->name, "chips65550")) {
+		chips_of_init(dp);
+		continue;
+	    }
+#endif /* CONFIG_FB_CT65550 */
 	}
 
 	info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC);
@@ -414,6 +411,7 @@
 #else
 	disp->dispsw = NULL;
 #endif
+	disp->scrollmode = SCROLL_YREDRAW;
 
 	strcpy(info->info.modename, "OFfb ");
 	strncat(info->info.modename, dp->full_name,
@@ -462,7 +460,6 @@
 		    display_info.cmap_data_address = address + 0x7ffcc1;
 	    }
 	    console_fb_info = &info->info;
-	    console_set_cmap_ptr = offb_set_cmap;
 	}
 #endif /* CONFIG_FB_COMPAT_XPMAC) */
     }
@@ -596,17 +593,6 @@
 
     /*
      *  Backward compatibility mode for Xpmac
-     *
-     *  To do:
-     *
-     *    - console_setmode() should fill in a struct fb_var_screeninfo (using
-     *	    the MacOS video mode database) and simply call a decode_var()
-     *	    function, so console_setmode_ptr is no longer needed.
-     *	    console_getmode() should convert in the other direction.
-     *
-     *    - instead of using the console_* stuff (filled in by the frame
-     *      buffer), we should use the correct struct fb_info for the
-     *	    foreground virtual console.
      */
 
 int console_getmode(struct vc_mode *mode)
@@ -617,12 +603,31 @@
 
 int console_setmode(struct vc_mode *mode, int doit)
 {
-    int err;
-
-    if (console_setmode_ptr == NULL)
-	return -EINVAL;
+    struct fb_var_screeninfo var;
+    int cmode, err;
 
-    err = (*console_setmode_ptr)(mode, doit);
+    if (!console_fb_info)
+	return -EOPNOTSUPP;
+    switch (mode->depth) {
+	case 8:
+	case 0:		/* default */
+	    cmode = 0;	/* CMODE_8 */
+	    break;
+	case 16:
+	    cmode = 1;	/* CMODE_16 */
+	    break;
+	case 24:
+	case 32:
+	    cmode = 2;	/* CMODE_32 */
+	    break;
+	default:
+	    return -EINVAL;
+    }
+    if ((err = mac_vmode_to_var(mode->mode, cmode, &var)))
+	return err;
+    var.activate = doit ? FB_ACTIVATE_NOW : FB_ACTIVATE_TEST;
+    err = console_fb_info->fbops->fb_set_var(&var, fg_console,
+					     console_fb_info);
     return err;
 }
 
@@ -637,9 +642,9 @@
 int console_setcmap(int n_entries, unsigned char *red, unsigned char *green,
 		    unsigned char *blue)
 {
-    int i, j, n;
+    int i, j, n, err;
 
-    if (console_set_cmap_ptr == NULL)
+    if (!console_fb_info)
 	return -EOPNOTSUPP;
     for (i = 0; i < n_entries; i += n) {
 	n = n_entries-i;
@@ -652,7 +657,10 @@
 	    palette_cmap.green[j] = (green[i+j] << 8) | green[i+j];
 	    palette_cmap.blue[j]  = (blue[i+j] << 8) | blue[i+j];
 	}
-	(*console_set_cmap_ptr)(&palette_cmap, 1, fg_console, console_fb_info);
+	err = console_fb_info->fbops->fb_set_cmap(&palette_cmap, 1, fg_console,
+						  console_fb_info);
+	if (err)
+	    return err;
     }
     return 0;
 }
diff -u --recursive --new-file v2.1.109/linux/drivers/video/promcon.c linux/drivers/video/promcon.c
--- v2.1.109/linux/drivers/video/promcon.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/promcon.c	Sun Jul 19 20:45:45 1998
@@ -0,0 +1,512 @@
+/* $Id: promcon.c,v 1.3 1998/07/13 01:06:19 ecd Exp $
+ * Console driver utilizing PROM sun terminal emulation
+ *
+ * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
+ * Copyright (C) 1998  Jakub Jelinek  (jj@ultra.linux.cz)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/console.h>
+#include <linux/console_struct.h>
+#include <linux/selection.h>
+#include <linux/fb.h>
+
+#include <asm/oplib.h>
+
+static short pw = 80 - 1, ph = 34 - 1;
+static short px, py;
+
+static __inline__ void
+promcon_puts(char *buf, int cnt)
+{
+	prom_printf("%*.*s", cnt, cnt, buf);
+}
+
+static int
+promcon_start(struct vc_data *conp, char *b)
+{
+	unsigned short *s = (unsigned short *)
+			(conp->vc_origin + py * conp->vc_size_row + (px << 1));
+
+	if (px == pw) {
+		unsigned short *t = s - 1;
+
+		if ((*s & 0x0800) && (*t & 0x0800))
+			return sprintf(b, "\b\033[7m%c\b\033[@%c\033[m",
+				       *s, *t);
+		else if (*s & 0x0800)
+			return sprintf(b, "\b\033[7m%c\033[m\b\033[@%c",
+				       *s, *t);
+		else if (*t & 0x0800)
+			return sprintf(b, "\b%c\b\033[@\033[7m%c\033[m",
+				       *s, *t);
+		else
+			return sprintf(b, "\b%c\b\033[@%c", *s, *t);
+	}
+
+	if (*s & 0x0800)
+		return sprintf(b, "\033[7m%c\033[m\b", *s);
+	else
+		return sprintf(b, "%c\b", *s);
+}
+
+static int
+promcon_end(struct vc_data *conp, char *b)
+{
+	unsigned short *s = (unsigned short *)
+			(conp->vc_origin + py * conp->vc_size_row + (px << 1));
+	char *p = b;
+
+	b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
+
+	if (px == pw) {
+		unsigned short *t = s - 1;
+
+		if ((*s & 0x0800) && (*t & 0x0800))
+			b += sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", *s, *t);
+		else if (*s & 0x0800)
+			b += sprintf(b, "\b%c\b\033[@%c", *s, *t);
+		else if (*t & 0x0800)
+			b += sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", *s, *t);
+		else
+			b += sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", *s, *t);
+		return b - p;
+	}
+
+	if (*s & 0x0800)
+		b += sprintf(b, "%c\b", *s);
+	else
+		b += sprintf(b, "\033[7m%c\033[m\b", *s);
+	return b - p;
+}
+
+__initfunc(const char *promcon_startup(void))
+{
+	const char *display_desc = "PROM";
+	int node;
+	char buf[40];
+	
+	node = prom_getchild(prom_root_node);
+	node = prom_searchsiblings(node, "options");
+	if (prom_getproperty(node,  "screen-#columns", buf, 40) != -1) {
+		pw = simple_strtoul(buf, NULL, 0);
+		if (pw < 10 || pw > 256)
+			pw = 80;
+		pw--;
+	}
+	if (prom_getproperty(node,  "screen-#rows", buf, 40) != -1) {
+		ph = simple_strtoul(buf, NULL, 0);
+		if (ph < 10 || ph > 256)
+			ph = 34;
+		ph--;
+	}
+	promcon_puts("\033[H\033[J", 6);
+	return display_desc;
+}
+
+static void
+promcon_init(struct vc_data *conp, int init)
+{
+	conp->vc_can_do_color = 0;
+	conp->vc_cols = pw + 1;
+	conp->vc_rows = ph + 1;
+}
+
+static int
+promcon_switch(struct vc_data *conp)
+{
+	return 1;
+}
+
+static unsigned short *
+promcon_repaint_line(unsigned short *s, unsigned char *buf, unsigned char **bp)
+{
+	int cnt = pw + 1;
+	unsigned short attr = 0;
+	unsigned char *b = *bp;
+
+	while (cnt--) {
+		if (attr != (*s & 0x0800)) {
+			attr = (*s & 0x0800);
+			if (attr) {
+				strcpy (b, "\033[7m");
+				b += 4;
+			} else {
+				strcpy (b, "\033[m");
+				b += 3;
+			}
+		}
+		*b++ = *s++;
+		if (b - buf >= 224) {
+			promcon_puts(buf, b - buf);
+			b = buf;
+		}
+	}
+	*bp = b;
+	return s;
+}
+
+static void
+promcon_putcs(struct vc_data *conp, const unsigned short *s,
+	      int count, int y, int x)
+{
+	unsigned char buf[256], *b = buf;
+	unsigned short attr = *s;
+	unsigned char save;
+	int i, last = 0;
+
+	if (console_blanked)
+		return;
+	
+	if (count <= 0)
+		return;
+
+	b += promcon_start(conp, b);
+
+	if (x + count >= pw + 1) {
+		if (count == 1) {
+			x -= 1;
+			save = *(unsigned short *)(conp->vc_origin
+						   + y * conp->vc_size_row
+						   + (x << 1));
+
+			if (px != x || py != y) {
+				b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
+				px = x;
+				py = y;
+			}
+
+			if (attr & 0x0800)
+				b += sprintf(b, "\033[7m%c\033[m", *s++);
+			else
+				b += sprintf(b, "%c", *s++);
+
+			strcpy(b, "\b\033[@");
+			b += 4;
+
+			if (save & 0x0800)
+				b += sprintf(b, "\033[7m%c\033[m", save);
+			else
+				b += sprintf(b, "%c", save);
+
+			px++;
+
+			b += promcon_end(conp, b);
+			promcon_puts(buf, b - buf);
+			return;
+		} else {
+			last = 1;
+			count = pw - x - 1;
+		}
+	}
+
+	if (attr & 0x0800) {
+		strcpy(b, "\033[7m");
+		b += 4;
+	}
+
+	if (px != x || py != y) {
+		b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
+		px = x;
+		py = y;
+	}
+
+	for (i = 0; i < count; i++) {
+		if (b - buf >= 224) {
+			promcon_puts(buf, b - buf);
+			b = buf;
+		}
+		*b++ = *s++;
+	}
+
+	px += count;
+
+	if (last) {
+		save = *s++;
+		b += sprintf(b, "%c\b\033[@%c", *s++, save);
+		px++;
+	}
+
+	if (attr & 0x0800) {
+		strcpy(b, "\033[m");
+		b += 3;
+	}
+
+	b += promcon_end(conp, b);
+	promcon_puts(buf, b - buf);
+}
+
+static void
+promcon_putc(struct vc_data *conp, int c, int y, int x)
+{
+	unsigned short s = c;
+
+	if (console_blanked)
+		return;
+	
+	promcon_putcs(conp, &s, 1, y, x);
+}
+
+static void
+promcon_clear(struct vc_data *conp, int sy, int sx, int height, int width)
+{
+	unsigned char buf[256], *b = buf;
+	int i, j;
+
+	if (console_blanked)
+		return;
+	
+	b += promcon_start(conp, b);
+
+	if (!sx && width == pw + 1) {
+
+		if (!sy && height == ph + 1) {
+			strcpy(b, "\033[H\033[J");
+			b += 6;
+			b += promcon_end(conp, b);
+			promcon_puts(buf, b - buf);
+			return;
+		} else if (sy + height == ph + 1) {
+			b += sprintf(b, "\033[%dH\033[J", sy + 1);
+			b += promcon_end(conp, b);
+			promcon_puts(buf, b - buf);
+			return;
+		}
+
+		b += sprintf(b, "\033[%dH", sy + 1);
+		for (i = 1; i < height; i++) {
+			strcpy(b, "\033[K\n");
+			b += 4;
+		}
+
+		strcpy(b, "\033[K");
+		b += 3;
+
+		b += promcon_end(conp, b);
+		promcon_puts(buf, b - buf);
+		return;
+
+	} else if (sx + width == pw + 1) {
+
+		b += sprintf(b, "\033[%d;%dH", sy + 1, sx + 1);
+		for (i = 1; i < height; i++) {
+			strcpy(b, "\033[K\n");
+			b += 4;
+		}
+
+		strcpy(b, "\033[K");
+		b += 3;
+
+		b += promcon_end(conp, b);
+		promcon_puts(buf, b - buf);
+		return;
+	}
+
+	for (i = sy + 1; i <= sy + height; i++) {
+		b += sprintf(b, "\033[%d;%dH", i, sx + 1);
+		for (j = 0; j < width; j++)
+			*b++ = ' ';
+		if (b - buf + width >= 224) {
+			promcon_puts(buf, b - buf);
+			b = buf;
+		}
+	}
+
+	b += promcon_end(conp, b);
+	promcon_puts(buf, b - buf);
+}
+                        
+static void
+promcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
+	      int height, int width)
+{
+	char buf[256], *b = buf;
+
+	if (console_blanked)
+		return;
+	
+	b += promcon_start(conp, b);
+	if (sy == dy && height == 1) {
+		if (dx > sx && dx + width == conp->vc_cols)
+			b += sprintf(b, "\033[%d;%dH\033[%d@\033[%d;%dH",
+				     sy + 1, sx + 1, dx - sx, py + 1, px + 1);
+		else if (dx < sx && sx + width == conp->vc_cols)
+			b += sprintf(b, "\033[%d;%dH\033[%dP\033[%d;%dH",
+				     dy + 1, dx + 1, sx - dx, py + 1, px + 1);
+
+		b += promcon_end(conp, b);
+		promcon_puts(buf, b - buf);
+		return;
+	}
+
+	/*
+	 * FIXME: What to do here???
+	 * Current console.c should not call it like that ever.
+	 */
+	prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
+}
+
+static void
+promcon_cursor(struct vc_data *conp, int mode)
+{
+	char buf[32], *b = buf;
+
+	switch (mode) {
+	case CM_ERASE:
+		break;
+
+	case CM_MOVE:
+	case CM_DRAW:
+		b += promcon_start(conp, b);
+		if (px != conp->vc_x || py != conp->vc_y) {
+			px = conp->vc_x;
+			py = conp->vc_y;
+			b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
+		}
+		promcon_puts(buf, b - buf);
+		break;
+	}
+}
+
+static int
+promcon_get_font(struct vc_data *conp, int *w, int *h, char *data)
+{
+	return -ENOSYS;
+}
+        
+static int
+promcon_set_font(struct vc_data *conp, int w, int h, char *data)
+{
+	return -ENOSYS;
+}
+
+static int
+promcon_blank(int blank)
+{
+	if (blank) {
+		promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
+		return 0;
+	} else {
+		/* Let console.c redraw */
+		return 1;
+	}
+}
+
+static int
+promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
+{
+	unsigned char buf[256], *p = buf;
+	unsigned short *s;
+	int i;
+
+	if (console_blanked)
+		return 0;
+	
+	p += promcon_start(conp, p);
+
+	switch (dir) {
+	case SM_UP:
+		if (b == ph + 1) {
+			p += sprintf(p, "\033[%dH\033[%dM", t + 1, count);
+			px = 0;
+			py = t;
+			p += promcon_end(conp, p);
+			promcon_puts(buf, p - buf);
+			break;
+		}
+
+		s = (unsigned short *)(conp->vc_origin
+				       + (t + count) * conp->vc_size_row);
+
+		p += sprintf(p, "\033[%dH", t + 1);
+
+		for (i = t; i < b - count; i++)
+			s = promcon_repaint_line(s, buf, &p);
+
+		for (; i < b - 1; i++) {
+			strcpy(p, "\033[K\n");
+			p += 4;
+			if (p - buf >= 224) {
+				promcon_puts(buf, p - buf);
+				p = buf;
+			}
+		}
+
+		strcpy(p, "\033[K");
+		p += 3;
+
+		p += promcon_end(conp, p);
+		promcon_puts(buf, p - buf);
+		break;
+
+	case SM_DOWN:
+		if (b == ph + 1) {
+			p += sprintf(p, "\033[%dH\033[%dL", t + 1, count);
+			px = 0;
+			py = t;
+			p += promcon_end(conp, p);
+			promcon_puts(buf, p - buf);
+			break;
+		}
+
+		s = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row);
+
+		p += sprintf(p, "\033[%dH", t + 1);
+
+		for (i = t; i < t + count; i++) {
+			strcpy(p, "\033[K\n");
+			p += 4;
+			if (p - buf >= 224) {
+				promcon_puts(buf, p - buf);
+				p = buf;
+			}
+		}
+
+		for (; i < b; i++)
+			s = promcon_repaint_line(s, buf, &p);
+
+		p += promcon_end(conp, p);
+		promcon_puts(buf, p - buf);
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ *  The console 'switch' structure for the VGA based console
+ */
+
+static int promcon_dummy(void)
+{
+        return 0;
+}
+
+#define DUMMY (void *) promcon_dummy
+
+struct consw prom_con = {
+	con_startup:		promcon_startup,
+	con_init:		promcon_init,
+	con_deinit:		DUMMY,
+	con_clear:		promcon_clear,
+	con_putc:		promcon_putc,
+	con_putcs:		promcon_putcs,
+	con_cursor:		promcon_cursor,
+	con_scroll:		promcon_scroll,
+	con_bmove:		promcon_bmove,
+	con_switch:		promcon_switch,
+	con_blank:		promcon_blank,
+	con_get_font:		promcon_get_font,
+	con_set_font:		promcon_set_font,
+	con_set_palette:	DUMMY,
+	con_scrolldelta:	DUMMY,
+	con_set_origin:		NULL,
+	con_save_screen:	NULL,
+};
diff -u --recursive --new-file v2.1.109/linux/drivers/video/promfb.c linux/drivers/video/promfb.c
--- v2.1.109/linux/drivers/video/promfb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/promfb.c	Wed Dec 31 16:00:00 1969
@@ -1,487 +0,0 @@
-/* $Id: promfb.c,v 1.3 1998/07/08 07:36:49 ecd Exp $
- *
- * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/malloc.h>
-#include <linux/delay.h>
-#include <linux/console.h>
-#include <linux/fb.h>
-
-#include "promfb.h"
-
-extern int prom_stdout;
-
-#define PROM_FONT_HEIGHT	22
-#define PROM_FONT_WIDTH		12
-
-void promfb_init(void);
-void promfb_setup(char *options, int *ints);
-
-
-static int
-promfb_open(struct fb_info *info, int user)
-{
-	MOD_INC_USE_COUNT;
-	return 0;
-}
-
-static int
-promfb_release(struct fb_info *info, int user)
-{
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-static int
-promfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-{
-	struct fb_info_promfb *fb = promfbinfo(info);
-
-	memcpy(fix, &fb->fix, sizeof(struct fb_fix_screeninfo));
-	return 0;
-}
-
-static int
-promfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-{
-	struct fb_info_promfb *fb = promfbinfo(info);
-
-	memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));
-	return 0;
-}
-
-static int
-promfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-{
-	return -EINVAL;
-}
-
-static int
-promfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-{
-	return 0;
-}
-
-static int
-promfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-{
-	return -EINVAL;
-}
-
-static int
-promfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-{
-	if (var->xoffset || var->yoffset)
-		return -EINVAL;
-	return 0;
-}
-
-static int
-promfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-	     u_long arg, int con, struct fb_info *info)
-{
-	return -EINVAL;
-}
-
-static int
-promfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
-{
-	return -EINVAL;
-}
-
-static struct fb_ops promfb_ops = {
-	promfb_open,
-	promfb_release,
-	promfb_get_fix,
-	promfb_get_var,
-	promfb_set_var,
-	promfb_get_cmap,
-	promfb_set_cmap,
-	promfb_pan_display,
-	promfb_ioctl,
-	promfb_mmap
-};
-
-
-static int
-promfbcon_switch(int con, struct fb_info *info)
-{
-	return 0;
-}
-
-static int
-promfbcon_updatevar(int con, struct fb_info *info)
-{
-	return 0;
-}
-
-static void
-promfbcon_blank(int blank, struct fb_info *info)
-{
-	/* nothing */
-}
-
-
-static void
-prom_start(struct fb_info_promfb *fb, struct display *d)
-{
-	unsigned short *dst = fb->data + d->next_line * fb->cury + fb->curx;
-
-	if (fb->curx == fb->maxx && fb->cury == fb->maxy)
-		return;
-
-	if (*dst & 0x0800)
-		prom_printf("\033[7m%c\033[m\033[%d;%dH",
-			    *dst, fb->cury + 1, fb->curx + 1);
-	else
-		prom_printf("%c\033[%d;%dH",
-			    *dst, fb->cury + 1, fb->curx + 1);
-}
-
-static void
-prom_stop(struct fb_info_promfb *fb, struct display *d)
-{
-	unsigned short *dst = fb->data + d->next_line * fb->cury + fb->curx;
-
-	if (fb->curx == fb->maxx && fb->cury == fb->maxy)
-		return;
-
-	if (*dst & 0x0800)
-		prom_printf("\033[%d;%dH%c\033[%d;%dH",
-			    fb->cury + 1, fb->curx + 1, *dst,
-			    fb->cury + 1, fb->curx + 1);
-	else
-		prom_printf("\033[%d;%dH\033[7m%c\033[m\033[%d;%dH",
-			    fb->cury + 1, fb->curx + 1, *dst,
-			    fb->cury + 1, fb->curx + 1);
-}
-
-static void
-fbcon_prom_setup(struct display *d)
-{
-	d->next_line = d->line_length;
-	d->next_plane = 0;
-}
-
-static void
-fbcon_prom_putc(struct vc_data *con, struct display *d, int c, int y, int x)
-{
-	struct fb_info_promfb *fb = promfbinfod(d);
-	unsigned short *dst;
-
-	dst = fb->data + y * d->line_length + x;
-	if (*dst != (c & 0xffff)) {
-		*dst = c & 0xffff;
-
-		prom_start(fb, d);
-
-		if (fb->curx != x || fb->cury != y) {
-			prom_printf("\033[%d;%dH", y + 1, x + 1);
-			fb->curx = x;
-			fb->cury = y;
-		}
-
-		if (x == fb->maxx && y == fb->maxy)
-			/* Sorry */ return;
-
-		if (c & 0x0800)
-			prom_printf("\033[7m%c\033[m", c);
-		else
-			prom_putchar(c);
-
-		prom_stop(fb, d);
-	}
-}
-
-static void
-fbcon_prom_putcs(struct vc_data *con, struct display *d,
-		 const unsigned short *s, int count, int y, int x)
-{
-	struct fb_info_promfb *fb = promfbinfod(d);
-	unsigned short *dst;
-	unsigned short attr = *s;
-	int i;
-
-	dst = fb->data + y * d->line_length + x;
-
-	prom_start(fb, d);
-
-	if (attr & 0x0800)
-		prom_printf("\033[7m");
-
-	for (i = 0; i < count; i++) {
-		if (*dst != *s) {
-			*dst = *s;
-
-			if (fb->curx != x + i || fb->cury != y) {
-				prom_printf("\033[%d;%dH", y + 1, x + i + 1);
-				fb->curx = x + i;
-				fb->cury = y;
-			}
-
-			if (fb->curx == fb->maxx && fb->cury == fb->maxy)
-				/* Sorry */ goto out;
-
-			prom_putchar(*s);
-
-			if (i < count - 1)
-				fb->curx++;
-		}
-		dst++;
-		s++;
-	}
-out:
-	if (attr & 0x0800)
-		prom_printf("\033[m");
-
-	prom_stop(fb, d);
-}
-
-static void
-fbcon_prom_clear(struct vc_data *con, struct display *d, int sy, int sx,
-		 int h, int w)
-{
-	int x, y;
-
-	for (y = sy; y < sy + h; y++)
-		for (x = sx; x < sx + w; x++)
-			fbcon_prom_putc(con, d, con->vc_video_erase_char, y, x);
-}
-
-static void
-fbcon_prom_bmove(struct display *d, int sy, int sx, int dy, int dx,
-		 int h, int w)
-{
-	struct fb_info_promfb *fb = promfbinfod(d);
-	int linesize = d->next_line;
-	unsigned short *src, *dst;
-	int x, y;
-
-	if (dx == 0 && sx == 0 && dy == 0 && sy == 1 &&
-	    w == linesize && h == fb->maxy) {
-		memcpy(fb->data, fb->data + linesize, 2 * linesize * fb->maxy);
-		prom_start(fb, d);
-		prom_printf("\033[%d;%dH", fb->maxy + 1, fb->maxx + 1);
-		prom_putchar(*(fb->data + linesize * fb->maxy + fb->maxx));
-		fb->curx = 0;
-		fb->cury = fb->maxy;
-		prom_stop(fb, d);
-	} else if (dy < sy || (dy == sy && dx < sx)) {
-		src = fb->data + sy * linesize + sx;
-		dst = fb->data + dy * linesize + dx;
-		for (y = dy; y < dy + h; y++) {
-			for (x = dx; x < dx + w; x++) {
-				if (*src != *dst)
-					fbcon_prom_putc(d->conp, d, *src, y, x);
-				src++;
-				dst++;
-			}
-		}
-	} else {
-		src = fb->data + (sy + h - 1) * linesize + sx + w - 1;
-		dst = fb->data + (dy + h - 1) * linesize + dx + w - 1;
-		for (y = dy + h - 1; y >= dy; y--) {
-			for (x = dx + w - 1; x >= dx; x--) {
-				if (*src != *dst)
-					fbcon_prom_putc(d->conp, d, *src, y, x);
-				src--;
-				dst--;
-			}
-		}
-	}
-}
-
-static void
-fbcon_prom_revc(struct display *d, int x, int y)
-{
-	struct fb_info_promfb *fb = promfbinfod(d);
-	unsigned short *dst = fb->data + y * d->next_line + x;
-	unsigned short val = *dst ^ 0x0800;
-
-	fbcon_prom_putc(d->conp, d, val, y, x);
-}
-
-static void
-fbcon_prom_cursor(struct display *d, int mode, int x, int y)
-{
-	struct fb_info_promfb *fb = promfbinfod(d);
-
-	switch (mode) {
-		case CM_ERASE:
-			break;
-
-		case CM_MOVE:
-		case CM_DRAW:
-			prom_start(fb, d);
-			if (fb->curx != x || fb->cury != y) {
-				prom_printf("\033[%d;%dH", y + 1, x + 1);
-				fb->curx = x;
-				fb->cury = y;
-			}
-			break;
-	}
-}
-
-static struct display_switch fbcon_promfb = {
-	fbcon_prom_setup,
-	fbcon_prom_bmove,
-	fbcon_prom_clear,
-	fbcon_prom_putc,
-	fbcon_prom_putcs,
-	fbcon_prom_revc,
-	fbcon_prom_cursor
-};
-
-
-struct promfb_size {
-	int xres, yres;
-	int width, height;
-	int x_margin, y_margin;
-} promfb_sizes[] __initdata = {
-	{ 1024, 768, 80, 34, 32, 10 },
-	{ 80 * PROM_FONT_WIDTH, 24 * PROM_FONT_HEIGHT, 80, 24, 0, 0 },
-	{ 0 }
-};
-
-__initfunc(void promfb_init(void))
-{
-	extern int con_is_present(void);
-	struct fb_info_promfb *fb;
-	struct fb_fix_screeninfo *fix;
-	struct fb_var_screeninfo *var;
-	struct display *disp;
-	struct promfb_size *size;
-	int i, w, h;
-
-	if (!con_is_present())
-		return;
-
-	fb = kmalloc(sizeof(struct fb_info_promfb), GFP_ATOMIC);
-	if (!fb) {
-		prom_printf("Could not allocate promfb structure\n");
-		return;
-	}
-
-	memset(fb, 0, sizeof(struct fb_info_promfb));
-	fix = &fb->fix;
-	var = &fb->var;
-	disp = &fb->disp;
-
-	fb->node = prom_inst2pkg(prom_stdout);
-	w = prom_getintdefault(fb->node, "width", 80 * PROM_FONT_WIDTH);
-	h = prom_getintdefault(fb->node, "height", 24 * PROM_FONT_HEIGHT);
-
-	size = promfb_sizes;
-	while (size->xres) {
-		if (size->xres == w && size->yres == h)
-			break;
-		size++;
-	}
-	if (!size->xres) {
-		size->xres = w;
-		size->yres = h;
-		size->width = w / PROM_FONT_WIDTH;
-		size->height = h / PROM_FONT_HEIGHT;
-		size->x_margin = (w - size->width * PROM_FONT_WIDTH) >> 1;
-		size->y_margin = (h - size->width * PROM_FONT_HEIGHT) >> 1;
-	}
-
-	fb->data = kmalloc(2 * size->width * size->height, GFP_ATOMIC);
-	if (!fb->data) {
-		kfree(fb);
-		return;
-	}
-
-	fb->maxx = size->width - 1;
-	fb->maxy = size->height - 1;
-
-	strcpy(fb->info.modename, "PROM pseudo");
-	fb->info.node = -1;
-	fb->info.fbops = &promfb_ops;
-	fb->info.disp = disp;
-	fb->info.fontname[0] = '\0';
-	fb->info.changevar = NULL;
-	fb->info.switch_con = promfbcon_switch;
-	fb->info.updatevar = promfbcon_updatevar;
-	fb->info.blank = promfbcon_blank;
-
-	strcpy(fix->id, "PROM pseudo");
-	fix->type = FB_TYPE_TEXT;
-	fix->type_aux = FB_AUX_TEXT_MDA;
-	fix->visual = FB_VISUAL_MONO01;
-	fix->xpanstep = 0;
-	fix->ypanstep = 16;
-	fix->ywrapstep = 0;
-	fix->line_length = size->width;
-	fix->accel = FB_ACCEL_NONE;
-
-	var->xres = size->width * 8;
-	var->yres = size->height * 16;
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
-	var->bits_per_pixel = 1;
-	var->xoffset = 0;
-	var->yoffset = 0;
-	var->activate = 0;
-	var->height = -1;
-	var->width = -1;
-	var->accel_flags = FB_ACCELF_TEXT;
-	var->vmode = FB_VMODE_NONINTERLACED;
-
-	disp->var = *var;
-	disp->visual = fix->visual;
-	disp->type = fix->type;
-	disp->type_aux = fix->type_aux;
-	disp->ypanstep = fix->ypanstep;
-	disp->ywrapstep = fix->ywrapstep;
-	disp->line_length = fix->line_length;
-	disp->can_soft_blank = 1;
-	disp->dispsw = &fbcon_promfb;
-
-	for (i = 0; i < fb->maxy * size->width + fb->maxx; i++)
-		fb->data[i] = ' ';
-	prom_printf("\033[H\033[J");
-
-	if (register_framebuffer(&fb->info) < 0) {
-		kfree(fb->data);
-		kfree(fb);
-		return;
-	}
-
-	printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb->info.node),
-	       fb->info.modename);
-	MOD_INC_USE_COUNT;
-}
-
-__initfunc(void promfb_setup(char *options, int *ints)) {}
-
-void
-promfb_cleanup(struct fb_info *info)
-{
-	struct fb_info_promfb *fb = promfbinfo(info);
-
-	unregister_framebuffer(info);
-	kfree(fb->data);
-	kfree(fb);
-}
-
-#ifdef MODULE
-int init_module(void)
-{
-	promfb_init();
-	return 0
-}
-
-void cleanup_module(void)
-{
-	promfb_cleanup();
-}
-#endif /* MODULE */
-
diff -u --recursive --new-file v2.1.109/linux/drivers/video/promfb.h linux/drivers/video/promfb.h
--- v2.1.109/linux/drivers/video/promfb.h	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/promfb.h	Wed Dec 31 16:00:00 1969
@@ -1,28 +0,0 @@
-/* $Id: promfb.h,v 1.1 1998/07/05 22:50:43 ecd Exp $
- *
- * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- */
-
-#ifndef _PROMFB_H
-#define _PROMFB_H 1
-
-#include <asm/oplib.h>
-
-#include "fbcon.h"
-
-struct fb_info_promfb {
-	struct fb_info info;
-	struct fb_fix_screeninfo fix;
-	struct fb_var_screeninfo var;
-	struct display disp;
-	struct display_switch dispsw;
-	int node;
-	unsigned short *data;
-	int curx, cury;
-	int maxx, maxy;
-};
-
-#define promfbinfo(info)	((struct fb_info_promfb *)(info))
-#define promfbinfod(disp)	((struct fb_info_promfb *)(disp->fb_info))
-
-#endif /* !(_PROM_FB_H) */
diff -u --recursive --new-file v2.1.109/linux/drivers/video/retz3fb.c linux/drivers/video/retz3fb.c
--- v2.1.109/linux/drivers/video/retz3fb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/retz3fb.c	Sat Jul 18 13:55:46 1998
@@ -1676,6 +1676,7 @@
 
 static struct display_switch fbcon_retz3_8 = {
     fbcon_cfb8_setup, fbcon_retz3_8_bmove, fbcon_retz3_8_clear,
-    fbcon_cfb8_putc, fbcon_cfb8_putcs, fbcon_cfb8_revc
+    fbcon_cfb8_putc, fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL,
+    NULL, FONTWIDTH(8)
 };
 #endif
diff -u --recursive --new-file v2.1.109/linux/drivers/video/sbusfb.c linux/drivers/video/sbusfb.c
--- v2.1.109/linux/drivers/video/sbusfb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/sbusfb.c	Sat Jul 18 13:55:46 1998
@@ -51,12 +51,14 @@
 void sbusfb_setup(char *options, int *ints);
 
 static int currcon;
-static int nomargins __initdata = 0;
+static int defx_margin = -1, defy_margin = -1;
+static int disable __initdata = 0;
+static char fontname[40] __initdata = { 0 };
 static struct {
 	int depth;
 	int xres, yres;
 	int x_margin, y_margin;
-} def_margins [] __initdata = {
+} def_margins [] = {
 	{ 8, 1280, 1024, 64, 80 },
 	{ 8, 1152, 1024, 64, 80 },
 	{ 8, 1152, 900,  64, 18 },
@@ -145,6 +147,8 @@
 			if (fb->mmaped)
 				sbusfb_clear_margin(&fb_display[fb->vtconsole], 0);
 		}
+		if (fb->reset)
+			fb->reset(fb);
 		fb->open = 0;
 	} else
 		fb->consolecnt--;
@@ -337,39 +341,7 @@
 static int sbusfb_set_var(struct fb_var_screeninfo *var, int con,
 			struct fb_info *info)
 {
-#if 1
 	return -EINVAL;
-#else
-    struct display *display;
-    int oldbpp = -1, err;
-    int activate = var->activate;
-    struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-    if (con >= 0)
-	display = &fb_display[con];
-    else
-	display = &fb->disp;	/* used during initialization */
-
-    if (var->xres > fb->var.xres || var->yres > fb->var.yres ||
-	var->xres_virtual > fb->var.xres_virtual ||
-	var->yres_virtual > fb->var.yres_virtual ||
-	var->bits_per_pixel > fb->var.bits_per_pixel ||
-	var->nonstd ||
-	(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-	return -EINVAL;
-    memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));
-
-    if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-	oldbpp = display->var.bits_per_pixel;
-	display->var = *var;
-    }
-    if (oldbpp != var->bits_per_pixel) {
-	if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
-	    return err;
-	do_install_cmap(con, info);
-    }
-    return 0;
-#endif
 }
 
     /*
@@ -487,9 +459,12 @@
 			(*fb->setcurshape) (fb);
 			fb->hw_cursor_shown = 1;
 		}
-		fb->cursor.cpos.fbx = (x << 3) + fb->x_margin; /* x * p->fontwidth */
-		if (p->fontheight == 16)
-			fb->cursor.cpos.fby = (y << 4) + fb->y_margin;
+		if (p->fontwidthlog)
+			fb->cursor.cpos.fbx = (x << p->fontwidthlog) + fb->x_margin;
+		else
+			fb->cursor.cpos.fbx = (x * p->fontwidth) + fb->x_margin;
+		if (p->fontheightlog)
+			fb->cursor.cpos.fby = (y << p->fontheightlog) + fb->y_margin;
 		else
 			fb->cursor.cpos.fby = (y * p->fontheight) + fb->y_margin;
 		(*fb->setcursor)(fb);
@@ -591,7 +566,7 @@
 	case FBIOGVIDEO:
 		put_user_ret(fb->blanked, (int *) arg, -EFAULT);
 		break;
-	case FBIOGETCMAP: {
+	case FBIOGETCMAP_SPARC: {
 		char *rp, *gp, *bp;
 		int end, count, index;
 		struct fbcmap *cmap;
@@ -623,7 +598,7 @@
 		(*fb->loadcmap)(fb, index, count);
 		break;			
 	}
-	case FBIOPUTCMAP: {	/* load color map entries */
+	case FBIOPUTCMAP_SPARC: {	/* load color map entries */
 		char *rp, *gp, *bp;
 		int end, count, index;
 		struct fbcmap *cmap;
@@ -696,19 +671,63 @@
      *  Setup: parse used options
      */
 
-void sbusfb_setup(char *options, int *ints)
+__initfunc(void sbusfb_setup(char *options, int *ints))
 {
-	if (!strncmp(options, "nomargins", 9))
-		nomargins = 1;
+	char *p;
+	
+	for (p = options;;) {
+		if (!strncmp(p, "nomargins", 9)) {
+			defx_margin = 0; defy_margin = 0;
+		} else if (!strncmp(p, "margins=", 8)) {
+			int i, j;
+			char *q;
+			
+			i = simple_strtoul(p+8,&q,10);
+			if (i >= 0 && *q == 'x') {
+			    j = simple_strtoul(q+1,&q,10);
+			    if (j >= 0 && (*q == ' ' || !*q)) {
+			    	defx_margin = i; defy_margin = j;
+			    }
+			}
+		} else if (!strncmp(p, "disable", 7))
+			disable = 1;
+		else if (!strncmp(p, "font=", 5)) {
+			int i;
+			
+			for (i = 0; i < sizeof(fontname) - 1; i++)
+				if (p[i+5] == ' ' || !p[i+5])
+					break;
+			memcpy(fontname, p+5, i);
+			fontname[i] = 0;
+		}
+		while (*p && *p != ' ' && *p != ',') p++;
+		if (*p != ',') break;
+		p++;
+	}
 }
 
 static int sbusfbcon_switch(int con, struct fb_info *info)
 {
+	int x_margin, y_margin;
+	struct fb_info_sbusfb *fb = sbusfbinfo(info);
+    
 	/* Do we have to save the colormap? */
 	if (fb_display[currcon].cmap.len)
 		fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1, sbusfb_getcolreg, info);
 
-	sbusfbinfo(info)->lastconsole = con;
+	if (fb->lastconsole != con && 
+	    (fb_display[fb->lastconsole].fontwidth != fb_display[con].fontwidth ||
+	     fb_display[fb->lastconsole].fontheight != fb_display[con].fontheight))
+		fb->hw_cursor_shown = 0;
+	fb->lastconsole = con;
+	x_margin = (fb_display[con].var.xres_virtual - fb_display[con].var.xres) / 2;
+	y_margin = (fb_display[con].var.yres_virtual - fb_display[con].var.yres) / 2;
+	if (fb->margins)
+		fb->margins(fb, &fb_display[con], x_margin, y_margin);
+	if (fb->x_margin != x_margin || fb->y_margin != y_margin) {
+		fb->x_margin = x_margin; fb->y_margin = y_margin;
+		sbusfb_clear_margin(&fb_display[con], 0);
+	}
 	currcon = con;
 	/* Install new colormap */
 	do_install_cmap(con, info);
@@ -731,23 +750,12 @@
 
 static void sbusfbcon_blank(int blank, struct fb_info *info)
 {
-#if 0
     struct fb_info_sbusfb *fb = sbusfbinfo(info);
-    int i, j;
-
-    if (!fb->cmap_adr)
-	return;
-
-    if (blank)
-	for (i = 0; i < 256; i++) {
-	    *fb->cmap_adr = i;
-	    for (j = 0; j < 3; j++) {
-		*fb->cmap_data = 0;
-	    }
-	}
-    else
-	do_install_cmap(currcon, info);
-#endif
+    
+    if (blank && fb->blank)
+    	return fb->blank(fb);
+    else if (!blank && fb->unblank)
+    	return fb->unblank(fb);
 }
 
     /*
@@ -805,6 +813,48 @@
 		(*fb->loadcmap)(fb, 0, 256);
 }
 
+static int sbusfb_set_font(struct display *p, int width, int height)
+{
+	int margin;
+	int w = p->var.xres_virtual, h = p->var.yres_virtual;
+	int depth = p->var.bits_per_pixel;
+	struct fb_info_sbusfb *fb = sbusfbinfod(p);
+	int x_margin, y_margin;
+	
+	if (depth > 8) depth = 8;
+	x_margin = 0;
+	y_margin = 0;
+	if (defx_margin < 0 || defy_margin < 0) {
+		for (margin = 0; def_margins[margin].depth; margin++)
+			if (w == def_margins[margin].xres &&
+			    h == def_margins[margin].yres &&
+			    depth == def_margins[margin].depth) {
+				x_margin = def_margins[margin].x_margin;
+				y_margin = def_margins[margin].y_margin;
+				break;
+			}
+	} else {
+		x_margin = defx_margin;
+		y_margin = defy_margin;
+	}
+	x_margin += ((w - 2*x_margin) % width) / 2;
+	y_margin += ((h - 2*y_margin) % height) / 2;
+
+	p->var.xres = w - 2*x_margin;
+	p->var.yres = h - 2*y_margin;
+	
+	fb->hw_cursor_shown = 0;
+	
+	if (fb->margins)
+		fb->margins(fb, p, x_margin, y_margin);
+	if (fb->x_margin != x_margin || fb->y_margin != y_margin) {
+		fb->x_margin = x_margin; fb->y_margin = y_margin;
+		sbusfb_clear_margin(p, 0);
+	}
+
+	return 1;
+}
+
     /*
      *  Initialisation
      */
@@ -852,7 +902,7 @@
 	linebytes = prom_getintdefault(node, "linebytes", w * depth / 8);
 	type->fb_size   = PAGE_ALIGN((linebytes) * h);
 	
-	if (!nomargins)
+	if (defx_margin < 0 || defy_margin < 0) {
 		for (margin = 0; def_margins[margin].depth; margin++)
 			if (w == def_margins[margin].xres &&
 			    h == def_margins[margin].yres &&
@@ -861,7 +911,11 @@
 				fb->y_margin = def_margins[margin].y_margin;
 				break;
 			}
-	fb->x_margin += ((w - 2*fb->x_margin) & 15) / 2;
+	} else {
+		fb->x_margin = defx_margin;
+		fb->y_margin = defy_margin;
+	}
+	fb->x_margin += ((w - 2*fb->x_margin) & 7) / 2;
 	fb->y_margin += ((h - 2*fb->y_margin) & 15) / 2;
 
 	var->xres_virtual = w;
@@ -883,7 +937,7 @@
 	fb->info.node = -1;
 	fb->info.fbops = &sbusfb_ops;
 	fb->info.disp = disp;
-	fb->info.fontname[0] = '\0';
+	strcpy(fb->info.fontname, fontname);
 	fb->info.changevar = NULL;
 	fb->info.switch_con = &sbusfbcon_switch;
 	fb->info.updatevar = &sbusfbcon_updatevar;
@@ -934,6 +988,7 @@
 	disp->dispsw = &fb->dispsw;
 	if (fb->setcursor)
 		fb->dispsw.cursor = sbusfb_cursor;
+	fb->dispsw.set_font = sbusfb_set_font;
 	fb->setup = fb->dispsw.setup;
 	fb->dispsw.setup = sbusfb_disp_setup;
 
@@ -942,6 +997,9 @@
 	disp->type = fix->type;
 	disp->type_aux = fix->type_aux;
 	disp->line_length = fix->line_length;
+	
+	if (fb->blank)
+		disp->can_soft_blank = 1;
 
 	sbusfb_set_var(var, -1, &fb->info);
 
@@ -978,7 +1036,10 @@
 	struct linux_sbus_device *sbdp;
 	struct linux_sbus *sbus;
 	char prom_name[40];
-    
+	extern int con_is_present(void);
+	
+	if (!con_is_present() || disable) return;
+	
 #ifdef CONFIG_FB_CREATOR
 	root = prom_getchild(prom_root_node);
 	for (node = prom_searchsiblings(root, "SUNW,ffb"); node;
diff -u --recursive --new-file v2.1.109/linux/drivers/video/sbusfb.h linux/drivers/video/sbusfb.h
--- v2.1.109/linux/drivers/video/sbusfb.h	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/sbusfb.h	Sat Jul 18 13:55:46 1998
@@ -21,6 +21,7 @@
 	struct bt_regs *bt;
 	struct cg6_fbc *fbc;
 	struct cg6_thc *thc;
+	struct cg6_tec *tec;
 	volatile u32 *fhc;
 };
 
@@ -76,6 +77,7 @@
 	void (*loadcmap)(struct fb_info_sbusfb *, int, int);
 	void (*blank)(struct fb_info_sbusfb *);
 	void (*unblank)(struct fb_info_sbusfb *);
+	void (*margins)(struct fb_info_sbusfb *, struct display *, int, int);
 	void (*reset)(struct fb_info_sbusfb *);
 	void (*fill)(struct fb_info_sbusfb *, int, int, unsigned short *);
 	void (*switch_from_graph)(struct fb_info_sbusfb *);
diff -u --recursive --new-file v2.1.109/linux/drivers/video/tgafb.c linux/drivers/video/tgafb.c
--- v2.1.109/linux/drivers/video/tgafb.c	Thu Jul 16 18:09:28 1998
+++ linux/drivers/video/tgafb.c	Sat Jul 18 14:07:35 1998
@@ -40,6 +40,7 @@
 #include <linux/selection.h>
 #include <asm/io.h>
 
+#include "fbcon.h"
 #include "fbcon-cfb8.h"
 #include "fbcon-cfb32.h"
 
@@ -743,12 +744,14 @@
 #ifdef CONFIG_FBCON_CFB8
 	case 0: /* 8-plane */
 	    disp.dispsw = &fbcon_cfb8;
+	    disp.scrollmode = SCROLL_YREDRAW;
 	    break;
 #endif
 #ifdef CONFIG_FBCON_CFB32
 	case 1: /* 24-plane */
 	case 3: /* 24plusZ */
 	    disp.dispsw = &fbcon_cfb32;
+	    disp.scrollmode = SCROLL_YREDRAW;
 	    break;
 #endif
 	default:
diff -u --recursive --new-file v2.1.109/linux/drivers/video/vesafb.c linux/drivers/video/vesafb.c
--- v2.1.109/linux/drivers/video/vesafb.c	Thu Jul 16 18:09:28 1998
+++ linux/drivers/video/vesafb.c	Sat Jul 18 13:57:53 1998
@@ -74,23 +74,13 @@
 	{0,0,0,0,0,0}
 };
 
-#define NUM_TOTAL_MODES		1
-#define NUM_PREDEF_MODES	1
-
 static struct display disp;
 static struct fb_info fb_info;
 static struct { u_char red, green, blue, pad; } palette[256];
 
 static int inverse = 0;
 
-struct vesafb_par
-{
-	void *unused;
-};
-
 static int currcon = 0;
-static int current_par_valid = 0;
-struct vesafb_par current_par;
 
 /* --------------------------------------------------------------------- */
 /* speed up scrolling                                                    */
@@ -98,19 +88,9 @@
 #define USE_REDRAW   1
 #define USE_MEMMOVE  2
   
-static vesafb_scroll = USE_REDRAW;
+static int vesafb_scroll = USE_REDRAW;
 static struct display_switch vesafb_sw;
 
-void vesafb_bmove(struct display *p, int sy, int sx, int dy, int dx,
-		  int height, int width)
-{
-	/*
-	 * this is really faster than memmove (at least with my box)
-	 *    read access to video memory is slow...
-	 */
-	update_screen(currcon);
-}
-
 /* --------------------------------------------------------------------- */
 
 	/*
@@ -132,33 +112,13 @@
 	return(0);
 }
 
-static void vesafb_encode_var(struct fb_var_screeninfo *var, 
-				struct vesafb_par *par)
-{
-	memcpy(var, &vesafb_defined, sizeof(struct fb_var_screeninfo));
-}
-
-static void vesafb_get_par(struct vesafb_par *par)
-{
-	*par=current_par;
-}
-
 static int fb_update_var(int con, struct fb_info *info)
 {
 	return 0;
 }
 
-static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
-{
-	struct vesafb_par par;
-	
-	vesafb_get_par(&par);
-	vesafb_encode_var(var, &par);
-	return 0;
-}
-
-static void vesafb_encode_fix(struct fb_fix_screeninfo *fix, 
-				struct vesafb_par *par)
+static int vesafb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			 struct fb_info *info)
 {
 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 	strcpy(fix->id,"VESA VGA");
@@ -171,27 +131,14 @@
 	fix->ypanstep=0;
 	fix->ywrapstep=0;
 	fix->line_length=video_linelength;
-	return;
-}
-
-static int vesafb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info)
-{
-	struct vesafb_par par;
-	vesafb_get_par(&par);
-	vesafb_encode_fix(fix, &par);
 	return 0;
 }
 
 static int vesafb_get_var(struct fb_var_screeninfo *var, int con,
 			 struct fb_info *info)
 {
-	struct vesafb_par par;
 	if(con==-1)
-	{
-		vesafb_get_par(&par);
-		vesafb_encode_var(var, &par);
-	}
+		memcpy(var, &vesafb_defined, sizeof(struct fb_var_screeninfo));
 	else
 		*var=fb_display[con].var;
 	return 0;
@@ -201,6 +148,7 @@
 {
 	struct fb_fix_screeninfo fix;
 	struct display *display;
+	struct display_switch *sw;
 	
 	if (con >= 0)
 		display = &fb_display[con];
@@ -209,6 +157,7 @@
 
 	vesafb_get_fix(&fix, con, 0);
 
+	memset(display, 0, sizeof(struct display));
 	display->screen_base = video_vbase;
 	display->visual = fix.visual;
 	display->type = fix.type;
@@ -219,42 +168,40 @@
 	display->next_line = fix.line_length;
 	display->can_soft_blank = 0;
 	display->inverse = inverse;
+	vesafb_get_var(&display->var, -1, &fb_info);
 
 	switch (video_bpp) {
 #ifdef CONFIG_FBCON_CFB8
 	case 8:
-		display->dispsw = &fbcon_cfb8;
+		sw = &fbcon_cfb8;
 		break;
 #endif
 #ifdef CONFIG_FBCON_CFB16
 	case 15:
 	case 16:
-		display->dispsw = &fbcon_cfb16;
+		sw = &fbcon_cfb16;
 		break;
 #endif
 #ifdef CONFIG_FBCON_CFB32
 	case 32:
-		display->dispsw = &fbcon_cfb32;
+		sw = &fbcon_cfb32;
 		break;
 #endif
 	default:
-		display->dispsw = NULL;
-		break;
+		return;
 	}
+	memcpy(&vesafb_sw, sw, sizeof(*sw));
+	display->dispsw = &vesafb_sw;
 	if (vesafb_scroll == USE_REDRAW) {
-		memcpy(&vesafb_sw,display->dispsw,sizeof(vesafb_sw));
-		vesafb_sw.bmove = vesafb_bmove;
-		display->dispsw = &vesafb_sw;
+		display->scrollmode = SCROLL_YREDRAW;
+		vesafb_sw.bmove = fbcon_redraw_bmove;
 	}
 }
 
 static int vesafb_set_var(struct fb_var_screeninfo *var, int con,
 			 struct fb_info *info)
 {
-	int err;
-	
-	if ((err=do_fb_set_var(var, 1)))
-		return err;
+	memcpy(var, &vesafb_defined, sizeof(struct fb_var_screeninfo));
 	return 0;
 }
 
@@ -297,7 +244,7 @@
 	switch (video_bpp) {
 #ifdef CONFIG_FBCON_CFB8
 	case 8:
-		/* Hmm, can we do it _allways_ this way ??? */
+		/* Hmm, can we do it _always_ this way ??? */
 		outb_p(regno, dac_reg);
 		outb_p(red, dac_val);
 		outb_p(green, dac_val);
@@ -432,7 +379,6 @@
 	currcon = con;
 	/* Install new colormap */
 	do_install_cmap(con, info);
-	fb_update_var(con, info);
 	return 0;
 }
 
@@ -515,9 +461,6 @@
 	fb_info.switch_con=&vesafb_switch;
 	fb_info.updatevar=&fb_update_var;
 	fb_info.blank=&vesafb_blank;
-	do_fb_set_var(&vesafb_defined,1);
-
-	vesafb_get_var(&disp.var, -1, &fb_info);
 	vesafb_set_disp(-1);
 
 	if (register_framebuffer(&fb_info)<0)
diff -u --recursive --new-file v2.1.109/linux/drivers/video/vgacon.c linux/drivers/video/vgacon.c
--- v2.1.109/linux/drivers/video/vgacon.c	Thu Jul 16 18:09:28 1998
+++ linux/drivers/video/vgacon.c	Sun Jul 19 20:45:45 1998
@@ -37,13 +37,12 @@
  *
  *	- monochrome attribute encoding (convert abscon <-> VGA style)
  *
- *	- add support for VESA blanking
- *
  *	- Cursor shape fixes
  *
  * KNOWN PROBLEMS/TO DO ==================================================== */
 
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -69,8 +68,15 @@
 
 #undef VGA_CAN_DO_64KB
 
-#define dac_reg	(0x3c8)
-#define dac_val	(0x3c9)
+#define dac_reg		0x3c8
+#define dac_val		0x3c9
+#define attrib_port	0x3c0
+#define seq_port_reg	0x3c4
+#define seq_port_val	0x3c5
+#define gr_port_reg	0x3ce
+#define gr_port_val	0x3cf
+#define video_misc_rd	0x3cc
+#define video_misc_wr	0x3c2
 
 /*
  *  Interface used by the world
@@ -78,9 +84,10 @@
 
 static const char *vgacon_startup(void);
 static void vgacon_init(struct vc_data *c, int init);
+static void vgacon_deinit(struct vc_data *c);
 static void vgacon_cursor(struct vc_data *c, int mode);
 static int vgacon_switch(struct vc_data *c);
-static int vgacon_blank(int blank);
+static int vgacon_blank(struct vc_data *c, int blank);
 static int vgacon_get_font(struct vc_data *c, int *w, int *h, char *data);
 static int vgacon_set_font(struct vc_data *c, int w, int h, char *data);
 static int vgacon_set_palette(struct vc_data *c, unsigned char *table);
@@ -103,6 +110,10 @@
 static unsigned char   vga_hardscroll_enabled;
 static unsigned char   vga_hardscroll_user_enable = 1;
 static unsigned char   vga_font_is_default = 1;
+static int	       vga_vesa_blanked;
+static int	       vga_palette_blanked;
+static int	       vga_is_gfx;
+
 
 void no_scroll(char *str, int *ints)
 {
@@ -114,7 +125,6 @@
 	vga_hardscroll_user_enable = vga_hardscroll_enabled = 0;
 }
 
-
 /*
  * By replacing the four outb_p with two back to back outw, we can reduce
  * the window of opportunity to see text mislocated to the RHS of the
@@ -139,13 +149,23 @@
 #endif
 }
 
-
 __initfunc(static const char *vgacon_startup(void))
 {
 	const char *display_desc = NULL;
 	u16 saved;
 	u16 *p;
 
+	if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB) {
+	no_vga:
+#ifdef CONFIG_DUMMY_CONSOLE
+		conswitchp = &dummy_con;
+		return conswitchp->con_startup();
+#else
+		return NULL;
+#endif
+	}
+
+
 	vga_video_num_lines = ORIG_VIDEO_LINES;
 	vga_video_num_columns = ORIG_VIDEO_COLS;
 
@@ -178,7 +198,7 @@
 		vga_video_port_val = 0x3d5;
 		if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
 		{
-			int i ;
+			int i;
 
 			vga_vram_end = 0xc0000;
 
@@ -248,12 +268,12 @@
 	scr_writew(0xAA55, p);
 	if (scr_readw(p) != 0xAA55) {
 		scr_writew(saved, p);
-		return NULL;
+		goto no_vga;
 	}
 	scr_writew(0x55AA, p);
 	if (scr_readw(p) != 0x55AA) {
 		scr_writew(saved, p);
-		return NULL;
+		goto no_vga;
 	}
 	scr_writew(saved, p);
 
@@ -271,7 +291,6 @@
 	return display_desc;
 }
 
-
 static void vgacon_init(struct vc_data *c, int init)
 {
 	/* We cannot be loaded as a module, therefore init is always 1 */
@@ -280,13 +299,16 @@
 	c->vc_rows = vga_video_num_lines;
 }
 
+static void vgacon_deinit(struct vc_data *c)
+{
+	vgacon_set_origin(c);
+}
 
 static inline void vga_set_mem_top(struct vc_data *c)
 {
 	write_vga(12, (c->vc_visible_origin-vga_vram_base)/2);
 }
 
-
 static void vgacon_cursor(struct vc_data *c, int mode)
 {
     if (c->vc_origin != c->vc_visible_origin)
@@ -303,7 +325,6 @@
     }
 }
 
-
 static int vgacon_switch(struct vc_data *c)
 {
 	/*
@@ -317,21 +338,198 @@
 	return 0;	/* Redrawing not needed */
 }
 
+static void vga_set_palette(struct vc_data *c, unsigned char *table)
+{
+	int i, j ;
+
+	for (i=j=0; i<16; i++) {
+		outb_p (table[i], dac_reg) ;
+		outb_p (c->vc_palette[j++]>>2, dac_val) ;
+		outb_p (c->vc_palette[j++]>>2, dac_val) ;
+		outb_p (c->vc_palette[j++]>>2, dac_val) ;
+	}
+}
 
-static int vgacon_blank(int blank)
+static int vgacon_set_palette(struct vc_data *c, unsigned char *table)
 {
-    /* FIXME: Implement! */
-    /* FIXME: Check if we really ignore everything when the console is blanked. */
-    if (blank) {
-	scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size);
+#ifdef CAN_LOAD_PALETTE
+
+	if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked)
+		return -EINVAL;
+	vga_set_palette(c, table);
 	return 0;
-    } else {
-	/* Tell console.c that it has to restore the screen itself */
-	return 1;
-    }
-    return 0;
+#else
+	return -EINVAL;
+#endif
 }
 
+/* structure holding original VGA register settings */
+static struct {
+	unsigned char	SeqCtrlIndex;		/* Sequencer Index reg.   */
+	unsigned char	CrtCtrlIndex;		/* CRT-Contr. Index reg.  */
+	unsigned char	CrtMiscIO;		/* Miscellaneous register */
+	unsigned char	HorizontalTotal;	/* CRT-Controller:00h */
+	unsigned char	HorizDisplayEnd;	/* CRT-Controller:01h */
+	unsigned char	StartHorizRetrace;	/* CRT-Controller:04h */
+	unsigned char	EndHorizRetrace;	/* CRT-Controller:05h */
+	unsigned char	Overflow;		/* CRT-Controller:07h */
+	unsigned char	StartVertRetrace;	/* CRT-Controller:10h */
+	unsigned char	EndVertRetrace;		/* CRT-Controller:11h */
+	unsigned char	ModeControl;		/* CRT-Controller:17h */
+	unsigned char	ClockingMode;		/* Seq-Controller:01h */
+} vga_state;
+
+static void vga_vesa_blank(int mode)
+{
+	/* save original values of VGA controller registers */
+	if(!vga_vesa_blanked) {
+		cli();
+		vga_state.SeqCtrlIndex = inb_p(seq_port_reg);
+		vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
+		vga_state.CrtMiscIO = inb_p(video_misc_rd);
+		sti();
+
+		outb_p(0x00,vga_video_port_reg);	/* HorizontalTotal */
+		vga_state.HorizontalTotal = inb_p(vga_video_port_val);
+		outb_p(0x01,vga_video_port_reg);	/* HorizDisplayEnd */
+		vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
+		outb_p(0x04,vga_video_port_reg);	/* StartHorizRetrace */
+		vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
+		outb_p(0x05,vga_video_port_reg);	/* EndHorizRetrace */
+		vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
+		outb_p(0x07,vga_video_port_reg);	/* Overflow */
+		vga_state.Overflow = inb_p(vga_video_port_val);
+		outb_p(0x10,vga_video_port_reg);	/* StartVertRetrace */
+		vga_state.StartVertRetrace = inb_p(vga_video_port_val);
+		outb_p(0x11,vga_video_port_reg);	/* EndVertRetrace */
+		vga_state.EndVertRetrace = inb_p(vga_video_port_val);
+		outb_p(0x17,vga_video_port_reg);	/* ModeControl */
+		vga_state.ModeControl = inb_p(vga_video_port_val);
+		outb_p(0x01,seq_port_reg);		/* ClockingMode */
+		vga_state.ClockingMode = inb_p(seq_port_val);
+	}
+
+	/* assure that video is enabled */
+	/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
+	cli();
+	outb_p(0x01,seq_port_reg);
+	outb_p(vga_state.ClockingMode | 0x20,seq_port_val);
+
+	/* test for vertical retrace in process.... */
+	if ((vga_state.CrtMiscIO & 0x80) == 0x80)
+		outb_p(vga_state.CrtMiscIO & 0xef,video_misc_wr);
+
+	/*
+	 * Set <End of vertical retrace> to minimum (0) and
+	 * <Start of vertical Retrace> to maximum (incl. overflow)
+	 * Result: turn off vertical sync (VSync) pulse.
+	 */
+	if (mode & VESA_VSYNC_SUSPEND) {
+		outb_p(0x10,vga_video_port_reg);	/* StartVertRetrace */
+		outb_p(0xff,vga_video_port_val); 	/* maximum value */
+		outb_p(0x11,vga_video_port_reg);	/* EndVertRetrace */
+		outb_p(0x40,vga_video_port_val);	/* minimum (bits 0..3)  */
+		outb_p(0x07,vga_video_port_reg);	/* Overflow */
+		outb_p(vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */
+	}
+
+	if (mode & VESA_HSYNC_SUSPEND) {
+		/*
+		 * Set <End of horizontal retrace> to minimum (0) and
+		 *  <Start of horizontal Retrace> to maximum
+		 * Result: turn off horizontal sync (HSync) pulse.
+		 */
+		outb_p(0x04,vga_video_port_reg);	/* StartHorizRetrace */
+		outb_p(0xff,vga_video_port_val);	/* maximum */
+		outb_p(0x05,vga_video_port_reg);	/* EndHorizRetrace */
+		outb_p(0x00,vga_video_port_val);	/* minimum (0) */
+	}
+
+	/* restore both index registers */
+	outb_p(vga_state.SeqCtrlIndex,seq_port_reg);
+	outb_p(vga_state.CrtCtrlIndex,vga_video_port_reg);
+	sti();
+}
+
+static void vga_vesa_unblank(void)
+{
+	/* restore original values of VGA controller registers */
+	cli();
+	outb_p(vga_state.CrtMiscIO,video_misc_wr);
+
+	outb_p(0x00,vga_video_port_reg);		/* HorizontalTotal */
+	outb_p(vga_state.HorizontalTotal,vga_video_port_val);
+	outb_p(0x01,vga_video_port_reg);		/* HorizDisplayEnd */
+	outb_p(vga_state.HorizDisplayEnd,vga_video_port_val);
+	outb_p(0x04,vga_video_port_reg);		/* StartHorizRetrace */
+	outb_p(vga_state.StartHorizRetrace,vga_video_port_val);
+	outb_p(0x05,vga_video_port_reg);		/* EndHorizRetrace */
+	outb_p(vga_state.EndHorizRetrace,vga_video_port_val);
+	outb_p(0x07,vga_video_port_reg);		/* Overflow */
+	outb_p(vga_state.Overflow,vga_video_port_val);
+	outb_p(0x10,vga_video_port_reg);		/* StartVertRetrace */
+	outb_p(vga_state.StartVertRetrace,vga_video_port_val);
+	outb_p(0x11,vga_video_port_reg);		/* EndVertRetrace */
+	outb_p(vga_state.EndVertRetrace,vga_video_port_val);
+	outb_p(0x17,vga_video_port_reg);		/* ModeControl */
+	outb_p(vga_state.ModeControl,vga_video_port_val);
+	outb_p(0x01,seq_port_reg);		/* ClockingMode */
+	outb_p(vga_state.ClockingMode,seq_port_val);
+
+	/* restore index/control registers */
+	outb_p(vga_state.SeqCtrlIndex,seq_port_reg);
+	outb_p(vga_state.CrtCtrlIndex,vga_video_port_reg);
+	sti();
+}
+
+static void vga_pal_blank(void)
+{
+	int i;
+
+	for (i=0; i<16; i++) {
+		outb_p (i, dac_reg) ;
+		outb_p (0, dac_val) ;
+		outb_p (0, dac_val) ;
+		outb_p (0, dac_val) ;
+	}
+}
+
+static int vgacon_blank(struct vc_data *c, int blank)
+{
+	switch (blank) {
+	case 0:				/* Unblank */
+		if (vga_vesa_blanked) {
+			vga_vesa_unblank();
+			vga_vesa_blanked = 0;
+		}
+		if (vga_palette_blanked) {
+			vga_set_palette(c, color_table);
+			vga_palette_blanked = 0;
+			return 0;
+		}
+		vga_is_gfx = 0;
+		/* Tell console.c that it has to restore the screen itself */
+		return 1;
+	case 1:				/* Normal blanking */
+		if (vga_video_type == VIDEO_TYPE_VGAC) {
+			vga_pal_blank();
+			vga_palette_blanked = 1;
+			return 0;
+		}
+		scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size);
+		return 0;
+	case -1:			/* Entering graphic mode */
+		scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size);
+		vga_is_gfx = 1;
+		return 0;
+	default:			/* VESA blanking */
+		if (vga_video_type == VIDEO_TYPE_VGAC) {
+			vga_vesa_blank(blank-1);
+			vga_vesa_blanked = blank;
+		}
+		return 0;
+	}
+}
 
 /*
  * PIO_FONT support.
@@ -350,11 +548,6 @@
    should use 0xA0000 for the bwmap as well.. */
 #define blackwmap 0xa0000
 #define cmapsz 8192
-#define attrib_port (0x3c0)
-#define seq_port_reg (0x3c4)
-#define seq_port_val (0x3c5)
-#define gr_port_reg (0x3ce)
-#define gr_port_val (0x3cf)
 
 static int
 vgacon_font_op(char *arg, int set)
@@ -578,26 +771,6 @@
 	return rc;
 }
 
-static int vgacon_set_palette(struct vc_data *c, unsigned char *table)
-{
-#ifdef CAN_LOAD_PALETTE
-	int i, j ;
-
-	if (vga_video_type != VIDEO_TYPE_VGAC || console_blanked)
-		return -EINVAL;
-
-	for (i=j=0; i<16; i++) {
-		outb_p (table[i], dac_reg) ;
-		outb_p (c->vc_palette[j++]>>2, dac_val) ;
-		outb_p (c->vc_palette[j++]>>2, dac_val) ;
-		outb_p (c->vc_palette[j++]>>2, dac_val) ;
-	}
-	return 0;
-#else
-	return -EINVAL;
-#endif
-}
-
 static int vgacon_scrolldelta(struct vc_data *c, int lines)
 {
 	/* FIXME: Better scrollback strategy, maybe move it to generic code
@@ -620,6 +793,8 @@
 
 static int vgacon_set_origin(struct vc_data *c)
 {
+	if (vga_is_gfx)		/* We don't play origin tricks in graphic modes */
+		return 0;
 	c->vc_origin = c->vc_visible_origin = vga_vram_base;
 	vga_set_mem_top(c);
 	return 1;
@@ -645,7 +820,7 @@
 {
 	unsigned long oldo;
 	
-	if (t || b != c->vc_rows)
+	if (t || b != c->vc_rows || vga_is_gfx)
 		return 0;
 
 	if (c->vc_origin != c->vc_visible_origin)
@@ -672,7 +847,6 @@
 }
 
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -687,7 +861,7 @@
 struct consw vga_con = {
 	vgacon_startup,
 	vgacon_init,
-	DUMMY,				/* con_deinit */
+	vgacon_deinit,
 	DUMMY,				/* con_clear */
 	DUMMY,				/* con_putc */
 	DUMMY,				/* con_putcs */
diff -u --recursive --new-file v2.1.109/linux/drivers/video/vgafb.c linux/drivers/video/vgafb.c
--- v2.1.109/linux/drivers/video/vgafb.c	Thu Jul 16 18:09:28 1998
+++ linux/drivers/video/vgafb.c	Sat Jul 18 13:55:47 1998
@@ -745,7 +745,7 @@
 
 static struct display_switch fbcon_vgafb = {
     fbcon_vga_setup, fbcon_vga_bmove, fbcon_vga_clear, fbcon_vga_putc,
-    fbcon_vga_putcs, fbcon_vga_revc, fbcon_vgafb_cursor
+    fbcon_vga_putcs, fbcon_vga_revc, fbcon_vgafb_cursor, NULL, FONTWIDTH(8)
 };
 
 
diff -u --recursive --new-file v2.1.109/linux/drivers/video/virgefb.c linux/drivers/video/virgefb.c
--- v2.1.109/linux/drivers/video/virgefb.c	Thu Jul 16 18:09:28 1998
+++ linux/drivers/video/virgefb.c	Sat Jul 18 13:55:47 1998
@@ -1163,7 +1163,7 @@
 
 static struct display_switch fbcon_virge8 = {
    fbcon_cfb8_setup, fbcon_virge8_bmove, fbcon_virge8_clear, fbcon_cfb8_putc,
-   fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL
+   fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, FONTWIDTH(8)
 };
 #endif
 
diff -u --recursive --new-file v2.1.109/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.1.109/linux/fs/coda/psdev.c	Thu Jul 16 18:09:28 1998
+++ linux/fs/coda/psdev.c	Sun Jul 19 20:49:15 1998
@@ -33,6 +33,7 @@
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
 #include <linux/poll.h>
+#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/segment.h>
 #include <asm/system.h>
@@ -401,15 +402,7 @@
 
 #ifdef CONFIG_PROC_FS
 
-struct proc_dir_entry proc_sys_root = {
-        PROC_SYS, 3, "sys",                     /* inode, name */
-        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,   /* mode, nlink, uid, gid */
-        0, &proc_dir_inode_operations,          /* size, ops */
-        NULL, NULL,                             /* get_info, fill_inode */
-        NULL,                                   /* next */
-        NULL, NULL                              /* parent, subdir */
-};
-
+extern struct proc_dir_entry proc_sys_root;
 
 struct proc_dir_entry proc_sys_coda = {
         0, 4, "coda",
diff -u --recursive --new-file v2.1.109/linux/fs/coda/upcall.c linux/fs/coda/upcall.c
--- v2.1.109/linux/fs/coda/upcall.c	Thu Jul 16 18:09:28 1998
+++ linux/fs/coda/upcall.c	Sun Jul 19 20:48:55 1998
@@ -39,6 +39,8 @@
 #include <linux/coda_cache.h>
 #include <linux/coda_proc.h> 
 
+extern void coda_purge_dentries(struct inode *inode);
+extern void coda_purge_children(struct inode *inode);
 
 static int  coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize, 
 		       union inputArgs *buffer);
diff -u --recursive --new-file v2.1.109/linux/fs/dcache.c linux/fs/dcache.c
--- v2.1.109/linux/fs/dcache.c	Thu May  7 22:51:53 1998
+++ linux/fs/dcache.c	Mon Jul 20 10:21:26 1998
@@ -438,9 +438,13 @@
  */
 void shrink_dcache_memory(int priority, unsigned int gfp_mask)
 {
+#if 0
 	int count = select_dcache(32, 8);
 	if (count)
 		prune_dcache((count << 6) >> priority);
+#else
+	prune_dcache(0);
+#endif
 }
 
 #define NAME_ALLOC_LEN(len)	((len+16) & ~15)
diff -u --recursive --new-file v2.1.109/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v2.1.109/linux/fs/nfs/file.c	Sun Jan  4 00:53:41 1998
+++ linux/fs/nfs/file.c	Mon Jul 20 17:22:35 1998
@@ -202,7 +202,7 @@
 	return result;
 
 out_swapfile:
-	printk("NFS: attempt to write to active swap file!\n");
+	printk(KERN_ERR "NFS: attempt to write to active swap file!\n");
 	goto out;
 }
 
diff -u --recursive --new-file v2.1.109/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.1.109/linux/fs/nfs/inode.c	Wed Jun 24 22:54:09 1998
+++ linux/fs/nfs/inode.c	Mon Jul 20 17:22:35 1998
@@ -43,6 +43,7 @@
 static void nfs_delete_inode(struct inode *);
 static int  nfs_notify_change(struct dentry *, struct iattr *);
 static void nfs_put_super(struct super_block *);
+static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct super_block *, struct statfs *, int);
 
 static struct super_operations nfs_sops = { 
@@ -54,7 +55,9 @@
 	nfs_put_super,		/* put superblock */
 	NULL,			/* write superblock */
 	nfs_statfs,		/* stat filesystem */
-	NULL
+	NULL,			/* no remount */
+	NULL,			/* no clear inode */
+	nfs_umount_begin	/* umount attempt begin */
 };
 
 struct rpc_stat			nfs_rpcstat = { &nfs_program };
@@ -140,6 +143,17 @@
 	kfree(server->hostname);
 
 	MOD_DEC_USE_COUNT;
+}
+
+void
+nfs_umount_begin(struct super_block *sb)
+{
+	struct nfs_server *server = &sb->u.nfs_sb.s_server;
+	struct rpc_clnt	*rpc;
+
+	/* -EIO all pending I/O */
+	if ((rpc = server->client) != NULL)
+		rpc_killall_tasks(rpc);
 }
 
 /*
diff -u --recursive --new-file v2.1.109/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.1.109/linux/fs/nfsd/vfs.c	Wed Jun 24 22:54:09 1998
+++ linux/fs/nfsd/vfs.c	Mon Jul 20 14:19:51 1998
@@ -551,7 +551,7 @@
 			interruptible_sleep_on(&inode->i_wait);
 #else
 			dprintk("nfsd: write defer %d\n", current->pid);
-			need_resched = 1;
+			current->need_resched = 1;
 			current->timeout = jiffies + HZ / 100;
 			schedule();
 			dprintk("nfsd: write resume %d\n", current->pid);
diff -u --recursive --new-file v2.1.109/linux/fs/ntfs/attr.c linux/fs/ntfs/attr.c
--- v2.1.109/linux/fs/ntfs/attr.c	Wed Jun 24 22:54:10 1998
+++ linux/fs/ntfs/attr.c	Fri Jul 17 10:33:34 1998
@@ -56,7 +56,7 @@
 		}
 	}
 	if(do_insert)
-		ntfs_memcpy(ino->attrs+i+1,ino->attrs+i,(ino->attr_count-i)*
+		ntfs_memmove(ino->attrs+i+1,ino->attrs+i,(ino->attr_count-i)*
 			    sizeof(ntfs_attribute));
 	ino->attr_count++;
 	ino->attrs[i].type=type;
@@ -95,7 +95,7 @@
 		}
 	}
 	if(attr->d.r.len>cnum)
-		ntfs_memcpy(attr->d.r.runlist+cnum+1,attr->d.r.runlist+cnum,
+		ntfs_memmove(attr->d.r.runlist+cnum+1,attr->d.r.runlist+cnum,
 			    (attr->d.r.len-cnum)*sizeof(ntfs_runlist));
 	attr->d.r.runlist[cnum].cluster=cluster;
 	attr->d.r.runlist[cnum].len=len;
diff -u --recursive --new-file v2.1.109/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- v2.1.109/linux/fs/ntfs/fs.c	Mon Apr  6 17:41:01 1998
+++ linux/fs/ntfs/fs.c	Fri Jul 17 10:33:35 1998
@@ -827,7 +827,7 @@
 
 	/* Inform the kernel that a device block is a NTFS cluster */
 	sb->s_blocksize=vol->clustersize;
-	for(i=sb->s_blocksize,sb->s_blocksize_bits=0;i;i>>=1)
+	for(i=sb->s_blocksize,sb->s_blocksize_bits=0;i != 1;i>>=1)
 		sb->s_blocksize_bits++;
 	set_blocksize(sb->s_dev,sb->s_blocksize);
 	ntfs_debug(DEBUG_OTHER, "set_blocksize\n");
diff -u --recursive --new-file v2.1.109/linux/fs/super.c linux/fs/super.c
--- v2.1.109/linux/fs/super.c	Wed Jun 24 22:54:10 1998
+++ linux/fs/super.c	Mon Jul 20 17:22:35 1998
@@ -656,6 +656,19 @@
 #endif
 
 	/*
+	 * If we may have to abort operations to get out of this
+	 * mount, and they will themselves hold resources we must
+	 * allow the fs to do things. In the Unix tradition of
+	 * 'Gee thats tricky lets do it in userspace' the umount_begin
+	 * might fail to complete on the first run through as other tasks
+	 * must return, and the like. Thats for the mount program to worry
+	 * about for the moment.
+	 */
+	 
+	if(sb->s_op->umount_begin)
+		sb->s_op->umount_begin(sb);
+
+	/*
 	 * Shrink dcache, then fsync. This guarantees that if the
 	 * filesystem is quiescent at this point, then (a) only the
 	 * root entry should be in use and (b) that root entry is
@@ -747,6 +760,8 @@
  * we give them the info they need without using a real inode.
  * If any other fields are ever needed by any block device release
  * functions, they should be faked here.  -- jrs
+ *
+ * For 2.3.x we want a new sys_umount syscall with flags (ie 'force')
  */
 
 asmlinkage int sys_umount(char * name)
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/apecs.h linux/include/asm-alpha/apecs.h
--- v2.1.109/linux/include/asm-alpha/apecs.h	Wed Jun 24 22:54:10 1998
+++ linux/include/asm-alpha/apecs.h	Sun Jul 19 20:44:41 1998
@@ -211,6 +211,7 @@
 #define APECS_IO			(IDENT_ADDR + 0x1c0000000UL)
 #define APECS_SPARSE_MEM		(IDENT_ADDR + 0x200000000UL)
 #define APECS_DENSE_MEM		        (IDENT_ADDR + 0x300000000UL)
+#define DENSE_MEM(addr)			APECS_DENSE_MEM
 
 /*
  * Bit definitions for I/O Controller status register 0:
@@ -286,6 +287,7 @@
  */
 
 #define vuip	volatile unsigned int *
+#define vulp	volatile unsigned long *
 
 extern inline unsigned int __inb(unsigned long addr)
 {
@@ -374,6 +376,11 @@
 	return *(vuip) (addr + APECS_DENSE_MEM);
 }
 
+extern inline unsigned long __readq(unsigned long addr)
+{
+	return *(vulp) (addr + APECS_DENSE_MEM);
+}
+
 extern inline void __writeb(unsigned char b, unsigned long addr)
 {
 	unsigned long msb;
@@ -407,6 +414,11 @@
 	*(vuip) (addr + APECS_DENSE_MEM) = b;
 }
 
+extern inline void __writeq(unsigned long b, unsigned long addr)
+{
+	*(vulp) (addr + APECS_DENSE_MEM) = b;
+}
+
 #define inb(port) \
 (__builtin_constant_p((port))?__inb(port):_inb(port))
 
@@ -414,9 +426,12 @@
 (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
 
 #define readl(a)	__readl((unsigned long)(a))
+#define readq(a)	__readq((unsigned long)(a))
 #define writel(v,a)	__writel((v),(unsigned long)(a))
+#define writeq(v,a)	__writeq((v),(unsigned long)(a))
 
 #undef vuip
+#undef vulp
 
 extern unsigned long apecs_init (unsigned long mem_start,
 				 unsigned long mem_end);
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/bitops.h linux/include/asm-alpha/bitops.h
--- v2.1.109/linux/include/asm-alpha/bitops.h	Tue Jun 23 10:01:25 1998
+++ linux/include/asm-alpha/bitops.h	Mon Jul 20 17:23:32 1998
@@ -182,6 +182,8 @@
 	return qofs*8 + bofs;
 }
 
+#ifdef __KERNEL__
+
 /*
  * ffs: find first bit set. This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
@@ -199,6 +201,7 @@
 #define hweight16(x) generic_hweight16(x)
 #define hweight8(x) generic_hweight8(x)
 
+#endif /* __KERNEL__ */
 
 /*
  * Find next zero bit in a bitmap reasonably efficiently..
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/cia.h linux/include/asm-alpha/cia.h
--- v2.1.109/linux/include/asm-alpha/cia.h	Tue Jun  9 11:57:31 1998
+++ linux/include/asm-alpha/cia.h	Sun Jul 19 20:44:41 1998
@@ -178,6 +178,7 @@
 #define CIA_SPARSE_MEM_R2		(IDENT_ADDR + 0x8400000000UL)
 #define CIA_SPARSE_MEM_R3		(IDENT_ADDR + 0x8500000000UL)
 #define CIA_DENSE_MEM		        (IDENT_ADDR + 0x8600000000UL)
+#define DENSE_MEM(addr)			CIA_DENSE_MEM
 
 /*
  * ALCOR's GRU ASIC registers
@@ -241,6 +242,7 @@
  */
 
 #define vuip	volatile unsigned int *
+#define vulp	volatile unsigned long *
 
 extern inline unsigned int __inb(unsigned long addr)
 {
@@ -491,11 +493,21 @@
 	return *(vuip) (addr + CIA_DENSE_MEM);
 }
 
+extern inline unsigned long __readq(unsigned long addr)
+{
+	return *(vulp) (addr + CIA_DENSE_MEM);
+}
+
 extern inline void __writel(unsigned int b, unsigned long addr)
 {
 	*(vuip) (addr + CIA_DENSE_MEM) = b;
 }
 
+extern inline void __writeq(unsigned long b, unsigned long addr)
+{
+	*(vulp) (addr + CIA_DENSE_MEM) = b;
+}
+
 #define inb(port) \
 (__builtin_constant_p((port))?__inb(port):_inb(port))
 
@@ -503,9 +515,12 @@
 (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
 
 #define readl(a)	__readl((unsigned long)(a))
+#define readq(a)	__readq((unsigned long)(a))
 #define writel(v,a)	__writel((v),(unsigned long)(a))
+#define writeq(v,a)	__writeq((v),(unsigned long)(a))
 
 #undef vuip
+#undef vulp
 
 extern unsigned long cia_init (unsigned long mem_start,
 				 unsigned long mem_end);
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- v2.1.109/linux/include/asm-alpha/io.h	Wed Jun 24 22:54:10 1998
+++ linux/include/asm-alpha/io.h	Sun Jul 19 20:44:41 1998
@@ -133,9 +133,11 @@
 extern unsigned long	_readb(unsigned long addr);
 extern unsigned long	_readw(unsigned long addr);
 extern unsigned long	_readl(unsigned long addr);
+extern unsigned long	_readq(unsigned long addr);
 extern void		_writeb(unsigned char b, unsigned long addr);
 extern void		_writew(unsigned short b, unsigned long addr);
 extern void		_writel(unsigned int b, unsigned long addr);
+extern void		_writeq(unsigned long b, unsigned long addr);
 
 /*
  * The platform header files may define some of these macros to use
@@ -206,6 +208,9 @@
 #ifndef readl
 # define readl(a)	_readl((unsigned long)(a))
 #endif
+#ifndef readq
+# define readq(a)	_readq((unsigned long)(a))
+#endif
 #ifndef writeb
 # define writeb(v,a)	_writeb((v),(unsigned long)(a))
 #endif
@@ -215,19 +220,29 @@
 #ifndef writel
 # define writel(v,a)	_writel((v),(unsigned long)(a))
 #endif
+#ifndef writeq
+# define writeq(v,a)	_writeq((v),(unsigned long)(a))
+#endif
 
 #ifdef __KERNEL__
 
 /*
  * String version of IO memory access ops:
  */
-extern void _memcpy_fromio(void *, unsigned long, unsigned long);
-extern void _memcpy_toio(unsigned long, void *, unsigned long);
-extern void _memset_io(unsigned long, int, unsigned long);
-
-#define memcpy_fromio(to,from,len)	_memcpy_fromio((to),(unsigned long)(from),(len))
-#define memcpy_toio(to,from,len)	_memcpy_toio((unsigned long)(to),(from),(len))
-#define memset_io(addr,c,len)		_memset_io((unsigned long)(addr),(c),(len))
+extern void _memcpy_fromio(void *, unsigned long, long);
+extern void _memcpy_toio(unsigned long, void *, long);
+extern void _memset_c_io(unsigned long, unsigned long, long);
+
+#define memcpy_fromio(to,from,len) \
+  _memcpy_fromio((to),(unsigned long)(from),(len))
+#define memcpy_toio(to,from,len) \
+  _memcpy_toio((unsigned long)(to),(from),(len))
+#define memset_io(addr,c,len) \
+  _memset_c_io((unsigned long)(addr),0x0101010101010101UL*(u8)(c),(len))
+
+#define __HAVE_ARCH_MEMSETW_IO
+#define memsetw_io(addr,c,len) \
+  _memset_c_io((unsigned long)(addr),0x0001000100010001UL*(u16)(c),(len))
 
 /*
  * String versions of in/out ops:
@@ -245,7 +260,8 @@
  * only used by some shared memory 8390 Ethernet cards anyway.
  */
 
-#define eth_io_copy_and_sum(skb,src,len,unused)	memcpy_fromio((skb)->data,(src),(len))
+#define eth_io_copy_and_sum(skb,src,len,unused) \
+  memcpy_fromio((skb)->data,(src),(len))
 
 static inline int check_signature(unsigned long io_addr,
 	const unsigned char *signature, int length)
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/jensen.h linux/include/asm-alpha/jensen.h
--- v2.1.109/linux/include/asm-alpha/jensen.h	Tue Oct  8 23:54:05 1996
+++ linux/include/asm-alpha/jensen.h	Sun Jul 19 20:44:41 1998
@@ -230,6 +230,17 @@
 	return *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x60);
 }
 
+extern inline unsigned long __readq(unsigned long addr)
+{
+	unsigned long r0, r1;
+	__set_hae(addr);
+	addr &= __HAE_MASK;
+	addr = (addr << 7) + EISA_MEM + 0x60;
+	r0 = *(volatile unsigned int *) (addr);
+	r1 = *(volatile unsigned int *) (addr + (4 << 7));
+	return r1 << 32 | r0;
+}
+
 extern inline void __writeb(unsigned short b, unsigned long addr)
 {
 	__set_hae(addr);
@@ -249,6 +260,15 @@
 	__set_hae(addr);
 	addr &= __HAE_MASK;
 	*(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x60) = b;
+}
+
+extern inline void __writeq(unsigned long b, unsigned long addr)
+{
+	__set_hae(addr);
+	addr &= __HAE_MASK;
+	addr = (addr << 7) + EISA_MEM + 0x60;
+	*(volatile unsigned int *) (addr) = b;
+	*(volatile unsigned int *) (addr + (4 << 7)) = b >> 32;
 }
 
 /*
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/lca.h linux/include/asm-alpha/lca.h
--- v2.1.109/linux/include/asm-alpha/lca.h	Tue Jun  9 11:57:31 1998
+++ linux/include/asm-alpha/lca.h	Sun Jul 19 20:44:41 1998
@@ -125,6 +125,7 @@
 #define LCA_IO			(IDENT_ADDR + 0x1c0000000UL)
 #define LCA_SPARSE_MEM		(IDENT_ADDR + 0x200000000UL)
 #define LCA_DENSE_MEM		(IDENT_ADDR + 0x300000000UL)
+#define DENSE_MEM(addr)		LCA_DENSE_MEM
 
 /*
  * Bit definitions for I/O Controller status register 0:
@@ -208,6 +209,7 @@
  */
 
 #define vuip	volatile unsigned int *
+#define vulp	volatile unsigned long *
 
 extern inline unsigned int __inb(unsigned long addr)
 {
@@ -296,6 +298,11 @@
 	return *(vuip) (addr + LCA_DENSE_MEM);
 }
 
+extern inline unsigned long __readq(unsigned long addr)
+{
+	return *(vulp) (addr + LCA_DENSE_MEM);
+}
+
 extern inline void __writeb(unsigned char b, unsigned long addr)
 {
 	unsigned long msb;
@@ -333,6 +340,11 @@
 	*(vuip) (addr + LCA_DENSE_MEM) = b;
 }
 
+extern inline void __writeq(unsigned long b, unsigned long addr)
+{
+	*(vulp) (addr + LCA_DENSE_MEM) = b;
+}
+
 /*
  * Most of the above have so much overhead that it probably doesn't
  * make sense to have them inlined (better icache behavior).
@@ -345,9 +357,12 @@
 (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
 
 #define readl(a)	__readl((unsigned long)(a))
+#define readq(a)	__readq((unsigned long)(a))
 #define writel(v,a)	__writel((v),(unsigned long)(a))
+#define writeq(v,a)	__writeq((v),(unsigned long)(a))
 
 #undef vuip
+#undef vulp
 
 extern unsigned long lca_init (unsigned long mem_start, unsigned long mem_end);
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/mcpcia.h linux/include/asm-alpha/mcpcia.h
--- v2.1.109/linux/include/asm-alpha/mcpcia.h	Tue Jun  9 11:57:31 1998
+++ linux/include/asm-alpha/mcpcia.h	Sun Jul 19 20:44:41 1998
@@ -167,6 +167,8 @@
 #define MCPCIA_DENSE(h)		(IDENT_ADDR + 0xf900000000UL + HOSE(h))
 #define MCPCIA_IACK_SC(h)	(IDENT_ADDR + 0xf9f0003f00UL + HOSE(h))
 
+#define DENSE_MEM(addr)		MCPCIA_DENSE(((unsigned long)(addr) >> 32) & 3)
+
 #define HAE_ADDRESS		MCPCIA_HAE_MEM(0)
 
 #ifdef __KERNEL__
@@ -197,6 +199,7 @@
  */
 
 #define vuip	volatile unsigned int *
+#define vulp	volatile unsigned long *
 
 #ifdef DISABLE_BWIO_ENABLED
 
@@ -375,7 +378,7 @@
 	__asm__ __volatile__ (
 		 "ldbu %0,%1"
 		 : "=r" (result)
-		 : "m"  (*(unsigned char *)(addr+MCPCIA_BW_MEM)));
+		 : "m"  (*(volatile unsigned char *)(addr+MCPCIA_BW_MEM)));
 
 	return result;
 }
@@ -387,21 +390,19 @@
 	__asm__ __volatile__ (
 		 "ldwu %0,%1"
 		 : "=r" (result)
-		 : "m"  (*(unsigned short *)(addr+MCPCIA_BW_MEM)));
+		 : "m"  (*(volatile unsigned short *)(addr+MCPCIA_BW_MEM)));
 
 	return result;
 }
 
 extern inline unsigned long __readl(unsigned long addr)
 {
-	register unsigned long result;
-
-	__asm__ __volatile__ (
-		 "ldl %0,%1"
-		 : "=r" (result)
-		 : "m"  (*(unsigned int *)(addr+MCPCIA_BW_MEM)));
+	return *(vuip)(addr + MCPCIA_BW_MEM);
+}
 
-	return result;
+extern inline unsigned long __readq(unsigned long addr)
+{
+	return *(vulp)(addr + MCPCIA_BW_MEM);
 }
 
 extern inline void __writeb(unsigned char b, unsigned long addr)
@@ -409,7 +410,8 @@
 	__asm__ __volatile__ (
 		 "stb %1,%0\n\t"
 		 "mb"
-		 : : "m" (*(unsigned char *)(addr+MCPCIA_BW_MEM)), "r" (b));
+		 : "m" (*(volatile unsigned char *)(addr+MCPCIA_BW_MEM))
+		 : "r" (b));
 }
 
 extern inline void __writew(unsigned short b, unsigned long addr)
@@ -417,15 +419,20 @@
 	__asm__ __volatile__ (
 		 "stw %1,%0\n\t"
 		 "mb"
-		 : : "m" (*(unsigned short *)(addr+MCPCIA_BW_MEM)), "r" (b));
+		 : "m" (*(volatile unsigned short *)(addr+MCPCIA_BW_MEM))
+		 : "r" (b));
 }
 
 extern inline void __writel(unsigned int b, unsigned long addr)
 {
-	__asm__ __volatile__ (
-		 "stl %1,%0\n\t"
-		 "mb"
-		 : : "m" (*(unsigned int *)(addr+MCPCIA_BW_MEM)), "r" (b));
+	*(vuip)(addr+MCPCIA_BW_MEM) = b;
+	mb();
+}
+
+extern inline void __writeq(unsigned long b, unsigned long addr)
+{
+	*(vulp)(addr+MCPCIA_BW_MEM) = b;
+	mb();
 }
 
 #define readb(addr) __readb((addr))
@@ -620,6 +627,13 @@
 	return *(vuip) (addr + MCPCIA_DENSE(hose));
 }
 
+extern inline unsigned long __readq(unsigned long in_addr)
+{
+	unsigned long addr = in_addr & 0xffffffffUL;
+	unsigned long hose = (in_addr >> 32) & 3;
+	return *(vulp) (addr + MCPCIA_DENSE(hose));
+}
+
 extern inline void __writel(unsigned int b, unsigned long in_addr)
 {
 	unsigned long addr = in_addr & 0xffffffffUL;
@@ -627,12 +641,22 @@
 	*(vuip) (addr + MCPCIA_DENSE(hose)) = b;
 }
 
+extern inline void __writeq(unsigned long b, unsigned long in_addr)
+{
+	unsigned long addr = in_addr & 0xffffffffUL;
+	unsigned long hose = (in_addr >> 32) & 3;
+	*(vulp) (addr + MCPCIA_DENSE(hose)) = b;
+}
+
 #endif /* BWIO_ENABLED */
 
 #define readl(a)	__readl((unsigned long)(a))
+#define readq(a)	__readq((unsigned long)(a))
 #define writel(v,a)	__writel((v),(unsigned long)(a))
+#define writeq(v,a)	__writeq((v),(unsigned long)(a))
 
 #undef vuip
+#undef vulp
 
 struct linux_hose_info {
         struct pci_bus                  pci_bus;
@@ -646,10 +670,8 @@
 	unsigned int                    pci_hose_index;
 };
 
-extern unsigned long mcpcia_init (unsigned long mem_start,
-				 unsigned long mem_end);
-extern unsigned long mcpcia_fixup (unsigned long mem_start,
-				 unsigned long mem_end);
+extern unsigned long mcpcia_init (unsigned long, unsigned long);
+extern void mcpcia_fixup (void);
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h
--- v2.1.109/linux/include/asm-alpha/pgtable.h	Wed Jun 24 22:54:10 1998
+++ linux/include/asm-alpha/pgtable.h	Sun Jul 19 20:44:41 1998
@@ -30,10 +30,11 @@
 static inline void reload_context(struct task_struct *task)
 {
 	__asm__ __volatile__(
-		"bis %0,%0,$16\n\t"
 #ifdef CONFIG_ALPHA_DP264
-		"zap $16,0xe0,$16\n\t"
-#endif /* DP264 */
+		"zap %0,0xe0,$16\n\t"
+#else
+		"bis %0,%0,$16\n\t"
+#endif
 		"call_pal %1"
 		: /* no outputs */
 		: "r" (&task->tss), "i" (PAL_swpctx)
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/pyxis.h linux/include/asm-alpha/pyxis.h
--- v2.1.109/linux/include/asm-alpha/pyxis.h	Tue Jun  9 11:57:31 1998
+++ linux/include/asm-alpha/pyxis.h	Sun Jul 19 20:44:41 1998
@@ -165,6 +165,7 @@
 #define PYXIS_SPARSE_MEM_R2		(IDENT_ADDR + 0x8400000000UL)
 #define PYXIS_SPARSE_MEM_R3		(IDENT_ADDR + 0x8500000000UL)
 #define PYXIS_DENSE_MEM		        (IDENT_ADDR + 0x8600000000UL)
+#define DENSE_MEM(addr)			PYXIS_DENSE_MEM
 
 /*
  * Byte/Word PCI Memory Spaces:
@@ -242,6 +243,7 @@
  */
 
 #define vuip	volatile unsigned int *
+#define vulp	volatile unsigned long *
 
 #ifdef BWIO_ENABLED
 
@@ -252,7 +254,7 @@
 	__asm__ __volatile__ (
 		 "ldbu %0,%1"
 		 : "=r" (result)
-		 : "m"  (*(unsigned char *)(addr+PYXIS_BW_IO)));
+		 : "m"  (*(volatile unsigned char *)(addr+PYXIS_BW_IO)));
 
 	return result;
 }
@@ -262,7 +264,8 @@
 	__asm__ __volatile__ (
 		 "stb %1,%0\n\t"
 		 "mb"
-		 : : "m" (*(unsigned char *)(addr+PYXIS_BW_IO)), "r" (b));
+		 : "=m" (*(volatile unsigned char *)(addr+PYXIS_BW_IO))
+		 : "r" (b));
 }
 
 extern inline unsigned int __inw(unsigned long addr)
@@ -272,7 +275,7 @@
 	__asm__ __volatile__ (
 		 "ldwu %0,%1"
 		 : "=r" (result)
-		 : "m"  (*(unsigned short *)(addr+PYXIS_BW_IO)));
+		 : "m"  (*(volatile unsigned short *)(addr+PYXIS_BW_IO)));
 
 	return result;
 }
@@ -282,27 +285,19 @@
 	__asm__ __volatile__ (
 		 "stw %1,%0\n\t"
 		 "mb"
-		 : : "m" (*(unsigned short *)(addr+PYXIS_BW_IO)), "r" (b));
+		 : "=m" (*(volatile unsigned short *)(addr+PYXIS_BW_IO))
+		 : "r" (b));
 }
 
 extern inline unsigned int __inl(unsigned long addr)
 {
-	register unsigned long result;
-
-	__asm__ __volatile__ (
-		 "ldl %0,%1"
-		 : "=r" (result)
-		 : "m"  (*(unsigned int *)(addr+PYXIS_BW_IO)));
-
-	return result;
+	return *(vuip)(addr+PYXIS_BW_IO);
 }
 
 extern inline void __outl(unsigned int b, unsigned long addr)
 {
-	__asm__ __volatile__ (
-		 "stl %1,%0\n\t"
-		 "mb"
-		 : : "m" (*(unsigned int *)(addr+PYXIS_BW_IO)), "r" (b));
+	*(vuip)(addr+PYXIS_BW_IO) = b;
+	mb();
 }
 
 #define inb(port) __inb((port))
@@ -408,7 +403,7 @@
 	__asm__ __volatile__ (
 		 "ldbu %0,%1"
 		 : "=r" (result)
-		 : "m"  (*(unsigned char *)(addr+PYXIS_BW_MEM)));
+		 : "m"  (*(volatile unsigned char *)(addr+PYXIS_BW_MEM)));
 
 	return result;
 }
@@ -420,21 +415,19 @@
 	__asm__ __volatile__ (
 		 "ldwu %0,%1"
 		 : "=r" (result)
-		 : "m"  (*(unsigned short *)(addr+PYXIS_BW_MEM)));
+		 : "m"  (*(volatile unsigned short *)(addr+PYXIS_BW_MEM)));
 
 	return result;
 }
 
 extern inline unsigned long __readl(unsigned long addr)
 {
-	register unsigned long result;
-
-	__asm__ __volatile__ (
-		 "ldl %0,%1"
-		 : "=r" (result)
-		 : "m"  (*(unsigned int *)(addr+PYXIS_BW_MEM)));
+	return *(vuip)(addr+PYXIS_BW_MEM);
+}
 
-	return result;
+extern inline unsigned long __readq(unsigned long addr)
+{
+	return *(vulp)(addr+PYXIS_BW_MEM);
 }
 
 extern inline void __writeb(unsigned char b, unsigned long addr)
@@ -442,7 +435,8 @@
 	__asm__ __volatile__ (
 		 "stb %1,%0\n\t"
 		 "mb"
-		 : : "m" (*(unsigned char *)(addr+PYXIS_BW_MEM)), "r" (b));
+		 : "=m" (*(volatile unsigned char *)(addr+PYXIS_BW_MEM))
+		 : "r" (b));
 }
 
 extern inline void __writew(unsigned short b, unsigned long addr)
@@ -450,15 +444,18 @@
 	__asm__ __volatile__ (
 		 "stw %1,%0\n\t"
 		 "mb"
-		 : : "m" (*(unsigned short *)(addr+PYXIS_BW_MEM)), "r" (b));
+		 : "=m" (*(volatile unsigned short *)(addr+PYXIS_BW_MEM))
+		 : "r" (b));
 }
 
 extern inline void __writel(unsigned int b, unsigned long addr)
 {
-	__asm__ __volatile__ (
-		 "stl %1,%0\n\t"
-		 "mb"
-		 : : "m" (*(unsigned int *)(addr+PYXIS_BW_MEM)), "r" (b));
+	*(vuip)(addr+PYXIS_BW_MEM) = b;
+}
+
+extern inline void __writeq(unsigned long b, unsigned long addr)
+{
+	*(vulp)(addr+PYXIS_BW_MEM) = b;
 }
 
 #define readb(addr) __readb((addr))
@@ -643,17 +640,30 @@
 	return *(vuip) (addr + PYXIS_DENSE_MEM);
 }
 
+extern inline unsigned long __readq(unsigned long addr)
+{
+	return *(vulp) (addr + PYXIS_DENSE_MEM);
+}
+
 extern inline void __writel(unsigned int b, unsigned long addr)
 {
 	*(vuip) (addr + PYXIS_DENSE_MEM) = b;
 }
 
+extern inline void __writeq(unsigned long b, unsigned long addr)
+{
+	*(vulp) (addr + PYXIS_DENSE_MEM) = b;
+}
+
 #endif /* BWIO_ENABLED */
 
 #define readl(a)	__readl((unsigned long)(a))
+#define readq(a)	__readq((unsigned long)(a))
 #define writel(v,a)	__writel((v),(unsigned long)(a))
+#define writeq(v,a)	__writeq((v),(unsigned long)(a))
 
 #undef vuip
+#undef vulp
 
 extern unsigned long pyxis_init (unsigned long mem_start,
 				 unsigned long mem_end);
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/serial.h linux/include/asm-alpha/serial.h
--- v2.1.109/linux/include/asm-alpha/serial.h	Sat Apr 25 18:13:12 1998
+++ linux/include/asm-alpha/serial.h	Sat Jul 18 11:30:24 1998
@@ -37,7 +37,7 @@
 
 
 #ifdef CONFIG_SERIAL_MANY_PORTS
-#define EXTRA_SERIAL_PORT_DEFNS			\	
+#define EXTRA_SERIAL_PORT_DEFNS			\
 	{ 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, 	/* ttyS4 */	\
 	{ 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS },	/* ttyS5 */	\
 	{ 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS },	/* ttyS6 */	\
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/string.h linux/include/asm-alpha/string.h
--- v2.1.109/linux/include/asm-alpha/string.h	Tue Jun  9 11:57:31 1998
+++ linux/include/asm-alpha/string.h	Sun Jul 19 20:44:41 1998
@@ -19,8 +19,8 @@
 #endif
 
 #define __HAVE_ARCH_MEMSET
-extern void * __constant_c_memset(void *, unsigned long, long);
-extern void * __memset(void *, char, size_t);
+extern void * __constant_c_memset(void *, unsigned long, size_t);
+extern void * __memset(void *, int, size_t);
 
 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
 #define memset(s, c, n)							    \
@@ -43,6 +43,18 @@
 #define __HAVE_ARCH_STRCHR
 #define __HAVE_ARCH_STRRCHR
 #define __HAVE_ARCH_STRLEN
+
+/* The following routine is like memset except that it writes 16-bit
+   aligned values.  The DEST and COUNT parameters must be even for 
+   correct operation.  */
+
+#define __HAVE_ARCH_MEMSETW
+extern void * __memsetw(void *dest, unsigned short, size_t count);
+
+#define memsetw(s, c, n)						 \
+(__builtin_constant_p(c)						 \
+ ? __constant_c_memset((s),0x0001000100010001UL*(unsigned short)(c),(n)) \
+ : __memsetw((s),(c),(n)))
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/t2.h linux/include/asm-alpha/t2.h
--- v2.1.109/linux/include/asm-alpha/t2.h	Wed Jun 24 22:54:10 1998
+++ linux/include/asm-alpha/t2.h	Sun Jul 19 20:44:41 1998
@@ -48,6 +48,7 @@
 #define T2_IO			(IDENT_ADDR + GAMMA_BIAS + 0x3a0000000UL)
 #define T2_SPARSE_MEM		(IDENT_ADDR + GAMMA_BIAS + 0x200000000UL)
 #define T2_DENSE_MEM	        (IDENT_ADDR + GAMMA_BIAS + 0x3c0000000UL)
+#define DENSE_MEM(addr)		T2_DENSE_MEM
 
 #define T2_IOCSR		(IDENT_ADDR + GAMMA_BIAS + 0x38e000000UL)
 #define T2_CERR1		(IDENT_ADDR + GAMMA_BIAS + 0x38e000020UL)
@@ -219,87 +220,79 @@
 
 extern unsigned long t2_sm_base;
 
+extern int __t2_ioaddr_check(unsigned long addr)
+{
+	if ((addr >= t2_sm_base && addr <= t2_sm_base + MEM_R1_MASK)
+	    || (addr >= 512*1024 && addr < 1024*1024))
+		return 1;
+#if 0
+	  printk("T2: address 0x%lx not covered by HAE\n", addr);
+#endif
+	return 0;
+}
+
+
 extern inline unsigned long __readb(unsigned long addr)
 {
 	unsigned long result, shift, work;
 
-	if ((addr >= t2_sm_base) && (addr <= (t2_sm_base + MEM_R1_MASK)))
-	  work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00);
-	else
-	if ((addr >= 512*1024) && (addr < 1024*1024)) /* check HOLE */
-	  work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00);
-	else
-	{
-#if 0
-	  printk("__readb: address 0x%lx not covered by HAE\n", addr);
-#endif
-	  return 0x0ffUL;
-	}
-	shift = (addr & 0x3) << 3;
+	if (!__t2_addr_check(addr))
+		return 0xFF;
+
+	work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00);
 	result = *(vuip) work;
-	result >>= shift;
-	return 0x0ffUL & result;
+	shift = (addr & 0x3) << 3;
+	return (result >> shift) & 0xFF;
 }
 
 extern inline unsigned long __readw(unsigned long addr)
 {
 	unsigned long result, shift, work;
 
-	if ((addr >= t2_sm_base) && (addr <= (t2_sm_base + MEM_R1_MASK)))
-	  work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08);
-	else
-	if ((addr >= 512*1024) && (addr < 1024*1024)) /* check HOLE */
-	  work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08);
-	else
-	{
-#if 0
-	  printk("__readw: address 0x%lx not covered by HAE\n", addr);
-#endif
-	  return 0x0ffffUL;
-	}
-	shift = (addr & 0x3) << 3;
+	if (!__t2_addr_check(addr))
+		return 0xFFFF;
+
+	work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08);
 	result = *(vuip) work;
-	result >>= shift;
-	return 0x0ffffUL & result;
+	shift = (addr & 0x3) << 3;
+	return (result >> shift) & 0xFF;
 }
 
-/* on SABLE with T2, we must use SPARSE memory even for 32-bit access */
+/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */
 extern inline unsigned long __readl(unsigned long addr)
 {
-	unsigned long result, work;
+	unsigned long work;
 
-	if ((addr >= t2_sm_base) && (addr <= (t2_sm_base + MEM_R1_MASK)))
-	  work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18);
-	else
-	if ((addr >= 512*1024) && (addr < 1024*1024)) /* check HOLE */
-	  work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18);
-	else
-	{
-#if 0
-	  printk("__readl: address 0x%lx not covered by HAE\n", addr);
-#endif
-	  return 0x0ffffffffUL;
-	}
-	result = *(vuip) work;
-	return 0xffffffffUL & result;
+	if (!__t2_addr_check(addr))
+		return 0xFFFFFFFF;
+
+	work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18);
+	return *(vuip) work;
+}
+
+/* ... which makes me wonder why we advertise we have DENSE memory at all.
+   Anyway, guess that means we should emulate 64-bit access as two cycles.  */
+extern inline unsigned long __readq(unsigned long addr)
+{
+	unsigned long work, r0, r1;
+
+	if (!__t2_addr_check(addr))
+		return ~0UL;
+
+	work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18);
+	r0 = *(vuip) work0;
+	r1 = *(vuip) (work0 + (4 << 5));
+	return r1 << 32 | r0;
 }
 
 extern inline void __writeb(unsigned char b, unsigned long addr)
 {
 	unsigned long work;
 
-	if ((addr >= t2_sm_base) && (addr <= (t2_sm_base + MEM_R1_MASK)))
-	  work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00);
-	else
-	if ((addr >= 512*1024) && (addr < 1024*1024)) /* check HOLE */
-	  work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00);
-	else
-	{
-#if 0
-	  printk("__writeb: address 0x%lx not covered by HAE\n", addr);
-#endif
-	  return;
-	}
+	if (!__t2_addr_check(addr))
+		return;
+
+	work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00);
 	*(vuip) work = b * 0x01010101;
 }
 
@@ -307,40 +300,39 @@
 {
 	unsigned long work;
 
-	if ((addr >= t2_sm_base) && (addr <= (t2_sm_base + MEM_R1_MASK)))
-	  work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08);
-	else
-	if ((addr >= 512*1024) && (addr < 1024*1024)) /* check HOLE */
-	  work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08);
-	else
-	{
-#if 0
-	  printk("__writew: address 0x%lx not covered by HAE\n", addr);
-#endif
-	  return;
-	}
+	if (!__t2_addr_check(addr))
+		return;
+
+	work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08);
 	*(vuip) work = b * 0x00010001;
 }
 
-/* on SABLE with T2, we must use SPARSE memory even for 32-bit access */
+/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */
 extern inline void __writel(unsigned int b, unsigned long addr)
 {
 	unsigned long work;
 
-	if ((addr >= t2_sm_base) && (addr <= (t2_sm_base + MEM_R1_MASK)))
-	  work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18);
-	else
-	if ((addr >= 512*1024) && (addr < 1024*1024)) /* check HOLE */
-	  work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18);
-	{
-#if 0
-	  printk("__writel: address 0x%lx not covered by HAE\n", addr);
-#endif
-	  return;
-	}
+	if (!__t2_addr_check(addr))
+		return;
+
+	work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18);
 	*(vuip) work = b;
 }
 
+/* ... which makes me wonder why we advertise we have DENSE memory at all.
+   Anyway, guess that means we should emulate 64-bit access as two cycles.  */
+extern inline void __writeq(unsigned long b, unsigned long addr)
+{
+	unsigned long work;
+
+	if (!__t2_addr_check(addr))
+		return;
+
+	work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18);
+	*(vuip) work0 = b;
+	*(vuip) (work0 + (4 << 5)) = (b >> 32);
+}
+
 #else /* SRM_SETUP */
 
 extern inline unsigned long __readb(unsigned long addr)
@@ -387,6 +379,20 @@
 	return 0xffffffffUL & result;
 }
 
+extern inline unsigned long __readq(unsigned long addr)
+{
+	unsigned long r0, r1, work, msb;
+
+	msb = addr & 0xE0000000 ;
+	addr &= MEM_R1_MASK ;
+	if (msb != hae.cache) {
+	  set_hae(msb);
+	}
+	work = (addr << 5) + T2_SPARSE_MEM + 0x18;
+	r0 = *(vuip)(work);
+	r1 = *(vuip)(work + (4 << 5));
+	return r1 << 32 | r0;
+}
 extern inline void __writeb(unsigned char b, unsigned long addr)
 {
         unsigned long msb ; 
@@ -424,6 +430,20 @@
 	*(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b;
 }
 
+extern inline void __writeq(unsigned long b, unsigned long addr)
+{
+        unsigned long msb, work;
+
+	msb = addr & 0xE0000000 ;
+	addr &= MEM_R1_MASK ;
+	if (msb != hae.cache) {
+	  set_hae(msb);
+	}
+	work = (addr << 5) + T2_SPARSE_MEM + 0x18;
+	*(vuip)work = b;
+	*(vuip)(work + (4 << 5)) = b >> 32;
+}
+
 #endif /* SRM_SETUP */
 
 #define inb(port) \
@@ -431,9 +451,6 @@
 
 #define outb(x, port) \
 (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
-
-#define readl(a)	__readl((unsigned long)(a))
-#define writel(v,a)	__writel((v),(unsigned long)(a))
 
 #undef vuip
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-alpha/tsunami.h linux/include/asm-alpha/tsunami.h
--- v2.1.109/linux/include/asm-alpha/tsunami.h	Wed Apr  1 20:11:54 1998
+++ linux/include/asm-alpha/tsunami.h	Sun Jul 19 20:44:41 1998
@@ -317,70 +317,50 @@
 
 /* only using PCI bus 0 for now in all routines */
 
+#define DENSE_MEM(addr)			TSUNAMI_PCI0_MEM
+
 /* HACK ALERT! HACK ALERT! */
 /* HACK ALERT! HACK ALERT! */
 
+/* Also assume we are optimizing for EV6, and so the compiler knows about
+   byte/word instructions.  */
 
+#define vucp	volatile unsigned char *
+#define vusp	volatile unsigned short *
 #define vuip	volatile unsigned int *
+#define vulp	volatile unsigned long *
 
 extern inline unsigned int __inb(unsigned long addr)
 {
-	register unsigned long result;
-
-	__asm__ __volatile__ (
-		 "ldbu %0,%1"
-		 : "=r" (result)
-		 : "m"  (*(unsigned char *)(addr+TSUNAMI_PCI0_IO)));
-
-	return result;
+	return *(vucp)(addr + TSUNAMI_PCI0_IO);
 }
 
 extern inline void __outb(unsigned char b, unsigned long addr)
 {
-	__asm__ __volatile__ (
-		 "stb %1,%0\n\t"
-		 "mb"
-		 : : "m" (*(unsigned char *)(addr+TSUNAMI_PCI0_IO)), "r" (b));
+	*(vucp)(addr + TSUNAMI_PCI0_IO) = b;
+	mb();
 }
 
 extern inline unsigned int __inw(unsigned long addr)
 {
-	register unsigned long result;
-
-	__asm__ __volatile__ (
-		 "ldwu %0,%1"
-		 : "=r" (result)
-		 : "m"  (*(unsigned short *)(addr+TSUNAMI_PCI0_IO)));
-
-	return result;
+	return *(vusp)(addr+TSUNAMI_PCI0_IO);
 }
 
 extern inline void __outw(unsigned short b, unsigned long addr)
 {
-	__asm__ __volatile__ (
-		 "stw %1,%0\n\t"
-		 "mb"
-		 : : "m" (*(unsigned short *)(addr+TSUNAMI_PCI0_IO)), "r" (b));
+	*(vusp)(addr+TSUNAMI_PCI0_IO) = b;
+	mb();
 }
 
 extern inline unsigned int __inl(unsigned long addr)
 {
-	register unsigned long result;
-
-	__asm__ __volatile__ (
-		 "ldl %0,%1"
-		 : "=r" (result)
-		 : "m"  (*(unsigned int *)(addr+TSUNAMI_PCI0_IO)));
-
-	return result;
+	return *(vuip)(addr+TSUNAMI_PCI0_IO);
 }
 
 extern inline void __outl(unsigned int b, unsigned long addr)
 {
-	__asm__ __volatile__ (
-		 "stl %1,%0\n\t"
-		 "mb"
-		 : : "m" (*(unsigned int *)(addr+TSUNAMI_PCI0_IO)), "r" (b));
+	*(vuip)(addr+TSUNAMI_PCI0_IO) = b;
+	mb();
 }
 
 /*
@@ -389,62 +369,46 @@
 
 extern inline unsigned long __readb(unsigned long addr)
 {
-	register unsigned long result;
-
-	__asm__ __volatile__ (
-		 "ldbu %0,%1"
-		 : "=r" (result)
-		 : "m"  (*(unsigned char *)(addr+TSUNAMI_PCI0_MEM)));
-
-	return result;
+	return *(vucp)(addr+TSUNAMI_PCI0_MEM);
 }
 
 extern inline unsigned long __readw(unsigned long addr)
 {
-	register unsigned long result;
-
-	__asm__ __volatile__ (
-		 "ldwu %0,%1"
-		 : "=r" (result)
-		 : "m"  (*(unsigned short *)(addr+TSUNAMI_PCI0_MEM)));
-
-	return result;
+	return *(vusp)(addr+TSUNAMI_PCI0_MEM);
 }
 
 extern inline unsigned long __readl(unsigned long addr)
 {
-	register unsigned long result;
-
-	__asm__ __volatile__ (
-		 "ldl %0,%1"
-		 : "=r" (result)
-		 : "m"  (*(unsigned int *)(addr+TSUNAMI_PCI0_MEM)));
+	return *(vuip)(addr+TSUNAMI_PCI0_MEM);
+}
 
-	return result;
+extern inline unsigned long __readq(unsigned long addr)
+{
+	return *(vulp)(addr+TSUNAMI_PCI0_MEM);
 }
 
 extern inline void __writeb(unsigned char b, unsigned long addr)
 {
-	__asm__ __volatile__ (
-		 "stb %1,%0\n\t"
-		 "mb"
-		 : : "m" (*(unsigned char *)(addr+TSUNAMI_PCI0_MEM)), "r" (b));
+	*(vucp)(addr+TSUNAMI_PCI0_MEM) = b;
+	mb();
 }
 
 extern inline void __writew(unsigned short b, unsigned long addr)
 {
-	__asm__ __volatile__ (
-		 "stw %1,%0\n\t"
-		 "mb"
-		 : : "m" (*(unsigned short *)(addr+TSUNAMI_PCI0_MEM)), "r" (b));
+	*(vusp)(addr+TSUNAMI_PCI0_MEM) = b;
+	mb();
 }
 
 extern inline void __writel(unsigned int b, unsigned long addr)
 {
-	__asm__ __volatile__ (
-		 "stl %1,%0\n\t"
-		 "mb"
-		 : : "m" (*(unsigned int *)(addr+TSUNAMI_PCI0_MEM)), "r" (b));
+	*(vuip)(addr+TSUNAMI_PCI0_MEM) = b;
+	mb();
+}
+
+extern inline void __writeq(unsigned long b, unsigned long addr)
+{
+	*(vulp)(addr+TSUNAMI_PCI0_MEM) = b;
+	mb();
 }
 
 #define inb(port) __inb((port))
@@ -458,15 +422,19 @@
 #define readb(a)	__readb((unsigned long)(a))
 #define readw(a)	__readw((unsigned long)(a))
 #define readl(a)	__readl((unsigned long)(a))
+#define readq(a)	__readq((unsigned long)(a))
 
 #define writeb(v,a)	__writeb((v),(unsigned long)(a))
 #define writew(v,a)	__writew((v),(unsigned long)(a))
 #define writel(v,a)	__writel((v),(unsigned long)(a))
+#define writeq(v,a)	__writeq((v),(unsigned long)(a))
 
+#undef vucp
+#undef vusp
 #undef vuip
+#undef vulp
 
-extern unsigned long tsunami_init (unsigned long mem_start,
-				 unsigned long mem_end);
+extern unsigned long tsunami_init (unsigned long, unsigned long);
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-arc/io.h linux/include/asm-arm/arch-arc/io.h
--- v2.1.109/linux/include/asm-arm/arch-arc/io.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/io.h	Sat Jul 18 11:55:25 1998
@@ -159,7 +159,18 @@
 	result & 0xffff;							\
 })
 
-#define __outlc(v,p) __outwc((v),(p))
+#define __outlc(value,port) 							\
+({										\
+	unsigned long v = value;						\
+	if (__PORT_PCIO((port)))						\
+		__asm__ __volatile__(						\
+		"str	%0, [%1, %2]"						\
+		: : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
+	else									\
+		__asm__ __volatile__(						\
+		"str	%0, [%1, %2]"						\
+		: : "r" (v), "r" (IO_BASE), "r" ((port) << 2));			\
+})
 
 #define __inlc(port)								\
 ({										\
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-arc/processor.h linux/include/asm-arm/arch-arc/processor.h
--- v2.1.109/linux/include/asm-arm/arch-arc/processor.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-arc/processor.h	Sat Jul 18 11:55:25 1998
@@ -26,7 +26,11 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
+#if 0
 #define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
+#else
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+#endif
 #define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-ebsa110/processor.h linux/include/asm-arm/arch-ebsa110/processor.h
--- v2.1.109/linux/include/asm-arm/arch-ebsa110/processor.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-ebsa110/processor.h	Sat Jul 18 11:55:25 1998
@@ -23,7 +23,11 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
+#if 0
 #define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
+#else
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+#endif
 #define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-ebsa285/hardware.h linux/include/asm-arm/arch-ebsa285/hardware.h
--- v2.1.109/linux/include/asm-arm/arch-ebsa285/hardware.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa285/hardware.h	Sat Jul 18 11:55:25 1998
@@ -15,15 +15,8 @@
  * 0xfd000000	0x78000000	Outbound write flush
  * 0xfc000000	0x79000000	PCI IACK/special space
  *
- * 0xf9030000	0x7a080000	PCI Config type 1 card 4
- * 0xf9020000	0x7a040000	PCI Config type 1 card 3
- * 0xf9010000	0x7a020000	PCI Config type 1 card 2
- * 0xf9000000	0x7a010000	PCI Config type 1 card 1
- *
- * 0xf8030000	0x7b080000	PCI Config type 0 card 4
- * 0xf8020000	0x7b040000	PCI Config type 0 card 3
- * 0xf8010000	0x7b020000	PCI Config type 0 card 2
- * 0xf8000000	0x7b010000	PCI Config type 0 card 1
+ * 0xf9000000	0x7a010000	PCI Config type 1
+ * 0xf8000000	0x7b010000	PCI Config type 0
  * 
  */
  
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-ebsa285/mmu.h linux/include/asm-arm/arch-ebsa285/mmu.h
--- v2.1.109/linux/include/asm-arm/arch-ebsa285/mmu.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa285/mmu.h	Sat Jul 18 11:55:25 1998
@@ -1,26 +1,25 @@
 /*
- * linux/include/asm-arm/arch-ebsa110/mmu.h
+ * linux/include/asm-arm/arch-ebsa285/mmu.h
  *
  * Copyright (c) 1996,1997,1998 Russell King.
  *
  * Changelog:
  *  20-10-1996	RMK	Created
  *  31-12-1997	RMK	Fixed definitions to reduce warnings
+ *  17-05-1998	DAG	Added __virt_to_bus and __bus_to_virt functions.
  */
 #ifndef __ASM_ARCH_MMU_H
 #define __ASM_ARCH_MMU_H
 
 /*
- * On ebsa, the dram is contiguous
+ * On ebsa285, the dram is contiguous
  */
 #define __virt_to_phys__is_a_macro
 #define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
 #define __phys_to_virt__is_a_macro
 #define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
 
-#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x)	__virt_to_phys(x)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x)	__phys_to_virt(x)
+extern unsigned long __virt_to_bus(unsigned long);
+extern unsigned long __bus_to_virt(unsigned long);
 
 #endif
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-ebsa285/serial.h linux/include/asm-arm/arch-ebsa285/serial.h
--- v2.1.109/linux/include/asm-arm/arch-ebsa285/serial.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-ebsa285/serial.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,41 @@
+/*
+ * linux/include/asm-arm/arch-ebsa285/serial.h
+ *
+ * Copyright (c) 1996,1997,1998 Russell King.
+ *
+ * Changelog:
+ *  15-10-1996	RMK	Created
+ */
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD (1843200 / 16)
+
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+
+     /* UART CLK        PORT  IRQ     FLAGS        */
+#define SERIAL_PORT_DFNS \
+	{ 0, BASE_BAUD, 0x3F8,  0, STD_COM_FLAGS },	/* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x2F8,  0, STD_COM_FLAGS },	/* ttyS1 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS2 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS3 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS }, 	/* ttyS4 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS5 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS6 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS7 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS8 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS9 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS10 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS11 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS12 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS13 */
+
+#endif
+
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-nexuspci/irq.h linux/include/asm-arm/arch-nexuspci/irq.h
--- v2.1.109/linux/include/asm-arm/arch-nexuspci/irq.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-nexuspci/irq.h	Sat Jul 18 11:55:25 1998
@@ -4,35 +4,35 @@
  * Copyright (C) 1998 Philip Blundell
  */
 
-#define INT_RESET	((volatile unsigned char *)0xfff00000)
-#define INT_ENABLE	((volatile unsigned char *)0xfff00000)
-#define INT_DISABLE	((volatile unsigned char *)0xfff00000)
+#include <asm/io.h>
 
-static __inline__ void mask_and_ack_irq(unsigned int irq)
-{
-	INT_DISABLE[irq << 2] = 0;
-	INT_RESET[irq << 2] = 0;
-}
+#define INTCONT		0xffe00000
+
+extern unsigned long soft_irq_mask;
 
 static __inline__ void mask_irq(unsigned int irq)
 {
-	INT_DISABLE[irq << 2] = 0;
+	writel((irq << 1), INTCONT);
+	soft_irq_mask &= ~(1<<irq);
 }
 
+#define mask_and_ack_irq(_x)	mask_irq(_x)
+
 static __inline__ void unmask_irq(unsigned int irq)
 {
-	INT_ENABLE[irq << 2] = 0;
+	writel((irq << 1) + 1, INTCONT);
+	soft_irq_mask |= (1<<irq);
 }
  
 static __inline__ unsigned long get_enabled_irqs(void)
 {
-	return 0;
+	return soft_irq_mask;
 }
 
 static __inline__ void irq_init_irq(void)
 {
 	unsigned int i;
 	/* Disable all interrupts initially. */
-	for (i = 0; i < 8; i++)
+	for (i = 0; i < NR_IRQS; i++)
 		mask_irq(i);
 }
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-nexuspci/irqs.h linux/include/asm-arm/arch-nexuspci/irqs.h
--- v2.1.109/linux/include/asm-arm/arch-nexuspci/irqs.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-nexuspci/irqs.h	Sat Jul 18 11:55:25 1998
@@ -1,19 +1,32 @@
 /*
  * linux/include/asm-arm/arch-nexuspci/irqs.h
  *
- * Copyright (C) 1997 Philip Blundell
+ * Copyright (C) 1997, 1998 Philip Blundell
  */
 
-#define IRQ_DUART		0
-#define IRQ_PLX 		1
-#define IRQ_PCI_D		2
-#define IRQ_PCI_C		3
-#define IRQ_PCI_B		4
-#define IRQ_PCI_A		5
-#define IRQ_SYSERR		6
+/* Most of the IRQ sources can generate both FIQs and IRQs.
+   The exceptions to this are the DUART, which can only generate IRQs,
+   and the PLX SYSERR output, which can only generate FIQs.  We route
+   both FIQs and IRQs through the generic IRQ handling system and the
+   choice by the driver of which to use is basically an arbitrary one.  */
+
+#define TREAT_FIQS_AS_IRQS
+
+#define FIQ_PLX			0
+#define FIQ_PCI_D		1
+#define FIQ_PCI_C		2
+#define FIQ_PCI_B		3
+#define FIQ_PCI_A		4
+#define FIQ_SYSERR		5
+
+#define IRQ_DUART		6
+#define IRQ_PLX 		7
+#define IRQ_PCI_D		8
+#define IRQ_PCI_C		9
+#define IRQ_PCI_B		10
+#define IRQ_PCI_A	        11
 
 /* timer is part of the DUART */
 #define IRQ_TIMER		IRQ_DUART
 
 #define irq_cannonicalize(i)	(i)
-
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-nexuspci/mmu.h linux/include/asm-arm/arch-nexuspci/mmu.h
--- v2.1.109/linux/include/asm-arm/arch-nexuspci/mmu.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-nexuspci/mmu.h	Sat Jul 18 11:55:25 1998
@@ -16,11 +16,11 @@
 #define __phys_to_virt__is_a_macro
 
 /*
- * These are exactly the same as the physical memory view.
+ * On the PCI bus the DRAM appears at address 0
  */
 #define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) __virt_to_phys(x)
+#define __virt_to_bus(x) ((x) - PAGE_OFFSET)
 #define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) __phys_to_virt(x)
+#define __bus_to_virt(x) ((x) + PAGE_OFFSET)
 
 #endif
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-nexuspci/processor.h linux/include/asm-arm/arch-nexuspci/processor.h
--- v2.1.109/linux/include/asm-arm/arch-nexuspci/processor.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-nexuspci/processor.h	Sat Jul 18 11:55:25 1998
@@ -24,7 +24,11 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
+#if 0
 #define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
+#else
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+#endif
 #define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-nexuspci/time.h linux/include/asm-arm/arch-nexuspci/time.h
--- v2.1.109/linux/include/asm-arm/arch-nexuspci/time.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-nexuspci/time.h	Sat Jul 18 11:55:25 1998
@@ -3,10 +3,13 @@
  *
  * Copyright (c) 1997 Phil Blundell.
  *
- * Nexus PCI card has no real-time clock.
- *
+ * Nexus PCI card has no real-time clock.  We get timer ticks from the
+ * SCC chip.
  */
 
+#define UART_BASE		0xfff00000
+#define INTCONT			0xffe00000
+
 #define update_rtc()
 
 extern __inline__ unsigned long gettimeoffset (void)
@@ -16,12 +19,31 @@
 
 extern __inline__ int reset_timer (void)
 {
-	return 0;
+	static int count = 50;
+	writeb(0x90, UART_BASE + 8);
+	if (--count == 0)
+	{
+		static int state = 1;
+		state ^= 1;
+		writeb(0x1a + state, INTCONT);
+		count = 50;
+	}
+	readb(UART_BASE + 0x14);
+	readb(UART_BASE + 0x14);
+	readb(UART_BASE + 0x14);
+	readb(UART_BASE + 0x14);
+	readb(UART_BASE + 0x14);
+	readb(UART_BASE + 0x14);
+	return 1;
 }
 
 extern __inline__ unsigned long setup_timer (void)
 {
-	reset_timer ();
+	int tick = 3686400 / 16 / 2 / 100;
+	writeb(tick & 0xff, UART_BASE + 0x1c);
+	writeb(tick >> 8, UART_BASE + 0x18);
+	writeb(0x80, UART_BASE + 8);
+	writeb(0x10, UART_BASE + 0x14);
 	/*
 	 * Default the date to 1 Jan 1970 0:0:0
 	 * You will have to run a time daemon to set the
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-rpc/hardware.h linux/include/asm-arm/arch-rpc/hardware.h
--- v2.1.109/linux/include/asm-arm/arch-rpc/hardware.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-rpc/hardware.h	Sat Jul 18 11:55:25 1998
@@ -53,7 +53,7 @@
 /*
  * Mapping areas
  */
-#define IO_END			0xe0ffffff
+#define IO_END			0xe1000000
 #define IO_BASE			0xe0000000
 #define IO_SIZE			(IO_END - IO_BASE)
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-rpc/keyboard.h linux/include/asm-arm/arch-rpc/keyboard.h
--- v2.1.109/linux/include/asm-arm/arch-rpc/keyboard.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-rpc/keyboard.h	Sat Jul 18 11:55:25 1998
@@ -28,7 +28,11 @@
  * Returns  : 0 to ignore scancode, *keycode set to keycode, *up_flag
  *            set to 0200 if scancode indicates release
  */
+#ifdef NEW_KEYBOARD
 #define kbd_translate(sc, kcp, ufp, rm)	ps2kbd_translate(sc, kcp, ufp)
+#else
+#define kbd_translate(sc, kcp, rm) ({ unsigned int up_flag; ps2kbd_translate(sc, kcp, &up_flag); })
+#endif
 #define kbd_unexpected_up(kc)		(0200)
 #define kbd_leds(leds)			ps2kbd_leds(leds)
 #define kbd_init_hw()			ps2kbd_init_hw()
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-rpc/processor.h linux/include/asm-arm/arch-rpc/processor.h
--- v2.1.109/linux/include/asm-arm/arch-rpc/processor.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-rpc/processor.h	Sat Jul 18 11:55:25 1998
@@ -26,7 +26,11 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
+#if 0
 #define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
+#else
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+#endif
 #define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/a.out.h linux/include/asm-arm/arch-vnc/a.out.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/a.out.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/a.out.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,16 @@
+/*
+ * linux/include/asm-arm/arch-ebsa110/a.out.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_ARCH_A_OUT_H
+#define __ASM_ARCH_A_OUT_H
+
+#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.1.109/linux/include/asm-arm/arch-vnc/dma.h linux/include/asm-arm/arch-vnc/dma.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/dma.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/dma.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,29 @@
+/*
+ * linux/include/asm-arm/arch-ebsa110/dma.h
+ *
+ * Architecture DMA routes
+ *
+ * Copyright (C) 1997.1998 Russell King
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+/*
+ * This is the maximum DMA address that can be DMAd to.
+ * There should not be more than (0xd0000000 - 0xc0000000)
+ * 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.1.109/linux/include/asm-arm/arch-vnc/hardware.h linux/include/asm-arm/arch-vnc/hardware.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/hardware.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/hardware.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,121 @@
+/*
+ * linux/include/asm-arm/arch-vnc/hardware.h
+ *
+ * Copyright (C) 1998 Corel Computer/Russell King.
+ *
+ * This file contains the hardware definitions of the VNC.
+ */
+
+/*    Logical    Physical
+ * 0xfff00000	0x40000000	X-Bus
+ * 0xffe00000	0x7c000000	PCI I/O space
+ *
+ * 0xfe000000	0x42000000	CSR
+ * 0xfd000000	0x78000000	Outbound write flush
+ * 0xfc000000	0x79000000	PCI IACK/special space
+ *
+ * 0xf9030000	0x7a080000	PCI Config type 1 card 4
+ * 0xf9020000	0x7a040000	PCI Config type 1 card 3
+ * 0xf9010000	0x7a020000	PCI Config type 1 card 2
+ * 0xf9000000	0x7a010000	PCI Config type 1 card 1
+ *
+ * 0xf8030000	0x7b080000	PCI Config type 0 card 4
+ * 0xf8020000	0x7b040000	PCI Config type 0 card 3
+ * 0xf8010000	0x7b020000	PCI Config type 0 card 2
+ * 0xf8000000	0x7b010000	PCI Config type 0 card 1
+ * 
+ */
+ 
+/*
+ * 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 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)
+
+/* LEDs */
+#define XBUS_LEDS		((volatile unsigned char *)0xfff12000)
+#define XBUS_LED_AMBER		(1 << 0)
+#define XBUS_LED_GREEN		(1 << 1)
+#define XBUS_LED_RED		(1 << 2)
+#define XBUS_LED_TOGGLE		(1 << 8)
+
+/* PIC irq control */
+#define PIC_LO			0x20
+#define PIC_MASK_LO		0x21
+#define PIC_HI			0xA0
+#define PIC_MASK_HI		0xA1
+
+#define IO_END			0xffffffff
+#define IO_BASE			0xe0000000
+#define IO_SIZE			(IO_END - IO_BASE)
+
+#define HAS_PCIO
+
+#define XBUS_SWITCH		((volatile unsigned char *)0xfff12000)
+#define XBUS_SWITCH_SWITCH	((*XBUS_SWITCH) & 15)
+#define XBUS_SWITCH_J17_13	((*XBUS_SWITCH) & (1 << 4))
+#define XBUS_SWITCH_J17_11	((*XBUS_SWITCH) & (1 << 5))
+#define XBUS_SWITCH_J17_9	((*XBUS_SWITCH) & (1 << 6))
+
+#define PCIO_BASE		0xffe00000
+
+#define KERNTOPHYS(a)		((unsigned long)(&a))
+
+#define PARAMS_OFFSET		0x0100
+#define PARAMS_BASE		(PAGE_OFFSET + PARAMS_OFFSET)
+
+#define SAFE_ADDR		0x50000000
+
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/ide.h linux/include/asm-arm/arch-vnc/ide.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/ide.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/ide.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1 @@
+/* no ide */
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/io.h linux/include/asm-arm/arch-vnc/io.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/io.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/io.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,176 @@
+/*
+ * linux/include/asm-arm/arch-ebsa110/io.h
+ *
+ * Copyright (C) 1997,1998 Russell King
+ *
+ * Modifications:
+ *  06-Dec-1997	RMK	Created.
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/*
+ * This architecture does not require any delayed IO, and
+ * has the constant-optimised IO
+ */
+#undef	ARCH_IO_DELAY
+
+/*
+ * Dynamic IO functions - let the compiler
+ * optimize the expressions
+ */
+#define DECLARE_DYN_OUT(fnsuffix,instr,typ)					\
+extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port)	\
+{										\
+	__asm__ __volatile__(							\
+	"str" ##instr## "	%0, [%1, %2]"					\
+	: 									\
+	: "r" (value), "r" (PCIO_BASE), typ (port));				\
+}
+
+#define DECLARE_DYN_IN(sz,fnsuffix,instr,typ)					\
+extern __inline__ unsigned sz __in##fnsuffix (unsigned int port)		\
+{										\
+	unsigned long value;							\
+	__asm__ __volatile__(							\
+	"ldr" ##instr## "	%0, [%1, %2]"					\
+	: "=&r" (value)								\
+	: "r" (PCIO_BASE), typ (port));						\
+	return (unsigned sz)value;						\
+}
+
+extern __inline__ unsigned int __ioaddr (unsigned int port)			\
+{										\
+	return (unsigned int)(PCIO_BASE + port);				\
+}
+
+#define DECLARE_IO(sz,fnsuffix,instr,typ)	\
+	DECLARE_DYN_OUT(fnsuffix,instr,typ)	\
+	DECLARE_DYN_IN(sz,fnsuffix,instr,typ)
+
+DECLARE_IO(char,b,"b","Jr")
+DECLARE_IO(short,w,"h","r")
+DECLARE_IO(long,l,"","Jr")
+
+#undef DECLARE_IO
+#undef DECLARE_DYN_OUT
+#undef DECLARE_DYN_IN
+
+/*
+ * Constant address IO functions
+ *
+ * These have to be macros for the 'J' constraint to work -
+ * +/-4096 immediate operand.
+ */
+#define __outbc(value,port)							\
+({										\
+	__asm__ __volatile__(							\
+	"strb	%0, [%1, %2]"							\
+	:									\
+	: "r" (value), "r" (PCIO_BASE), "Jr" (port));				\
+})
+
+#define __inbc(port)								\
+({										\
+	unsigned char result;							\
+	__asm__ __volatile__(							\
+	"ldrb	%0, [%1, %2]"							\
+	: "=r" (result)								\
+	: "r" (PCIO_BASE), "Jr" (port));					\
+	result;									\
+})
+
+#define __outwc(value,port)							\
+({										\
+	__asm__ __volatile__(							\
+	"strh	%0, [%1, %2]"							\
+	:									\
+	: "r" (value), "r" (PCIO_BASE), "r" (port));				\
+})
+
+#define __inwc(port)								\
+({										\
+	unsigned short result;							\
+	__asm__ __volatile__(							\
+	"ldrh	%0, [%1, %2]"							\
+	: "=r" (result)								\
+	: "r" (PCIO_BASE), "r" (port));						\
+	result & 0xffff;							\
+})
+
+#define __outlc(value,port)							\
+({										\
+	__asm__ __volatile__(							\
+	"str	%0, [%1, %2]"							\
+	:									\
+	: "r" (value), "r" (PCIO_BASE), "Jr" (port));				\
+})
+
+#define __inlc(port)								\
+({										\
+	unsigned long result;							\
+	__asm__ __volatile__(							\
+	"ldr	%0, [%1, %2]"							\
+	: "=r" (result)								\
+	: "r" (PCIO_BASE), "Jr" (port));					\
+	result;									\
+})
+
+#define __ioaddrc(port)								\
+({										\
+	unsigned long addr;							\
+	addr = PCIO_BASE + port;						\
+	addr;									\
+})
+
+/*
+ * Translated address IO functions
+ *
+ * IO address has already been translated to a virtual address
+ */
+#define outb_t(v,p)								\
+	(*(volatile unsigned char *)(p) = (v))
+
+#define inb_t(p)								\
+	(*(volatile unsigned char *)(p))
+
+#define outl_t(v,p)								\
+	(*(volatile unsigned long *)(p) = (v))
+
+#define inl_t(p)								\
+	(*(volatile unsigned long *)(p))
+
+/*
+ * This is not sufficient... (and it's a hack anyway)
+ */
+static inline void writeb(unsigned char b, unsigned int addr)
+{
+	*(volatile unsigned char *)(0xe0000000 + (addr)) = b;
+}
+
+static inline unsigned char readb(unsigned int addr)
+{
+	return *(volatile unsigned char *)(0xe0000000 + (addr));
+}
+
+static inline void writew(unsigned short b, unsigned int addr)
+{
+	*(volatile unsigned short *)(0xe0000000 + (addr)) = b;
+}
+
+static inline unsigned short readw(unsigned int addr)
+{
+	return *(volatile unsigned short *)(0xe0000000 + (addr));
+}
+
+static inline void writew(unsigned long b, unsigned int addr)
+{
+	*(volatile unsigned long *)(0xe0000000 + (addr)) = b;
+}
+
+static inline unsigned long readw(unsigned int addr)
+{
+	return *(volatile unsigned long *)(0xe0000000 + (addr));
+}
+
+#endif
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/irq.h linux/include/asm-arm/arch-vnc/irq.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/irq.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,106 @@
+/*
+ * include/asm-arm/arch-vnc/irq.h
+ *
+ * Copyright (C) 1998 Russell King
+ */
+
+#include <asm/irq.h>
+
+/*
+ * FootBridge IRQ translation table
+ *  Converts form our IRQ numbers into FootBridge masks (defined in irqs.h)
+ */
+static int fb_irq_mask[16] = {
+	0,
+	IRQ_MASK_SOFTIRQ,
+	IRQ_MASK_UART_DEBUG,
+	0,
+	IRQ_MASK_TIMER0,
+	IRQ_MASK_TIMER1,
+	IRQ_MASK_TIMER2,
+	IRQ_MASK_WATCHDOG,
+	IRQ_MASK_ETHER10,
+	IRQ_MASK_ETHER100,
+	IRQ_MASK_VIDCOMP,
+	IRQ_MASK_EXTERN_IRQ,
+	IRQ_MASK_DMA1,
+	0,
+	0,
+	IRQ_MASK_PCI_ERR
+};
+
+static __inline__ void mask_and_ack_irq(unsigned int irq)
+{
+	if (irq < 16)
+		*CSR_IRQ_DISABLE = fb_irq_mask[irq];
+	else {
+		unsigned int pic_mask, mask;
+
+		if (irq < 24)
+			pic_mask = PIC_MASK_LO;
+		else
+			pic_mask = PIC_MASK_HI;
+
+		mask = 1 << (irq & 7);
+
+		outb(inb(pic_mask) | mask, pic_mask);
+	}
+}
+
+static __inline__ void mask_irq(unsigned int irq)
+{
+	if (irq < 16)
+		*CSR_IRQ_DISABLE = fb_irq_mask[irq];
+	else {
+		unsigned int pic_mask, mask;
+
+		if (irq < 24)
+			pic_mask = PIC_MASK_LO;
+		else
+			pic_mask = PIC_MASK_HI;
+
+		mask = 1 << (irq & 7);
+
+		outb(inb(pic_mask) | mask, pic_mask);
+	}
+}
+
+static __inline__ void unmask_irq(unsigned int irq)
+{
+	if (irq < 16)
+		*CSR_IRQ_ENABLE = fb_irq_mask[irq];
+	else {
+		unsigned int pic_mask, mask;
+
+		if (irq < 24)
+			pic_mask = PIC_MASK_LO;
+		else
+			pic_mask = PIC_MASK_HI;
+
+		mask = 1 << (irq & 7);
+
+		outb(inb(pic_mask) & ~mask, pic_mask);
+	}
+}
+ 
+static __inline__ unsigned long get_enabled_irqs(void)
+{
+	return 0;
+}
+
+static __inline__ void irq_init_irq(void)
+{
+	outb(0x11, PIC_LO);
+	outb(0x10, PIC_MASK_LO);
+	outb(0x04, PIC_MASK_LO);
+	outb(1, PIC_MASK_LO);
+
+	outb(0x11, PIC_HI);
+	outb(0x18, PIC_MASK_HI);
+	outb(0x02, PIC_MASK_HI);
+	outb(1, PIC_MASK_HI);
+
+	*CSR_IRQ_DISABLE = ~IRQ_MASK_EXTERN_IRQ;
+	*CSR_IRQ_ENABLE  = IRQ_MASK_EXTERN_IRQ;
+	*CSR_FIQ_DISABLE = -1;
+}
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/irqs.h linux/include/asm-arm/arch-vnc/irqs.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/irqs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/irqs.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,63 @@
+/*
+ * linux/include/asm-arm/arch-vnc/irqs.h
+ *
+ * Copyright (C) 1998 Russell King
+ */
+
+#define NR_IRQS			32
+
+/*
+ * This is a list of all interrupts that the 21285
+ * can generate
+ */
+#define IRQ_SOFTIRQ		1	/* from FB.1 */
+#define IRQ_CONRX		2	/* from FB.2 */
+#define IRQ_CONTX		3	/* from FB.3 */
+#define IRQ_TIMER0		4	/* from FB.4 */
+#define IRQ_TIMER1		5	/* from FB.5 */
+#define IRQ_TIMER2		6	/* from FB.6 */
+#define IRQ_WATCHDOG		7	/* from FB.7 */
+#define IRQ_ETHER10		8	/* from FB.8 */
+#define IRQ_ETHER100		9	/* from FB.9 */
+#define IRQ_VIDCOMP		10	/* from FB.10 */
+#define IRQ_EXTERN_IRQ		11	/* from FB.11: chain to IDE irq's */
+#define IRQ_DMA1		12	/* from future */
+#define IRQ_PCI_ERR		15	/* from FB.[28:31] */
+
+#define IRQ_TIMER4		16	/* from 553.0 */
+#define IRQ_KEYBOARD		17	/* from 553.1 */
+#define IRQ_PIC_HI		18	/* from 533.2: chained to 553.[8:15] */
+#define IRQ_UART2		19	/* from 553.3 */
+#define IRQ_UART		20	/* from 553.4 */
+#define IRQ_MOUSE		21	/* from 553.5 */
+#define IRQ_UART_IR		22	/* from 553.6 */
+#define IRQ_PRINTER		23	/* from 553.7 */
+#define IRQ_RTC_ALARM		24	/* from 553.8 */
+#define IRQ_POWERLOW		26	/* from 553.10 */
+#define IRQ_VGA			27	/* from 553.11 */
+#define IRQ_SOUND		28	/* from 553.12 */
+#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
+ */
+#define IRQ_MASK_SOFTIRQ	0x00000002
+#define IRQ_MASK_UART_DEBUG	0x0000000C
+#define IRQ_MASK_TIMER0		0x00000010
+#define IRQ_MASK_TIMER1		0x00000020
+#define IRQ_MASK_TIMER2		0x00000040
+#define IRQ_MASK_WATCHDOG	0x00000080
+#define IRQ_MASK_ETHERH10	0x00000100
+#define IRQ_MASK_ETHERH100	0x00000200
+#define IRQ_MASK_VIDCOMP	0x00000400
+#define IRQ_MASK_EXTERN_IRQ	0x00000800
+#define IRQ_MASK_DMA1		0x00030000
+#define IRQ_MASK_PCI_ERR	0xf0000000
+
+/*
+ * Now map them to the Linux interrupts
+ */
+#define IRQ_TIMER		IRQ_TIMER0
+
+#define irq_cannonicalize(i)	(i)
+
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/keyboard.h linux/include/asm-arm/arch-vnc/keyboard.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/keyboard.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/keyboard.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,37 @@
+/*
+ * linux/include/asm-arm/arch-ebsa285/keyboard.h
+ *
+ * Keyboard driver definitions for EBSA285 architecture
+ *
+ * (C) 1998 Russell King
+ */
+
+#include <linux/config.h>
+#include <asm/irq.h>
+
+#define NR_SCANCODES 128
+
+#ifdef CONFIG_MAGIC_SYSRQ
+static unsigned char kbd_sysrq_xlate[NR_SCANCODES];
+#endif
+
+#define kbd_setkeycode(sc,kc)		(-EINVAL)
+#define kbd_getkeycode(sc)		(-EINVAL)
+
+/* Prototype: int kbd_pretranslate(scancode, raw_mode)
+ * Returns  : 0 to ignore scancode
+ */
+#define kbd_pretranslate(sc,rm)		(1)
+
+/* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode)
+ * Returns  : 0 to ignore scancode, *keycode set to keycode, *up_flag
+ *            set to 0200 if scancode indicates release
+ */
+#define kbd_translate(sc, kcp, ufp, rm)	(1)
+#define kbd_unexpected_up(kc)		(0200)
+#define kbd_leds(leds)
+#define kbd_init_hw()
+//#define kbd_sysrq_xlate			ps2kbd_sysrq_xlate
+#define kbd_disable_irq()
+#define kbd_enable_irq()
+
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/mm-init.h linux/include/asm-arm/arch-vnc/mm-init.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/mm-init.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/mm-init.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,5 @@
+/*
+ * linux/include/asm-arm/arch-ebsa110/mmap.h
+ *
+ * Copyright (C) 1996,1997,1998 Russell King
+ */
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/mmu.h linux/include/asm-arm/arch-vnc/mmu.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/mmu.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/mmu.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,26 @@
+/*
+ * linux/include/asm-arm/arch-ebsa110/mmu.h
+ *
+ * Copyright (c) 1996,1997,1998 Russell King.
+ *
+ * Changelog:
+ *  20-10-1996	RMK	Created
+ *  31-12-1997	RMK	Fixed definitions to reduce warnings
+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+
+/*
+ * On ebsa, the dram is contiguous
+ */
+#define __virt_to_phys__is_a_macro
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
+#define __phys_to_virt__is_a_macro
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
+
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x)	(x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x)	(x)
+
+#endif
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/oldlatches.h linux/include/asm-arm/arch-vnc/oldlatches.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/oldlatches.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/oldlatches.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,9 @@
+/*
+ * Dummy oldlatches.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifdef __need_oldlatches
+#error "Old latches not present in this (rpc) machine"
+#endif
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/processor.h linux/include/asm-arm/arch-vnc/processor.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/processor.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/processor.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,31 @@
+/*
+ * linux/include/asm-arm/arch-vnc/processor.h
+ *
+ * Copyright (C) 1996,1997,1998 Russell King
+ */
+
+#ifndef __ASM_ARCH_PROCESSOR_H
+#define __ASM_ARCH_PROCESSOR_H
+
+/*
+ * Bus types
+ */
+#define EISA_bus 0
+#define EISA_bus__is_a_macro /* for versions in ksyms.c */
+#define MCA_bus 0
+#define MCA_bus__is_a_macro /* for versions in ksyms.c */
+
+/*
+ * User space: 3GB
+ */
+#define TASK_SIZE	(0xc0000000UL)
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
+
+#define INIT_MMAP \
+{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
+
+#endif
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/serial.h linux/include/asm-arm/arch-vnc/serial.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/serial.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/serial.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,43 @@
+/*
+ * linux/include/asm-arm/arch-vnc/serial.h
+ *
+ * Copyright (c) 1996 Russell King.
+ *
+ * Changelog:
+ *  15-10-1996	RMK	Created
+ *  03-05-1998	RMK	Modified for Corel Video NC
+ */
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+#include <asm/irq.h>
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD (1843200 / 16)
+
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+
+     /* UART CLK        PORT  IRQ     FLAGS        */
+#define SERIAL_PORT_DFNS \
+	{ 0, BASE_BAUD, 0x3F8, IRQ_UART	, STD_COM_FLAGS },	/* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x2F8, IRQ_UART2, STD_COM_FLAGS },	/* ttyS1 */	\
+	{ 0, BASE_BAUD, 0    , 0	, STD_COM_FLAGS },	/* ttyS2 */	\
+	{ 0, BASE_BAUD, 0    , 0	, STD_COM_FLAGS },	/* ttyS3 */	\
+	{ 0, BASE_BAUD, 0    , 0	, STD_COM_FLAGS }, 	/* ttyS4 */	\
+	{ 0, BASE_BAUD, 0    , 0	, STD_COM_FLAGS },	/* ttyS5 */	\
+	{ 0, BASE_BAUD, 0    , 0	, STD_COM_FLAGS },	/* ttyS6 */	\
+	{ 0, BASE_BAUD, 0    , 0	, STD_COM_FLAGS },	/* ttyS7 */	\
+	{ 0, BASE_BAUD, 0    , 0	, STD_COM_FLAGS },	/* ttyS8 */	\
+	{ 0, BASE_BAUD, 0    , 0	, STD_COM_FLAGS },	/* ttyS9 */	\
+	{ 0, BASE_BAUD, 0    , 0	, STD_COM_FLAGS },	/* ttyS10 */	\
+	{ 0, BASE_BAUD, 0    , 0	, STD_COM_FLAGS },	/* ttyS11 */	\
+	{ 0, BASE_BAUD, 0    , 0	, STD_COM_FLAGS },	/* ttyS12 */	\
+	{ 0, BASE_BAUD, 0    , 0	, STD_COM_FLAGS },	/* ttyS13 */
+
+#endif
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/shmparam.h linux/include/asm-arm/arch-vnc/shmparam.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/shmparam.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/shmparam.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,5 @@
+/*
+ * linux/include/asm-arm/arch-ebsa110/shmparam.h
+ *
+ * Copyright (c) 1996 Russell King.
+ */
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/system.h linux/include/asm-arm/arch-vnc/system.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/system.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/system.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-arm/arch-ebsa285/system.h
+ *
+ * Copyright (c) 1996,1997,1998 Russell King.
+ */
+#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)
+{
+	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
+
+#define arch_start_idle()	leds_event(led_idle_start)
+#define arch_end_idle()		leds_event(led_idle_end)
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/time.h linux/include/asm-arm/arch-vnc/time.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/time.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/time.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,40 @@
+/*
+ * linux/include/asm-arm/arch-vnc/time.h
+ *
+ * Copyright (c) 1997 Corel Computer Corp.
+ * Slight modifications to bring in line with ebsa285 port.
+ *  -- Russell King.
+ */
+
+extern __inline__ unsigned long gettimeoffset (void)
+{
+	return 0;
+}
+
+extern __inline__ int reset_timer (void)
+{
+	*CSR_TIMER1_CLR = 0;
+	return 1;
+}
+
+/*
+ * We don't have a RTC to update!
+ */
+#define update_rtc()
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+extern __inline__ unsigned long setup_timer (void)
+{
+	*CSR_TIMER1_CLR  = 1;
+	*CSR_TIMER1_LOAD = LATCH;
+	*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
+
+	/*
+	 * Default the date to 1 Jan 1970 00:00:00
+	 * You will have to run a time daemon to set the
+	 * clock correctly at bootup
+	 */
+	return mktime(1970, 1, 1, 0, 0, 0);
+}
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/timex.h linux/include/asm-arm/arch-vnc/timex.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/timex.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,13 @@
+/*
+ * linux/include/asm-arm/arch-vnc/timex.h
+ *
+ * Corel Video NC architecture timex specifications
+ *
+ * Copyright (C) 1998 Corel Computer/Russell King
+ */
+
+/*
+ * On the VNC, the clock runs at 66MHz and is divided
+ * by a 4-bit prescaler.
+ */
+#define CLOCK_TICK_RATE		(66000000 / 16)
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/arch-vnc/uncompress.h linux/include/asm-arm/arch-vnc/uncompress.h
--- v2.1.109/linux/include/asm-arm/arch-vnc/uncompress.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-vnc/uncompress.h	Sat Jul 18 11:55:25 1998
@@ -0,0 +1,33 @@
+/*
+ * linux/include/asm-arm/arch-ebsa110/uncompress.h
+ *
+ * Copyright (C) 1996,1997,1998 Russell King
+ */
+
+/*
+ * 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");
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/bitops.h linux/include/asm-arm/bitops.h
--- v2.1.109/linux/include/asm-arm/bitops.h	Tue Jun 23 10:01:26 1998
+++ linux/include/asm-arm/bitops.h	Mon Jul 20 17:23:32 1998
@@ -53,6 +53,8 @@
         return k;
 }
 
+#ifdef __KERNEL__
+
 /*
  * ffs: find first bit set. This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
@@ -70,6 +72,7 @@
 #define hweight16(x) generic_hweight16(x)
 #define hweight8(x) generic_hweight8(x)
 
+#endif /* __KERNEL__ */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/elf.h linux/include/asm-arm/elf.h
--- v2.1.109/linux/include/asm-arm/elf.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/elf.h	Sat Jul 18 11:55:25 1998
@@ -40,10 +40,9 @@
 #define ELF_ET_DYN_BASE	(2 * TASK_SIZE / 3)
 
 /* This yields a mask that user programs can use to figure out what
-   instruction set this cpu supports.  This could be done in userspace,
-   but it's not easy, and we've already done it here.  */
+   instruction set this cpu supports. */
 
-#define ELF_HWCAP	(0)
+#define ELF_HWCAP	(armidlist[armidindex].hwcap)
 
 /* This yields a string that ld.so will use to load implementation
    specific libraries for optimization.  This is more specific in
@@ -52,12 +51,14 @@
 /* For now we just provide a fairly general string that describes the
    processor family.  This could be made more specific later if someone
    implemented optimisations that require it.  26-bit CPUs give you
-   "arm2" for ARM2 (no SWP) and "arm3" for anything else (ARM1 isn't
-   supported).  32-bit CPUs give you "arm6" for anything based on an
-   ARM6 or ARM7 core and "sa1x" for anything based on a StrongARM-1
+   "v1l" for ARM2 (no SWP) and "v2l" for anything else (ARM1 isn't
+   supported).  32-bit CPUs give you "v3[lb]" for anything based on an
+   ARM6 or ARM7 core and "armv4[lb]" for anything based on a StrongARM-1
    core.  */
 
-#define ELF_PLATFORM	(armidlist[armidindex].optname)
+#define ELF_PLATFORM_SIZE 8
+extern char elf_platform[];
+#define ELF_PLATFORM	(elf_platform)
 
 #ifdef __KERNEL__
 #define SET_PERSONALITY(ex,ibcs2) \
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/fiq.h linux/include/asm-arm/fiq.h
--- v2.1.109/linux/include/asm-arm/fiq.h	Tue Jun 23 10:01:26 1998
+++ linux/include/asm-arm/fiq.h	Sat Jul 18 11:55:25 1998
@@ -14,3 +14,19 @@
 extern void release_fiq(struct fiq_handler *f);
 
 #endif
+/* Support for FIQ on ARM architectures.
+ * Written by Philip Blundell <philb@gnu.org>, 1998
+ */
+
+#ifndef __ASM_FIQ_H
+#define __ASM_FIQ_H
+
+struct fiq_handler {
+	 const char *name;
+	 int (*callback)(void);
+};
+
+extern int claim_fiq(struct fiq_handler *f);
+extern void release_fiq(struct fiq_handler *f);
+
+#endif
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/init.h linux/include/asm-arm/init.h
--- v2.1.109/linux/include/asm-arm/init.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/init.h	Sun Jul 19 20:45:45 1998
@@ -1,24 +1,29 @@
 #ifndef _ASMARM_INIT_H
 #define _ASMARM_INIT_H
 
-#if 0
+#include <linux/config.h>
+
+/* C routines */
+
+#ifdef CONFIG_BINUTILS_NEW
+
 #define __init __attribute__ ((__section__ (".text.init")))
-#define __initdata __attribute__ ((__section__ (".data.init")))
 #define __initfunc(__arginit) \
 	__arginit __init; \
 	__arginit
-/* For assembly routines */
-#define __INIT		.section	".text.init",@alloc,@execinstr
-#define __FINIT	.previous
-#define __INITDATA	.section	".data.init",@alloc,@write
+
 #else
+
 #define __init
-#define __initdata
 #define __initfunc(__arginit) __arginit
-/* For assembly routines */
-#define __INIT
-#define __FINIT
-#define __INITDATA
+
 #endif
+
+#define __initdata __attribute__ ((__section__ (".data.init")))
+
+/* Assembly routines */
+#define __INIT		.section	".text.init",@alloc,@execinstr
+#define __INITDATA	.section	".data.init",@alloc,@write
+#define __FINIT	.previous
 
 #endif
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/io.h linux/include/asm-arm/io.h
--- v2.1.109/linux/include/asm-arm/io.h	Tue Jun 23 10:01:26 1998
+++ linux/include/asm-arm/io.h	Sat Jul 18 11:55:25 1998
@@ -170,5 +170,20 @@
 #undef ARCH_IO_DELAY
 #undef ARCH_IO_CONSTANT
 
+#ifdef __KERNEL__
+
+/*
+ * String version of IO memory access ops:
+ */
+extern void _memcpy_fromio(void *, unsigned long, unsigned long);
+extern void _memcpy_toio(unsigned long, void *, unsigned long);
+extern void _memset_io(unsigned long, int, unsigned long);
+
+#define memcpy_fromio(to,from,len)	_memcpy_fromio((to),(unsigned long)(from),(len))
+#define memcpy_toio(to,from,len)	_memcpy_toio((unsigned long)(to),(from),(len))
+#define memset_io(addr,c,len)		_memset_io((unsigned long)(addr),(c),(len))
+
+#endif
+
 #endif
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/proc-armo/pgtable.h linux/include/asm-arm/proc-armo/pgtable.h
--- v2.1.109/linux/include/asm-arm/proc-armo/pgtable.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/proc-armo/pgtable.h	Sat Jul 18 11:55:25 1998
@@ -117,6 +117,7 @@
 #define PTRS_PER_PTE    32
 #define PTRS_PER_PMD    1
 #define PTRS_PER_PGD    32
+#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
 
 /* Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 8MB value just means that there will be a 8MB "hole" after the
@@ -450,7 +451,6 @@
 #define pmd_alloc_kernel        pmd_alloc
 #define pte_alloc_kernel        pte_alloc
 
-#if 0
 extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
 {
 	struct task_struct * p;
@@ -466,7 +466,6 @@
 	for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
 		pgd[address >> PGDIR_SHIFT] = entry;
 }
-#endif
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/proc-armv/mm-init.h linux/include/asm-arm/proc-armv/mm-init.h
--- v2.1.109/linux/include/asm-arm/proc-armv/mm-init.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/proc-armv/mm-init.h	Sat Jul 18 11:55:25 1998
@@ -48,12 +48,13 @@
 alloc_init_section(unsigned long *mem, unsigned long virt, unsigned long phys, int domain, int prot)
 {
 	pgd_t *pgdp;
-	pmd_t *pmdp;
+	pmd_t *pmdp, pmd;
 
 	pgdp = pgd_offset_k(virt);
 	pmdp = pmd_offset(pgdp, virt);
 
-	pmd_val(*pmdp) = phys | PMD_TYPE_SECT | PMD_DOMAIN(domain) | prot;
+	pmd_val(pmd) = phys | PMD_TYPE_SECT | PMD_DOMAIN(domain) | prot;
+	set_pmd(pmdp, pmd);
 }
 
 /*
@@ -78,7 +79,7 @@
 alloc_init_page(unsigned long *mem, unsigned long virt, unsigned long phys, int domain, int prot)
 {
 	pgd_t *pgdp;
-	pmd_t *pmdp;
+	pmd_t *pmdp, pmd;
 	pte_t *ptep;
 
 	pgdp = pgd_offset_k(virt);
@@ -92,7 +93,8 @@
 		ptep = (pte_t *)memory;
 		memzero(ptep, PTE_SIZE);
 
-		pmd_val(*pmdp) = __virt_to_phys(memory) | PMD_TYPE_TABLE | PMD_DOMAIN(domain);
+		pmd_val(pmd) = __virt_to_phys(memory) | PMD_TYPE_TABLE | PMD_DOMAIN(domain);
+		set_pmd(pmdp, pmd);
 
 		*mem = memory + PTE_SIZE;
 	}
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/proc-armv/pgtable.h linux/include/asm-arm/proc-armv/pgtable.h
--- v2.1.109/linux/include/asm-arm/proc-armv/pgtable.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/proc-armv/pgtable.h	Sat Jul 18 11:55:25 1998
@@ -133,6 +133,7 @@
 #define PTRS_PER_PTE    256
 #define PTRS_PER_PMD    1
 #define PTRS_PER_PGD    4096
+#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
 
 /* Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 8MB value just means that there will be a 8MB "hole" after the
@@ -177,23 +178,22 @@
 
 /*
  * We define the bits in the page tables as follows:
- *  PTE_BUFFERABLE	page is writable
- *  PTE_AP_WRITE	page is dirty
+ *  PTE_BUFFERABLE	page is dirty
+ *  PTE_AP_WRITE	page is writable
  *  PTE_AP_READ		page is a young (unsetting this causes faults for any access)
+ *  PTE_CACHEABLE       page is readable
  *
- * Any page that is mapped in is assumed to be readable...
+ * A page will not be made writable without the dirty bit set.
+ * It is not legal to have a writable non-dirty page though (it breaks).
+ *
+ * A readable page is marked as being cacheable.
+ * Youngness is indicated by hardware read.  If the page is old,
+ * then we will fault and make the page young again.
  */
-#if 0
 #define _PTE_YOUNG	PTE_AP_READ
-#define _PTE_DIRTY	PTE_AP_WRITE
-#define _PTE_READ	PTE_CACHEABLE
-#define _PTE_WRITE	PTE_BUFFERABLE
-#else
-#define _PTE_YOUNG	PTE_CACHEABLE
 #define _PTE_DIRTY	PTE_BUFFERABLE
-#define _PTE_READ	PTE_AP_READ
+#define _PTE_READ	PTE_CACHEABLE
 #define _PTE_WRITE	PTE_AP_WRITE
-#endif
 
 #define PAGE_NONE       __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG)
 #define PAGE_SHARED     __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG | _PTE_READ | _PTE_WRITE)
@@ -350,7 +350,7 @@
 
 extern __inline__ int pte_write(pte_t pte)
 {
-	return pte_val(pte) & PTE_AP_WRITE;
+	return pte_val(pte) & _PTE_WRITE;
 }
 
 extern __inline__ int pte_dirty(pte_t pte)
@@ -365,7 +365,7 @@
 
 extern __inline__ pte_t pte_wrprotect(pte_t pte)
 {
-	pte_val(pte) &= ~PTE_AP_WRITE;
+	pte_val(pte) &= ~_PTE_WRITE;
 	return pte;
 }
 
@@ -377,31 +377,31 @@
 
 extern __inline__ pte_t pte_mkclean(pte_t pte)
 {
-	pte_val(pte) &= ~PTE_BUFFERABLE;
+	pte_val(pte) &= ~_PTE_DIRTY;
 	return pte;
 }
 
 extern __inline__ pte_t pte_mkold(pte_t pte)
 {
-	pte_val(pte) &= ~PTE_AP_READ;
+	pte_val(pte) &= ~_PTE_YOUNG;
 	return pte;
 }
 
 extern __inline__ pte_t pte_mkwrite(pte_t pte)
 {
-	pte_val(pte) |= PTE_AP_WRITE;
+	pte_val(pte) |= _PTE_WRITE;
 	return pte;
 }
 
 extern __inline__ pte_t pte_mkdirty(pte_t pte)
 {
-	pte_val(pte) |= PTE_BUFFERABLE;
+	pte_val(pte) |= _PTE_DIRTY;
 	return pte;
 }
 
 extern __inline__ pte_t pte_mkyoung(pte_t pte)
 {
-	pte_val(pte) |= PTE_AP_READ;
+	pte_val(pte) |= _PTE_YOUNG;
 	return pte;
 }
 
@@ -670,7 +670,6 @@
 #define pmd_free_kernel		pmd_free
 #define pmd_alloc_kernel	pmd_alloc
 
-#if 0
 extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
 {
 	struct task_struct * p;
@@ -686,7 +685,6 @@
 	for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
 		pgd[address >> PGDIR_SHIFT] = entry;
 }
-#endif
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/procinfo.h linux/include/asm-arm/procinfo.h
--- v2.1.109/linux/include/asm-arm/procinfo.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/procinfo.h	Sat Jul 18 11:55:25 1998
@@ -9,25 +9,23 @@
 
 #include <asm/proc-fns.h>
 
-#define F_MEMC   (1<<0)
-#define F_MMU    (1<<1)
-#define F_32BIT  (1<<2)
-#define F_CACHE  (1<<3)
-#define F_IOEB   (1<<31)
-
 #ifndef __ASSEMBLER__
 
+#define HWCAP_SWP	(1 << 0)
+#define HWCAP_HALF	(1 << 1)
+
 struct armversions {
-	unsigned long id;		/* Processor ID			*/
-	unsigned long mask;		/* Processor ID mask		*/
-	unsigned long features;		/* Features (see above)		*/
+	const unsigned long id;		/* Processor ID			*/
+	const unsigned long mask;	/* Processor ID mask		*/
 	const char *manu;		/* Manufacturer			*/
 	const char *name;		/* Processor name		*/
+	const char *arch_vsn;		/* Architecture version		*/
+	const char *elf_vsn;		/* ELF library version		*/
+	const int hwcap;		/* ELF HWCAP			*/
 	const struct processor *proc;	/* Processor-specific ASM	*/
-	const char *optname;		/* Optimisation name		*/
 };
 
-extern struct armversions armidlist[];
+extern const struct armversions armidlist[];
 extern int armidindex;
 
 #endif
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/signal.h linux/include/asm-arm/signal.h
--- v2.1.109/linux/include/asm-arm/signal.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/signal.h	Sat Jul 18 11:55:25 1998
@@ -6,6 +6,7 @@
 /* Avoid too many header ordering problems.  */
 struct siginfo;
 
+#ifdef __KERNEL__
 /* Most things should be clean enough to redefine this at will, if care
    is taken to make libc match.  */
 
@@ -19,6 +20,14 @@
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
+#else
+/* Here we must cater to lics that poke about in kernel headers.  */
+
+#define NSIG		32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
 #define SIGHUP		 1
 #define SIGINT		 2
 #define SIGQUIT		 3
@@ -87,6 +96,15 @@
 #define SA_INTERRUPT	0x20000000 /* dummy -- ignored */
 
 #define SA_RESTORER	0x04000000
+
+/* 
+ * sigaltstack controls
+ */
+#define SS_ONSTACK	1
+#define SS_DISABLE	2
+
+#define MINSIGSTKSZ	2048
+#define SIGSTKSZ	8192
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/spinlock.h linux/include/asm-arm/spinlock.h
--- v2.1.109/linux/include/asm-arm/spinlock.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/spinlock.h	Sat Jul 18 11:55:25 1998
@@ -18,7 +18,7 @@
 #define spin_unlock_irq(lock)	sti()
 
 #define spin_lock_irqsave(lock, flags) \
-	do { save_flags(flags); cli(); } while (0)
+	do { __save_flags_cli(flags); } while (0)
 #define spin_unlock_irqrestore(lock, flags) \
 	restore_flags(flags)
 
@@ -45,11 +45,11 @@
 #define write_unlock_irq(lock)	sti()
 
 #define read_lock_irqsave(lock, flags)	\
-	do { save_flags(flags); cli(); } while (0)
+	do { __save_flags_cli(flags); } while (0)
 #define read_unlock_irqrestore(lock, flags) \
 	restore_flags(flags)
 #define write_lock_irqsave(lock, flags)	\
-	do { save_flags(flags); cli(); } while (0)
+	do { __save_flags_cli(flags); } while (0)
 #define write_unlock_irqrestore(lock, flags) \
 	restore_flags(flags)
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-arm/system.h linux/include/asm-arm/system.h
--- v2.1.109/linux/include/asm-arm/system.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/system.h	Sat Jul 18 11:55:25 1998
@@ -29,5 +29,7 @@
 #define mb() __asm__ __volatile__ ("" : : : "memory")
 #define nop() __asm__ __volatile__("mov r0,r0\n\t");
 
+extern asmlinkage void __backtrace(void);
+
 #endif
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-generic/bitops.h linux/include/asm-generic/bitops.h
--- v2.1.109/linux/include/asm-generic/bitops.h	Tue Jun 23 10:01:26 1998
+++ linux/include/asm-generic/bitops.h	Mon Jul 20 17:23:32 1998
@@ -51,6 +51,8 @@
 	return ((mask & *addr) != 0);
 }
 
+#ifdef __KERNEL__
+
 /*
  * ffs: find first bit set. This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
@@ -67,5 +69,7 @@
 #define hweight32(x) generic_hweight32(x)
 #define hweight16(x) generic_hweight16(x)
 #define hweight8(x) generic_hweight8(x)
+
+#endif /* __KERNEL__ */
 
 #endif /* _ASM_GENERIC_BITOPS_H */
diff -u --recursive --new-file v2.1.109/linux/include/asm-i386/bitops.h linux/include/asm-i386/bitops.h
--- v2.1.109/linux/include/asm-i386/bitops.h	Tue Jun 23 10:01:26 1998
+++ linux/include/asm-i386/bitops.h	Mon Jul 20 17:23:32 1998
@@ -187,6 +187,8 @@
 	return word;
 }
 
+#ifdef __KERNEL__
+
 /*
  * ffs: find first bit set. This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
@@ -213,6 +215,7 @@
 #define hweight16(x) generic_hweight16(x)
 #define hweight8(x) generic_hweight8(x)
 
+#endif /* __KERNEL__ */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h
--- v2.1.109/linux/include/asm-i386/bugs.h	Thu Jul 16 18:09:28 1998
+++ linux/include/asm-i386/bugs.h	Mon Jul 20 17:32:00 1998
@@ -232,22 +232,24 @@
 }
 
 /*
- * perform the Cyrix 5/2 test (!0 means it's a Cyrix)
+ * Perform the Cyrix 5/2 test. A Cyrix won't change
+ * the flags, while other 486 chips will.
  */
 
 static inline int test_cyrix_52div(void)
 {
-	int test;
+	unsigned int test;
 
-	__asm__ __volatile__("xor %%eax,%%eax\n\t"
-	     "sahf\n\t"
-	     "movb $5,%%al\n\t"
-	     "movb $2,%%bl\n\t"
-	     "div %%bl\n\t"
-	     "lahf\n\t"
-	     "andl $0x200,%%eax": "=a" (test) : : "bx", "cc");
+	__asm__ __volatile__(
+	     "sahf\n\t"		/* clear flags (%eax = 0x0005) */
+	     "div %b2\n\t"	/* divide 5 by 2 */
+	     "lahf"		/* store flags into %ah */
+	     : "=a" (test)
+	     : "0" (5), "q" (2)
+	     : "cc");
 
-	return test;
+	/* AH is 0x02 on Cyrix after the divide.. */
+	return (unsigned char) (test >> 8) == 0x02;
 }
 
 /*
@@ -258,10 +260,10 @@
 
 __initfunc(static void check_cyrix_cpu(void))
 {
-	if (boot_cpu_data.cpuid_level == -1 && boot_cpu_data.x86 == 4
+	if ((boot_cpu_data.cpuid_level == -1) && (boot_cpu_data.x86 == 4)
 	    && test_cyrix_52div()) {
 
-		/* default to an unknown Cx486, (we will diferentiate later) */
+		/* default to an unknown Cx486, (we will differentiate later) */
 		/* NOTE:  using 0xff since 0x00 is a valid DIR0 value */
 		strcpy(boot_cpu_data.x86_vendor_id, "CyrixInstead");
 		boot_cpu_data.x86_model = 0xff;
@@ -270,7 +272,7 @@
 }
 
 /*
- * Fix two problems with the Cyrix 686 and 686L:
+ * Fix two problems with the Cyrix 6x86 and 6x86L:
  *   -- the cpuid is disabled on power up, enable it, use it.
  *   -- the SLOP bit needs resetting on some motherboards due to old BIOS,
  *      so that the udelay loop calibration works well.  Recalibrate.
@@ -281,7 +283,7 @@
 __initfunc(static void check_cx686_cpuid_slop(void))
 {
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX &&
-	    (boot_cpu_data.x86_model & 0xf0) == 0x30) {  /* 686(L) */
+	    (boot_cpu_data.x86_model & 0xf0) == 0x30) {  /* 6x86(L) */
 		int dummy;
 		unsigned char ccr3, ccr5;
 
@@ -331,10 +333,7 @@
 	check_amd_k6();
 	check_pentium_f00f();
 	system_utsname.machine[1] = '0' + boot_cpu_data.x86;
-#if !defined(__SMP__) && defined(CONFIG_MTRR)
-	/*  Must be done after other processors booted: at this point we are
-	    called before SMP initialisation, so this is for the non-SMP case
-	    only. The SMP case is handled in arch/i386/kernel/smp.c  */
+#if defined(CONFIG_MTRR)
 	mtrr_init ();
 #endif
 }
diff -u --recursive --new-file v2.1.109/linux/include/asm-i386/fixmap.h linux/include/asm-i386/fixmap.h
--- v2.1.109/linux/include/asm-i386/fixmap.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/fixmap.h	Mon Jul 20 14:00:06 1998
@@ -0,0 +1,76 @@
+/*
+ * fixmap.h: compile-time virtual memory allocation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998 Ingo Molnar
+ */
+
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+#include <asm/page.h>
+#include <linux/kernel.h>
+
+/*
+ * Here we define all the compile-time 'special' virtual
+ * addresses. The point is to have a constant address at
+ * compile time, but to set the physical address only
+ * in the boot process. We allocate these special  addresses
+ * from the end of virtual memory (0xfffff000) backwards.
+ * Also this lets us do fail-safe vmalloc(), we
+ * can guarantee that these special addresses and
+ * vmalloc()-ed addresses never overlap.
+ *
+ * these 'compile-time allocated' memory buffers are
+ * fixed-size 4k pages. (or larger if used with an increment
+ * bigger than 1) use fixmap_set(idx,phys) to associate
+ * physical memory with fixmap indices.
+ *
+ * TLB entries of such buffers will not be flushed across
+ * task switches.
+ */
+
+enum fixed_addresses {
+/*
+ * on UP currently we will have no trace of the fixmap mechanizm,
+ * no page table allocations, etc. This might change in the
+ * future, say framebuffers for the console driver(s) could be
+ * fix-mapped?
+ */
+#if __SMP__
+	FIX_APIC_BASE 			= 1,	/* 0xfffff000 */
+	FIX_IO_APIC_BASE 		= 2,	/* 0xffffe000 */
+#endif
+	__end_of_fixed_addresses
+};
+
+extern void set_fixmap (enum fixed_addresses idx, unsigned long phys);
+
+/*
+ * used by vmalloc.c:
+ */
+#define FIXADDR_START (0UL-((__end_of_fixed_addresses-1)<<PAGE_SHIFT))
+
+/*
+ * 'index to address' translation. If anyone tries to use the idx
+ * directly without tranlation, we catch the bug with a NULL-deference
+ * kernel oops. Illegal ranges of incoming indices are caught too.
+ */
+extern inline unsigned long fix_to_virt(const unsigned int idx)
+{
+	/*
+	 * this branch gets completely eliminated after inlining,
+	 * except when someone tries to use fixaddr indices in an
+	 * illegal way. (such as mixing up address types or using
+	 * out-of-range indices)
+	 */
+	if ((!idx) || (idx >= __end_of_fixed_addresses))
+		panic("illegal fixaddr index!");
+
+        return (0UL-(unsigned long)(idx<<PAGE_SHIFT));
+}
+
+#endif
diff -u --recursive --new-file v2.1.109/linux/include/asm-i386/irq.h linux/include/asm-i386/irq.h
--- v2.1.109/linux/include/asm-i386/irq.h	Sun Jun  7 11:16:36 1998
+++ linux/include/asm-i386/irq.h	Thu Jul 16 18:11:35 1998
@@ -17,7 +17,7 @@
  * Right now the APIC is only used for SMP, but this
  * may change.
  */
-#define NR_IRQS 24
+#define NR_IRQS 64
 
 static __inline__ int irq_cannonicalize(int irq)
 {
diff -u --recursive --new-file v2.1.109/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v2.1.109/linux/include/asm-i386/pgtable.h	Thu Jul 16 18:09:28 1998
+++ linux/include/asm-i386/pgtable.h	Mon Jul 20 17:32:00 1998
@@ -14,6 +14,7 @@
  */
 #ifndef __ASSEMBLY__
 #include <asm/processor.h>
+#include <asm/fixmap.h>
 #include <linux/tasks.h>
 
 /* Caches aren't brain-dead on the intel. */
@@ -206,6 +207,7 @@
 #define VMALLOC_OFFSET	(8*1024*1024)
 #define VMALLOC_START	(((unsigned long) high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END	(FIXADDR_START)
 
 /*
  * The 4MB page is guessing..  Detailed in the infamous "Chapter H"
diff -u --recursive --new-file v2.1.109/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v2.1.109/linux/include/asm-i386/processor.h	Thu Jul 16 18:09:29 1998
+++ linux/include/asm-i386/processor.h	Mon Jul 20 16:57:56 1998
@@ -234,6 +234,8 @@
 	unsigned long	tr;
 	unsigned long	cr2, trap_no, error_code;
 	mm_segment_t	segment;
+/* debug registers */
+	long debugreg[8];  /* Hardware debugging registers */
 /* floating point info */
 	union i387_union i387;
 /* virtual 86 mode info */
@@ -260,6 +262,7 @@
 	0, 0x8000, /* tace, bitmap */				\
 	{~0, }, /* ioperm */					\
 	_TSS(0), 0, 0, 0, (mm_segment_t) { 0 }, /* obsolete */	\
+	{ 0, },							\
 	{ { 0, }, },  /* 387 state */				\
 	NULL, 0, 0, 0, 0, 0, /* vm86_info */			\
 }
diff -u --recursive --new-file v2.1.109/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h
--- v2.1.109/linux/include/asm-i386/smp.h	Wed Jun 24 22:54:10 1998
+++ linux/include/asm-i386/smp.h	Mon Jul 20 17:32:00 1998
@@ -6,6 +6,7 @@
 
 #include <asm/i82489.h>
 #include <asm/bitops.h>
+#include <asm/fixmap.h>
 #include <linux/tasks.h>
 #include <linux/ptrace.h>
 
@@ -196,7 +197,7 @@
  *	"Back to Back Assertions of HOLD May Cause Lost APIC Write Cycle"
  */
 
-#define APIC_BASE ((char *)0xFEE00000)
+#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 
 extern __inline void apic_write(unsigned long reg, unsigned long v)
 {
diff -u --recursive --new-file v2.1.109/linux/include/asm-m68k/bitops.h linux/include/asm-m68k/bitops.h
--- v2.1.109/linux/include/asm-m68k/bitops.h	Tue Jun 23 10:01:28 1998
+++ linux/include/asm-m68k/bitops.h	Mon Jul 20 17:23:32 1998
@@ -210,6 +210,8 @@
 	return res ^ 31;
 }
 
+#ifdef __KERNEL__
+
 /*
  * ffs: find first bit set. This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
@@ -226,6 +228,8 @@
 #define hweight32(x) generic_hweight32(x)
 #define hweight16(x) generic_hweight16(x)
 #define hweight8(x) generic_hweight8(x)
+
+#endif /* __KERNEL__ */
 
 /* Bitmap functions for the minix filesystem */
 
diff -u --recursive --new-file v2.1.109/linux/include/asm-mips/bitops.h linux/include/asm-mips/bitops.h
--- v2.1.109/linux/include/asm-mips/bitops.h	Tue Jun 23 10:01:28 1998
+++ linux/include/asm-mips/bitops.h	Mon Jul 20 17:23:32 1998
@@ -372,6 +372,8 @@
 	return __res;
 }
 
+#ifdef __KERNEL__
+
 /*
  * ffs: find first bit set. This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
@@ -388,6 +390,8 @@
 #define hweight32(x) generic_hweight32(x)
 #define hweight16(x) generic_hweight16(x)
 #define hweight8(x) generic_hweight8(x)
+
+#endif /* __KERNEL__ */
 
 #ifdef __MIPSEB__
 /* For now I steal the Sparc C versions, no need for speed, just need to
diff -u --recursive --new-file v2.1.109/linux/include/asm-ppc/bitops.h linux/include/asm-ppc/bitops.h
--- v2.1.109/linux/include/asm-ppc/bitops.h	Tue Jun 23 10:01:29 1998
+++ linux/include/asm-ppc/bitops.h	Mon Jul 20 17:23:32 1998
@@ -96,6 +96,8 @@
 	return 31 - n;
 }
 
+#ifdef __KERNEL__
+
 /*
  * ffs: find first bit set. This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
@@ -123,6 +125,8 @@
 #define hweight32(x) generic_hweight32(x)
 #define hweight16(x) generic_hweight16(x)
 #define hweight8(x) generic_hweight8(x)
+
+#endif /* __KERNEL__ */
 
 /*
  * This implementation of find_{first,next}_zero_bit was stolen from
diff -u --recursive --new-file v2.1.109/linux/include/asm-sparc/bitops.h linux/include/asm-sparc/bitops.h
--- v2.1.109/linux/include/asm-sparc/bitops.h	Tue Jun 23 10:01:29 1998
+++ linux/include/asm-sparc/bitops.h	Mon Jul 20 17:23:32 1998
@@ -182,6 +182,8 @@
 	return result;
 }
 
+#ifdef __KERNEL__
+
 /*
  * ffs: find first bit set. This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
@@ -199,6 +201,7 @@
 #define hweight16(x) generic_hweight16(x)
 #define hweight8(x) generic_hweight8(x)
 
+#endif /* __KERNEL__ */
 
 /* find_next_zero_bit() finds the first zero bit in a bit string of length
  * 'size' bits, starting the search at bit 'offset'. This is largely based
diff -u --recursive --new-file v2.1.109/linux/include/asm-sparc64/bitops.h linux/include/asm-sparc64/bitops.h
--- v2.1.109/linux/include/asm-sparc64/bitops.h	Tue Jun 23 10:01:29 1998
+++ linux/include/asm-sparc64/bitops.h	Mon Jul 20 17:23:32 1998
@@ -186,6 +186,8 @@
 	return result;
 }
 
+#ifdef __KERNEL__
+
 /*
  * ffs: find first bit set. This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
@@ -232,6 +234,7 @@
 #define hweight8(x) generic_hweight8(x)
 
 #endif
+#endif /* __KERNEL__ */
 
 /* find_next_zero_bit() finds the first zero bit in a bit string of length
  * 'size' bits, starting the search at bit 'offset'. This is largely based
diff -u --recursive --new-file v2.1.109/linux/include/linux/atalk.h linux/include/linux/atalk.h
--- v2.1.109/linux/include/linux/atalk.h	Wed Jun 24 22:54:11 1998
+++ linux/include/linux/atalk.h	Mon Jul 20 17:32:55 1998
@@ -54,7 +54,7 @@
 {
 	struct device *dev;
 	struct at_addr address;		/* Our address */
-	int status;			/* What are we doing ?? */
+	int status;			/* What are we doing? */
 #define ATIF_PROBE	1		/* Probing for an address */
 #define ATIF_PROBE_FAIL	2		/* Probe collided */
 	struct netrange nets;		/* Associated direct netrange */
@@ -90,6 +90,20 @@
 	__u8	deh_dport;
 	__u8	deh_sport;
 	/* And netatalk apps expect to stick the type in themselves */
+};
+
+/*
+ *	Don't drop the struct into the struct above.  You'll get some
+ *	surprise padding.
+ */
+ 
+struct ddpebits
+{
+#ifdef __LITTLE_ENDIAN_BITFIELD
+	__u16	deh_len:10, deh_hops:4, deh_pad:2;
+#else
+	__u16	deh_pad:2, deh_hops:4, deh_len:10;
+#endif
 };
 
 /*
diff -u --recursive --new-file v2.1.109/linux/include/linux/console.h linux/include/linux/console.h
--- v2.1.109/linux/include/linux/console.h	Thu Jul 16 18:09:29 1998
+++ linux/include/linux/console.h	Sat Jul 18 13:55:47 1998
@@ -35,7 +35,7 @@
 	int	(*con_scroll)(struct vc_data *, int, int, int, int);
 	void	(*con_bmove)(struct vc_data *, int, int, int, int, int, int);
 	int	(*con_switch)(struct vc_data *);
-	int	(*con_blank)(int);
+	int	(*con_blank)(struct vc_data *, int);
 	int	(*con_get_font)(struct vc_data *, int *, int *, char *);
 	int	(*con_set_font)(struct vc_data *, int, int, char *);
 	int	(*con_set_palette)(struct vc_data *, unsigned char *);
@@ -51,6 +51,8 @@
 extern struct consw vga_con;	/* VGA text console */
 extern struct consw compat_con;	/* console wrapper */
 extern struct consw prom_con;	/* SPARC PROM console */
+
+void take_over_console(struct consw *sw, int first, int last, int deflt);
 
 /* flag bits */
 #define CON_INITED  (1)
diff -u --recursive --new-file v2.1.109/linux/include/linux/console_compat.h linux/include/linux/console_compat.h
--- v2.1.109/linux/include/linux/console_compat.h	Thu Jul 16 18:09:29 1998
+++ linux/include/linux/console_compat.h	Wed Dec 31 16:00:00 1969
@@ -1,165 +0,0 @@
-/*
- *  linux/include/linux/console_compat.h -- Abstract console wrapper
- *
- *	Copyright (C) 1998 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#include <linux/config.h>
-
-#ifndef _LINUX_CONSOLE_COMPAT_H_
-#define _LINUX_CONSOLE_COMPAT_H_
-
-#undef video_num_columns
-#undef video_num_lines
-#undef video_size_row
-#undef video_type
-#undef video_mem_base
-#undef video_mem_term
-#undef video_screen_size
-#undef can_do_color
-#undef scr_writew
-#undef scr_readw
-#undef scr_memsetw
-#undef scr_memcpyw
-#undef set_cursor
-#undef hide_cursor
-#undef set_get_cmap
-#undef set_palette
-#undef set_get_font
-#undef set_vesa_blanking
-#undef vesa_blank
-#undef vesa_powerdown
-#undef con_adjust_height
-#undef con_type_init
-#undef con_type_init_finish
-
-#define video_num_columns	compat_video_num_columns
-#define video_num_lines		compat_video_num_lines
-#define video_size_row		compat_video_size_row
-#define video_type		compat_video_type
-#define video_mem_base		compat_video_mem_base
-#define video_mem_term		compat_video_mem_term
-#define video_screen_size	compat_video_screen_size
-#define can_do_color		compat_can_do_color
-#define scr_writew		compat_scr_writew
-#define scr_readw		compat_scr_readw
-#define scr_memsetw		compat_memsetw
-#define scr_memcpyw		compat_memcpyw
-#define set_cursor		compat_set_cursor
-#define hide_cursor		compat_hide_cursor
-#define set_get_cmap		compat_set_get_cmap
-#define set_palette		compat_set_palette
-#define set_get_font		compat_set_get_font
-#define set_vesa_blanking	compat_set_vesa_blanking
-#define vesa_blank		compat_vesa_blank
-#define vesa_powerdown		compat_vesa_powerdown
-#define con_adjust_height	compat_con_adjust_height
-#define con_type_init		compat_con_type_init
-#define con_type_init_finish	compat_con_type_init_finish
-
-extern unsigned long compat_video_num_columns; 
-extern unsigned long compat_video_num_lines;
-extern unsigned long compat_video_size_row;    
-extern unsigned char compat_video_type;
-extern unsigned long compat_video_mem_base;
-extern unsigned long compat_video_mem_term;
-extern unsigned long compat_video_screen_size;
-extern int compat_can_do_color;
-extern void compat_set_cursor(int currcons);
-extern void compat_hide_cursor(void);
-extern int compat_set_get_cmap(unsigned char *arg, int set);
-extern void compat_set_palette(void);
-extern int compat_set_get_font(unsigned char * arg, int set, int ch512);
-extern void compat_set_vesa_blanking(unsigned long arg);
-extern void compat_vesa_blank(void);
-extern void compat_vesa_powerdown(void);
-extern int compat_con_adjust_height(unsigned long fontheight);
-extern void compat_con_type_init(const char **);
-extern void compat_con_type_init_finish(void);
-
-#if defined(CONFIG_SUN_CONSOLE)
-	void (*memsetw)(void *, unsigned short, unsigned int);
-	void (*memcpyw)(unsigned short *, unsigned short *, unsigned int);
-	void (*scr_writew)(unsigned short, unsigned short *);
-	unsigned short (*scr_readw)(unsigned short *);
-	void (*get_scrmem)(int);
-	void (*set_scrmem)(int, long);
-	void (*set_origin)(unsigned short);
-	void (*hide_cursor)(void);
-	void (*set_cursor)(int);
-	int (*set_get_font)(char *, int, int);
-	int (*con_adjust_height)(unsigned long);
-	int (*set_get_cmap)(unsigned char *, int);
-	void (*set_palette)(void);
-	void (*set_other_palette)(int);
-	void (*console_restore_palette)(void);
-	void (*con_type_init)(const char **);
-	void (*con_type_init_finish)(void);
-
-	/* VESA powerdown methods */
-	void (*vesa_blank)(void);
-	void (*vesa_unblank)(void);
-	void (*set_vesa_blanking)(const unsigned long);
-	void (*vesa_powerdown)(void);
-
-	void (*clear_screen)(void);
-	void (*render_screen)(void);
-	void (*clear_margin)(void);
-};
-
-#define compat_memsetw(s,c,count)	suncons_ops.memsetw((s),(c),(count))
-#define compat_memcpyw(to,from,count)	suncons_ops.memcpyw((to),(from),(count))
-#define compat_scr_writew(val,addr)	suncons_ops.scr_writew((val),(addr))
-#define compat_scr_readw(addr)		suncons_ops.scr_readw((addr))
-
-#elif defined(CONFIG_PMAC_CONSOLE)
-extern void pmac_blitc(unsigned, unsigned long);
-extern void compat_memsetw(unsigned short *p, unsigned short c, unsigned count);
-extern void compat_memcpyw(unsigned short *to, unsigned short *from, unsigned count);
-
-static inline void compat_scr_writew(unsigned short val, unsigned short * addr)
-{
-	if ((unsigned long)addr < video_mem_term &&
-	    (unsigned long)addr >= video_mem_base) {
-		if (*addr != val) {
-			*addr = val;
-			pmac_blitc(val, (unsigned long) addr);
-		}
-	} else
-		*addr = val;
-}
-
-static inline unsigned short compat_scr_readw(unsigned short * addr)
-{
-	return *addr;
-}
-#endif
-
-#if !defined(CONFIG_SUN_CONSOLE) && !defined(CONFIG_PMAC_CONSOLE)
-static inline void compat_memsetw(void * s, unsigned short c, unsigned int count)
-{
-	unsigned short * addr = (unsigned short *) s;
-
-	count /= 2;
-	while (count) {
-		count--;
-		scr_writew(c, addr++);
-	}
-}
-
-static inline void compat_memcpyw(unsigned short *to, unsigned short *from,
-				  unsigned int count)
-{
-	count /= 2;
-	while (count) {
-		count--;
-		scr_writew(scr_readw(from++), to++);
-	}
-}
-#endif
-
-#endif /* _LINUX_CONSOLE_COMPAT_H_ */
diff -u --recursive --new-file v2.1.109/linux/include/linux/console_struct.h linux/include/linux/console_struct.h
--- v2.1.109/linux/include/linux/console_struct.h	Thu Jul 16 18:09:29 1998
+++ linux/include/linux/console_struct.h	Sun Jul 19 20:45:45 1998
@@ -77,6 +77,7 @@
 	unsigned int	vc_bell_pitch;		/* Console bell pitch */
 	unsigned int	vc_bell_duration;	/* Console bell duration */
 	unsigned int	vc_cursor_type;
+	struct vc_data **vc_display_fg;		/* Ptr to var holding fg console for this display */
 	/* additional information is in vt_kern.h */
 };
 
diff -u --recursive --new-file v2.1.109/linux/include/linux/fb.h linux/include/linux/fb.h
--- v2.1.109/linux/include/linux/fb.h	Thu Jul 16 18:09:29 1998
+++ linux/include/linux/fb.h	Sat Jul 18 13:55:47 1998
@@ -257,20 +257,22 @@
    struct vc_data *conp;            /* pointer to console data */
    struct fb_info *fb_info;         /* frame buffer for this console */
    int vrows;                       /* number of virtual rows */
-   int cursor_x;                    /* current cursor position */
-   int cursor_y;
+   unsigned short cursor_x;	    /* current cursor position */
+   unsigned short cursor_y;
    int fgcol;                       /* text colors */
    int bgcol;
    u_long next_line;                /* offset to one line below */
    u_long next_plane;               /* offset to next plane */
    u_char *fontdata;                /* Font associated to this display */
-   int fontheight;
-   int fontwidth;
+   unsigned short fontheightlog;
+   unsigned short fontwidthlog;
+   unsigned short fontheight;
+   unsigned short fontwidth;
    int userfont;                    /* != 0 if fontdata kmalloc()ed */
    struct display_switch *dispsw;   /* low level operations */
    u_short scrollmode;              /* Scroll Method */
    short yscroll;                   /* Hardware scrolling */
-}; 
+};
 
 
 struct fb_info {
@@ -279,6 +281,7 @@
    struct fb_ops *fbops;
    struct fb_monspecs monspecs;
    struct display *disp;		/* initial display variable */
+   struct vc_data *display_fg;		/* Console visible on this display */
    char fontname[40];			/* default font name */
    int (*changevar)(int);		/* tell console var has changed */
    int (*switch_con)(int, struct fb_info*);
diff -u --recursive --new-file v2.1.109/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.1.109/linux/include/linux/fs.h	Thu May 14 19:47:43 1998
+++ linux/include/linux/fs.h	Mon Jul 20 17:32:00 1998
@@ -633,6 +633,7 @@
 	int (*statfs) (struct super_block *, struct statfs *, int);
 	int (*remount_fs) (struct super_block *, int *, char *);
 	void (*clear_inode) (struct inode *);
+	void (*umount_begin) (struct super_block *);
 };
 
 struct dquot_operations {
diff -u --recursive --new-file v2.1.109/linux/include/linux/loop.h linux/include/linux/loop.h
--- v2.1.109/linux/include/linux/loop.h	Wed Jun 24 22:54:11 1998
+++ linux/include/linux/loop.h	Mon Jul 20 17:22:35 1998
@@ -36,6 +36,7 @@
         idea_key        lo_idea_en_key;
         idea_key        lo_idea_de_key;
 #endif
+	struct file *	lo_backing_file;
 };
 
 typedef	int (* transfer_proc_t)(struct loop_device *, int cmd,
diff -u --recursive --new-file v2.1.109/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.1.109/linux/include/linux/mm.h	Thu Jul 16 18:09:29 1998
+++ linux/include/linux/mm.h	Mon Jul 20 17:32:01 1998
@@ -298,6 +298,7 @@
 extern int do_munmap(unsigned long, size_t);
 
 /* filemap.c */
+extern void remove_inode_page(struct page *);
 extern unsigned long page_unuse(struct page *);
 extern int shrink_mmap(int, int);
 extern void truncate_inode_pages(struct inode *, unsigned long);
diff -u --recursive --new-file v2.1.109/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v2.1.109/linux/include/linux/netdevice.h	Wed Jun 24 22:54:11 1998
+++ linux/include/linux/netdevice.h	Mon Jul 20 17:32:55 1998
@@ -189,10 +189,15 @@
 	unsigned int		irq;		/* device IRQ number	*/
 	
 	/* Low-level status flags. */
-	volatile unsigned char	start,		/* start an operation	*/
-				interrupt;	/* interrupt arrived	*/
-	unsigned long		tbusy;		/* transmitter busy must be
-						   long for bitops	*/
+	volatile unsigned char	start;		/* start an operation	*/
+	/*
+	 * These two are just single-bit flags, but due to atomicity
+	 * reasons they have to be inside a "unsigned long". However,
+	 * they should be inside the SAME unsigned long instead of
+	 * this wasteful use of memory..
+	 */
+	unsigned long		interrupt;	/* bitops.. */
+	unsigned long		tbusy;		/* transmitter busy */
 	
 	struct device		*next;
 	
diff -u --recursive --new-file v2.1.109/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.1.109/linux/include/linux/parport.h	Tue Jun 23 10:01:29 1998
+++ linux/include/linux/parport.h	Sun Jul 19 20:42:56 1998
@@ -127,14 +127,16 @@
 
 	void (*inc_use_count)(void);
 	void (*dec_use_count)(void);
+	void (*fill_inode)(struct inode *inode, int fill);
 };
 
 struct parport_device_info {
 	parport_device_class class;
-	char *mfr;
-	char *model;
-	char *cmdset;
-	char *description;
+	const char *class_name;
+	const char *mfr;
+	const char *model;
+	const char *cmdset;
+	const char *description;
 };
 
 /* Each device can have two callback functions:
@@ -151,7 +153,7 @@
 
 /* A parallel port device */
 struct pardevice {
-	char *name;
+	const char *name;
 	struct parport *port;
 	int (*preempt)(void *);
 	void (*wakeup)(void *);
@@ -183,7 +185,7 @@
 struct parport {
 	unsigned long base;	/* base address */
 	unsigned int size;	/* IO extent */
-	char *name;
+	const char *name;
 	int irq;		/* interrupt (or -1 for none) */
 	int dma;
 	unsigned int modes;
diff -u --recursive --new-file v2.1.109/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.1.109/linux/include/linux/pci.h	Thu Jul 16 18:09:29 1998
+++ linux/include/linux/pci.h	Mon Jul 20 17:32:00 1998
@@ -1,5 +1,5 @@
 /*
- *	$Id: pci.h,v 1.72 1998/05/12 07:35:54 mj Exp $
+ *	$Id: pci.h,v 1.76 1998/07/15 20:34:50 mj Exp $
  *
  *	PCI defines and function prototypes
  *	Copyright 1994, Drew Eckhardt
@@ -76,7 +76,7 @@
  * 1 bits are decoded.
  */
 #define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
-#define PCI_BASE_ADDRESS_1	0x14	/* 32 bits */
+#define PCI_BASE_ADDRESS_1	0x14	/* 32 bits [htype 0,1 only] */
 #define PCI_BASE_ADDRESS_2	0x18	/* 32 bits [htype 0 only] */
 #define PCI_BASE_ADDRESS_3	0x1c	/* 32 bits */
 #define PCI_BASE_ADDRESS_4	0x20	/* 32 bits */
@@ -145,17 +145,13 @@
 #define  PCI_BRIDGE_CTL_BUS_RESET 0x40	/* Secondary bus reset */
 #define  PCI_BRIDGE_CTL_FAST_BACK 0x80	/* Fast Back2Back enabled on secondary interface */
 
-/* Header type 2 (CardBus bridges) -- detailed info welcome */
-#define PCI_CB_CARDBUS_BASE	0x10	/* CardBus Socket/ExCa base address */
-#define  PCI_CB_CARDBUS_BASE_TYPE_MASK 0xfff
-#define  PCI_CB_CARDBUS_BASE_MASK ~0xfff
-#define PCI_CB_CAPABILITIES	0x14	/* Offset of list of capabilities in cfg space */
-/* 0x15 reserved */
+/* Header type 2 (CardBus bridges) */
+/* 0x14-0x15 reserved */
 #define PCI_CB_SEC_STATUS	0x16	/* Secondary status */
-#define PCI_CB_BUS_NUMBER	0x18	/* PCI bus number */
-#define PCI_CB_CARDBUS_NUMBER	0x19	/* CardBus bus number */
+#define PCI_CB_PRIMARY_BUS	0x18	/* PCI bus number */
+#define PCI_CB_CARD_BUS		0x19	/* CardBus bus number */
 #define PCI_CB_SUBORDINATE_BUS	0x1a	/* Subordinate bus number */
-#define PCI_CB_CARDBUS_LATENCY	0x1b	/* CardBus latency timer */
+#define PCI_CB_LATENCY_TIMER	0x1b	/* CardBus latency timer */
 #define PCI_CB_MEMORY_BASE_0	0x1c
 #define PCI_CB_MEMORY_LIMIT_0	0x20
 #define PCI_CB_MEMORY_BASE_1	0x24
@@ -168,8 +164,19 @@
 #define PCI_CB_IO_BASE_1_HI	0x36
 #define PCI_CB_IO_LIMIT_1	0x38
 #define PCI_CB_IO_LIMIT_1_HI	0x3a
+#define  PCI_CB_IO_RANGE_MASK	~0x03
 /* 0x3c-0x3d are same as for htype 0 */
-/* 0x3e-0x3f are same as for htype 1 */
+#define PCI_CB_BRIDGE_CONTROL	0x3e
+#define  PCI_CB_BRIDGE_CTL_PARITY	0x01	/* Similar to standard bridge control register */
+#define  PCI_CB_BRIDGE_CTL_SERR		0x02
+#define  PCI_CB_BRIDGE_CTL_ISA		0x04
+#define  PCI_CB_BRIDGE_CTL_VGA		0x08
+#define  PCI_CB_BRIDGE_CTL_MASTER_ABORT	0x20
+#define  PCI_CB_BRIDGE_CTL_CB_RESET	0x40	/* CardBus reset */
+#define  PCI_CB_BRIDGE_CTL_16BIT_INT	0x80	/* Enable interrupt for 16-bit cards */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100	/* Prefetch enable for both memory regions */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define  PCI_CB_BRIDGE_CTL_POST_WRITES	0x400
 #define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
 #define PCI_CB_SUBSYSTEM_ID	0x42
 #define PCI_CB_LEGACY_MODE_BASE	0x44	/* 16-bit PC Card legacy mode base address (ExCa) */
@@ -1035,43 +1042,7 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
-
-/*
- * Error values that may be returned by the PCI bios.
- */
-#define PCIBIOS_SUCCESSFUL		0x00
-#define PCIBIOS_FUNC_NOT_SUPPORTED	0x81
-#define PCIBIOS_BAD_VENDOR_ID		0x83
-#define PCIBIOS_DEVICE_NOT_FOUND	0x86
-#define PCIBIOS_BAD_REGISTER_NUMBER	0x87
-#define PCIBIOS_SET_FAILED		0x88
-#define PCIBIOS_BUFFER_TOO_SMALL	0x89
-
-/* Direct configuration space access */
-
-int pcibios_present (void);
-void pcibios_init(void);
-void pcibios_fixup(void);
-char *pcibios_setup (char *str);
-int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
-			      unsigned char where, unsigned char *val);
-int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn,
-			      unsigned char where, unsigned short *val);
-int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn,
-			       unsigned char where, unsigned int *val);
-int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn,
-			       unsigned char where, unsigned char val);
-int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn,
-			       unsigned char where, unsigned short val);
-int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
-				unsigned char where, unsigned int val);
-
-/* Don't use these in new code, use pci_find_... instead */
-
-int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *dev_fn);
-int pcibios_find_device (unsigned short vendor, unsigned short dev_id,
-			 unsigned short index, unsigned char *bus,
-			 unsigned char *dev_fn);
+#include <linux/config.h>
 
 /*
  * There is one pci_dev structure for each slot-number/function-number
@@ -1131,6 +1102,46 @@
 extern struct pci_bus	pci_root;	/* root bus */
 extern struct pci_dev	*pci_devices;	/* list of all devices */
 
+/*
+ * Error values that may be returned by the PCI bios.
+ */
+#define PCIBIOS_SUCCESSFUL		0x00
+#define PCIBIOS_FUNC_NOT_SUPPORTED	0x81
+#define PCIBIOS_BAD_VENDOR_ID		0x83
+#define PCIBIOS_DEVICE_NOT_FOUND	0x86
+#define PCIBIOS_BAD_REGISTER_NUMBER	0x87
+#define PCIBIOS_SET_FAILED		0x88
+#define PCIBIOS_BUFFER_TOO_SMALL	0x89
+
+/* Low-level architecture-dependent routines */
+
+int pcibios_present (void);
+void pcibios_init(void);
+void pcibios_fixup(void);
+void pcibios_fixup_bus(struct pci_bus *);
+char *pcibios_setup (char *str);
+int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
+			      unsigned char where, unsigned char *val);
+int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn,
+			      unsigned char where, unsigned short *val);
+int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn,
+			       unsigned char where, unsigned int *val);
+int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn,
+			       unsigned char where, unsigned char val);
+int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn,
+			       unsigned char where, unsigned short val);
+int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
+				unsigned char where, unsigned int val);
+
+/* Don't use these in new code, use pci_find_... instead */
+
+int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *dev_fn);
+int pcibios_find_device (unsigned short vendor, unsigned short dev_id,
+			 unsigned short index, unsigned char *bus,
+			 unsigned char *dev_fn);
+
+/* Generic PCI interface functions */
+
 void pci_init(void);
 void pci_setup(char *str, int *ints);
 void pci_quirks_init(void);
@@ -1153,6 +1164,80 @@
 int pci_write_config_word(struct pci_dev *dev, u8 where, u16 val);
 int pci_write_config_dword(struct pci_dev *dev, u8 where, u32 val);
 void pci_set_master(struct pci_dev *dev);
+
+#ifndef CONFIG_PCI
+/* If the system does not have PCI, clearly these return errors.  Define
+   these as simple inline functions to avoid hair in drivers.  */
+extern inline
+int pcibios_present(void) { return 0; }
+
+extern inline
+int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
+                              unsigned char where, unsigned char *val)
+{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
+
+extern inline
+int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn,
+                              unsigned char where, unsigned short *val)
+{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
+
+extern inline
+int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn,
+                               unsigned char where, unsigned int *val)
+{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
+
+extern inline
+int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn,
+                               unsigned char where, unsigned char val)
+{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
+
+extern inline
+int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn,
+                               unsigned char where, unsigned short val)
+{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
+
+extern inline
+int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
+                                unsigned char where, unsigned int val)
+{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
+
+extern inline
+int pci_read_config_byte(struct pci_dev *dev, u8 where, u8 *val)
+{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
+
+extern inline
+int pci_read_config_word(struct pci_dev *dev, u8 where, u16 *val)
+{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
+
+extern inline
+int pci_read_config_dword(struct pci_dev *dev, u8 where, u32 *val)
+{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
+
+extern inline
+int pci_write_config_byte(struct pci_dev *dev, u8 where, u8 val)
+{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
+
+extern inline
+int pci_write_config_word(struct pci_dev *dev, u8 where, u16 val)
+{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
+
+extern inline
+int pci_write_config_dword(struct pci_dev *dev, u8 where, u32 val)
+{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
+
+extern inline struct pci_dev *
+pci_find_device (unsigned int vendor, unsigned int device, struct pci_dev *from)
+{ return NULL; }
+
+extern inline
+struct pci_dev *pci_find_class (unsigned int class, struct pci_dev *from)
+{ return NULL; }
+
+extern inline
+struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn)
+{ return NULL; }
+
+#endif /* !CONFIG_PCI */
 
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
diff -u --recursive --new-file v2.1.109/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.1.109/linux/include/linux/proc_fs.h	Thu Jul 16 18:09:29 1998
+++ linux/include/linux/proc_fs.h	Mon Jul 20 17:32:08 1998
@@ -136,6 +136,7 @@
 	PROC_NET_DN_ADJ,
 	PROC_NET_DN_L1,
 	PROC_NET_DN_L2,
+	PROC_NET_DN_CACHE,
 	PROC_NET_DN_SKT,
 	PROC_NET_NETSTAT,
 	PROC_NET_IPFW_CHAINS,
diff -u --recursive --new-file v2.1.109/linux/include/linux/quotaops.h linux/include/linux/quotaops.h
--- v2.1.109/linux/include/linux/quotaops.h	Thu May 14 19:47:44 1998
+++ linux/include/linux/quotaops.h	Mon Jul 20 17:33:37 1998
@@ -51,7 +51,7 @@
 	}
 }
 
-extern __inline__ int DQUOT_PREALLOC_BLOCK(struct super_block *sb, struct inode *inode, int nr)
+extern __inline__ int DQUOT_PREALLOC_BLOCK(struct super_block *sb, const struct inode *inode, int nr)
 {
 	if (sb->dq_op) {
 		if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize),
@@ -61,7 +61,7 @@
 	return 0;
 }
 
-extern __inline__ int DQUOT_ALLOC_BLOCK(struct super_block *sb, struct inode *inode, int nr)
+extern __inline__ int DQUOT_ALLOC_BLOCK(struct super_block *sb, const struct inode *inode, int nr)
 {
 	if (sb->dq_op) {
 		if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize),
@@ -82,7 +82,7 @@
 	return 0;
 }
 
-extern __inline__ void DQUOT_FREE_BLOCK(struct super_block *sb, struct inode *inode, int nr)
+extern __inline__ void DQUOT_FREE_BLOCK(struct super_block *sb, const struct inode *inode, int nr)
 {
 	if (sb->dq_op)
 		sb->dq_op->free_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize));
diff -u --recursive --new-file v2.1.109/linux/include/linux/random.h linux/include/linux/random.h
--- v2.1.109/linux/include/linux/random.h	Tue Jun  9 11:57:31 1998
+++ linux/include/linux/random.h	Sun Jul 19 20:48:55 1998
@@ -59,6 +59,10 @@
 				   __u16 sport, __u16 dport,
 				   __u32 sseq, __u32 count,
 				   __u32 data);
+extern __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr,
+				  __u32 daddr, __u16 sport,
+				  __u16 dport, __u32 sseq,
+				  __u32 count, __u32 maxdiff);
 
 #ifndef MODULE
 extern struct file_operations random_fops, urandom_fops;
diff -u --recursive --new-file v2.1.109/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.1.109/linux/include/linux/sched.h	Wed Jun 24 22:54:11 1998
+++ linux/include/linux/sched.h	Mon Jul 20 17:32:01 1998
@@ -208,9 +208,9 @@
 						0-0xFFFFFFFF for kernel-thread
 					 */
 	struct exec_domain *exec_domain;
+	long need_resched;
 
 /* various fields */
-	long debugreg[8];  /* Hardware debugging registers */
 	long counter;
 	long priority;
 	struct linux_binfmt *binfmt;
@@ -337,8 +337,7 @@
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
  */
 #define INIT_TASK \
-/* state etc */	{ 0,0,0,KERNEL_DS,&default_exec_domain, \
-/* debugregs */ { 0, },            \
+/* state etc */	{ 0,0,0,KERNEL_DS,&default_exec_domain,0, \
 /* counter */	DEF_PRIORITY,DEF_PRIORITY, \
 /* binfmt */	NULL, \
 /* schedlink */	&init_task,&init_task, &init_task, &init_task, \
@@ -448,7 +447,6 @@
 extern unsigned long itimer_ticks;
 extern unsigned long itimer_next;
 extern struct timeval xtime;
-extern int need_resched;
 extern void do_timer(struct pt_regs *);
 
 extern unsigned int * prof_buffer;
diff -u --recursive --new-file v2.1.109/linux/include/linux/videodev.h linux/include/linux/videodev.h
--- v2.1.109/linux/include/linux/videodev.h	Tue Jun  9 11:57:31 1998
+++ linux/include/linux/videodev.h	Sat Jul 18 14:15:20 1998
@@ -199,6 +199,8 @@
 #define VID_HARDWARE_AZTECH	7
 #define VID_HARDWARE_SF16MI	8
 #define VID_HARDWARE_RTRACK	9
+#define VID_HARDWARE_ZOLTRIX	10
+#define VID_HARDWARE_SAA7146    11
 
 /*
  *	Initialiser list
diff -u --recursive --new-file v2.1.109/linux/include/linux/videotext.h linux/include/linux/videotext.h
--- v2.1.109/linux/include/linux/videotext.h	Wed Apr  8 19:36:29 1998
+++ linux/include/linux/videotext.h	Sat Jul 18 14:15:20 1998
@@ -99,7 +99,7 @@
 	unsigned serial : 1;		/* serial mode (C11) */
 	unsigned notfound : 1;		/* /FOUND */
 	unsigned pblf : 1;		/* PBLF */
-	unsigned hamming : 1;		/* hamming-error occured */
+	unsigned hamming : 1;		/* hamming-error occurred */
 }
 vtx_pageinfo_t;
 
diff -u --recursive --new-file v2.1.109/linux/include/linux/vt_kern.h linux/include/linux/vt_kern.h
--- v2.1.109/linux/include/linux/vt_kern.h	Thu Jul 16 18:09:30 1998
+++ linux/include/linux/vt_kern.h	Sat Jul 18 13:55:47 1998
@@ -6,7 +6,6 @@
  * with information needed by the vt package
  */
 
-#include <linux/config.h>
 #include <linux/vt.h>
 
 /*
@@ -60,15 +59,6 @@
 
 struct tty_struct;
 int tioclinux(struct tty_struct *tty, unsigned long arg);
-
-#if defined(CONFIG_PMAC_CONSOLE) || defined(CONFIG_FB_COMPAT_XPMAC)
-#include <asm/vc_ioctl.h>
-extern int console_getmode(struct vc_mode *);
-extern int console_setmode(struct vc_mode *, int);
-extern int console_setcmap(int, unsigned char *,
-			   unsigned char *, unsigned char *);
-extern int console_powermode(int);
-#endif
 
 /* consolemap.c */
 
diff -u --recursive --new-file v2.1.109/linux/include/linux/wavefront.h linux/include/linux/wavefront.h
--- v2.1.109/linux/include/linux/wavefront.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/wavefront.h	Sat Jul 18 14:15:20 1998
@@ -0,0 +1,670 @@
+#ifndef __wavefront_h__
+#define __wavefront_h__
+
+/* WaveFront header file.
+ *   
+ * Copyright (C) by Paul Barton-Davis 1998
+ *
+ * This program is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info.  
+ */
+
+#if (!defined(__GNUC__) && !defined(__GNUG__))
+
+     You will not be able to compile this file correctly without gcc, because
+     it is necessary to pack the "wavefront_alias" structure to a size
+     of 22 bytes, corresponding to 16-bit alignment (as would have been
+     the case on the original platform, MS-DOS). If this is not done,
+     then WavePatch-format files cannot be read/written correctly.
+     The method used to do this here ("__attribute__((packed)") is
+     completely compiler dependent.
+     
+     All other wavefront_* types end up aligned to 32 bit values and
+     still have the same (correct) size.
+
+#else
+
+     /* However, note that as of G++ 2.7.3.2, g++ was unable to
+	correctly parse *type* __attribute__ tags. It will do the
+	right thing if we use the "packed" attribute on each struct
+	member, which has the same semantics anyway. 
+     */
+
+#endif __GNUC__
+
+/***************************** WARNING ********************************
+  PLEASE DO NOT MODIFY THIS FILE IN ANY WAY THAT AFFECTS ITS ABILITY TO 
+  BE USED WITH EITHER C *OR* C++.
+ **********************************************************************/
+
+#ifndef NUM_MIDIKEYS 
+#define NUM_MIDIKEYS 128
+#endif  NUM_MIDIKEYS
+
+#ifndef NUM_MIDICHANNELS
+#define NUM_MIDICHANNELS 16
+#endif  NUM_MIDICHANNELS
+
+/* These are very useful/important. the original wavefront interface
+   was developed on a 16 bit system, where sizeof(int) = 2
+   bytes. Defining things like this makes the code much more portable, and
+   easier to understand without having to toggle back and forth
+   between a 16-bit view of the world and a 32-bit one. 
+ */   
+
+typedef short INT16;
+typedef unsigned short UINT16;
+typedef int INT32;
+typedef unsigned int UINT32;
+typedef char CHAR8;
+typedef unsigned char UCHAR8;
+
+/* Pseudo-commands not part of the WaveFront command set.
+   These are used for various driver controls and direct
+   hardware control.
+ */
+
+#define WFC_DEBUG_DRIVER                0
+#define WFC_FX_IOCTL                    1
+#define WFC_PATCH_STATUS                2
+#define WFC_PROGRAM_STATUS              3
+#define WFC_SAMPLE_STATUS               4
+#define WFC_DISABLE_INTERRUPTS          5
+#define WFC_ENABLE_INTERRUPTS           6
+#define WFC_INTERRUPT_STATUS            7
+#define WFC_ROMSAMPLES_RDONLY           8
+#define WFC_IDENTIFY_SLOT_TYPE          9
+
+/* Wavefront synth commands
+ */
+
+#define WFC_DOWNLOAD_SAMPLE		0x80
+#define WFC_DOWNLOAD_BLOCK		0x81
+#define WFC_DOWNLOAD_MULTISAMPLE	0x82
+#define WFC_DOWNLOAD_SAMPLE_ALIAS	0x83
+#define WFC_DELETE_SAMPLE		0x84
+#define WFC_REPORT_FREE_MEMORY		0x85
+#define WFC_DOWNLOAD_PATCH		0x86
+#define WFC_DOWNLOAD_PROGRAM		0x87
+#define WFC_SET_SYNTHVOL		0x89
+#define WFC_SET_NVOICES			0x8B
+#define WFC_DOWNLOAD_DRUM		0x90
+#define WFC_GET_SYNTHVOL		0x92
+#define WFC_GET_NVOICES			0x94
+#define WFC_DISABLE_CHANNEL		0x9A
+#define WFC_ENABLE_CHANNEL		0x9B
+#define WFC_MISYNTH_OFF			0x9D
+#define WFC_MISYNTH_ON			0x9E
+#define WFC_FIRMWARE_VERSION		0x9F
+#define WFC_GET_NSAMPLES		0xA0
+#define WFC_DISABLE_DRUM_PROGRAM	0xA2
+#define WFC_UPLOAD_PATCH		0xA3
+#define WFC_UPLOAD_PROGRAM		0xA4
+#define WFC_SET_TUNING			0xA6
+#define WFC_GET_TUNING			0xA7
+#define WFC_VMIDI_ON			0xA8
+#define WFC_VMIDI_OFF			0xA9
+#define WFC_MIDI_STATUS			0xAA
+#define WFC_GET_CHANNEL_STATUS		0xAB
+#define WFC_DOWNLOAD_SAMPLE_HEADER	0xAC
+#define WFC_UPLOAD_SAMPLE_HEADER	0xAD
+#define WFC_UPLOAD_MULTISAMPLE		0xAE
+#define WFC_UPLOAD_SAMPLE_ALIAS		0xAF
+#define WFC_IDENTIFY_SAMPLE_TYPE	0xB0
+#define WFC_DOWNLOAD_EDRUM_PROGRAM	0xB1
+#define WFC_UPLOAD_EDRUM_PROGRAM	0xB2
+#define WFC_SET_EDRUM_CHANNEL		0xB3
+#define WFC_INSTOUT_LEVELS		0xB4
+#define WFC_PEAKOUT_LEVELS		0xB5
+#define WFC_REPORT_CHANNEL_PROGRAMS	0xB6
+#define WFC_HARDWARE_VERSION		0xCF
+#define WFC_UPLOAD_SAMPLE_PARAMS	0xD7
+#define WFC_DOWNLOAD_OS			0xF1
+#define WFC_NOOP                        0xFF
+
+#define WF_MAX_SAMPLE   512
+#define WF_MAX_PATCH    256
+#define WF_MAX_PROGRAM  128
+
+#define WF_SECTION_MAX  44   /* longest OS section length */
+
+/* # of bytes we send to the board when sending it various kinds of
+   substantive data, such as samples, patches and programs.
+*/
+
+#define WF_PROGRAM_BYTES 32
+#define WF_PATCH_BYTES 132
+#define WF_SAMPLE_BYTES 27
+#define WF_SAMPLE_HDR_BYTES 25
+#define WF_ALIAS_BYTES 25
+#define WF_DRUM_BYTES 9
+#define WF_MSAMPLE_BYTES 259 /* (MIDI_KEYS * 2) + 3 */
+
+#define WF_ACK     0x80
+#define WF_DMA_ACK 0x81
+
+/* OR-values for MIDI status bits */
+
+#define WF_MIDI_VIRTUAL_ENABLED 0x1
+#define WF_MIDI_VIRTUAL_IS_EXTERNAL 0x2
+#define WF_MIDI_IN_TO_SYNTH_DISABLED 0x4
+
+/* See wavefront.c for details */
+
+#define WAVEFRONT_MAX_DEVICES 1 /* How many WaveFront cards we can handle */
+
+/* slot indexes for struct address_info: makes code a little more mnemonic */
+
+#define WF_SYNTH_SLOT         0
+#define WF_INTERNAL_MIDI_SLOT 1
+#define WF_EXTERNAL_MIDI_SLOT 2
+
+/* Magic MIDI bytes used to switch I/O streams on the ICS2115 MPU401
+   emulation. Note these NEVER show up in output from the device and
+   should NEVER be used in input unless Virtual MIDI mode has been 
+   disabled. If they do show up as input, the results are unpredictable.
+*/
+
+#define WF_EXTERNAL_SWITCH  0xFD
+#define WF_INTERNAL_SWITCH  0xF9
+
+/* Debugging flags */
+
+#define WF_DEBUG_CMD 0x1
+#define WF_DEBUG_DATA 0x2
+#define WF_DEBUG_LOAD_PATCH 0x4
+#define WF_DEBUG_IO 0x8
+
+/* WavePatch file format stuff */
+
+#define WF_WAVEPATCH_VERSION     120;  /*  Current version number (1.2)  */
+#define WF_MAX_COMMENT           64    /*  Comment length */
+#define WF_NUM_LAYERS            4
+#define WF_NAME_LENGTH           32
+#define WF_SOURCE_LENGTH         260
+
+#define BankFileID     "Bank"
+#define DrumkitFileID  "DrumKit"
+#define ProgramFileID  "Program"
+
+struct wf_envelope
+{
+    UCHAR8 attack_time:7;
+    UCHAR8 Unused1:1;
+
+    UCHAR8 decay1_time:7;
+    UCHAR8 Unused2:1;
+
+    UCHAR8 decay2_time:7;
+    UCHAR8 Unused3:1;
+
+    UCHAR8 sustain_time:7;
+    UCHAR8 Unused4:1;
+
+    UCHAR8 release_time:7;
+    UCHAR8 Unused5:1;
+
+    UCHAR8 release2_time:7;
+    UCHAR8 Unused6:1;
+
+    CHAR8 attack_level;
+    CHAR8 decay1_level;
+    CHAR8 decay2_level;
+    CHAR8 sustain_level;
+    CHAR8 release_level;
+
+    UCHAR8 attack_velocity:7;
+    UCHAR8 Unused7:1;
+
+    UCHAR8 volume_velocity:7;
+    UCHAR8 Unused8:1;
+
+    UCHAR8 keyboard_scaling:7;
+    UCHAR8 Unused9:1;
+};
+typedef struct wf_envelope wavefront_envelope;
+
+struct wf_lfo
+{
+    UCHAR8 sample_number;
+
+    UCHAR8 frequency:7;
+    UCHAR8 Unused1:1;
+
+    UCHAR8 am_src:4;
+    UCHAR8 fm_src:4;
+
+    CHAR8 fm_amount;
+    CHAR8 am_amount;
+    CHAR8 start_level;
+    CHAR8 end_level;
+
+    UCHAR8 ramp_delay:7;
+    UCHAR8 wave_restart:1; /* for LFO2 only */
+
+    UCHAR8 ramp_time:7;
+    UCHAR8 Unused2:1;
+};
+typedef struct wf_lfo wavefront_lfo;
+
+struct wf_patch
+{
+    INT16  frequency_bias;         /*  ** THIS IS IN MOTOROLA FORMAT!! ** */
+
+    UCHAR8 amplitude_bias:7;
+    UCHAR8 Unused1:1;
+
+    UCHAR8 portamento:7;
+    UCHAR8 Unused2:1;
+
+    UCHAR8 sample_number;
+
+    UCHAR8 pitch_bend:4;
+    UCHAR8 sample_msb:1;
+    UCHAR8 Unused3:3;
+
+    UCHAR8 mono:1;
+    UCHAR8 retrigger:1;
+    UCHAR8 nohold:1;
+    UCHAR8 restart:1;
+    UCHAR8 filterconfig:2; /* SDK says "not used" */
+    UCHAR8 reuse:1;
+    UCHAR8 reset_lfo:1;    
+
+    UCHAR8 fm_src2:4;
+    UCHAR8 fm_src1:4;   
+
+    CHAR8 fm_amount1;
+    CHAR8 fm_amount2;
+
+    UCHAR8 am_src:4;
+    UCHAR8 Unused4:4;
+
+    CHAR8 am_amount;
+
+    UCHAR8 fc1_mode:4;
+    UCHAR8 fc2_mode:4;
+
+    CHAR8 fc1_mod_amount;
+    CHAR8 fc1_keyboard_scaling;
+    CHAR8 fc1_bias;
+    CHAR8 fc2_mod_amount;
+    CHAR8 fc2_keyboard_scaling;
+    CHAR8 fc2_bias;
+
+    UCHAR8 randomizer:7;
+    UCHAR8 Unused5:1;
+
+    struct wf_envelope envelope1;
+    struct wf_envelope envelope2;
+    struct wf_lfo lfo1;
+    struct wf_lfo lfo2;
+};
+typedef struct wf_patch wavefront_patch;
+
+struct wf_layer
+{
+    UCHAR8 patch_number;
+
+    UCHAR8 mix_level:7;
+    UCHAR8 mute:1;
+
+    UCHAR8 split_point:7;
+    UCHAR8 updown:1;
+
+    UCHAR8 pan_mod_src:2;
+    UCHAR8 pan_or_mod:1;
+    UCHAR8 pan:4;
+    UCHAR8 split_type:1;
+};
+typedef struct wf_layer wavefront_layer;
+
+struct wf_program
+{
+    struct wf_layer layer[WF_NUM_LAYERS];
+};
+typedef struct wf_program wavefront_program;
+
+struct wf_sample_offset
+{
+    INT32 Fraction:4;
+    INT32 Integer:20;
+    INT32 Unused:8;
+};
+typedef struct wf_sample_offset wavefront_sample_offset;          
+     
+/* Sample slot types */
+
+#define WF_ST_SAMPLE      0
+#define WF_ST_MULTISAMPLE 1
+#define WF_ST_ALIAS       2
+#define WF_ST_EMPTY       3
+
+/* pseudo's */
+
+#define WF_ST_DRUM        4
+#define WF_ST_PROGRAM     5
+#define WF_ST_PATCH       6
+#define WF_ST_SAMPLEHDR   7
+
+#define WF_ST_MASK        0xf
+
+/* Flags for slot status. These occupy the upper bits of the same byte
+   as a sample type.
+*/
+
+#define WF_SLOT_USED      0x80   /* XXX don't rely on this being accurate */
+#define WF_SLOT_FILLED    0x40
+#define WF_SLOT_ROM       0x20
+
+#define WF_SLOT_MASK      0xf0
+
+/* channel constants */
+
+#define WF_CH_MONO  0
+#define WF_CH_LEFT  1
+#define WF_CH_RIGHT 2
+
+/* Sample formats */
+
+#define LINEAR_16BIT 0
+#define WHITE_NOISE  1
+#define LINEAR_8BIT  2
+#define MULAW_8BIT   3
+
+#define WF_SAMPLE_IS_8BIT(smpl) ((smpl)->SampleResolution&2)
+
+
+/* 
+
+  Because most/all of the sample data we pass in via pointers has
+  never been copied (just mmap-ed into user space straight from the
+  disk), it would be nice to allow handling of multi-channel sample
+  data without forcing user-level extraction of the relevant bytes.
+  
+  So, we need a way of specifying which channel to use (the WaveFront
+  only handles mono samples in a given slot), and the only way to do
+  this without using some struct other than wavefront_sample as the
+  interface is the awful hack of using the unused bits in a
+  wavefront_sample:
+  
+  Val      Meaning
+  ---      -------
+  0        no channel selection (use channel 1, sample is MONO)
+  1        use first channel, and skip one
+  2        use second channel, and skip one
+  3        use third channel, and skip two
+  4        use fourth channel, skip three
+  5        use fifth channel, skip four
+  6        use six channel, skip five
+
+
+  This can handle up to 4 channels, and anyone downloading >4 channels
+  of sample data just to select one of them needs to find some tools
+  like sox ...
+
+  NOTE: values 0, 1 and 2 correspond to WF_CH_* above. This is 
+  important.
+
+*/
+
+#define WF_SET_CHANNEL(samp,chn) \
+ (samp)->Unused1 = chn & 0x1; \
+ (samp)->Unused2 = chn & 0x2; \
+ (samp)->Unused3 = chn & 0x4 
+  
+#define WF_GET_CHANNEL(samp) \
+  (((samp)->Unused3 << 2)|((samp)->Unused2<<1)|(samp)->Unused1)
+  
+typedef struct wf_sample {
+    struct wf_sample_offset sampleStartOffset;
+    struct wf_sample_offset loopStartOffset;
+    struct wf_sample_offset loopEndOffset;
+    struct wf_sample_offset sampleEndOffset;
+    INT16 FrequencyBias;
+    UCHAR8 SampleResolution:2;  /* sample_format */
+    UCHAR8 Unused1:1;
+    UCHAR8 Loop:1;
+    UCHAR8 Bidirectional:1;
+    UCHAR8 Unused2:1;
+    UCHAR8 Reverse:1;
+    UCHAR8 Unused3:1;
+} wavefront_sample;
+
+typedef struct wf_multisample {
+    INT16 NumberOfSamples;   /* log2 of the number of samples */
+    INT16 SampleNumber[NUM_MIDIKEYS];
+} wavefront_multisample;
+
+typedef struct wf_alias {
+    INT16 OriginalSample __attribute__ ((packed));
+
+    struct wf_sample_offset sampleStartOffset __attribute__ ((packed));
+    struct wf_sample_offset loopStartOffset __attribute__ ((packed));
+    struct wf_sample_offset sampleEndOffset __attribute__ ((packed));
+    struct wf_sample_offset loopEndOffset __attribute__ ((packed));
+
+    INT16  FrequencyBias __attribute__ ((packed));
+
+    UCHAR8 SampleResolution:2  __attribute__ ((packed));
+    UCHAR8 Unused1:1  __attribute__ ((packed));
+    UCHAR8 Loop:1 __attribute__ ((packed));
+    UCHAR8 Bidirectional:1  __attribute__ ((packed));
+    UCHAR8 Unused2:1 __attribute__ ((packed));
+    UCHAR8 Reverse:1 __attribute__ ((packed));
+    UCHAR8 Unused3:1 __attribute__ ((packed)); 
+    
+    /* This structure is meant to be padded only to 16 bits on their
+       original. Of course, whoever wrote their documentation didn't
+       realize that sizeof(struct) can be >=
+       sum(sizeof(struct-fields)) and so thought that giving a C level
+       description of the structs used in WavePatch files was
+       sufficient. I suppose it was, as long as you remember the 
+       standard 16->32 bit issues.
+    */
+
+    UCHAR8 sixteen_bit_padding __attribute__ ((packed));
+} wavefront_alias;
+
+typedef struct wf_drum {
+    UCHAR8 PatchNumber;
+    UCHAR8 MixLevel:7;
+    UCHAR8 Unmute:1;
+    UCHAR8 Group:4;
+    UCHAR8 Unused1:4;
+    UCHAR8 PanModSource:2;
+    UCHAR8 PanModulated:1;
+    UCHAR8 PanAmount:4;
+    UCHAR8 Unused2:1;
+} wavefront_drum;
+
+typedef struct wf_drumkit {
+    struct wf_drum drum[NUM_MIDIKEYS];
+} wavefront_drumkit;
+
+typedef struct wf_channel_programs {
+    UCHAR8 Program[NUM_MIDICHANNELS];
+} wavefront_channel_programs;
+
+/* How to get MIDI channel status from the data returned by
+   a WFC_GET_CHANNEL_STATUS command (a struct wf_channel_programs)
+*/
+
+#define WF_CHANNEL_STATUS(ch,wcp) (wcp)[(ch/7)] & (1<<((ch)%7))
+
+typedef union wf_any {
+    wavefront_sample s;
+    wavefront_multisample ms;
+    wavefront_alias a;
+    wavefront_program pr;
+    wavefront_patch p;
+    wavefront_drum d;
+} wavefront_any;
+
+/* Hannu Solvainen hoped that his "patch_info" struct in soundcard.h
+   might work for other wave-table based patch loading situations.
+   Alas, his fears were correct. The WaveFront doesn't even come with
+   just "patches", but several different kind of structures that
+   control the sound generation process.
+ */
+
+typedef struct wf_patch_info {
+    
+    INT16   key;               /* Use WAVEFRONT_PATCH here */
+    UINT16  devno;             /* fill in when sending */
+    UCHAR8  subkey;            /* WF_ST_{SAMPLE,ALIAS,etc.} */
+    UINT16  number;            /* patch/sample/prog number */
+
+    UINT32  size;              /* size of any data included in 
+				  one of the fields in `hdrptr', or
+				  as `dataptr'.
+
+				  NOTE: for actual samples, this is
+				  the size of the *SELECTED CHANNEL*
+				  even if more data is actually available.
+				  
+				  So, a stereo sample (2 channels) of
+				  6000 bytes total has `size' = 3000.
+
+				  See the macros and comments for
+				  WF_{GET,SET}_CHANNEL above.
+
+			       */
+    wavefront_any *hdrptr;      /* user-space ptr to hdr bytes */
+    UINT16 *dataptr;            /* actual sample data */
+
+    wavefront_any hdr;          /* kernel-space copy of hdr bytes */         
+} wavefront_patch_info;
+
+/* The maximum number of bytes we will ever move to or from user space
+   in response to a WFC_* command.  This obviously doesn't cover
+   actual sample data.
+*/
+
+#define WF_MAX_READ sizeof(wavefront_multisample)
+#define WF_MAX_WRITE sizeof(wavefront_multisample)
+
+/*
+   This allows us to execute any WF command except the download/upload
+   ones, which are handled differently due to copyin/copyout issues as
+   well as data-nybbling to/from the card.
+ */
+
+typedef struct wavefront_control {
+    int devno;                         /* from /dev/sequencer interface */
+    int cmd;                           /* WFC_* */
+    char status;                       /* return status to user-space */
+    unsigned char rbuf[WF_MAX_READ];   /* bytes read from card */
+    unsigned char wbuf[WF_MAX_WRITE];  /* bytes written to card */
+} wavefront_control;
+
+/* Modulator table */
+
+#define WF_MOD_LFO1      0
+#define WF_MOD_LFO2      1
+#define WF_MOD_ENV1      2
+#define WF_MOD_ENV2      3
+#define WF_MOD_KEYBOARD  4
+#define WF_MOD_LOGKEY    5
+#define WF_MOD_VELOCITY  6
+#define WF_MOD_LOGVEL    7
+#define WF_MOD_RANDOM    8
+#define WF_MOD_PRESSURE  9
+#define WF_MOD_MOD_WHEEL 10
+#define WF_MOD_1         WF_MOD_MOD_WHEEL 
+#define WF_MOD_BREATH    11
+#define WF_MOD_2         WF_MOD_BREATH
+#define WF_MOD_FOOT      12
+#define WF_MOD_4         WF_MOD_FOOT
+#define WF_MOD_VOLUME    13
+#define WF_MOD_7         WF_MOD_VOLUME
+#define WF_MOD_PAN       14
+#define WF_MOD_10        WF_MOD_PAN
+#define WF_MOD_EXPR      15
+#define WF_MOD_11        WF_MOD_EXPR
+
+/* FX-related material */
+
+typedef struct wf_fx_info {
+    int request;             /* see list below */
+    int data[4];             /* we don't need much */
+} wavefront_fx_info;
+
+/* support for each of these will be forthcoming once I or someone 
+   else has figured out which of the addresses on page 6 and page 7 of 
+   the YSS225 control each parameter. Incidentally, these come from
+   the Windows driver interface, but again, Turtle Beach didn't
+   document the API to use them.
+*/
+
+#define WFFX_SETOUTGAIN		        0
+#define WFFX_SETSTEREOOUTGAIN		1
+#define WFFX_SETREVERBIN1GAIN		2
+#define WFFX_SETREVERBIN2GAIN		3
+#define WFFX_SETREVERBIN3GAIN		4
+#define WFFX_SETCHORUSINPORT		5
+#define WFFX_SETREVERBIN1PORT		6
+#define WFFX_SETREVERBIN2PORT		7
+#define WFFX_SETREVERBIN3PORT		8
+#define WFFX_SETEFFECTPORT		9
+#define WFFX_SETAUXPORT		        10
+#define WFFX_SETREVERBTYPE		11
+#define WFFX_SETREVERBDELAY		12
+#define WFFX_SETCHORUSLFO		13
+#define WFFX_SETCHORUSPMD		14
+#define WFFX_SETCHORUSAMD		15
+#define WFFX_SETEFFECT		        16
+#define WFFX_SETBASEALL		        17
+#define WFFX_SETREVERBALL		18
+#define WFFX_SETCHORUSALL		20
+#define WFFX_SETREVERBDEF		22
+#define WFFX_SETCHORUSDEF		23
+#define WFFX_DELAYSETINGAIN		24
+#define WFFX_DELAYSETFBGAIN	        25
+#define WFFX_DELAYSETFBLPF		26
+#define WFFX_DELAYSETGAIN		27
+#define WFFX_DELAYSETTIME		28
+#define WFFX_DELAYSETFBTIME		29
+#define WFFX_DELAYSETALL		30
+#define WFFX_DELAYSETDEF		32
+#define WFFX_SDELAYSETINGAIN		33
+#define WFFX_SDELAYSETFBGAIN		34
+#define WFFX_SDELAYSETFBLPF		35
+#define WFFX_SDELAYSETGAIN		36
+#define WFFX_SDELAYSETTIME		37
+#define WFFX_SDELAYSETFBTIME		38
+#define WFFX_SDELAYSETALL		39
+#define WFFX_SDELAYSETDEF		41
+#define WFFX_DEQSETINGAIN		42
+#define WFFX_DEQSETFILTER		43
+#define WFFX_DEQSETALL		        44
+#define WFFX_DEQSETDEF		        46
+#define WFFX_MUTE		        47
+#define WFFX_FLANGESETBALANCE	        48	
+#define WFFX_FLANGESETDELAY		49
+#define WFFX_FLANGESETDWFFX_TH		50
+#define WFFX_FLANGESETFBGAIN		51
+#define WFFX_FLANGESETINGAIN		52
+#define WFFX_FLANGESETLFO		53
+#define WFFX_FLANGESETALL		54
+#define WFFX_FLANGESETDEF		56
+#define WFFX_PITCHSETSHIFT		57
+#define WFFX_PITCHSETBALANCE		58
+#define WFFX_PITCHSETALL		59
+#define WFFX_PITCHSETDEF		61
+#define WFFX_SRSSETINGAIN		62
+#define WFFX_SRSSETSPACE		63
+#define WFFX_SRSSETCENTER		64
+#define WFFX_SRSSETGAIN		        65
+#define WFFX_SRSSETMODE	        	66
+#define WFFX_SRSSETDEF		        68
+
+/* Allow direct user-space control over FX memory/coefficient data.
+   In theory this could be used to download the FX microprogram,
+   but it would be a little slower, and involve some wierd code.
+ */
+
+#define WFFX_MEMSET              69
+
+#endif __wavefront_h__
diff -u --recursive --new-file v2.1.109/linux/include/net/sock.h linux/include/net/sock.h
--- v2.1.109/linux/include/net/sock.h	Thu May 14 19:47:44 1998
+++ linux/include/net/sock.h	Mon Jul 20 17:32:57 1998
@@ -448,6 +448,9 @@
 #if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
 		struct ipx_opt		af_ipx;
 #endif
+#if defined (CONFIG_DECNET) || defined(CONFIG_DECNET_MODULE)
+		struct dn_scp           dn;
+#endif
 #if defined (CONFIG_PACKET) || defined(CONFIG_PACKET_MODULE)
 		struct packet_opt	*af_packet;
 #endif
@@ -456,15 +459,12 @@
 #endif
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 		ax25_cb			*ax25;
+#endif
 #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
 		nr_cb			*nr;
 #endif
 #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 		rose_cb			*rose;
-#endif
-#endif
-#if defined(CONFIG_DECNET) || defined(CONFIG_DECNET_MODULE)
-	        dn_cb                    *dn;
 #endif
 #ifdef CONFIG_NETLINK
 		struct netlink_opt	af_netlink;
diff -u --recursive --new-file v2.1.109/linux/init/main.c linux/init/main.c
--- v2.1.109/linux/init/main.c	Wed Jun 24 22:54:12 1998
+++ linux/init/main.c	Mon Jul 20 14:21:43 1998
@@ -88,7 +88,9 @@
 #ifdef __i386__
 extern void ioapic_pirq_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_VGA_CONSOLE
 extern void no_scroll(char *str, int *ints);
+#endif
 extern void kbd_reset_setup(char *str, int *ints);
 extern void panic_setup(char *str, int *ints);
 extern void bmouse_setup(char *str, int *ints);
@@ -536,7 +538,9 @@
 	{ "panic=", panic_setup },
 	{ "console=", console_setup },
 #ifdef CONFIG_VT
+#ifdef CONFIG_VGA_CONSOLE
 	{ "no-scroll", no_scroll },
+#endif
 	{ "kbd-reset", kbd_reset_setup },
 #endif
 #ifdef CONFIG_BUGi386
@@ -1105,12 +1109,12 @@
 #if defined(CONFIG_QUOTA)
 	dquot_init_hash();
 #endif
-	check_bugs();
-
-	printk("POSIX conformance testing by UNIFIX\n");
 #ifdef __SMP__
 	smp_init();
 #endif
+	printk("POSIX conformance testing by UNIFIX\n");
+	check_bugs();
+
 	sock_init();
 #ifdef CONFIG_SYSCTL
 	sysctl_init();
diff -u --recursive --new-file v2.1.109/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.1.109/linux/kernel/ksyms.c	Tue Jun 23 10:01:30 1998
+++ linux/kernel/ksyms.c	Mon Jul 20 14:00:10 1998
@@ -316,7 +316,6 @@
 EXPORT_SYMBOL(xtime);
 EXPORT_SYMBOL(do_gettimeofday);
 EXPORT_SYMBOL(loops_per_sec);
-EXPORT_SYMBOL(need_resched);
 EXPORT_SYMBOL(kstat);
 
 /* misc */
diff -u --recursive --new-file v2.1.109/linux/kernel/sched.c linux/kernel/sched.c
--- v2.1.109/linux/kernel/sched.c	Thu Jul 16 18:09:30 1998
+++ linux/kernel/sched.c	Mon Jul 20 23:34:41 1998
@@ -81,7 +81,6 @@
 long time_adjust = 0;
 long time_adjust_step = 0;
 
-int need_resched = 0;
 unsigned long event = 0;
 
 extern int do_setitimer(int, struct itimerval *, struct itimerval *);
@@ -104,11 +103,41 @@
 
 void scheduling_functions_start_here(void) { }
 
-static inline void add_to_runqueue(struct task_struct * p)
+static inline void reschedule_idle(struct task_struct * p)
 {
+	/*
+	 * For SMP, we try to find another CPU to put the
+	 * new task on, and fall back on the local CPU only
+	 * if no other CPU is idle.
+	 *
+	 * FIXME: try to select the idle CPU to be the old
+	 * CPU of the task 'p' if possible.
+	 */
+#ifdef __SMP__
+	struct task_struct **idle = task;
+	int current_cpu = smp_processor_id();
+	int i = smp_num_cpus;
+
+	do {
+		struct task_struct *tsk = *idle;
+		idle++;
+		/* Something like this.. */
+		if (tsk->has_cpu && !tsk->need_resched && tsk->processor != current_cpu) {
+			tsk->need_resched = 1;
+			smp_send_reschedule(tsk->processor);
+			return;
+		}
+	} while (--i > 0);
+#endif
 	if (p->policy != SCHED_OTHER || p->counter > current->counter + 3)
-		need_resched = 1;
+		current->need_resched = 1;	
+}
+
+	
+static inline void add_to_runqueue(struct task_struct * p)
+{
 	nr_running++;
+	reschedule_idle(p);
 	(p->prev_run = init_task.prev_run)->next_run = p;
 	p->next_run = &init_task;
 	init_task.prev_run = p;
@@ -410,7 +439,6 @@
 	unsigned long timeout;
 	int this_cpu;
 
-	need_resched = 0;
 	prev = current;
 	this_cpu = smp_processor_id();
 	if (in_interrupt())
@@ -512,8 +540,15 @@
 		if (timeout)
 			del_timer(&timer);
 	}
+
 	spin_unlock(&scheduler_lock);
 
+	/*
+	 * At this point "prev" is "current", as we just
+	 * switched into it (from an even more "previous"
+	 * prev)
+	 */
+	prev->need_resched = 0;
 	reacquire_kernel_lock(prev, smp_processor_id(), lock_depth);
 	return;
 
@@ -1058,7 +1093,7 @@
 		p->counter -= ticks;
 		if (p->counter < 0) {
 			p->counter = 0;
-			need_resched = 1;
+			p->need_resched = 1;
 		}
 		if (p->priority < DEF_PRIORITY)
 			kstat.cpu_nice += user;
@@ -1347,7 +1382,7 @@
 	if (p->next_run)
 		move_first_runqueue(p);
 
-	need_resched = 1;
+	current->need_resched = 1;
 
 out_unlock:
 	read_unlock(&tasklist_lock);
@@ -1430,10 +1465,10 @@
 	spin_lock(&scheduler_lock);
 	spin_lock_irq(&runqueue_lock);
 	current->policy |= SCHED_YIELD;
+	current->need_resched = 1;
 	move_last_runqueue(current);
 	spin_unlock_irq(&runqueue_lock);
 	spin_unlock(&scheduler_lock);
-	need_resched = 1;
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.109/linux/mm/filemap.c linux/mm/filemap.c
--- v2.1.109/linux/mm/filemap.c	Thu Jul 16 18:09:30 1998
+++ linux/mm/filemap.c	Fri Jul 17 11:41:46 1998
@@ -117,12 +117,98 @@
 	}
 }
 
+/*
+ * Remove a page from the page cache and free it.
+ */
+void remove_inode_page(struct page *page)
+{
+	remove_page_from_hash_queue(page);
+	remove_page_from_inode_queue(page);
+	__free_page(page);
+}
+
+/*
+ * Check whether we can free this page.
+ */
+static inline int shrink_one_page(struct page *page, int gfp_mask)
+{
+	struct buffer_head *tmp, *bh;
+
+	if (PageLocked(page))
+		goto next;
+	if ((gfp_mask & __GFP_DMA) && !PageDMA(page))
+		goto next;
+	/* First of all, regenerate the page's referenced bit
+         * from any buffers in the page
+	 */
+	bh = page->buffers;
+	if (bh) {
+		tmp = bh;
+		do {
+			if (buffer_touched(tmp)) {
+				clear_bit(BH_Touched, &tmp->b_state);
+				set_bit(PG_referenced, &page->flags);
+			}
+			tmp = tmp->b_this_page;
+		} while (tmp != bh);
+
+		/* Refuse to swap out all buffer pages */
+		if ((buffermem >> PAGE_SHIFT) * 100 < (buffer_mem.min_percent * num_physpages))
+			goto next;
+	}
+
+	/* We can't throw away shared pages, but we do mark
+	   them as referenced.  This relies on the fact that
+	   no page is currently in both the page cache and the
+	   buffer cache; we'd have to modify the following
+	   test to allow for that case. */
+
+	switch (atomic_read(&page->count)) {
+	case 1:
+		/* is it a swap-cache or page-cache page? */
+		if (page->inode) {
+			if (test_and_clear_bit(PG_referenced, &page->flags)) {
+				touch_page(page);
+				break;
+			}
+			age_page(page);
+			if (page->age)
+				break;
+			if (page_cache_size * 100 < (page_cache.min_percent * num_physpages))
+				break;
+			if (PageSwapCache(page)) {
+				delete_from_swap_cache(page);
+				return 1;
+			}
+			remove_inode_page(page);
+			return 1;
+		}
+		/* It's not a cache page, so we don't do aging.
+		 * If it has been referenced recently, don't free it */
+		if (test_and_clear_bit(PG_referenced, &page->flags))
+			break;
+
+		/* is it a buffer cache page? */
+		if ((gfp_mask & __GFP_IO) && bh && try_to_free_buffer(bh, &bh, 6))
+			return 1;
+		break;
+
+	default:
+		/* more than one user: we can't throw it away */
+		set_bit(PG_referenced, &page->flags);
+		/* fall through */
+	case 0:
+		/* nothing */
+	}
+next:
+	return 0;
+}
+
 int shrink_mmap(int priority, int gfp_mask)
 {
 	static unsigned long clock = 0;
-	struct page * page;
 	unsigned long limit = num_physpages;
-	struct buffer_head *tmp, *bh;
+	struct page * page;
 	int count_max, count_min;
 
 	count_max = (limit<<2) >> (priority>>1);
@@ -130,76 +216,11 @@
 
 	page = mem_map + clock;
 	do {
+		if (shrink_one_page(page, gfp_mask))
+			return 1;
 		count_max--;
 		if (page->inode || page->buffers)
 			count_min--;
-
-		if (PageLocked(page))
-			goto next;
-		if ((gfp_mask & __GFP_DMA) && !PageDMA(page))
-			goto next;
-		/* First of all, regenerate the page's referenced bit
-                   from any buffers in the page */
-		bh = page->buffers;
-		if (bh) {
-			tmp = bh;
-			do {
-				if (buffer_touched(tmp)) {
-					clear_bit(BH_Touched, &tmp->b_state);
-					set_bit(PG_referenced, &page->flags);
-				}
-				tmp = tmp->b_this_page;
-			} while (tmp != bh);
-
-			/* Refuse to swap out all buffer pages */
-			if ((buffermem >> PAGE_SHIFT) * 100 < (buffer_mem.min_percent * num_physpages))
-				goto next;
-		}
-
-		/* We can't throw away shared pages, but we do mark
-		   them as referenced.  This relies on the fact that
-		   no page is currently in both the page cache and the
-		   buffer cache; we'd have to modify the following
-		   test to allow for that case. */
-
-		switch (atomic_read(&page->count)) {
-			case 1:
-				/* is it a swap-cache or page-cache page? */
-				if (page->inode) {
-					if (test_and_clear_bit(PG_referenced, &page->flags)) {
-						touch_page(page);
-						break;
-					}
-					age_page(page);
-					if (page->age || page_cache_size * 100 < (page_cache.min_percent * num_physpages))
-						break;
-					if (PageSwapCache(page)) {
-						delete_from_swap_cache(page);
-						return 1;
-					}
-					remove_page_from_hash_queue(page);
-					remove_page_from_inode_queue(page);
-					__free_page(page);
-					return 1;
-				}
-				/* It's not a cache page, so we don't do aging.
-				 * If it has been referenced recently, don't free it */
-				if (test_and_clear_bit(PG_referenced, &page->flags))
-					break;
-
-				/* is it a buffer cache page? */
-				if ((gfp_mask & __GFP_IO) && bh && try_to_free_buffer(bh, &bh, 6))
-					return 1;
-				break;
-
-			default:
-				/* more than one users: we can't throw it away */
-				set_bit(PG_referenced, &page->flags);
-				/* fall through */
-			case 0:
-				/* nothing */
-		}
-next:
 		page++;
 		clock++;
 		if (clock >= limit) {
@@ -226,9 +247,7 @@
 		return count;
 	if (PageSwapCache(page))
 		panic ("Doing a normal page_unuse of a swap cache page");
-	remove_page_from_hash_queue(page);
-	remove_page_from_inode_queue(page);
-	__free_page(page);
+	remove_inode_page(page);
 	return 1;
 }
 
diff -u --recursive --new-file v2.1.109/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.1.109/linux/mm/page_alloc.c	Thu Jul 16 18:09:30 1998
+++ linux/mm/page_alloc.c	Sun Jul 19 13:39:02 1998
@@ -312,22 +312,23 @@
 {
 	mem_map_t * p;
 	unsigned long mask = PAGE_MASK;
-	int i;
+	unsigned long i;
 
 	/*
 	 * Select nr of pages we try to keep free for important stuff
-	 * with a minimum of 48 pages and a maximum of 256 pages, so
+	 * with a minimum of 10 pages and a maximum of 256 pages, so
 	 * that we don't waste too much memory on large systems.
-	 * This is totally arbitrary.
+	 * This is fairly arbitrary, but based on some behaviour
+	 * analysis.
 	 */
 	i = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT+7);
-	if (i < 48)
-		i = 48;
+	if (i < 10)
+		i = 10;
 	if (i > 256)
 		i = 256;
 	freepages.min = i;
-	freepages.low = i << 1;
-	freepages.high = freepages.low + i;
+	freepages.low = i * 2;
+	freepages.high = i * 3;
 	mem_map = (mem_map_t *) LONG_ALIGN(start_mem);
 	p = mem_map + MAP_NR(end_mem);
 	start_mem = LONG_ALIGN((unsigned long) p);
diff -u --recursive --new-file v2.1.109/linux/mm/page_io.c linux/mm/page_io.c
--- v2.1.109/linux/mm/page_io.c	Wed Jun 24 22:54:14 1998
+++ linux/mm/page_io.c	Fri Jul 17 11:40:58 1998
@@ -74,18 +74,19 @@
 		return;
 	}
 	if (p->swap_map && !p->swap_map[offset]) {
-		printk("Hmm.. Trying to %s unallocated swap (%08lx)\n", 
-		       (rw == READ) ? "read" : "write", 
-		       entry);
+		printk(KERN_ERR "rw_swap_page: "
+			"Trying to %s unallocated swap (%08lx)\n", 
+			(rw == READ) ? "read" : "write", entry);
 		return;
 	}
 	if (!(p->flags & SWP_USED)) {
-		printk("Trying to swap to unused swap-device\n");
+		printk(KERN_ERR "rw_swap_page: "
+			"Trying to swap to unused swap-device\n");
 		return;
 	}
 
 	if (!PageLocked(page)) {
-		printk("VM: swap page is unlocked\n");
+		printk(KERN_ERR "VM: swap page is unlocked\n");
 		return;
 	}
 	
@@ -111,11 +112,11 @@
 	 * hashing for locked pages.
 	 */
 	if (!PageSwapCache(page)) {
-		printk("VM: swap page is not in swap cache\n");
+		printk(KERN_ERR "VM: swap page is not in swap cache\n");
 		return;
 	}
 	if (page->offset != entry) {
-		printk ("swap entry mismatch");
+		printk (KERN_ERR "VM: swap entry mismatch\n");
 		return;
 	}
 
@@ -179,11 +180,14 @@
 		clear_bit(PG_locked, &page->flags);
 		wake_up(&page->wait);
 	} else
-		printk("rw_swap_page: no swap file or device\n");
+		printk(KERN_ERR "rw_swap_page: no swap file or device\n");
 
+	/* This shouldn't happen, but check to be sure. */
+	if (atomic_read(&page->count) == 1)
+		printk(KERN_ERR "rw_swap_page: page unused while waiting!\n");
 	atomic_dec(&page->count);
 	if (offset && !test_and_clear_bit(offset,p->swap_lockmap))
-		printk("rw_swap_page: lock already cleared\n");
+		printk(KERN_ERR "rw_swap_page: lock already cleared\n");
 	wake_up(&lock_queue);
 #ifdef DEBUG_SWAP
 	printk ("DebugVM: %s_swap_page finished on page %p (count %d)\n",
diff -u --recursive --new-file v2.1.109/linux/mm/vmalloc.c linux/mm/vmalloc.c
--- v2.1.109/linux/mm/vmalloc.c	Tue Jun 23 10:01:30 1998
+++ linux/mm/vmalloc.c	Mon Jul 20 14:00:06 1998
@@ -152,19 +152,21 @@
 
 struct vm_struct * get_vm_area(unsigned long size)
 {
-	void *addr;
+	unsigned long addr;
 	struct vm_struct **p, *tmp, *area;
 
 	area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
 	if (!area)
 		return NULL;
-	addr = (void *) VMALLOC_START;
+	addr = VMALLOC_START;
 	for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {
-		if (size + (unsigned long) addr < (unsigned long) tmp->addr)
+		if (size + addr < (unsigned long) tmp->addr)
 			break;
-		addr = (void *) (tmp->size + (unsigned long) tmp->addr);
+		if (addr > VMALLOC_END-size)
+			return NULL;
+		addr = tmp->size + (unsigned long) tmp->addr;
 	}
-	area->addr = addr;
+	area->addr = (void *)addr;
 	area->size = size + PAGE_SIZE;
 	area->next = *p;
 	*p = area;
diff -u --recursive --new-file v2.1.109/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.1.109/linux/mm/vmscan.c	Thu Jul 16 18:09:30 1998
+++ linux/mm/vmscan.c	Mon Jul 20 10:37:39 1998
@@ -533,7 +533,6 @@
 	add_wait_queue(&kswapd_wait, &wait);
 	while (1) {
 		int tries;
-		int tried = 0;
 
 		current->state = TASK_INTERRUPTIBLE;
 		flush_signals(current);
@@ -594,9 +593,10 @@
 	int retval;
 
 	lock_kernel();
-	retval = 0;
 	do {
-		retval |= do_try_to_free_page(gfp_mask);
+		retval = do_try_to_free_page(gfp_mask);
+		if (!retval)
+			break;
 		count--;
 	} while (count > 0);
 	unlock_kernel();
diff -u --recursive --new-file v2.1.109/linux/net/appletalk/aarp.c linux/net/appletalk/aarp.c
--- v2.1.109/linux/net/appletalk/aarp.c	Wed Jun 24 22:54:14 1998
+++ linux/net/appletalk/aarp.c	Mon Jul 20 17:23:32 1998
@@ -21,6 +21,9 @@
  *
  *	References:
  *		Inside AppleTalk (2nd Ed).
+ *	Fixes:
+ *		Jaume Grau	-	flush caches on AARP_PROBE
+ *
  */
 
 #include <linux/config.h>
@@ -773,6 +776,21 @@
 			sa.s_node=ea->pa_dst_node;
 			sa.s_net=ea->pa_dst_net;
 			
+			if(ea->function==AARP_PROBE)
+			{
+				/* A probe implies someone trying to get an
+				   address. So as a precaution flush any
+				   entries we have for this address */
+				struct aarp_entry *a=aarp_find_entry(
+						resolved[sa.s_node%(AARP_HASH_SIZE-1)],
+						skb->dev,
+						&sa);
+				/* Make it expire next tick - that avoids us
+				   getting into a probe/flush/learn/probe/flush/learn
+				   cycle during probing of a slow to respond host addr */
+				if(a!=NULL)
+					a->expires_at=jiffies-1;
+			}
 			if(sa.s_node!=ma->s_node)
 				break;
 			if(sa.s_net && ma->s_net && sa.s_net!=ma->s_net)
diff -u --recursive --new-file v2.1.109/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v2.1.109/linux/net/appletalk/ddp.c	Wed Jun 24 22:54:14 1998
+++ linux/net/appletalk/ddp.c	Mon Jul 20 17:23:32 1998
@@ -1254,6 +1254,7 @@
 	struct atalk_iface *atif;
 	struct sockaddr_at tosat;
         int origlen;
+        struct ddpebits ddphv;
 
 	/* Size check */
 	if(skb->len < sizeof(*ddp))
@@ -1272,7 +1273,7 @@
 	 *	run until we put it back)
 	 */
 
-	*((__u16 *)ddp) = ntohs(*((__u16 *)ddp));
+	*((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
 
 	/*
 	 * Trim buffer in case of stray trailing data
@@ -1280,7 +1281,7 @@
 
 	origlen = skb->len;
 
-	skb_trim(skb, min(skb->len, ddp->deh_len));
+	skb_trim(skb, min(skb->len, ddphv.deh_len));
 
 	/*
 	 * Size check to see if ddp->deh_len was crap
@@ -1297,7 +1298,7 @@
 	 * Any checksums. Note we don't do htons() on this == is assumed to be
 	 * valid for net byte orders all over the networking code...
 	 */
-	if(ddp->deh_sum && atalk_checksum(ddp, ddp->deh_len) != ddp->deh_sum)
+	if(ddp->deh_sum && atalk_checksum(ddp, ddphv.deh_len) != ddp->deh_sum)
 	{
 		/* Not a valid AppleTalk frame - dustbin time */
 		kfree_skb(skb);
@@ -1349,12 +1350,12 @@
 
 		/* Route the packet */
 		rt = atrtr_find(&ta);
-		if(rt == NULL || ddp->deh_hops == DDP_MAXHOPS)
+		if(rt == NULL || ddphv.deh_hops == DDP_MAXHOPS)
 		{
 			kfree_skb(skb);
 			return (0);
 		}
-		ddp->deh_hops++;
+		ddphv.deh_hops++;
 
 		/*
 		 * Route goes through another gateway, so
@@ -1368,10 +1369,10 @@
 
                 /* Fix up skb->len field */
                 skb_trim(skb, min(origlen, rt->dev->hard_header_len +
-			ddp_dl->header_length + ddp->deh_len));
+			ddp_dl->header_length + ddphv.deh_len));
 
 		/* Mend the byte order */
-		*((__u16 *)ddp) = ntohs(*((__u16 *)ddp));
+		*((__u16 *)ddp) = ntohs(*((__u16 *)&ddphv));
 
 		/*
 		 * Send the buffer onwards
@@ -1711,18 +1712,22 @@
 	struct sock *sk=sock->sk;
 	struct sockaddr_at *sat=(struct sockaddr_at *)msg->msg_name;
 	struct ddpehdr	*ddp = NULL;
+        struct ddpebits ddphv;
 	int copied = 0;
 	struct sk_buff *skb;
 	int err = 0;
 
+
 	skb = skb_recv_datagram(sk,flags&~MSG_DONTWAIT,flags&MSG_DONTWAIT,&err);
 	if(skb == NULL)
 		return (err);
 
 	ddp = (struct ddpehdr *)(skb->h.raw);
+	*((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
+
 	if(sk->type == SOCK_RAW)
 	{
-		copied = ddp->deh_len;
+		copied = ddphv.deh_len;
 		if(copied > size)
 		{
 			copied = size;
@@ -1733,7 +1738,7 @@
 	}
 	else
 	{
-		copied = ddp->deh_len - sizeof(*ddp);
+		copied = ddphv.deh_len - sizeof(*ddp);
 		if(copied > size)
 		{
 			copied = size;
diff -u --recursive --new-file v2.1.109/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.1.109/linux/net/ipv4/tcp.c	Tue Jun 23 10:01:31 1998
+++ linux/net/ipv4/tcp.c	Thu Jul 16 19:43:24 1998
@@ -580,7 +580,7 @@
 		/* Always wake the user up when an error occurred */
 		if (sock_wspace(sk) >= space || sk->err)
 			mask |= POLLOUT | POLLWRNORM;
-		if (tp->urg_data)
+		if (tp->urg_data & URG_VALID)
 		    	mask |= POLLPRI;
 	}
 	return mask;
diff -u --recursive --new-file v2.1.109/linux/net/sched/sch_api.c linux/net/sched/sch_api.c
--- v2.1.109/linux/net/sched/sch_api.c	Thu Jul 16 18:09:32 1998
+++ linux/net/sched/sch_api.c	Sat Jul 18 11:48:24 1998
@@ -9,10 +9,6 @@
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  */
 
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -29,9 +25,14 @@
 #include <linux/rtnetlink.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
+
 #include <net/sock.h>
 #include <net/pkt_sched.h>
 
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
 
 #define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
 
diff -u --recursive --new-file v2.1.109/linux/net/sunrpc/clnt.c linux/net/sunrpc/clnt.c
--- v2.1.109/linux/net/sunrpc/clnt.c	Mon Feb 23 18:12:15 1998
+++ linux/net/sunrpc/clnt.c	Mon Jul 20 17:22:35 1998
@@ -203,6 +203,10 @@
 	unsigned long	irqflags;
 	int		async, status;
 
+	/* If this client is slain all further I/O fails */
+	if (clnt->cl_dead) 
+		return -EIO;
+		
 	/* Turn off various signals */
 	if (clnt->cl_intr) {
 		struct k_sigaction *action = current->sig->action;
@@ -637,7 +641,8 @@
 	 * The following is an NFS-specific hack to cater for setuid
 	 * processes whose uid is mapped to nobody on the server.
 	 */
-	if (task->tk_client->cl_prog == 100003 && ntohl(*p) == NFSERR_PERM) {
+	if (task->tk_client->cl_prog == 100003 && 
+            (ntohl(*p) == NFSERR_ACCES || ntohl(*p) == NFSERR_PERM)) {
 		if (RPC_IS_SETUID(task) && (task->tk_suid_retry)--) {
 			dprintk("RPC: %4d retry squashed uid\n", task->tk_pid);
 			task->tk_flags ^= RPC_CALL_REALUID;
diff -u --recursive --new-file v2.1.109/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c
--- v2.1.109/linux/net/sunrpc/sched.c	Mon Jan 19 13:57:37 1998
+++ linux/net/sunrpc/sched.c	Mon Jul 20 14:34:12 1998
@@ -466,10 +466,12 @@
 	struct rpc_task	*task;
 	int		count = 0;
 	unsigned long	oldflags;
+	int need_resched = current->need_resched;
 
 	dprintk("RPC:      rpc_schedule enter\n");
+	save_flags(oldflags);
 	while (1) {
-		save_flags(oldflags); cli();
+		cli();
 		if (!(task = schedq.task))
 			break;
 		rpc_del_timer(task);
diff -u --recursive --new-file v2.1.109/linux/net/sunrpc/sunrpc_syms.c linux/net/sunrpc/sunrpc_syms.c
--- v2.1.109/linux/net/sunrpc/sunrpc_syms.c	Fri Dec 19 10:54:10 1997
+++ linux/net/sunrpc/sunrpc_syms.c	Mon Jul 20 17:22:35 1998
@@ -40,6 +40,7 @@
 EXPORT_SYMBOL(rpc_create_client);
 EXPORT_SYMBOL(rpc_destroy_client);
 EXPORT_SYMBOL(rpc_shutdown_client);
+EXPORT_SYMBOL(rpc_killall_tasks);
 EXPORT_SYMBOL(rpc_do_call);
 EXPORT_SYMBOL(rpc_call_setup);
 EXPORT_SYMBOL(rpc_delay);
diff -u --recursive --new-file v2.1.109/linux/scripts/Makefile linux/scripts/Makefile
--- v2.1.109/linux/scripts/Makefile	Mon Jan  5 01:41:01 1998
+++ linux/scripts/Makefile	Mon Jul 20 10:05:16 1998
@@ -1,4 +1,3 @@
-HOSTCFLAGS:=$(HOSTCFLAGS) -g -Wall
 HEADER=header.tk
 TAIL=tail.tk
 
diff -u --recursive --new-file v2.1.109/linux/scripts/lxdialog/Makefile linux/scripts/lxdialog/Makefile
--- v2.1.109/linux/scripts/lxdialog/Makefile	Sat Apr 20 01:18:14 1996
+++ linux/scripts/lxdialog/Makefile	Mon Jul 20 10:05:16 1998
@@ -1,8 +1,7 @@
-CC = gcc
-CPP = gcc -E
-OPTIM = -O2 -Wall -fomit-frame-pointer
+CC = $(HOSTCC)
+CPP = $(HOSTCC) -E
 
-CFLAGS = $(OPTIM) -DLOCALE 
+CFLAGS = $(HOSTCFLAGS) -DLOCALE 
 LDFLAGS = -s -L .
 LDLIBS = -lncurses
 
diff -u --recursive --new-file v2.1.109/linux/scripts/lxdialog/menubox.c linux/scripts/lxdialog/menubox.c
--- v2.1.109/linux/scripts/lxdialog/menubox.c	Sat Apr 27 03:18:18 1996
+++ linux/scripts/lxdialog/menubox.c	Mon Jul 20 17:23:32 1998
@@ -19,6 +19,37 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/*
+ *  Changes by Clifford Wolf (god@clifford.at)
+ *
+ *  [ 1998-06-13 ]
+ *
+ *    *)  A bugfix for the Page-Down problem
+ *
+ *    *)  Formerly when I used Page Down and Page Up, the cursor would be set 
+ *        to the first position in the menu box.  Now lxdialog is a bit
+ *        smarter and works more like other menu systems (just have a look at
+ *        it).
+ *
+ *    *)  Formerly if I selected something my scrolling would be broken because
+ *        lxdialog is re-invoked by the Menuconfig shell script, can't
+ *        remember the last scrolling position, and just sets it so that the
+ *        cursor is at the bottom of the box.  Now it writes the temporary file
+ *        lxdialog.scrltmp which contains this information. The file is
+ *        deleted by lxdialog if the user leaves a submenu or enters a new
+ *        one, but it would be nice if Menuconfig could make another "rm -f"
+ *        just to be sure.  Just try it out - you will recognise a difference!
+ *
+ *  [ 1998-06-14 ]
+ *
+ *    *)  Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
+ *        and menus change their size on the fly.
+ *
+ *    *)  If for some reason the last scrolling position is not saved by
+ *        lxdialog, it sets the scrolling so that the selected item is in the
+ *        middle of the menu box, not at the bottom.
+ */
+
 #include "dialog.h"
 
 static int menu_width, item_x;
@@ -123,6 +154,7 @@
     int i, j, x, y, box_x, box_y;
     int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice;
     WINDOW *dialog, *menu;
+    FILE *f;
 
     max_choice = MIN (menu_height, item_no);
 
@@ -178,9 +210,26 @@
 
     item_x = (menu_width - item_x) / 2;
 
-    if (choice >= max_choice){
-	scroll = first_item = choice - max_choice + 1;
-	choice = max_choice-1;
+    /* get the scroll info from the temp file */
+    if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) {
+	if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) &&
+	     (scroll+max_choice > choice) && (scroll >= 0) &&
+	     (scroll+max_choice <= item_no) ) {
+	    first_item = scroll;
+	    choice = choice - scroll;
+	    fclose(f);
+	} else {
+	    remove("lxdialog.scrltmp");
+	    fclose(f);
+	    f=NULL;
+	}
+    }
+    if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) {
+	if (choice >= item_no-max_choice/2)
+	    scroll = first_item = item_no-max_choice;
+	else
+	    scroll = first_item = choice - max_choice/2;
+	choice = choice - scroll;
     }
 
     /* Print the menu */
@@ -262,26 +311,34 @@
 
 	    } else if (key == KEY_PPAGE) {
 	        scrollok (menu, TRUE);
-                for (i=0; (i < max_choice) && (scroll > 0); i++) {
-                    wscrl (menu, -1);
-                    scroll--;
-                    print_item (menu, items[scroll * 2 + 1], 0, FALSE,
-                               (items[scroll*2][0] != ':'));
+                for (i=0; (i < max_choice); i++) {
+                    if (scroll > 0) {
+                	wscrl (menu, -1);
+                	scroll--;
+                	print_item (menu, items[scroll * 2 + 1], 0, FALSE,
+                	(items[scroll*2][0] != ':'));
+                    } else {
+                        if (choice > 0)
+                            choice--;
+                    }
                 }
                 scrollok (menu, FALSE);
-                choice = 0;
 
             } else if (key == KEY_NPAGE) {
-	        scrollok (menu, TRUE);
-                for (i=0; (i < max_choice) && (scroll+max_choice < item_no); i++) {
-		    scroll(menu);
-                    scroll++;
-                    print_item (menu, items[(scroll+max_choice-1)*2+1],
-                                max_choice-1, FALSE,
-                                (items[(scroll+max_choice-1)*2][0] != ':'));
+                for (i=0; (i < max_choice); i++) {
+                    if (scroll+max_choice < item_no) {
+			scrollok (menu, TRUE);
+			scroll(menu);
+			scrollok (menu, FALSE);
+                	scroll++;
+                	print_item (menu, items[(scroll+max_choice-1)*2+1],
+			            max_choice-1, FALSE,
+			            (items[(scroll+max_choice-1)*2][0] != ':'));
+		    } else {
+			if (choice+1 < max_choice)
+			    choice++;
+		    }
                 }
-                scrollok (menu, FALSE);
-                choice = 0;
 
             } else
                 choice = i;
@@ -313,6 +370,11 @@
 	case 'y':
 	case 'n':
 	case 'm':
+	    /* save scroll info */
+	    if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) {
+		fprintf(f,"%d\n",scroll);
+		fclose(f);
+	    }
 	    delwin (dialog);
             fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
             switch (key) {
@@ -336,6 +398,7 @@
 	    else
             	fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
 
+	    remove("lxdialog.scrltmp");
 	    return button;
 	case 'e':
 	case 'x':
@@ -346,5 +409,6 @@
     }
 
     delwin (dialog);
+    remove("lxdialog.scrltmp");
     return -1;			/* ESC pressed */
 }
