diff -u --recursive --new-file v2.1.130/linux/CREDITS linux/CREDITS
--- v2.1.130/linux/CREDITS	Fri Nov 27 13:09:20 1998
+++ linux/CREDITS	Tue Dec  1 09:39:09 1998
@@ -1116,11 +1116,11 @@
 D: SCSI Tape Driver
 
 N: Hamish Macdonald
-E: hamish@border.ocunix.on.ca
+E: hamish_macdonald@westendsys.com
 D: Linux/68k port
-S: 102-B Valleystream Drive
-S: Nepean, Ontario
-S: Canada K2H-9E1
+S: 32 Clydesdale Avenue
+S: Kanata, Ontario
+S: Canada K2M-2G7
 
 N: Peter MacDonald
 D: SLS distribution
@@ -2074,7 +2074,7 @@
 S: USA
 
 N: Marc Zyngier
-E: maz@gloups.fdn.fr
+E: maz@wild-wind.fr.eu.org
 D: MD driver
 S: 11 rue Victor HUGO
 S: 95560 Montsoult
diff -u --recursive --new-file v2.1.130/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.130/linux/Documentation/Configure.help	Fri Nov 27 13:09:21 1998
+++ linux/Documentation/Configure.help	Tue Dec  1 19:05:05 1998
@@ -2397,9 +2397,6 @@
   information on the WWW at
   http://www.tor.shaw.wave.ca/~ambrose/kernel21.html. 
 
-  If you say Y here, you should also say Y to "IP: always defragment",
-  below. 
-
   If you say Y here, then the modules ip_masq_ftp.o (for ftp file
   transfers), ip_masq_irc.o (for irc chats), ip_masq_quake.o (you
   guessed it), ip_masq_vdolive.o (for VDOLive video connections),
@@ -2503,7 +2500,7 @@
   The module will be called ip_masq_markfw.o. If you want to compile
   it as a module, say M here and read Documentation/modules.txt.
 
-IP: always defragment 
+IP: always defragment (required for masquerading)
 CONFIG_IP_ALWAYS_DEFRAG
   If you say Y here, then all incoming fragments (parts of IP packets
   that arose when some host between origin and destination decided
@@ -2511,18 +2508,13 @@
   reassembled (defragmented) before being processed, even if they are
   about to be forwarded.
 
-  This option is highly recommended if you have said Y to "IP:
-  masquerading" because that facility requires that second and further
-  fragments can be related to TCP or UDP port numbers, which are only
-  stored in the first fragment.
+  You must say Y here if you want to enable "IP: masquerading" or "IP:
+  transparent proxying".
 
   When using "IP: firewalling" support, you might also want to say Y
   here, to have a more reliable firewall (otherwise second and further
   fragments must be dealt with by the firewall, which can be tricky).
 
-  When using "IP: transparent proxying", this option is implicit,
-  although it is safe to say Y here.
-
   Only say Y here if running either a firewall that is the sole link
   to your network or a transparent proxy; never ever say Y here for a
   normal router or host.
@@ -3868,7 +3860,7 @@
 
 NCR53C8XX SCSI support
 CONFIG_SCSI_NCR53C8XX
-  This is the BSD ncr driver adapted to linux for the NCR53C8XX family
+  This is the BSD ncr driver adapted to Linux for the NCR53C8XX family
   of PCI-SCSI controllers. This driver supports parity checking,
   tagged command queuing and fast synchronous data transfers up to 80
   MB/s with wide FAST-40 LVD devices and controllers.
@@ -8328,6 +8320,16 @@
   ignored. Without this the Thinkpad 560 has troubles with the user
   level daemon apmd, and with the PCMCIA package pcmcia-cs.
 
+Ignore multiple suspend/resume cycles
+CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+  This option is necessary on the Dell Inspiron 3200, but should be
+  safe for all other laptops. When enabled, a system suspend event
+  that occurs within one second of a resume is ignored. Without this
+  the Inspiron will shut itself off a few seconds after you open the
+  lid, requiring you to press the power button to resume it a second
+  time.
+  Say Y.
+
 Watchdog Timer Support 
 CONFIG_WATCHDOG
   If you say Y here (and to one of the following options) and create a
@@ -8490,13 +8492,14 @@
   The module will be called joystick.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-Classic PC analog joysticks
+Classic PC analog joysticks and gamepads
 CONFIG_JOY_ANALOG
   Say Y here if you have an analog joystick or gamepad that connects
   to the PC gameport. This supports many different types, including
-  joysticks with throttle control, and with CHF / FCS / 6-button
-  extensions. For more information on how to use the driver please
-  read Documentation/joystick.txt
+  joysticks with throttle control, with rudders, or with extensions
+  like additional hats and buttons compatible with CH Flightstick Pro,
+  ThrustMaster FCS or 6 and 8 button gamepads. For more information on
+  how to use the driver please read Documentation/joystick.txt
 
 FPGaming and MadCatz A3D controllers
 CONFIG_JOY_ASSASIN
@@ -8504,25 +8507,26 @@
   MadCatz Panther XL. For more information on how to use the driver
   please read Documentation/joystick.txt
 
-Gravis GrIP gamepads
+Gravis GrIP joysticks and gamepads
 CONFIG_JOY_GRAVIS
-  Say Y here if you have a Gravis GamePad Pro. For more information
-  on how to use the driver please read Documentation/joystick.txt
+  Say Y here if you have a Gravis GamePad Pro, Gravis Xterminator or
+  Gravis Blackhawk Digital. For more information on how to use the
+  driver please read Documentation/joystick.txt
 
-PDPI Lightning L4 gamecards
+PDPI Lightning 4 gamecards
 CONFIG_JOY_LIGHTNING
-  Say Y here if you have a PDPI Lightning L4 gamecard and an analog
+  Say Y here if you have a PDPI Lightning 4 gamecard and an analog
   joystick or gamepad connected to it. For more information on how to
   use the driver please read Documentation/joystick.txt
 
-Logitech Digital joysticks
+Logitech Digital joysticks and gamepads
 CONFIG_JOY_LOGITECH
   Say Y here if you have a Logitech WingMan Extreme Digital,
   Logitech ThunderPad Digital or Logitech CyberMan 2. For more
   information on how to use the driver please read
   Documentation/joystick.txt
 
-Microsoft SideWinder, Genius Digital joysticks
+Microsoft SideWinder, Genius Digital joysticks and gamepads
 CONFIG_JOY_SIDEWINDER
   Say Y here if you have a Microsoft SideWinder 3d Pro, Microsoft
   SideWinder Precision Pro, Microsoft SideWinder Force Feedback Pro,
@@ -8530,34 +8534,35 @@
   more information on how to use the driver please read
   Documentation/joystick.txt
 
-ThrustMaster DirectConnect (BSP) joysticks
+ThrustMaster DirectConnect joysticks and gamepads
 CONFIG_JOY_THRUSTMASTER
-  Say Y here if you have a ThrustMaster Millenium 3D Inceptor,
-  ThrustMaster 3D Rage Pad, or ThrustMaster WCS III. For more
-  information on how to use the driver please read
-  Documentation/joystick.txt
+  Say Y here if you have a ThrustMaster Millenium 3D Inceptor or a
+  ThrustMaster 3D Rage Pad. For more information on how to use the
+  driver please read Documentation/joystick.txt
 
-NES, SNES, PSX, Multisystem gamepads
+NES, SNES, PSX, Multisystem joysticks and gamepads
 CONFIG_JOY_CONSOLE
   Say Y here if you have a Nintendo Entertainment System gamepad,
   Super Nintendo Entertainment System gamepad, Sony PlayStation
   gamepad or a Multisystem -- Atari, Amiga, Commodore, Amstrad CPC
   joystick. For more information on how to use the driver please read
-  Documentation/joystick.txt
+  Documentation/joystick.txt and Documentation/joystick-parport.txt
 
-Sega, Multisystem gamepads
+Sega, Multisystem joysticks and gamepads
 CONFIG_JOY_DB9
   Say Y here if you have a Sega Master System gamepad, Sega Genesis
   gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
   Commodore, Amstrad CPC joystick. For more information on how to use
-  the driver please read Documentation/joystick.txt
+  the driver please read Documentation/joystick.txt and
+  Documentation/joystick-parport.txt
 
 TurboGraFX Multisystem joystick interface
 CONFIG_JOY_TURBOGRAFX
   Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
   and want to use it with Multiststem -- Atari, Amiga, Commodore,
   Amstrad CPC joystick. For more information on how to use the driver
-  please read Documentation/joystick-parport.txt
+  please read Documentation/joystick-parport.txt and
+  Documentation/joystick-parport.txt
 
 Amiga joysticks
 CONFIG_JOY_AMIGA
diff -u --recursive --new-file v2.1.130/linux/Documentation/joystick-parport.txt linux/Documentation/joystick-parport.txt
--- v2.1.130/linux/Documentation/joystick-parport.txt	Fri Oct 23 22:01:18 1998
+++ linux/Documentation/joystick-parport.txt	Tue Dec  1 19:05:05 1998
@@ -506,14 +506,14 @@
 ~~~~~~~~~~~~~~~~~~~~
   The joy-turbografx.c driver uses a very simple kernel/module command line:
 
-	js_tg=port,count
+	js_tg=port,js1,js2,js3,js4,js5,js6,js7
 
   Where 'port' is either the address of the parallel port the interface is
 connected to (eg. 0x378), or, if you are using the parport driver of 2.1+
 Linux kernels, the number of the parport interface (eg. 0 for parport0).
 
-  'Count' is the number of Multisystem, 1-button joysticks connected to the
-interface.
+  'jsX' is the number of buttons the Multisystem joysticks connected to the
+interface ports 1-7 have. For a standard multisystem joystick, this is 1.
 
   Should you want to use more than one of these interfaces at once, you can
 use js_tg_2 and js_tg_3 as additional command line parameters for two more
diff -u --recursive --new-file v2.1.130/linux/Documentation/joystick.txt linux/Documentation/joystick.txt
--- v2.1.130/linux/Documentation/joystick.txt	Fri Oct 23 22:01:18 1998
+++ linux/Documentation/joystick.txt	Tue Dec  1 19:05:05 1998
@@ -1,4 +1,4 @@
-		     Linux Joystick driver v1.2.12
+		     Linux Joystick driver v1.2.13
 	       (c) 1996-1998 Vojtech Pavlik <vojtech@ucw.cz>
 ----------------------------------------------------------------------------
 
@@ -30,10 +30,11 @@
   The joystick driver for Linux provides support for a variety of joysticks
 and similar devices.
 
-  These currently include various analog joysticks (both variable resistor
-based and microswitch+resistor based), following IBM PC joystick standard,
-with extensions like additional hats and buttons compatible with CH
-Flightstick Pro, ThrustMaster FCS or 6 and 8 button gamepads.
+  These currently include various analog joysticks and gamepads (both
+variable resistor based and microswitch+resistor based), following IBM PC
+joystick standard, with extensions like additional hats and buttons
+compatible with CH Flightstick Pro, ThrustMaster FCS or 6 and 8 button
+gamepads.
 
   In addition to these it also supports some of the new PC joysticks that
 use proprietary digital protocols to communicate over the gameport,
@@ -54,13 +55,23 @@
 this driver can't make complete use of, I'm very interested in hearing about
 them. Bug reports and success stories are also welcome.
 
-  The joystick package is available at the following FTP site:
+  The joystick package is available at the following FTP sites:
 
-	ftp://atrey.karlin.mff.cuni.cz/pub/linux/joystick/joystick-1.2.x.tar.gz
+	ftp://atrey.karlin.mff.cuni.cz/pub/linux/joystick/
+	ftp://artax.karlin.mff.cuni.cz/pub/linux/joystick/
+
+  The joystick driver is also included in the Linux 2.1 kernels:
+
+	ftp://linux.kernel.org/pub/linux/kernel/v2.1/
 
   And a homepage of the driver is at:
 
 	http://atrey.karlin.mff.cuni.cz/~vojtech/joystick/
+	http://artax.karlin.mff.cuni.cz/~vojtech/joystick/
+
+  A mirror of the homepage is at:
+
+	http://www.trylinux.com/projects/joystick/
 
   There is also a mailing list for the driver at:
 
@@ -70,27 +81,42 @@
 
 2. Usage
 ~~~~~~~~
-  To use the driver as a standalone module, without patching the kernel, you
-first need to edit the Makefile to meet your needs (namely whether you use
-MODVERSIONS). Then you compile the driver by typing
+  You could have obtained this driver in two different ways - either in the
+joystick package or in the kernel. Because, for successful usage of the
+joysticks, the utilities in the package are useful, maybe necessary, and
+definitely recommended, I suggest you getting the package at some of the
+above mentioned locations. The rest of this file assumes you have it.
+
+2.1 Compiling the driver package
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  To compile the utilities in the joystick package, and the driver itself,
+as a standalone module, you first unpack the package, and then edit the
+Makefile to meet your needs (namely whether are you using versioned
+modules). Then you compile it
 
 	make
 
-  And after compiling you first
+  And after that you install it
 
-	insmod joystick.o
+	make install
 
-  and then
+  In case you have not used the driver before, you'll need to create the
+joystick device files in /dev so that applications can use them:
 
-	insmod joy-something.o
+	make devs
 
-  where 'something' is the type of your joystick. See below for more precise
-explanation. Of course, you can insmod more than one hardware specific
-module at once, if you have more than one joystick installed.
+  For manual creation of the joystick devices, check the
+Documentation/devices.txt file in the Linux source tree.
 
-  If you want to have the driver compiled into your kernel, you first need
-to patch the kernel, so that it contains the current driver version. You do
-that with a command: 
+  Should you not want to mess with the kernel, and just use the driver
+standalone, as modules, skip the next two sections, proceeding right to 2.4,
+because all you need is already done.
+
+2.2 Patching the kernel
+~~~~~~~~~~~~~~~~~~~~~~~
+  If you already have the most recent joystick driver in your kernel, skip
+this section. If not, you need to patch the kernel, so that it contains the
+current driver version.  You do that with a command: 
 
 	patch -Esp1 < /usr/src/joystick-1.2.x/kernel-2.x.y.diff
 
@@ -98,29 +124,101 @@
 
 	/usr/src/linux
 
+2.3 Compiling the kernel
+~~~~~~~~~~~~~~~~~~~~~~~~
   To compile joystick support into the kernel, use the kernel configuration
 scripts, and answer 'Y' to Joystick support and also to at least one of the
-hardware specific options.
+hardware specific options. After doing something like
+
+	make bzlilo
+
+  you are done with the driver installation. Just reboot and the driver
+should find all the connected joysticks. Read the notes about the hardware
+specific drivers later in this file, though.
 
   You can also compile the driver as modules, answering 'M' to all joystick
 support you want to have modules for. It is possible to have the main
 joystick driver compiled into the kernel and the hardware dependent drivers
-as modules.
+as modules. After you compile the modules 
 
-  After you're done with installation of the driver itself, you'll need to
-create the joystick device files in /dev so that applications can use them.
-This is done by typing
+	make modules
 
-	make devs
+  And install them
+
+	make modules_install
+
+ you're set, and can proceed to the next step.
+
+2.4 Inserting the modules into the kernel
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  After installing the modules you'll first need to insert the generic
+joystick driver module into the kernel
+
+	insmod joystick
+
+  and then one or more of the hardware specific modules
+
+	insmod joy-something
+
+  where 'something' is the type of your joystick. See below for more precise
+explanation.
+
+2.5 Verifying that it works
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  For testing the joystick driver functionality, there is the jstest
+program. You run it by typing:
+
+	jstest /dev/js0
+
+  And it should show a line with the joystick values, which update as you
+move the stick, and press its buttons. The axes should all be zero when the
+joystick is in the center position. They should not jitter by themselves to
+other close values, and they also should be steady in any other position of
+the stick. They should have the full range from -32767 to 32767. If all this
+is met, then it's all fine, and you can play the games. :)
+
+  If it's not, then there might be a problem. Try to calibrate the joystick,
+and if it still doesn't work, read the drivers section of this file, the
+troubleshooting section, and the FAQ.
+
+2.6. Calibration
+~~~~~~~~~~~~~~~~
+  For most joysticks you won't need any manual calibration, since the
+joystick should be autocalibrated by the driver automagically. However, with
+some analog joysticks, that either do not use linear resistors, or if you
+want better precision, you can use the jscal program
+
+	jscal -c /dev/js0
+
+ included in the joystick package to set better correction coefficients than
+what the driver would choose itself.
+
+  After calibrating the joystick you can verify if you like the new
+calibration using the jstest command, and if you do, you then can save the
+correction coefficients into a file
+
+	jscal -s /dev/js0 > /etc/joystick.cal
 
-in the joystick driver's directory. For manual creation of the joystick
-devices, check the Documentation/devices.txt file in the Linux source tree.
+  And add a line to your rc script executing that file
 
-2.1 Analog joysticks
+	source /etc/joystick.cal
+
+  This way, after the next reboot your joystick will remain calibrated. You
+can also add the jscal -s line to your shutdown script.
+
+
+3. HW specific driver information
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In this section each of the separate hardware specific drivers is described.
+
+3.1 Analog joysticks
 ~~~~~~~~~~~~~~~~~~~~
-  The joy-analog.c uses the standard analog inputs of the gameport, and
-thus supports all standard joysticks. However the only types that can be
-autodetected are:
+  The joy-analog.c uses the standard analog inputs of the gameport, and thus
+supports all standard joysticks and gamepads. It also supports extensions
+like additional hats and buttons compatible with CH Flightstick Pro,
+ThrustMaster FCS or 6 and 8 button gamepads. 
+
+  However the only types that can be autodetected are:
 
 * 2-axis, 4-button joystick
 * 3-axis, 4-button joystick
@@ -204,7 +302,7 @@
   And it would do the same as the above explained command line. Use
 whichever way you like best.
 
-2.2 Microsoft SideWinder and Genius Digital joysticks
+3.2 Microsoft SideWinder and Genius Digital joysticks
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   SideWinder and Genius Digital joysticks are supported by the
 joy-sidewinder.c module. All currently supported joysticks:
@@ -221,7 +319,7 @@
 by the analog driver described above. SideWinder FreeStyle Pro and
 SideWinder Force Feedback Wheel are not supported yet.
 
-2.3 Logitech Digital joysticks
+3.3 Logitech Digital joysticks
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   Logitech Digital joysticks are supported by the joy-logitech.c module. It
 currently supports these devices:
@@ -239,24 +337,25 @@
 Formula, Wingman Formula Force, Wingman Gamepad, Wingman Interceptor are USB
 joysticks, with optional serial port connection, and are not supported yet.
 
-2.4 Gravis GrIP
+3.4 Gravis GrIP
 ~~~~~~~~~~~~~~~
   Gravis GrIP gamepads are supported by the joy-gravis.c module. It
-currently supports only:
+currently supports:
 
 * Gravis GamePad Pro
 * Gravis Xterminator
+* Gravis Blackhawk Digital
 
-  Both the pads are be autodetected, and you can even use any combination of
-up to two these pads either chained together or using an Y-cable on a single
+  All these pads are autodetected, and you can even use any combination of
+up to two of these pads either chained together or using an Y-cable on a single
 gameport.
 
-  Gravis Blackhawk Digital, and GrIP MultiPort pads are not supported yet.
 GrIP MultiPort support is in the works. Gravis Xcalibur, ArcadeXtreme,
 GamePad Pro/M are joysticks/pads that probably never reached mass
-production. 
+production. Gravis Stinger is a serial device and hopefully will be
+supported in the future.
 
-2.5 FPGaming A3D and MadCatz A3D
+3.5 FPGaming A3D and MadCatz A3D
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   The Assasin 3D protocol created by FPGaming, is used both by FPGaming
 themselves and is licensed to MadCatz. A3D devices are supported by the
@@ -274,22 +373,22 @@
   The trackball support is far from perfect at this stage of development,
 but should be well usable.
 
-2.6 ThrustMaster DirectConnect (BSP)
+3.6 ThrustMaster DirectConnect (BSP)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   The TM DirectConnect (BSP) protocol is supported by the joy-thrustmaster.c
 module. It currently supports:
 
 * ThrustMaster Millenium 3D Inceptor
 * ThrustMaster 3D Rage Pad
-* ThrustMaster Weapon Control System III
 
-  All these drvices are autodetected, and thus no parameters to the module
+  Both these drvices are autodetected, and thus no parameters to the module
 are needed.
 
-  The only tested device was the Millenium. Rage Pad might work, and
-WCS III won't, because important parts of code for that are missing.
+  The Millenium and Rage Pad should work fine now. TM WCS III won't work,
+because important parts of code for that are missing. I'm not sure if it was
+ever mass produced.
 
-2.7 PDPI Lightning 4 gamecards
+3.7 PDPI Lightning 4 gamecards
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   PDPI Lightning 4 gamecards are supported by the joy-lightning.c module.
 This driver is only for analog joysticks connected to the card - if you want
@@ -321,7 +420,7 @@
   See the description of analog joystick driver for explanations of m0 and
 n0 values.
 
-2.8 Amiga
+3.8 Amiga
 ~~~~~~~~~
   Amiga joysticks, connected to an Amiga, are supported by the joy-amiga.c
 driver. Since they can't be autodetected, the driver has a command line.
@@ -339,11 +438,11 @@
   No more joystick types are supported now, but that should change in the
 future if I get an Amiga in the reach of my fingers.
 
-2.9 Game console and 8-bit pads and joysticks
+3.9 Game console and 8-bit pads and joysticks
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 See joystick-parport.txt for more info.
 
-3. Troubleshooting
+4. Troubleshooting
 ~~~~~~~~~~~~~~~~~~
   There is quite a high probability that you run into some problems. For
 testing whether the driver works, if in doubt, use the jstest utility in
@@ -359,7 +458,8 @@
 
 	make joydump.o
 
-  in the driver's directory. It is run then by typing
+  in the directory where you unpacked the joystick package. It is run then
+by typing
 
 	insmod joydump.o
 
@@ -370,7 +470,7 @@
 
   Oh, and read the FAQ! :)
 
-4. FAQ
+5. FAQ
 ~~~~~~
  Q: The driver doesn't find any joysticks connected to my soundcard with the
 message "joy-something: no joysticks found" and "joy-something.o:
@@ -420,14 +520,9 @@
   A: Yes, it is possible, but it'll burn your serial port or the pad. It
 won't work, of course.
 
-5. Calibration
-~~~~~~~~~~~~~~
-  For most joysticks you won't need any manual calibration, since the
-joystick should be autocalibrated by the driver automagically. However, with
-some analog joysticks, that either do not use linear resistors, or if you
-want better precision, you can use the jscal program included in the
-joystick package to set better correction coefficients than what the driver
-would choose itself.
+  Q: My joystick doesnt work with Quake / Quake 2. What's the cause?
+  A: Quake / Quake 2 don't support joystick. Use joy2key to simulate keypresses
+for them.
 
 6. Programming Interface
 ~~~~~~~~~~~~~~~~~~~~~~~~
@@ -449,27 +544,27 @@
   Thanks to the following people who contributed code, ideas or specifications
 to the joystick driver development:
 
-  0.1-0.5	Arthur C. Smith		<asmith@cbnewsd.att.com>
-  0.5		Eyal Lebedinsky		<eyal@eyal.emu.id.au>
-  0.6		Jeff Tranter		<tranter@software.mitel.com>
-  0.7		Carlos Puchol		<cpg@cs.utexas.edu>
-  0.7.1-0.8	Matt Rhoten		<mrhoten@oz.net>
-  0.7.3		Dan Fandrich		<dan@fch.wimsey.bc.ca>
-  0.7.3		Sverker Wilberg		<sverkerw@manila.docs.uu.se>
-  0.8		Hal Maney		<maney@norden.com>
-  0.8		Bernd Schmidt		<crux@pool.informatik.rwth-aachen.de>
-  0.9		Alan Cox		<alan@lxorguk.ukuu.org.uk>
-  1.1.0		John Markus Bjorndalen	<johnm@cs.uit.no>
-  1.1.0		Boris Muehmer		<mhs@cybernet-ag.de>
-  1.1.0		Robert W. Grubbs	<rwgrubbs@vt.edu>
-  1.1.0		Pete Chown		<pete.chown@skygate.co.uk>
-  1.1.0		Benji York		<benji@cookeville.com>
-  1.1.3		Leslie F. Donaldson	<donaldlf@cs.rose-hulman.edu>
-  1.2.0		Eng-Jon Ong		<ongej@dcs.qmw.ac.uk>
-  1.2.8		Ragnar Hojland Espinosa	<ragnar@lightside.ddns.org>
-  1.1.0-1.2.9	Brian Gerst		<bgerst@quark.vpplus.com>
-  1.2.3-1.2.12	Andree Borrmann		<a.borrmann@tu-bs.de>
-  0.9.0-1.2.12	Vojtech Pavlik		<vojtech@ucw.cz>
+	Arthur C. Smith		<asmith@cbnewsd.att.com>
+	Eyal Lebedinsky		<eyal@eyal.emu.id.au>
+	Jeff Tranter		<tranter@software.mitel.com>
+	Carlos Puchol		<cpg@cs.utexas.edu>
+	Matt Rhoten		<mrhoten@oz.net>
+	Dan Fandrich		<dan@fch.wimsey.bc.ca>
+	Sverker Wilberg		<sverkerw@manila.docs.uu.se>
+	Hal Maney		<maney@norden.com>
+	Bernd Schmidt		<crux@pool.informatik.rwth-aachen.de>
+	Alan Cox		<alan@lxorguk.ukuu.org.uk>
+	John Markus Bjorndalen	<johnm@cs.uit.no>
+	Boris Muehmer		<mhs@cybernet-ag.de>
+	Robert W. Grubbs	<rwgrubbs@vt.edu>
+	Pete Chown		<pete.chown@skygate.co.uk>
+	Benji York		<benji@cookeville.com>
+	Leslie F. Donaldson	<donaldlf@cs.rose-hulman.edu>
+	Eng-Jon Ong		<ongej@dcs.qmw.ac.uk>
+	Ragnar Hojland Espinosa	<ragnar@lightside.ddns.org>
+	Brian Gerst		<bgerst@quark.vpplus.com>
+	Andree Borrmann		<a.borrmann@tu-bs.de>
+	Martin Giguere		<zefrench@hotmail.com>
 
   If you think you should be in this list and are not, it's possible that
 I forgot to include you - contact me and I'll correct the error. :)
@@ -506,14 +601,7 @@
 
 9. To do
 ~~~~~~~~
-  Sooner or later I'll do these:
-
-		Fix possible races at open/close
-		Fix possible read/timer races
-		Make the driver SMP-friendly
-		Support joysticks on Linux/m68k/Atari
-		Support joysticks on Linux/FM-TOWNS (?)
-		Support even more joystick types
+  See the TODO file for the list of things planned.
 
 10. Current driver status
 ~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -545,6 +633,7 @@
 			Sega Saturn pad		- unknown
 joy-gravis.c		Gravis GamePad Pro	- OK
 			Gravis Xterminator	- OK
+			Gravis Blackhawk Digital- OK
 joy-lightning.c		PDPI Lightning 4	- OK
 joy-logitech.c		WingMan Extreme Digital	- OK
 			CyberMan 2		- OK
@@ -555,8 +644,7 @@
 			SW PP			- OK
 			SW FFP			- OK
 joy-thrustmaster.c	Millenium 3D Inceptor	- OK
-			3D-Rage pad		- unknown
-			WCS III			- incomplete
+			3D-Rage Pad		- OK
 joy-turbografx.c	Multi1 stick		- OK
 
 Please help me and send me success / failure reports for the drivers,
diff -u --recursive --new-file v2.1.130/linux/Makefile linux/Makefile
--- v2.1.130/linux/Makefile	Fri Nov 27 13:09:21 1998
+++ linux/Makefile	Fri Nov 27 13:19:07 1998
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 130
+SUBLEVEL = 131
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
diff -u --recursive --new-file v2.1.130/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.1.130/linux/arch/alpha/config.in	Fri Oct 23 22:01:19 1998
+++ linux/arch/alpha/config.in	Tue Dec  1 09:33:59 1998
@@ -22,14 +22,6 @@
 mainmenu_option next_comment
 comment 'General setup'
 
-unset CONFIG_CROSSCOMPILE CONFIG_NATIVE
-
-if [ "`uname`" != "Linux" ]; then
-  define_bool CONFIG_CROSSCOMPILE y
-else
-  define_bool CONFIG_NATIVE y
-fi
-
 choice 'Alpha system type' \
 	"Generic		CONFIG_ALPHA_GENERIC		\
 	 Alcor/Alpha-XLT	CONFIG_ALPHA_ALCOR		\
diff -u --recursive --new-file v2.1.130/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
--- v2.1.130/linux/arch/alpha/kernel/bios32.c	Fri Nov 27 13:09:21 1998
+++ linux/arch/alpha/kernel/bios32.c	Tue Dec  1 09:33:59 1998
@@ -296,60 +296,82 @@
  * on SRM.  It is more trouble than it iw worth to conditionalize this.
  */
 
-static struct {
-	struct reset_irq {
-		struct pci_dev *dev;
-		u8 irq;
-	} irq[16];
-	int irq_count;
-
-	struct reset_io {
-		struct pci_dev *dev;
-		u8 reg;
-		u32 io;
-	} io[16];
-	int io_count;
-} srm_resets;
+struct srm_irq_reset {
+	struct srm_irq_reset *next;
+	struct pci_dev *dev;
+	u8 irq;
+} *srm_irq_resets;
+
+struct srm_io_reset {
+	struct srm_io_reset *next;
+	struct pci_dev *dev;
+	u32 io;
+	u8 reg;
+} *srm_io_resets;
 
 /* Apply the collected reset modifications.  */
 
 void
 reset_for_srm(void)
 {
-	struct pci_dev *dev;
-	int i;
+	struct srm_irq_reset *qreset;
+	struct srm_io_reset *ireset;
 
 	/* Reset any IRQs that we changed.  */
-	for (i = 0; i < srm_resets.irq_count; i++) {
-		dev = srm_resets.irq[i].dev;
-
-		pcibios_write_config_byte(dev->bus->number, dev->devfn,
+	for (qreset = srm_irq_resets; qreset ; qreset = qreset->next) {
+		pcibios_write_config_byte(qreset->dev->bus->number,
+					  qreset->dev->devfn,
 					  PCI_INTERRUPT_LINE,
-					  srm_resets.irq[i].irq);
+					  qreset->irq);
 #if 1
 		printk("reset_for_srm: bus %d slot 0x%x "
 		       "SRM IRQ 0x%x changed back from 0x%x\n",
-		       dev->bus->number, PCI_SLOT(dev->devfn),
-		       srm_resets.irq[i].irq, dev->irq);
+		       qreset->dev->bus->number,
+		       PCI_SLOT(qreset->dev->devfn),
+		       qreset->irq, qreset->dev->irq);
 #endif
 	}
 
 	/* Reset any IO addresses that we changed.  */
-	for (i = 0; i < srm_resets.io_count; i++) {
-		dev = srm_resets.io[i].dev;
-
-		pcibios_write_config_byte(dev->bus->number, dev->devfn,
-					  srm_resets.io[i].reg,
-					  srm_resets.io[i].io);
+	for (ireset = srm_io_resets; ireset ; ireset = ireset->next) {
+		pcibios_write_config_dword(ireset->dev->bus->number,
+					   ireset->dev->devfn,
+					   ireset->reg, ireset->io);
 #if 1
 		printk("reset_for_srm: bus %d slot 0x%x "
-		       "SRM IO restored to 0x%x\n",
-		       dev->bus->number, PCI_SLOT(dev->devfn),
-		       srm_resets.io[i].io);
+		       "SRM MEM/IO restored to 0x%x\n",
+		       ireset->dev->bus->number,
+		       PCI_SLOT(ireset->dev->devfn),
+		       ireset->io);
 #endif
 	}
 }
 
+static void
+new_irq_reset(struct pci_dev *dev, u8 irq)
+{
+	struct srm_irq_reset *n;
+	n = kmalloc(sizeof(*n), GFP_KERNEL);
+
+	n->next = srm_irq_resets;
+	n->dev = dev;
+	n->irq = irq;
+	srm_irq_resets = n;
+}
+
+static void
+new_io_reset(struct pci_dev *dev, u8 reg, u32 io)
+{
+	struct srm_io_reset *n;
+	n = kmalloc(sizeof(*n), GFP_KERNEL);
+
+	n->next = srm_io_resets;
+	n->dev = dev;
+	n->reg = reg;
+	n->io = io;
+	srm_io_resets = n;
+}
+
 
 /*
  * Disable PCI device DEV so that it does not respond to I/O or memory
@@ -426,6 +448,7 @@
 	struct pci_bus *bus;
 	unsigned short cmd;
 	unsigned int base, mask, size, off, idx;
+	unsigned int orig_base;
 	unsigned int alignto;
 	unsigned long handle;
 
@@ -467,6 +490,8 @@
 		 * Figure out how much space and of what type this
 		 * device wants.
 		 */
+		pcibios_read_config_dword(bus->number, dev->devfn, off,
+					  &orig_base);
 		pcibios_write_config_dword(bus->number, dev->devfn, off,
 					   0xffffffff);
 		pcibios_read_config_dword(bus->number, dev->devfn, off, &base);
@@ -504,8 +529,10 @@
 			alignto = MAX(0x800, size);
 			base = ALIGN(io_base, alignto);
 			io_base = base + size;
+
 			pcibios_write_config_dword(bus->number, dev->devfn, 
 						   off, base | 0x1);
+			new_io_reset(dev, off, orig_base);
 
 			handle = PCI_HANDLE(bus->number) | base | 1;
 			dev->base_address[idx] = handle;
@@ -582,8 +609,11 @@
 				}
 			}
 			mem_base = base + size;
+
 			pcibios_write_config_dword(bus->number, dev->devfn,
 						   off, base);
+			new_io_reset(dev, off, orig_base);
+
 			handle = PCI_HANDLE(bus->number) | base;
 			dev->base_address[idx] = handle;
 
@@ -596,9 +626,16 @@
 			 * addresses to be used.
 			 */
 			if (type == PCI_BASE_ADDRESS_MEM_TYPE_64) {
-				pcibios_write_config_dword(bus->number,
-							   dev->devfn,
-							   off+4, 0);
+				unsigned int orig_base2;
+				pcibios_read_config_dword(bus->number,
+							  dev->devfn,
+							  off+4, &orig_base2);
+				if (0 != orig_base2) {
+					pcibios_write_config_dword(bus->number,
+								   dev->devfn,
+								   off+4, 0);
+					new_io_reset (dev, off+4, orig_base2);
+				}
 				/* Bypass hi reg in the loop.  */
 				dev->base_address[++idx] = 0;
 
@@ -720,10 +757,9 @@
 					   PCI_IO_BASE, l);
 
 		/*
-		 * Also:
-		 *       clear out the upper 16 bits of IO base/limit.
-		 *       clear out the upper 32 bits of PREF base/limit.
-		*/
+		 * Clear out the upper 16 bits of IO base/limit.
+		 * Clear out the upper 32 bits of PREF base/limit.
+		 */
 		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
 					   PCI_IO_BASE_UPPER16, 0);
 		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
@@ -738,6 +774,7 @@
 		l = ((bmem & 0xfff00000) >> 16) | ((tmem - 1) & 0xfff00000);
 		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
 					   PCI_MEMORY_BASE, l);
+
 		/*
 		 * Turn off downstream PF memory address range, unless
 		 * there is a VGA behind this bridge, in which case, we
@@ -839,7 +876,6 @@
 {
 	struct pci_bus *bus = dev->bus;
 	unsigned int reg, orig_base, new_base, found_one = 0;
-	struct reset_io *ior;
 
 	for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
 		/* Read the current setting, check for I/O space and >= 64K */
@@ -870,10 +906,7 @@
 		pcibios_write_config_dword(bus->number, dev->devfn,
 					   reg, new_base);
 
-		ior = &srm_resets.io[srm_resets.io_count++];
-		ior->dev = dev;
-		ior->reg = reg;
-		ior->io = orig_base;
+		new_io_reset(dev, reg, orig_base);
 		found_one++;
 	}
 
@@ -990,8 +1023,6 @@
 						 &irq_orig);
 
 			if (irq_orig != dev->irq) {
-				struct reset_irq *r;
-
 				DBG_DEVS(("common_pci_fixup: bus %d "
 					  "slot 0x%x SRM IRQ 0x%x "
 					  "changed to 0x%x\n",
@@ -999,9 +1030,7 @@
 					  PCI_SLOT(dev->devfn),
 					  irq_orig, dev->irq));
 
-				r = &srm_resets.irq[srm_resets.irq_count++];
-				r->dev = dev;
-				r->irq = irq_orig;
+				new_irq_reset(dev, irq_orig);
 			}
 		}
 
diff -u --recursive --new-file v2.1.130/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.1.130/linux/arch/alpha/kernel/process.c	Fri Oct 23 22:01:19 1998
+++ linux/arch/alpha/kernel/process.c	Tue Dec  1 09:33:59 1998
@@ -133,18 +133,15 @@
 				strncpy((char *)cpup->ipc_buffer, restart_cmd,
 					sizeof(cpup->ipc_buffer));
 			}
-		}
-		else {
+		} else {
 			flags |=  0x00040000UL; /* "remain halted" */
 		}
 			
 		cpup->flags = flags;					       
 		mb();						
 
-		if (alpha_use_srm_setup) {
-			reset_for_srm();
-			set_hae(srm_hae);
-		}
+		reset_for_srm();
+		set_hae(srm_hae);
 
 #ifdef CONFIG_DUMMY_CONSOLE
 		/* This has the effect of reseting the VGA video origin.  */
@@ -156,10 +153,8 @@
 	/* Reset rtc to defaults.  */
 	{
 		unsigned char control;
-		unsigned long flags;
 
-		/* I'm not sure if i really need to disable interrupts here. */
-		save_and_cli(flags);
+		cli();
 
 		/* Reset periodic interrupt frequency.  */
 		CMOS_WRITE(0x26, RTC_FREQ_SELECT);
@@ -170,7 +165,7 @@
 		CMOS_WRITE(control, RTC_CONTROL);	
 		CMOS_READ(RTC_INTR_FLAGS);
 
-		restore_flags(flags);
+		sti();
 	}
 #endif
 
diff -u --recursive --new-file v2.1.130/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v2.1.130/linux/arch/alpha/kernel/setup.c	Fri Nov 27 13:09:22 1998
+++ linux/arch/alpha/kernel/setup.c	Tue Dec  1 09:33:59 1998
@@ -43,12 +43,6 @@
 
 #include "proto.h"
 
-#if 1
-# define DBG_SRM(args)         printk args
-#else
-# define DBG_SRM(args)
-#endif
-
 struct hwrpb_struct *hwrpb;
 unsigned long srm_hae;
 
@@ -114,6 +108,7 @@
 extern struct alpha_machine_vector miata_mv;
 extern struct alpha_machine_vector mikasa_mv;
 extern struct alpha_machine_vector mikasa_primo_mv;
+extern struct alpha_machine_vector monet_mv;
 extern struct alpha_machine_vector noname_mv;
 extern struct alpha_machine_vector noritake_mv;
 extern struct alpha_machine_vector noritake_primo_mv;
@@ -127,6 +122,34 @@
 extern struct alpha_machine_vector takara_mv;
 extern struct alpha_machine_vector xl_mv;
 extern struct alpha_machine_vector xlt_mv;
+#pragma weak alcor_mv
+#pragma weak alphabook1_mv
+#pragma weak avanti_mv
+#pragma weak cabriolet_mv
+#pragma weak dp264_mv
+#pragma weak eb164_mv
+#pragma weak eb64p_mv
+#pragma weak eb66_mv
+#pragma weak eb66p_mv
+#pragma weak jensen_mv
+#pragma weak lx164_mv
+#pragma weak miata_mv
+#pragma weak mikasa_mv
+#pragma weak mikasa_primo_mv
+#pragma weak monet_mv
+#pragma weak noname_mv
+#pragma weak noritake_mv
+#pragma weak noritake_primo_mv
+#pragma weak p2k_mv
+#pragma weak pc164_mv
+#pragma weak rawhide_mv
+#pragma weak ruffian_mv
+#pragma weak sable_mv
+#pragma weak sable_gamma_mv
+#pragma weak sx164_mv
+#pragma weak takara_mv
+#pragma weak xl_mv
+#pragma weak xlt_mv
 
 
 void __init
@@ -197,26 +220,18 @@
 				 cpu->type);
 	}
 
-#ifdef CONFIG_ALPHA_GENERIC
 	if (!vec) {
 		panic("Unsupported system type: %s%s%s (%ld %ld)\n",
 		      type_name, (*var_name ? " variation " : ""), var_name,
 		      hwrpb->sys_type, hwrpb->sys_variation);
 	}
-	alpha_mv = *vec;
+	if (vec != &alpha_mv)
+		alpha_mv = *vec;
 
+#ifdef CONFIG_ALPHA_GENERIC
 	/* Assume that we've booted from SRM if we havn't booted from MILO.
 	   Detect the later by looking for "MILO" in the system serial nr.  */
 	alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
-#else
-	/* Once we're sure we can reliably identify systems, we should
-	   simply panic as we do above.  */
-	if (vec != &alpha_mv) {
-		printk("WARNING: Not configured for system type: %s%s%s "
-		       "(%ld %ld)\nContinuing with trepidation...\n",
-		       type_name, (*var_name ? " variation " : ""), var_name,
-		       hwrpb->sys_type, hwrpb->sys_variation);
-	}
 #endif
 
 	printk("Booting on %s%s%s using machine vector %s\n",
@@ -361,7 +376,6 @@
 static struct alpha_machine_vector * __init
 get_sysvec(long type, long variation, long cpu)
 {
-#ifdef CONFIG_ALPHA_GENERIC
 	static struct alpha_machine_vector *systype_vecs[] __initlocaldata =
 	{
 		NULL,		/* 0 */
@@ -398,7 +412,7 @@
 		NULL,		/* XXM */
 		&takara_mv,
 		NULL,		/* Yukon */
-		&dp264_mv,
+		NULL,		/* Tsunami -- see variation.  */
 		NULL,		/* Wildfire */
 		NULL,		/* CUSCO */
 	};
@@ -432,6 +446,19 @@
 		&eb66p_mv
 	};
 
+	static struct alpha_machine_vector *tsunami_vecs[]  __initlocaldata =
+	{
+		NULL,
+		&dp264_mv,		/* dp164 */
+		&dp264_mv,		/* warhol */
+		&dp264_mv,		/* windjammer */
+		&monet_mv,		/* monet */
+		&dp264_mv,		/* clipper */
+		&dp264_mv,		/* goldrush */
+		&dp264_mv,		/* webbrick */
+		&dp264_mv,		/* catamaran */
+	};
+
 	/* ??? Do we need to distinguish between Rawhides?  */
 
 	struct alpha_machine_vector *vec;
@@ -472,6 +499,10 @@
 			if (member < N(eb66_indices))
 				vec = eb66_vecs[eb66_indices[member]];
 			break;
+		case ST_DEC_TSUNAMI:
+			if (member < N(tsunami_indices))
+				vec = tsunami_vecs[tsunami_indices[member]];
+			break;
 		case ST_DEC_1000:
 			cpu &= 0xffffffff;
 			if (cpu == EV5_CPU || cpu == EV56_CPU)
@@ -496,17 +527,11 @@
 		}
 	}
 	return vec;
-#else
-	/* TODO: verify that the system is of the type for which we
-	   were configured.  For now, cop out and return success.  */
-	return &alpha_mv;
-#endif /* GENERIC */
 }
 
 static struct alpha_machine_vector * __init
 get_sysvec_byname(const char *name)
 {
-#ifdef CONFIG_ALPHA_GENERIC
 	static struct alpha_machine_vector *all_vecs[] __initlocaldata =
 	{
 		&alcor_mv,
@@ -523,6 +548,7 @@
 		&miata_mv,
 		&mikasa_mv,
 		&mikasa_primo_mv,
+		&monet_mv,
 		&noname_mv,
 		&noritake_mv,
 		&noritake_primo_mv,
@@ -545,11 +571,6 @@
 			return mv;
 	}
 	return NULL;
-#else
-	if (strcasecmp(alpha_mv.vector_name, name) == 0)
-		return &alpha_mv;
-	return NULL;
-#endif
 }
 
 static void
diff -u --recursive --new-file v2.1.130/linux/arch/alpha/kernel/sys_dp264.c linux/arch/alpha/kernel/sys_dp264.c
--- v2.1.130/linux/arch/alpha/kernel/sys_dp264.c	Fri Nov 27 13:09:22 1998
+++ linux/arch/alpha/kernel/sys_dp264.c	Tue Dec  1 09:33:59 1998
@@ -32,16 +32,6 @@
 #include "bios32.h"
 #include "machvec.h"
 
-struct hwrpb_struct *hwrpb;
-
-/* hwrpb->sys_variation helpers */
-#define MEMBER_ID(x) (((x)>>10)&0x3f)
-
-#define DP264_ID	1
-#define MONET_ID	4
-#define GOLDRUSH_ID	6
-#define WEBBRICK_ID	7
-
 #define dev2hose(d) (bus2hose[(d)->bus->number]->pci_hose_index)
 
 /*
@@ -301,28 +291,22 @@
 dp264_pci_fixup(void)
 {
 	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+	common_pci_fixup(dp264_map_irq, common_swizzle);
+	SMC669_Init();
+}
 
-	/* must do map and/or swizzle different on some */
-	switch (MEMBER_ID(hwrpb->sys_variation)) {
-	case MONET_ID:
-	    common_pci_fixup(monet_map_irq, monet_swizzle);
-	    /* es1888_init(); */ /* later? */
-	    break;
-
-	case DP264_ID:
-	case GOLDRUSH_ID:
-	case WEBBRICK_ID:
-	default:
-	    common_pci_fixup(dp264_map_irq, common_swizzle);
-	    break;
-	} /* end MEMBER_ID switch */
-
+static void __init
+monet_pci_fixup(void)
+{
+	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+	common_pci_fixup(monet_map_irq, monet_swizzle);
+	/* es1888_init(); */ /* later? */
 	SMC669_Init();
 }
 
 
 /*
- * The System Vector
+ * The System Vectors
  */
 
 struct alpha_machine_vector dp264_mv __initmv = {
@@ -347,3 +331,27 @@
 	kill_arch:		generic_kill_arch,
 };
 ALIAS_MV(dp264)
+
+struct alpha_machine_vector monet_mv __initmv = {
+	vector_name:		"Monet",
+	DO_EV6_MMU,
+	DO_DEFAULT_RTC,
+	DO_TSUNAMI_IO,
+	DO_TSUNAMI_BUS,
+	machine_check:		tsunami_machine_check,
+	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+
+	nr_irqs:		64,
+	irq_probe_mask:		_PROBE_MASK(64),
+	update_irq_hw:		dp264_update_irq_hw,
+	ack_irq:		generic_ack_irq,
+	device_interrupt:	dp264_device_interrupt,
+
+	init_arch:		tsunami_init_arch,
+	init_irq:		dp264_init_irq,
+	init_pit:		generic_init_pit,
+	pci_fixup:		monet_pci_fixup,
+	kill_arch:		generic_kill_arch,
+};
+/* No alpha_mv alias for monet, since we compile it in unconditionally
+   with DP264; setup_arch knows how to cope.  */
diff -u --recursive --new-file v2.1.130/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c
--- v2.1.130/linux/arch/alpha/kernel/time.c	Fri Oct 23 22:01:19 1998
+++ linux/arch/alpha/kernel/time.c	Wed Dec  2 17:15:19 1998
@@ -60,6 +60,8 @@
 	unsigned long scaled_ticks_per_cycle;
 	/* last time the CMOS clock got updated */
 	time_t last_rtc_update;
+	/* partial unused tick */
+	unsigned long partial_tick;
 } state;
 
 unsigned long est_cycle_freq;
@@ -79,8 +81,6 @@
  */
 void timer_interrupt(int irq, void *dev, struct pt_regs * regs)
 {
-	const unsigned long half = 1UL << (FIX_SHIFT - 1);
-	const unsigned long mask = (1UL << (FIX_SHIFT + 1)) - 1;
 	unsigned long delta;
 	__u32 now;
 	long nticks;
@@ -96,22 +96,21 @@
 #endif
 
 	/*
-	 * Estimate how many ticks have passed since the last update.
-	 * Round the result, .5 to even.  When we loose ticks due to
-	 * say using IDE, the clock has been seen to run up to 15% slow
-	 * if we truncate.
+	 * Calculate how many ticks have passed since the last update,
+	 * including any previous partial leftover.  Save any resulting
+	 * fraction for the next pass.
 	 */
 	now = rpcc();
 	delta = now - state.last_time;
 	state.last_time = now;
-	delta = delta * state.scaled_ticks_per_cycle;
-	if ((delta & mask) != half)
-		delta += half;
+	delta = delta * state.scaled_ticks_per_cycle + state.partial_tick;
+	state.partial_tick = delta & ((1UL << FIX_SHIFT) - 1); 
 	nticks = delta >> FIX_SHIFT;
 
-	do {
+	while (nticks > 0) {
 		do_timer(regs);
-	} while (--nticks > 0);
+		nticks--;
+	}
 
 	/*
 	 * If we have an externally synchronized Linux clock, then update
@@ -325,6 +324,7 @@
 	state.scaled_ticks_per_cycle
 		= ((unsigned long) HZ << FIX_SHIFT) / cycle_freq;
 	state.last_rtc_update = 0;
+	state.partial_tick = 0L;
 
 	/* setup timer */ 
         irq_handler = timer_interrupt;
@@ -366,7 +366,7 @@
 	 */
 
 	delta_usec = delta_cycles * state.scaled_ticks_per_cycle * 15625;
-	delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6)) * HZ)) + 1) / 2;
+	delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
 
 	usec += delta_usec;
 	if (usec >= 1000000) {
diff -u --recursive --new-file v2.1.130/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S
--- v2.1.130/linux/arch/i386/boot/setup.S	Fri Oct  9 13:27:05 1998
+++ linux/arch/i386/boot/setup.S	Sat Nov 28 17:18:54 1998
@@ -396,8 +396,6 @@
 	cmp	bx,#0x0504d	! check for "PM" signature
 	jne	done_apm_bios	! no signature -> no APM BIOS
 
-	mov	[64],ax		! record the APM BIOS version
-	mov	[76],cx		!	and flags
 	and	cx,#0x02	! Is 32 bit supported?
 	je	done_apm_bios	!	no ...
 
@@ -416,6 +414,26 @@
 	mov	[74],dx		! BIOS data segment
 	mov	[78],esi	! BIOS code segment length
 	mov	[82],di		! BIOS data segment length
+!
+! Redo the installation check as the 32 bit connect
+! modifies the flags returned on some BIOSs
+!
+	mov	ax,#0x05300	! APM BIOS installation check
+	xor	bx,bx
+	int	0x15
+	jc	apm_disconnect	! error -> should not happen, tidy up
+
+	cmp	bx,#0x0504d	! check for "PM" signature
+	jne	apm_disconnect	! no signature -> should not happen, tidy up
+
+	mov	[64],ax		! record the APM BIOS version
+	mov	[76],cx		!	and flags
+	jmp	done_apm_bios
+
+apm_disconnect:
+	mov	ax,#0x05304	! Disconnect
+	xor	bx,bx
+	int	0x15		! ignore return code
 	jmp	done_apm_bios
 
 no_32_apm_bios:
diff -u --recursive --new-file v2.1.130/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.1.130/linux/arch/i386/config.in	Mon Oct  5 13:13:35 1998
+++ linux/arch/i386/config.in	Sat Nov 28 20:32:10 1998
@@ -72,6 +72,7 @@
   bool '   Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK
   bool '   Power off on shutdown' CONFIG_APM_POWER_OFF
   bool '   Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+  bool '   Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
 fi
 
 endmenu
diff -u --recursive --new-file v2.1.130/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.1.130/linux/arch/i386/kernel/apm.c	Fri Oct  9 13:27:05 1998
+++ linux/arch/i386/kernel/apm.c	Sat Nov 28 17:18:54 1998
@@ -30,6 +30,7 @@
  * Feb 1998, Version 1.4
  * Aug 1998, Version 1.5
  * Sep 1998, Version 1.6
+ * Nov 1998, Version 1.7
  *
  * History:
  *    0.6b: first version in official kernel, Linux 1.3.46
@@ -60,6 +61,17 @@
  *         Fix OOPS at power off with no APM BIOS by Jan Echternach
  *                   <echter@informatik.uni-rostock.de>
  *         Stephen Rothwell
+ *    1.7: Modify driver's cached copy of the disabled/disengaged flags
+ *         to reflect current state of APM BIOS.
+ *         Chris Rankin <rankinc@bellsouth.net>
+ *         Reset interrupt 0 timer to 100Hz after suspend
+ *         Chad Miller <cmiller@surfsouth.com>
+ *         Add CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+ *         Richard Gooch <rgooch@atnf.csiro.au>
+ *         Allow boot time disabling of APM
+ *         Make boot messages far less verbose by default
+ *         Make asm safer
+ *         Stephen Rothwell
  *
  * APM 1.1 Reference:
  *
@@ -167,7 +179,7 @@
  *
  * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant
  *                         [Confirmed by TI representative]
- * U: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
+ * ?: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
  *                    [Confirmed by BIOS disassembly]
  *                    [This may work now ...]
  * P: Toshiba 1950S: battery life information only gets updated after resume
@@ -215,6 +227,19 @@
 #define APM_RELAX_SEGMENTS
 
 /*
+ * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
+ * This patched by Chad Miller <cmiller@surfsouth.com>, orig code by David 
+ * Chen <chen@ctpa04.mit.edu>
+ */
+#undef INIT_TIMER_AFTER_SUSPEND
+
+#ifdef INIT_TIMER_AFTER_SUSPEND
+#include <linux/timex.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#endif
+
+/*
  * Need to poll the APM BIOS every second
  */
 #define APM_CHECK_TIMEOUT	(HZ)
@@ -267,13 +292,15 @@
 
 static long			clock_cmos_diff;
 static int			got_clock_diff = 0;
+static int			debug = 0;
+static int			apm_disabled = 0;
 
 static struct wait_queue *	process_list = NULL;
 static struct apm_bios_struct *	user_list = NULL;
 
 static struct timer_list	apm_timer;
 
-static char			driver_version[] = "1.6";	/* no spaces */
+static char			driver_version[] = "1.7";	/* no spaces */
 
 #ifdef APM_DEBUG
 static char *	apm_event_name[] = {
@@ -393,7 +420,7 @@
 #	define APM_DO_RESTORE_SEGS
 #endif
 
-static inline u8 apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in,
+static u8 apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in,
 	u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi)
 {
 	unsigned int	saved_fs;
@@ -404,13 +431,17 @@
 	APM_DO_CLI;
 	APM_DO_SAVE_SEGS;
 	__asm__ __volatile__(APM_DO_ZERO_SEGS
+		"pushl %%edi\n\t"
+		"pushl %%ebp\n\t"
 		"lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
 		"setc %%al\n\t"
+		"popl %%ebp\n\t"
+		"popl %%edi\n\t"
 		APM_DO_POP_SEGS
-		:  "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx),
-		   "=S" (*esi)
+		: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx),
+		  "=S" (*esi)
 		: "a" (eax_in), "b" (ebx_in), "c" (ecx_in)
-		: "ax", "bx", "cx", "dx", "si", "di", "bp", "memory", "cc");
+		: "memory", "cc");
 	APM_DO_RESTORE_SEGS;
 	__restore_flags(flags);
 	return *eax & 0xff;
@@ -420,7 +451,7 @@
  * This version only returns one value (usually an error code)
  */
 
-static inline u8 apm_bios_call_simple(u32 eax_in, u32 ebx_in, u32 ecx_in,
+static u8 apm_bios_call_simple(u32 eax_in, u32 ebx_in, u32 ecx_in,
 	u32 *eax)
 {
 	u8		error;
@@ -431,13 +462,22 @@
 	__save_flags(flags);
 	APM_DO_CLI;
 	APM_DO_SAVE_SEGS;
-	__asm__ __volatile__(APM_DO_ZERO_SEGS
-		"lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
-		"setc %%bl\n\t"
-		APM_DO_POP_SEGS
-		: "=a" (*eax), "=b" (error)
-		: "a" (eax_in), "b" (ebx_in), "c" (ecx_in)
-		: "ax", "bx", "cx", "dx", "si", "di", "bp", "memory", "cc");
+	{
+		int	cx, dx, si;
+
+		__asm__ __volatile__(APM_DO_ZERO_SEGS
+			"pushl %%edi\n\t"
+			"pushl %%ebp\n\t"
+			"lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
+			"setc %%bl\n\t"
+			"popl %%ebp\n\t"
+			"popl %%edi\n\t"
+			APM_DO_POP_SEGS
+			: "=a" (*eax), "=b" (error), "=c" (cx), "=d" (dx),
+			  "=S" (si)
+			: "a" (eax_in), "b" (ebx_in), "c" (ecx_in)
+			: "memory", "cc");
+	}
 	APM_DO_RESTORE_SEGS;
 	__restore_flags(flags);
 	return error;
@@ -470,7 +510,7 @@
 	return APM_SUCCESS;
 }
 
-static inline int set_power_state(u_short what, u_short state)
+static int set_power_state(u_short what, u_short state)
 {
 	u32	eax;
 
@@ -499,7 +539,6 @@
 #endif
 
 #ifdef CONFIG_APM_DO_ENABLE
-/* Called by apm_setup if apm_enabled will be true. */
 static int apm_enable_power_management(void)
 {
 	u32	eax;
@@ -508,6 +547,7 @@
 			(apm_bios_info.version > 0x100) ? 0x0001 : 0xffff,
 			1, &eax))
 		return (eax >> 8) & 0xff;
+	apm_bios_info.flags &= ~APM_BIOS_DISABLED;
 	return APM_SUCCESS;
 }
 #endif
@@ -574,9 +614,10 @@
 	for (i = 0; i < ERROR_COUNT; i++)
 		if (error_table[i].key == err) break;
 	if (i < ERROR_COUNT)
-		printk(KERN_NOTICE "apm_bios: %s: %s\n", str, error_table[i].msg);
+		printk(KERN_NOTICE "apm: %s: %s\n", str, error_table[i].msg);
 	else
-		printk(KERN_NOTICE "apm_bios: %s: unknown error code %#2.2x\n", str, err);
+		printk(KERN_NOTICE "apm: %s: unknown error code %#2.2x\n",
+			str, err);
 }
 
 /* Called from console driver -- must make sure apm_enabled. */
@@ -629,7 +670,6 @@
 	callback_list_t **	ptr;
 	callback_list_t *	old;
 
-	ptr = &callback_list;
 	for (ptr = &callback_list; *ptr != NULL; ptr = &(*ptr)->next)
 		if ((*ptr)->callback == callback)
 			break;
@@ -663,7 +703,7 @@
 			static int notified;
 
 			if (notified == 0) {
-			    printk( "apm_bios: an event queue overflowed\n" );
+			    printk(KERN_ERR "apm: an event queue overflowed\n");
 			    notified = 1;
 			}
 			as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
@@ -719,6 +759,18 @@
 	err = apm_set_power_state(APM_STATE_SUSPEND);
 	if (err)
 		apm_error("suspend", err);
+#ifdef INIT_TIMER_AFTER_SUSPEND
+	save_flags(flags);
+	cli();
+	/* set the clock to 100 Hz */
+	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
+	udelay(10);
+	outb_p(LATCH & 0xff , 0x40);	/* LSB */
+	udelay(10);
+	outb(LATCH >> 8 , 0x40);	/* MSB */
+	udelay(10);
+	restore_flags(flags);
+#endif
 	set_time();
 }
 
@@ -771,24 +823,27 @@
 
 static void check_events(void)
 {
-	apm_event_t	event;
+	apm_event_t		event;
+#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+	static unsigned long	last_resume = 0;
+	static int		did_resume = 0;
+#endif
 
 	while ((event = get_event()) != 0) {
 #ifdef APM_DEBUG
 		if (event <= NR_APM_EVENT_NAME)
-			printk(KERN_DEBUG "APM BIOS received %s notify\n",
+			printk(KERN_DEBUG "apm: received %s notify\n",
 			       apm_event_name[event - 1]);
 		else
-			printk(KERN_DEBUG "APM BIOS received unknown "
+			printk(KERN_DEBUG "apm: received unknown "
 			       "event 0x%02x\n", event);
 #endif
 		switch (event) {
 		case APM_SYS_STANDBY:
 		case APM_USER_STANDBY:
 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-			if (waiting_for_resume) {
-			    return;
-			}
+			if (waiting_for_resume)
+				return;
 			waiting_for_resume = 1;
 #endif
 			send_event(event, APM_STANDBY_RESUME, NULL);
@@ -803,10 +858,13 @@
 			break;
 #endif
 		case APM_SYS_SUSPEND:
+#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+			if (did_resume && ((jiffies - last_resume) < HZ))
+				break;
+#endif
 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-			if (waiting_for_resume) {
-			    return;
-			}
+			if (waiting_for_resume)
+				return;
 			waiting_for_resume = 1;
 #endif
 			send_event(event, APM_NORMAL_RESUME, NULL);
@@ -820,6 +878,10 @@
 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
 			waiting_for_resume = 0;
 #endif
+#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+			last_resume = jiffies;
+			did_resume = 1;
+#endif
 			set_time();
 			send_event(event, 0, NULL);
 			break;
@@ -905,7 +967,7 @@
 static int check_apm_bios_struct(struct apm_bios_struct *as, const char *func)
 {
 	if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
-		printk(KERN_ERR "apm_bios: %s passed bad filp", func);
+		printk(KERN_ERR "apm: %s passed bad filp", func);
 		return 1;
 	}
 	return 0;
@@ -1041,7 +1103,7 @@
 		     as1 = as1->next)
 			;
 		if (as1 == NULL)
-			printk(KERN_ERR "apm_bios: filp not in user list");
+			printk(KERN_ERR "apm: filp not in user list");
 		else
 			as1->next = as->next;
 	}
@@ -1055,7 +1117,7 @@
 
 	as = (struct apm_bios_struct *)kmalloc(sizeof(*as), GFP_KERNEL);
 	if (as == NULL) {
-		printk(KERN_ERR "apm_bios: cannot allocate struct of size %d bytes",
+		printk(KERN_ERR "apm: cannot allocate struct of size %d bytes",
 		       sizeof(*as));
 		return -ENOMEM;
 	}
@@ -1168,6 +1230,26 @@
 }
 #endif
 
+void __init apm_setup(char *str, int *dummy)
+{
+	int	invert;
+
+	while ((str != NULL) && (*str != '\0')) {
+		if (strncmp(str, "off", 3) == 0)
+			apm_disabled = 1;
+		if (strncmp(str, "on", 2) == 0)
+			apm_disabled = 0;
+		invert = (strncmp(str, "no-", 3) == 0);
+		if (invert)
+			str += 3;
+		if (strncmp(str, "debug", 5) == 0)
+			debug = !invert;
+		str = strchr(str, ',');
+		if (str != NULL)
+			str += strspn(str, ", \t");
+	}
+}
+
 void __init apm_bios_init(void)
 {
 	unsigned short	bx;
@@ -1178,23 +1260,18 @@
 	char *		bat_stat;
 	static struct proc_dir_entry *ent;
 
-#ifdef __SMP__
-	if (smp_num_cpus > 1) {
-		printk(KERN_NOTICE "APM disabled: APM is not SMP safe.\n");
-		return;
-	}
-#endif
 	if (apm_bios_info.version == 0) {
-		printk(KERN_INFO "APM BIOS not found.\n");
+		printk(KERN_INFO "apm: BIOS not found.\n");
 		return;
 	}
-	printk(KERN_INFO "APM BIOS version %c.%c Flags 0x%02x (Driver version %s)\n",
-	       ((apm_bios_info.version >> 8) & 0xff) + '0',
-	       (apm_bios_info.version & 0xff) + '0',
-	       apm_bios_info.flags,
-	       driver_version);
+	printk(KERN_INFO
+		"apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
+		((apm_bios_info.version >> 8) & 0xff),
+		(apm_bios_info.version & 0xff),
+		apm_bios_info.flags,
+		driver_version);
 	if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) {
-		printk(KERN_INFO "    No 32 bit BIOS support\n");
+		printk(KERN_INFO "apm: no 32 bit BIOS support\n");
 		return;
 	}
 
@@ -1209,14 +1286,28 @@
 	if (apm_bios_info.version < 0x102)
 		apm_bios_info.cseg_16_len = 0xFFFF; /* 64k */
 
-	printk(KERN_INFO "    Entry %x:%lx cseg16 %x dseg %x",
-	       apm_bios_info.cseg, apm_bios_info.offset,
-	       apm_bios_info.cseg_16, apm_bios_info.dseg);
-	if (apm_bios_info.version > 0x100)
-		printk(" cseg len %x, cseg16 len %x, dseg len %x",
-		       apm_bios_info.cseg_len, apm_bios_info.cseg_16_len,
-		       apm_bios_info.dseg_len);
-	printk("\n");
+	if (debug) {
+		printk(KERN_INFO "apm: entry %x:%lx cseg16 %x dseg %x",
+			apm_bios_info.cseg, apm_bios_info.offset,
+			apm_bios_info.cseg_16, apm_bios_info.dseg);
+		if (apm_bios_info.version > 0x100)
+			printk(" cseg len %x, cseg16 len %x, dseg len %x",
+				apm_bios_info.cseg_len,
+				apm_bios_info.cseg_16_len,
+				apm_bios_info.dseg_len);
+		printk("\n");
+	}
+
+	if (apm_disabled) {
+		printk(KERN_NOTICE "apm: disabled on user request.\n");
+		return;
+	}
+#ifdef __SMP__
+	if (smp_num_cpus > 1) {
+		printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
+		return;
+	}
+#endif
 
 	/*
 	 * Set up a segment that references the real mode segment 0x40
@@ -1253,74 +1344,78 @@
 		set_limit(gdt[APM_CS_16 >> 3], apm_bios_info.cseg_16_len);
 		set_limit(gdt[APM_DS >> 3], apm_bios_info.dseg_len);
 #endif
-		/* The APM 1.2 docs state that the apm_driver_version
-		 * call can fail if we try to connect as 1.2 to a 1.1 bios.
+		/*
+		 * We only support BIOSs up to version 1.2
 		 */
-		apm_bios_info.version = 0x0102;
-		error = apm_driver_version(&apm_bios_info.version);
-		if (error != APM_SUCCESS) { /* Fall back to an APM 1.1 connection. */
-			apm_bios_info.version = 0x0101;
-			error = apm_driver_version(&apm_bios_info.version);
-		}
-		if (error != APM_SUCCESS) /* Fall back to an APM 1.0 connection. */
+		if (apm_bios_info.version > 0x0102)
+			apm_bios_info.version = 0x0102;
+		if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) {
+			/* Fall back to an APM 1.0 connection. */
 			apm_bios_info.version = 0x100;
-		else {
-			apm_engage_power_management(0x0001);
-			printk( "    Connection version %d.%d\n",
-				(apm_bios_info.version >> 8) & 0xff,
-				apm_bios_info.version & 0xff );
 		}
 	}
-
-	error = apm_get_power_status(&bx, &cx, &dx);
-	if (error)
-		printk(KERN_INFO "    Power status not available\n");
-	else {
-		switch ((bx >> 8) & 0xff) {
-		case 0: power_stat = "off line"; break;
-		case 1: power_stat = "on line"; break;
-		case 2: power_stat = "on backup power"; break;
-		default: power_stat = "unknown"; break;
-		}
-		switch (bx & 0xff) {
-		case 0: bat_stat = "high"; break;
-		case 1: bat_stat = "low"; break;
-		case 2: bat_stat = "critical"; break;
-		case 3: bat_stat = "charging"; break;
-		default: bat_stat = "unknown"; break;
-		}
-		printk(KERN_INFO "    AC %s, battery status %s, battery life ",
-		       power_stat, bat_stat);
-		if ((cx & 0xff) == 0xff)
-			printk("unknown\n");
-		else
-			printk("%d%%\n", cx & 0xff);
-		if (apm_bios_info.version > 0x100) {
-			printk("    battery flag 0x%02x, battery life ",
-			       (cx >> 8) & 0xff);
-			if (dx == 0xffff)
+	if (debug) {
+		printk(KERN_INFO "apm: onnection version %d.%d\n",
+			(apm_bios_info.version >> 8) & 0xff,
+			apm_bios_info.version & 0xff );
+
+		error = apm_get_power_status(&bx, &cx, &dx);
+		if (error)
+			printk(KERN_INFO "apm: power status not available\n");
+		else {
+			switch ((bx >> 8) & 0xff) {
+			case 0: power_stat = "off line"; break;
+			case 1: power_stat = "on line"; break;
+			case 2: power_stat = "on backup power"; break;
+			default: power_stat = "unknown"; break;
+			}
+			switch (bx & 0xff) {
+			case 0: bat_stat = "high"; break;
+			case 1: bat_stat = "low"; break;
+			case 2: bat_stat = "critical"; break;
+			case 3: bat_stat = "charging"; break;
+			default: bat_stat = "unknown"; break;
+			}
+			printk(KERN_INFO "apm: AC %s, battery status %s, battery life ",
+			       power_stat, bat_stat);
+			if ((cx & 0xff) == 0xff)
 				printk("unknown\n");
-			else {
-				if ((dx & 0x8000))
-					printk("%d minutes\n", dx & 0x7ffe );
-				else
-					printk("%d seconds\n", dx & 0x7fff );
+			else
+				printk("%d%%\n", cx & 0xff);
+			if (apm_bios_info.version > 0x100) {
+				printk("apm: battery flag 0x%02x, battery life ",
+				       (cx >> 8) & 0xff);
+				if (dx == 0xffff)
+					printk("unknown\n");
+				else {
+					if ((dx & 0x8000))
+						printk("%d minutes\n", dx & 0x7ffe );
+					else
+						printk("%d seconds\n", dx & 0x7fff );
+				}
 			}
 		}
 	}
 
 #ifdef CONFIG_APM_DO_ENABLE
-	/*
-	 * This call causes my NEC UltraLite Versa 33/C to hang if it is
-	 * booted with PM disabled but not in the docking station.
-	 * Unfortunate ...
-	 */
-	error = apm_enable_power_management();
-	if (error)
-		apm_error("enable power management", error);
-	if (error == APM_DISABLED)
-		return;
+	if (apm_bios_info.flags & APM_BIOS_DISABLED) {
+		/*
+		 * This call causes my NEC UltraLite Versa 33/C to hang if it
+		 * is booted with PM disabled but not in the docking station.
+		 * Unfortunate ...
+		 */
+		error = apm_enable_power_management();
+		if (error) {
+			apm_error("enable power management", error);
+			return;
+		}
+	}
 #endif
+	if (((apm_bios_info.flags & APM_BIOS_DISABLED) == 0)
+	    && (apm_bios_info.version > 0x0100)) {
+		if (apm_engage_power_management(0x0001) == APM_SUCCESS)
+			apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
+	}
 
 	init_timer(&apm_timer);
 	apm_timer.function = do_apm_timer;
diff -u --recursive --new-file v2.1.130/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.1.130/linux/arch/i386/kernel/entry.S	Fri Nov 27 13:09:22 1998
+++ linux/arch/i386/kernel/entry.S	Wed Dec  2 16:06:48 1998
@@ -237,14 +237,13 @@
 
 	ALIGN
 handle_bottom_half:
-	pushl $ret_from_intr
-	jmp SYMBOL_NAME(do_bottom_half)
+	call SYMBOL_NAME(do_bottom_half)
+	jmp ret_from_intr
 
 	ALIGN
 reschedule:
-	pushl $ret_from_sys_call
-	jmp SYMBOL_NAME(schedule)    # test
-
+	call SYMBOL_NAME(schedule)    # test
+	jmp ret_from_sys_call
 
 ENTRY(divide_error)
 	pushl $0		# no error code
diff -u --recursive --new-file v2.1.130/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.1.130/linux/arch/i386/kernel/process.c	Fri Nov 27 13:09:22 1998
+++ linux/arch/i386/kernel/process.c	Tue Dec  1 11:28:24 1998
@@ -102,44 +102,25 @@
 
 /*
  * The idle loop on a uniprocessor i386..
- */
- 
-asmlinkage int sys_idle(void)
+ */ 
+static int cpu_idle(void *unused)
 {
-        unsigned long start_idle = 0;
-	int ret = -EPERM;
+	unsigned long start_idle = jiffies;
 
-	lock_kernel();
-	if (current->pid != 0)
-		goto out;
 	/* endless idle loop with no priority at all */
-	current->priority = 0;
-	current->counter = 0;
 	for (;;) {
-		/*
-		 *	We are locked at this point. So we can safely call
-		 *	the APM bios knowing only one CPU at a time will do
-		 *	so.
-		 */
-		if (!start_idle) {
-			check_pgt_cache();
-			start_idle = jiffies;
-		}
 		if (jiffies - start_idle > HARD_IDLE_TIMEOUT) 
 			hard_idle();
 		else  {
 			if (boot_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched)
 		        	__asm__("hlt");
 		}
-		run_task_queue(&tq_scheduler);
 		if (current->need_resched) 
-			start_idle = 0;
+			start_idle = jiffies;
+		current->policy = SCHED_YIELD;
 		schedule();
+		check_pgt_cache();
 	}
-	ret = 0;
-out:
-	unlock_kernel();
-	return ret;
 }
 
 #else
@@ -150,21 +131,19 @@
 
 int cpu_idle(void *unused)
 {
-	current->priority = 0;
-	while(1)
-	{
-		if(current_cpu_data.hlt_works_ok &&
-		 		!hlt_counter && !current->need_resched)
-			__asm("hlt");
-		check_pgt_cache();
-		run_task_queue(&tq_scheduler);
 
-		/* endless idle loop with no priority at all */
-		current->counter = 0;
+	/* endless idle loop with no priority at all */
+	while(1) {
+		if (current_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched)
+			__asm__("hlt");
+		current->policy = SCHED_YIELD;
 		schedule();
+		check_pgt_cache();
 	}
 }
 
+#endif
+
 asmlinkage int sys_idle(void)
 {
 	if (current->pid != 0)
@@ -173,8 +152,6 @@
 	return 0;
 }
 
-#endif
-
 /*
  * This routine reboots the machine by asking the keyboard
  * controller to pulse the reset-line low. We try that for a while,
@@ -509,23 +486,27 @@
  */
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
-	long retval;
+	long retval, d0;
 
 	__asm__ __volatile__(
 		"movl %%esp,%%esi\n\t"
 		"int $0x80\n\t"		/* Linux/i386 system call */
 		"cmpl %%esp,%%esi\n\t"	/* child or parent? */
 		"je 1f\n\t"		/* parent - jump */
-		"pushl %3\n\t"		/* push argument */
-		"call *%4\n\t"		/* call fn */
-		"movl %2,%0\n\t"	/* exit */
+		/* Load the argument into eax, and push it.  That way, it does
+		 * not matter whether the called function is compiled with
+		 * -mregparm or not.  */
+		"movl %4,%%eax\n\t"
+		"pushl %%eax\n\t"		
+		"call *%5\n\t"		/* call fn */
+		"movl %3,%0\n\t"	/* exit */
 		"int $0x80\n"
 		"1:\t"
-		:"=a" (retval)
+		:"=&a" (retval), "=&S" (d0)
 		:"0" (__NR_clone), "i" (__NR_exit),
 		 "r" (arg), "r" (fn),
 		 "b" (flags | CLONE_VM)
-		:"si");
+		: "memory");
 	return retval;
 }
 
diff -u --recursive --new-file v2.1.130/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- v2.1.130/linux/arch/i386/kernel/signal.c	Mon Oct  5 13:13:35 1998
+++ linux/arch/i386/kernel/signal.c	Tue Dec  1 11:28:24 1998
@@ -592,7 +592,7 @@
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
+int do_signal(struct pt_regs *regs, sigset_t *oldset)
 {
 	siginfo_t info;
 	struct k_sigaction *ka;
diff -u --recursive --new-file v2.1.130/linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c
--- v2.1.130/linux/arch/i386/kernel/vm86.c	Thu Sep 17 17:53:34 1998
+++ linux/arch/i386/kernel/vm86.c	Tue Dec  1 11:28:24 1998
@@ -63,7 +63,7 @@
 #define VM86_REGS_SIZE2 (sizeof(struct kernel_vm86_regs) - VM86_REGS_SIZE1)
 
 asmlinkage struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs));
-asmlinkage struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
+struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
 {
 	struct pt_regs *ret;
 	unsigned long tmp;
diff -u --recursive --new-file v2.1.130/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.1.130/linux/arch/i386/mm/init.c	Wed Sep  9 14:51:05 1998
+++ linux/arch/i386/mm/init.c	Fri Nov 27 12:46:56 1998
@@ -293,11 +293,18 @@
 		 * extended bios data area. 
 		 *
 		 * there is a real-mode segmented pointer pointing to the
-		 * 4K EBDA area at 0x40E, calculate and scan it here:
+		 * 4K EBDA area at 0x40E, calculate and scan it here.
+		 *
+		 * NOTE! There are Linux loaders that will corrupt the EBDA
+		 * area, and as such this kind of SMP config may be less
+		 * trustworthy, simply because the SMP table may have been
+		 * stomped on during early boot.
 		 */
 		address = *(unsigned short *)phys_to_virt(0x40E);
 		address<<=4;
 		smp_scan_config(address, 0x1000);
+		if (smp_found_config)
+			printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n");
 	}
 #endif
 	start_mem = PAGE_ALIGN(start_mem);
diff -u --recursive --new-file v2.1.130/linux/arch/i386/mm/ioremap.c linux/arch/i386/mm/ioremap.c
--- v2.1.130/linux/arch/i386/mm/ioremap.c	Tue Jul 28 14:21:07 1998
+++ linux/arch/i386/mm/ioremap.c	Fri Nov 27 15:03:14 1998
@@ -84,11 +84,16 @@
  * Remap an arbitrary physical address space into the kernel virtual
  * address space. Needed when the kernel wants to access high addresses
  * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
  */
 void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
 {
 	void * addr;
 	struct vm_struct * area;
+	unsigned long offset;
 
 	/*
 	 * Don't remap the low PCI/ISA area, it's always mapped..
@@ -105,9 +110,9 @@
 	/*
 	 * Mappings have to be page-aligned
 	 */
-	if (phys_addr & ~PAGE_MASK)
-		return NULL;
-	size = PAGE_ALIGN(size);
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(size + offset);
 
 	/*
 	 * Don't allow mappings that wrap..
@@ -126,11 +131,11 @@
 		vfree(addr);
 		return NULL;
 	}
-	return addr;
+	return (void *) (offset + (char *)addr);
 }
 
 void iounmap(void *addr)
 {
 	if (addr > high_memory)
-		return vfree(addr);
+		return vfree((void *) (PAGE_MASK & (unsigned long) addr));
 }
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/Config.in linux/drivers/char/joystick/Config.in
--- v2.1.130/linux/drivers/char/joystick/Config.in	Fri Oct  9 13:27:08 1998
+++ linux/drivers/char/joystick/Config.in	Tue Dec  1 19:05:05 1998
@@ -2,16 +2,16 @@
 # Joystick lowlevel driver configuration
 #
 
-dep_tristate '   Classic PC analog joysticks' CONFIG_JOY_ANALOG $CONFIG_JOYSTICK
+dep_tristate '   Classic PC analog joysticks and gamepads' CONFIG_JOY_ANALOG $CONFIG_JOYSTICK
 dep_tristate '   FPGaming and MadCatz A3D controllers' CONFIG_JOY_ASSASIN $CONFIG_JOYSTICK
-dep_tristate '   Gravis GrIP gamepads' CONFIG_JOY_GRAVIS $CONFIG_JOYSTICK
-dep_tristate '   Logitech Digital joysticks' CONFIG_JOY_LOGITECH $CONFIG_JOYSTICK
-dep_tristate '   Microsoft SideWinder, Genius Digital joysticks' CONFIG_JOY_SIDEWINDER $CONFIG_JOYSTICK
-dep_tristate '   ThrustMaster DirectConnect (BSP) joysticks' CONFIG_JOY_THRUSTMASTER $CONFIG_JOYSTICK
-dep_tristate '   PDPI Lightning L4 gamecards' CONFIG_JOY_LIGHTNING $CONFIG_JOYSTICK
+dep_tristate '   Gravis GrIP joysticks and gamepads' CONFIG_JOY_GRAVIS $CONFIG_JOYSTICK
+dep_tristate '   Logitech Digital joysticks and gamepads' CONFIG_JOY_LOGITECH $CONFIG_JOYSTICK
+dep_tristate '   Microsoft SideWinder, Genius Digital joysticks and gamepads' CONFIG_JOY_SIDEWINDER $CONFIG_JOYSTICK
+dep_tristate '   ThrustMaster DirectConnect joysticks and gamepads' CONFIG_JOY_THRUSTMASTER $CONFIG_JOYSTICK
+dep_tristate '   PDPI Lightning 4 gamecards' CONFIG_JOY_LIGHTNING $CONFIG_JOYSTICK
 if [ "$CONFIG_PARPORT" != "n" ]; then
-  dep_tristate '   NES, SNES, PSX, Multisystem gamepads' CONFIG_JOY_CONSOLE $CONFIG_JOYSTICK
-  dep_tristate '   Sega, Multisystem gamepads' CONFIG_JOY_DB9 $CONFIG_JOYSTICK
+  dep_tristate '   NES, SNES, PSX, Multisystem joysticks and gamepads' CONFIG_JOY_CONSOLE $CONFIG_JOYSTICK
+  dep_tristate '   Sega, Multisystem joysticks and gamepads' CONFIG_JOY_DB9 $CONFIG_JOYSTICK
   dep_tristate '   TurboGraFX Multisystem joystick interface' CONFIG_JOY_TURBOGRAFX $CONFIG_JOYSTICK
 fi  
 if [ "$CONFIG_AMIGA" = "y" ]; then
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/joy-amiga.c linux/drivers/char/joystick/joy-amiga.c
--- v2.1.130/linux/drivers/char/joystick/joy-amiga.c	Fri Oct  9 13:27:08 1998
+++ linux/drivers/char/joystick/joy-amiga.c	Tue Dec  1 19:05:05 1998
@@ -148,8 +148,8 @@
 #ifdef MODULE
 void cleanup_module(void)
 {
-	while (js_am_port) {
-		if (js_am_port->devs[0])
+	while (js_am_port != NULL) {
+		if (js_am_port->devs[0] != NULL)
 			js_unregister_device(js_am_port->devs[0]);
 		js_am_port = js_unregister_port(js_am_port);
 	}
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/joy-analog.c linux/drivers/char/joystick/joy-analog.c
--- v2.1.130/linux/drivers/char/joystick/joy-analog.c	Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/joystick/joy-analog.c	Tue Dec  1 19:05:05 1998
@@ -195,9 +195,9 @@
 	int i;
 	struct js_an_info *info;
 
-	while (js_an_port) {
+	while (js_an_port != NULL) {
 		for (i = 0; i < js_an_port->ndevs; i++)
-			if (js_an_port->devs[i])
+			if (js_an_port->devs[i] != NULL)
 				js_unregister_device(js_an_port->devs[i]);
 		info = js_an_port->info;
 		release_region(info->io, 1);
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/joy-assasin.c linux/drivers/char/joystick/joy-assasin.c
--- v2.1.130/linux/drivers/char/joystick/joy-assasin.c	Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/joystick/joy-assasin.c	Tue Dec  1 19:05:05 1998
@@ -410,9 +410,9 @@
 	int i;
 	struct js_as_info *info;
 
-	while (js_as_port) {
+	while (js_as_port != NULL) {
 		for (i = 0; i < js_as_port->ndevs; i++)
-			if (js_as_port->devs[i])
+			if (js_as_port->devs[i] != NULL)
 				js_unregister_device(js_as_port->devs[i]);
 		info = js_as_port->info;
 		release_region(info->io, 1);
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/joy-console.c linux/drivers/char/joystick/joy-console.c
--- v2.1.130/linux/drivers/char/joystick/joy-console.c	Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/joystick/joy-console.c	Tue Dec  1 19:05:05 1998
@@ -373,9 +373,9 @@
 	struct js_console_info *info;
 	int i;
 
-	while (js_console_port) {
+	while (js_console_port != NULL) {
 		for (i = 0; i < js_console_port->ndevs; i++)
-			if (js_console_port->devs[i])
+			if (js_console_port->devs[i] != NULL)
 				js_unregister_device(js_console_port->devs[i]);
 		info = js_console_port->info;
 #ifdef USE_PARPORT
@@ -428,11 +428,11 @@
 		struct parport *pp;
 
 		if (config[0] > 0x10)
-			for (pp=parport_enumerate(); pp && (pp->base!=config[0]); pp=pp->next);
+			for (pp=parport_enumerate(); pp != NULL && (pp->base!=config[0]); pp=pp->next);
 		else
-			for (pp=parport_enumerate(); pp && (config[0]>0); pp=pp->next) config[0]--;
+			for (pp=parport_enumerate(); pp != NULL && (config[0]>0); pp=pp->next) config[0]--;
 
-		if (!pp) {
+		if (pp == NULL) {
 			printk(KERN_ERR "joy-console: no such parport\n");
 			return port;
 		}
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/joy-db9.c linux/drivers/char/joystick/joy-db9.c
--- v2.1.130/linux/drivers/char/joystick/joy-db9.c	Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/joystick/joy-db9.c	Tue Dec  1 19:05:05 1998
@@ -38,8 +38,8 @@
 
 MODULE_AUTHOR("Andree Borrmann <A.Borrmann@tu-bs.de>");
 MODULE_PARM(js_db9, "2i");
-MODULE_PARM(js_db9_2, "0-2i");
-MODULE_PARM(js_db9_3, "0-2i");
+MODULE_PARM(js_db9_2, "2i");
+MODULE_PARM(js_db9_3, "2i");
 
 #define JS_MULTI_STICK	0x01
 #define JS_MULTI2_STICK 0x02
@@ -228,42 +228,6 @@
 }
 
 /*
- * js_db9_enable_ps2() enables PS/2 capabilities on a parallel port and
- * switches data lines to input mode. We should use parport_change_mode() for
- * that if parport present - unfortunately that does nothing and only contains
- * a FIXME comment.
- */
-
-static inline void js_db9_enable_ps2(struct js_db9_info *info)
-{
-#ifdef USE_PARPORT
-	int io = info->port->port->base;
-#else
-	int io = info->port;
-#endif
-
-	outb(0x35,io+0x402);		/* enable PS/2 mode: */
-	outb(JS_DB9_NORMAL,io+2);	/* reverse direction, enable Select signal: */
-}
-
-/*
- * js_db9_disable_ps2() disables PS/2 capabilities on a parallel port
- * and restores it to standard mode.
- */
-
-static inline void js_db9_disable_ps2(struct js_db9_info *info)
-{
-#ifdef USE_PARPORT
-	int io = info->port->port->base;
-#else
-	int io = info->port;
-#endif
-
-	outb(0,io+2);		/* normal direction */
-	outb(0x15,io+0x402);	/* enable normal mode */
-}
-
-/*
  * open callback: claim parport.
  */
 
@@ -275,7 +239,9 @@
 #ifdef USE_PARPORT
 		if (parport_claim(info->port)) return -EBUSY;
 #endif
-		js_db9_enable_ps2(info);
+
+		JS_PAR_ECTRL_OUT(0x35,info->port);		/* enable PS/2 mode: */
+		JS_PAR_CTRL_OUT(JS_DB9_NORMAL,info->port);	/* reverse direction, enable Select signal */
 	}
 		
 	MOD_INC_USE_COUNT;
@@ -293,7 +259,10 @@
 	MOD_DEC_USE_COUNT;
 
 	if (!MOD_IN_USE) {
-		js_db9_disable_ps2(info);
+
+		JS_PAR_CTRL_OUT(0x00,info->port);	/* normal direction */
+		JS_PAR_ECTRL_OUT(0x15,info->port);	/* enable normal mode */
+
 #ifdef USE_PARPORT
 		parport_release(info->port);
 #endif
@@ -306,7 +275,7 @@
 {
 	struct js_db9_info *info;
 
-	while (js_db9_port) {
+	while (js_db9_port != NULL) {
 		js_unregister_device(js_db9_port->devs[0]);
 		info = js_db9_port->info;
 #ifdef USE_PARPORT
@@ -359,11 +328,11 @@
 		struct parport *pp;
 
 		if (config[0] > 0x10)
-			for (pp=parport_enumerate(); pp && (pp->base!=config[0]); pp=pp->next);
+			for (pp=parport_enumerate(); pp != NULL && (pp->base!=config[0]); pp=pp->next);
 		else
-			for (pp=parport_enumerate(); pp && (config[0]>0); pp=pp->next) config[0]--;
+			for (pp=parport_enumerate(); pp != NULL && (config[0]>0); pp=pp->next) config[0]--;
 
-		if (!pp) {
+		if (pp == NULL) {
 			printk(KERN_ERR "joy-db9: no such parport\n");
 			return port;
 		}
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/joy-gravis.c linux/drivers/char/joystick/joy-gravis.c
--- v2.1.130/linux/drivers/char/joystick/joy-gravis.c	Fri Oct  9 13:27:08 1998
+++ linux/drivers/char/joystick/joy-gravis.c	Tue Dec  1 19:05:05 1998
@@ -43,6 +43,7 @@
 #define JS_GR_STROBE_GPP	75
 
 #define JS_GR_MODE_XT		2
+#define JS_GR_MODE_BD		3
 #define JS_GR_LENGTH_XT		4
 #define JS_GR_STROBE_XT		30
 #define JS_GR_MAX_CHUNKS_XT	10	
@@ -189,9 +190,10 @@
 
 				axes[i][0] =       (data[0] >> 2) & 0x3f;
 				axes[i][1] = 63 - ((data[0] >> 8) & 0x3f);
-				axes[i][2] = (data[1] >> 2) & 0x3f;
-				axes[i][3] = (data[1] >> 8) & 0x3f;
-				axes[i][4] = (data[2] >> 8) & 0x3f;
+				axes[i][2] =       (data[1] >> 2) & 0x3f;
+				axes[i][3] =       (data[1] >> 8) & 0x3f;
+				axes[i][4] =       (data[2] >> 8) & 0x3f;
+
 				axes[i][5] = ((data[2] >> 1) & 1) - ( data[2]       & 1);
 				axes[i][6] = ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1);
 				axes[i][7] = ((data[2] >> 5) & 1) - ((data[2] >> 4) & 1);
@@ -201,6 +203,22 @@
 
 				break;
 
+			case JS_GR_MODE_BD:
+
+				if (js_gr_xt_read_packet(info->io, (i << 1) + 4, data)) return -1;
+
+				axes[i][0] =       (data[0] >> 2) & 0x3f;
+				axes[i][1] = 63 - ((data[0] >> 8) & 0x3f);
+				axes[i][2] =       (data[2] >> 8) & 0x3f;
+
+				axes[i][3] = ((data[2] >> 1) & 1) - ( data[2]       & 1);
+				axes[i][4] = ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1);
+
+				buttons[i][0] = ((data[3] >> 6) & 0x01) | ((data[3] >> 3) & 0x06)
+					      | ((data[3] >> 4) & 0x18);
+
+				break;
+
 			default:
 				break;
 
@@ -276,6 +294,28 @@
 
 			break;
 
+		case JS_GR_MODE_BD:
+
+			for (i = 0; i < 3; i++) {
+				corr[i].type = JS_CORR_BROKEN;
+				corr[i].prec = 0;
+				corr[i].coef[0] = 31 - 4;
+				corr[i].coef[1] = 32 + 4;
+				corr[i].coef[2] = (1 << 29) / (32 - 14);
+				corr[i].coef[3] = (1 << 29) / (32 - 14);
+			}
+
+			for (i = 3; i < 5; i++) {
+				corr[i].type = JS_CORR_BROKEN;
+				corr[i].prec = 0;
+				corr[i].coef[0] = 0;
+				corr[i].coef[1] = 0;
+				corr[i].coef[2] = (1 << 29);
+				corr[i].coef[3] = (1 << 29);
+			}
+			
+			break;
+
 	}
 }
 
@@ -286,9 +326,9 @@
 static struct js_port __init *js_gr_probe(int io, struct js_port *port)
 {
 	struct js_gr_info info;
-	char *names[] = { NULL, "Gravis GamePad Pro", "Gravis Xterminator" };
-	char axes[] = { 0, 2, 9 };
-	char buttons[] = { 0, 10, 11 };
+	char *names[] = { NULL, "Gravis GamePad Pro", "Gravis Xterminator", "Gravis Blackhawk Digital"};
+	char axes[] = { 0, 2, 9, 5};
+	char buttons[] = { 0, 10, 11, 5};
 	unsigned int data[JS_GR_LENGTH_XT];
 	int i;
 
@@ -298,7 +338,12 @@
 
 	for (i = 0; i < 2; i++) {
 		if (!js_gr_gpp_read_packet(io, (i << 1) + 4, data)) info.mode[i] = JS_GR_MODE_GPP;
-		if (!js_gr_xt_read_packet(io, (i << 1) + 4, data)) info.mode[i] = JS_GR_MODE_XT;
+		if (!js_gr_xt_read_packet(io, (i << 1) + 4, data)) {
+			if ((data[3] & 7) == 7)
+				info.mode[i] = JS_GR_MODE_XT;
+			if ((data[3] & 7) == 0)
+				info.mode[i] = JS_GR_MODE_BD;
+		}
 	}
 
 	if (!info.mode[0] && !info.mode[1]) return port;
@@ -344,9 +389,9 @@
 	int i;
 	struct js_gr_info *info;
 
-	while (js_gr_port) {
+	while (js_gr_port != NULL) {
 		for (i = 0; i < js_gr_port->ndevs; i++)
-			if (js_gr_port->devs[i])
+			if (js_gr_port->devs[i] != NULL)
 				js_unregister_device(js_gr_port->devs[i]);
 		info = js_gr_port->info;
 		release_region(info->io, 1);
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/joy-lightning.c linux/drivers/char/joystick/joy-lightning.c
--- v2.1.130/linux/drivers/char/joystick/joy-lightning.c	Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/joystick/joy-lightning.c	Tue Dec  1 19:05:05 1998
@@ -352,9 +352,9 @@
 	int cal[4] = {59, 59, 59, 59};
 	struct js_l4_info *info;
 
-	while (js_l4_port) {
+	while (js_l4_port != NULL) {
 		for (i = 0; i < js_l4_port->ndevs; i++)
-			if (js_l4_port->devs[i])
+			if (js_l4_port->devs[i] != NULL)
 				js_unregister_device(js_l4_port->devs[i]);
 		info = js_l4_port->info;
 		js_l4_setcal(info->port, cal);
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/joy-logitech.c linux/drivers/char/joystick/joy-logitech.c
--- v2.1.130/linux/drivers/char/joystick/joy-logitech.c	Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/joystick/joy-logitech.c	Tue Dec  1 19:05:05 1998
@@ -361,7 +361,7 @@
 {
 	struct js_lt_info *info;
 
-	while (js_lt_port) {
+	while (js_lt_port != NULL) {
 		js_unregister_device(js_lt_port->devs[0]);
 		info = js_lt_port->info;
 		release_region(info->io, 1);
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/joy-sidewinder.c linux/drivers/char/joystick/joy-sidewinder.c
--- v2.1.130/linux/drivers/char/joystick/joy-sidewinder.c	Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/joystick/joy-sidewinder.c	Tue Dec  1 19:05:05 1998
@@ -88,6 +88,11 @@
 	} while (delays[i++]);
 	__restore_flags(flags);
 
+	for (i = 0; i < 4; i++) {
+		udelay(300);
+		outb(0xff, io);
+	}
+
 	return;
 }
 
@@ -137,19 +142,21 @@
 	__restore_flags(flags);
 
 	*data = 0;
-	t = i;
 
-	if (t == l1) {
+	if (i == l1) {
+		t = i > 64 ? 64 : i;
 		for (i = 0; i < t; i++)
 			*data |= (__u64) (buf[i] & 1) << i;
 		return t;
 	}
-	if (t == l2) {
+	if (i == l2) {
+		t = i > 22 ? 22 : i;
 		for (i = 0; i < t; i++)
 			*data |= (__u64) buf[i] << (3 * i);
 		return t * 3;
 	}
-	return t;
+
+	return i;
 }
 
 /*
@@ -199,7 +206,7 @@
 				i = js_sw_read_packet(info->io, -1, 22, JS_SW_EXT_STROBE, &data);
 			} else {
 				i = js_sw_read_packet(info->io, 64, 66, JS_SW_EXT_STROBE, &data);
-				if (i == 192) info->optimize = 1;
+				if (i == 198) info->optimize = 1;
 			}
 
 			if (i < 60) {
@@ -456,9 +463,9 @@
 	int i;
 	struct js_sw_info *info;
 
-	while (js_sw_port) {
+	while (js_sw_port != NULL) {
 		for (i = 0; i < js_sw_port->ndevs; i++)
-			if (js_sw_port->devs[i])
+			if (js_sw_port->devs[i] != NULL)
 				js_unregister_device(js_sw_port->devs[i]);
 		info = js_sw_port->info;
 		release_region(info->io, 1);
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/joy-thrustmaster.c linux/drivers/char/joystick/joy-thrustmaster.c
--- v2.1.130/linux/drivers/char/joystick/joy-thrustmaster.c	Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/joystick/joy-thrustmaster.c	Tue Dec  1 19:05:05 1998
@@ -39,12 +39,12 @@
 #include <linux/module.h>
 #include <linux/string.h>
 
-#define JS_TM_MAX_START		200
-#define JS_TM_MAX_STROBE	15
+#define JS_TM_MAX_START		400
+#define JS_TM_MAX_STROBE	25
 #define JS_TM_MAX_LENGTH	13
 
 #define JS_TM_MODE_M3DI		1
-#define JS_TM_MODE_3DRP		2
+#define JS_TM_MODE_3DRP		3
 #define JS_TM_MODE_WCS3		4
 
 #define JS_TM_MODE_MAX		5	/* Last mode + 1 */
@@ -73,7 +73,7 @@
 	unsigned char mode;
 };
 
-static int js_tm_id_to_def[JS_TM_MODE_MAX] = {0x00, 0x42, 0x22, 0x00, 0x00};
+static int js_tm_id_to_def[JS_TM_MODE_MAX] = {0x00, 0x42, 0x00, 0x22, 0x00};
 
 /*
  * js_tm_read_packet() reads a ThrustMaster packet.
@@ -120,6 +120,7 @@
 					i++;
 				}
 			} else {					/* Start bit */
+				data[i] = 0;
 				error |= ~v & 1;
 				j++;
 			}
@@ -251,10 +252,10 @@
 static struct js_port __init *js_tm_probe(int io, struct js_port *port)
 {
 	struct js_tm_info info;
-	char *names[JS_TM_MODE_MAX] = { NULL, "ThrustMaster Millenium 3D Inceptor",
-						"ThrustMaster Rage 3D Gamepad", NULL, "ThrustMaster WCS III" };
-	char axes[JS_TM_MODE_MAX] = { 0, 6, 2, 0, 0 };
-	char buttons[JS_TM_MODE_MAX] = { 0, 5, 10, 0, 0 };
+	char *names[JS_TM_MODE_MAX] = { NULL, "ThrustMaster Millenium 3D Inceptor", NULL,
+						"ThrustMaster Rage 3D Gamepad", "ThrustMaster WCS III" };
+	char axes[JS_TM_MODE_MAX] = { 0, 6, 0, 2, 0 };
+	char buttons[JS_TM_MODE_MAX] = { 0, 5, 0, 10, 0 };
 
 	unsigned char data[JS_TM_MAX_LENGTH];
 	unsigned char u;
@@ -320,7 +321,7 @@
 {
 	struct js_tm_info *info;
 
-	while (js_tm_port) {
+	while (js_tm_port != NULL) {
 		js_unregister_device(js_tm_port->devs[0]);
 		info = js_tm_port->info;
 		release_region(info->io, 1);
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/joy-turbografx.c linux/drivers/char/joystick/joy-turbografx.c
--- v2.1.130/linux/drivers/char/joystick/joy-turbografx.c	Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/joystick/joy-turbografx.c	Tue Dec  1 19:05:05 1998
@@ -42,21 +42,26 @@
 
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_PARM(js_tg, "2i");
-MODULE_PARM(js_tg_2, "0-2i");
-MODULE_PARM(js_tg_3, "0-2i");
-
-#define JS_TG_BUTTON	3
-#define JS_TG_UP	4
-#define JS_TG_DOWN	5
-#define JS_TG_LEFT	6
-#define JS_TG_RIGHT	7
+MODULE_PARM(js_tg, "2-8i");
+MODULE_PARM(js_tg_2, "2-8i");
+MODULE_PARM(js_tg_3, "2-8i");
+
+#define JS_TG_BUTTON1	0x08
+#define JS_TG_UP	0x10
+#define JS_TG_DOWN	0x20	
+#define JS_TG_LEFT	0x40
+#define JS_TG_RIGHT	0x80
+
+#define JS_TG_BUTTON2	0x02
+#define JS_TG_BUTTON3	0x04
+#define JS_TG_BUTTON4	0x01
+#define JS_TG_BUTTON5	0x08
 
 static struct js_port* js_tg_port = NULL;
 
-static int js_tg[] __initdata = { -1, 0 };
-static int js_tg_2[] __initdata = { -1, 0 };
-static int js_tg_3[] __initdata = { -1, 0 };
+static int js_tg[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
+static int js_tg_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
+static int js_tg_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
 
 struct js_tg_info {
 #ifdef USE_PARPORT
@@ -64,7 +69,7 @@
 #else
 	int port;		/* hw port */
 #endif
-	int count;		/* number of joysticks */
+	int sticks;		/* joysticks connected */
 };
 
 /*
@@ -74,17 +79,21 @@
 static int js_tg_read(void *xinfo, int **axes, int **buttons)
 {
 	struct js_tg_info *info = xinfo;
-	int data, i;
+	int data1, data2, i;
 
-	for (i = 0; i < info->count; i++) {
+	for (i = 0; i < 7; i++)
+		if ((info->sticks >> i) & 1) {
 
 		JS_PAR_DATA_OUT(~(1 << i), info->port);
-		data = JS_PAR_STATUS(info->port) ^ ~JS_PAR_STATUS_INVERT;
+		data1 = JS_PAR_STATUS(info->port) ^ ~JS_PAR_STATUS_INVERT;
+		data2 = JS_PAR_CTRL_IN(info->port) ^ JS_PAR_CTRL_INVERT;
 
-		axes[i][0] = ((data >> JS_TG_RIGHT) & 1) - ((data >> JS_TG_LEFT) & 1);
-		axes[i][1] = ((data >> JS_TG_DOWN ) & 1) - ((data >> JS_TG_UP  ) & 1);
+		axes[i][0] = ((data1 & JS_TG_RIGHT) ? 1 : 0) - ((data1 & JS_TG_LEFT) ? 1 : 0);
+		axes[i][1] = ((data1 & JS_TG_DOWN ) ? 1 : 0) - ((data1 & JS_TG_UP  ) ? 1 : 0);
 
-		buttons[i][0] = (data >> JS_TG_BUTTON) & 1;
+		buttons[i][0] = ((data1 & JS_TG_BUTTON1) ? 0x01 : 0) | ((data2 & JS_TG_BUTTON2) ? 0x02 : 0)
+			      | ((data2 & JS_TG_BUTTON3) ? 0x04 : 0) | ((data2 & JS_TG_BUTTON4) ? 0x08 : 0)
+			      | ((data2 & JS_TG_BUTTON5) ? 0x10 : 0);
 
 	}
 
@@ -97,10 +106,14 @@
 
 int js_tg_open(struct js_dev *dev)
 {
-#ifdef USE_PARPORT
 	struct js_tg_info *info = dev->port->info;
-	if (!MOD_IN_USE && parport_claim(info->port)) return -EBUSY; 
+
+	if (!MOD_IN_USE) {
+#ifdef USE_PARPORT
+		if (parport_claim(info->port)) return -EBUSY; 
 #endif
+		JS_PAR_CTRL_OUT(0x04, info->port);
+	}
 	MOD_INC_USE_COUNT;
 	return 0;
 }
@@ -111,13 +124,15 @@
 
 int js_tg_close(struct js_dev *dev)
 {
-#ifdef USE_PARPORT
         struct js_tg_info *info = dev->port->info;
-#endif
+
         MOD_DEC_USE_COUNT;
+	if (!MOD_IN_USE) {
+		JS_PAR_CTRL_OUT(0x00, info->port);
 #ifdef USE_PARPORT
-        if (!MOD_IN_USE) parport_release(info->port);
+        	parport_release(info->port);
 #endif
+	}
         return 0;
 }
 
@@ -127,9 +142,9 @@
 	struct js_tg_info *info;
 	int i;
 
-	while (js_tg_port) {
+	while (js_tg_port != NULL) {
 		for (i = 0; i < js_tg_port->ndevs; i++)
-			if (js_tg_port->devs[i])
+			if (js_tg_port->devs[i] != NULL)
 				js_unregister_device(js_tg_port->devs[i]);
 		info = js_tg_port->info;
 #ifdef USE_PARPORT
@@ -147,19 +162,20 @@
  * tg gamepads.
  */
 
-static void __init js_tg_init_corr(int count, struct js_corr **corr)
+static void __init js_tg_init_corr(int sticks, struct js_corr **corr)
 {
 	int i, j;
 
-	for (i = 0; i < count; i++)
-		for (j = 0; j < 2; j++) {
-			corr[i][j].type = JS_CORR_BROKEN;
-			corr[i][j].prec = 0;
-			corr[i][j].coef[0] = 0;
-			corr[i][j].coef[1] = 0;
-			corr[i][j].coef[2] = (1 << 29);
-			corr[i][j].coef[3] = (1 << 29);
-		}
+	for (i = 0; i < 7; i++)
+		if ((sticks >> i) & 1)
+			for (j = 0; j < 2; j++) {
+				corr[i][j].type = JS_CORR_BROKEN;
+				corr[i][j].prec = 0;
+				corr[i][j].coef[0] = 0;
+				corr[i][j].coef[1] = 0;
+				corr[i][j].coef[2] = (1 << 29);
+				corr[i][j].coef[3] = (1 << 29);
+			}
 }
 
 /*
@@ -168,53 +184,65 @@
 
 static struct js_port __init *js_tg_probe(int *config, struct js_port *port)
 {
-	struct js_tg_info info;
+	struct js_tg_info iniinfo;
+	struct js_tg_info *info = &iniinfo;
 	int i;
 
 	if (config[0] < 0) return port;
-	if (config[1] < 1 || config[1] > 8) return port;
 
 #ifdef USE_PARPORT
 	{
 		struct parport *pp;
 
 		if (config[0] > 0x10)
-			for (pp=parport_enumerate(); pp && (pp->base!=config[0]); pp=pp->next);
+			for (pp=parport_enumerate(); pp != NULL && (pp->base!=config[0]); pp=pp->next);
 		else
-			for (pp=parport_enumerate(); pp && (config[0]>0); pp=pp->next) config[0]--;
+			for (pp=parport_enumerate(); pp != NULL && (config[0]>0); pp=pp->next) config[0]--;
 
-		if (!pp) {
+		if (pp == NULL) {
 			printk(KERN_ERR "joy-tg: no such parport\n");
 			return port;
 		}
 
-		info.port = parport_register_device(pp, "joystick (turbografx)", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
-		if (!info.port)
+		info->port = parport_register_device(pp, "joystick (turbografx)", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+		if (!info->port)
 			return port;
 	}
 #else
-	info.port = config[0];
-	if (check_region(info.port, 3)) return port;
-	request_region(info.port, 3, "joystick (turbografx)");
+	info->port = config[0];
+	if (check_region(info->port, 3)) return port;
+	request_region(info->port, 3, "joystick (turbografx)");
 #endif
 
-	info.count = config[1];
-
-	port = js_register_port(port, &info, info.count, sizeof(struct js_tg_info), js_tg_read);
+	port = js_register_port(port, info, 7, sizeof(struct js_tg_info), js_tg_read);
+	info = port->info;
 
+	info->sticks = 0;
 
-	for (i = 0; i < info.count; i++)
+	for (i = 0; i < 7; i++)
+		if (config[i+1] > 0 && config[i+1] < 6) {
 #ifdef USE_PARPORT
-		printk(KERN_INFO "js%d: Multisystem joystick on %s\n",
-			js_register_device(port, i, 2, 1, "Multisystem joystick", js_tg_open, js_tg_close),
-			info.port->port->name);
+			printk(KERN_INFO "js%d: Multisystem joystick on %s\n",
+				js_register_device(port, i, 2, config[i+1], "Multisystem joystick", js_tg_open, js_tg_close),
+				info->port->port->name);
 #else
-		printk(KERN_INFO "js%d: Multisystem joystick at %#x\n",
-			js_register_device(port, i, 2, 1, "Multisystem joystick", js_tg_open, js_tg_close),
-			info.port);
+			printk(KERN_INFO "js%d: Multisystem joystick at %#x\n",
+				js_register_device(port, i, 2, config[i+1], "Multisystem joystick", js_tg_open, js_tg_close),
+				info->port);
 #endif
+			info->sticks |= (1 << i);
+		}
 
-	js_tg_init_corr(info.count, port->corr);
+        if (!info->sticks) {
+#ifdef USE_PARPORT
+		parport_unregister_device(info->port);
+#else
+		release_region(info->port, 3);
+#endif
+		return port;
+        }
+		
+	js_tg_init_corr(info->sticks, port->corr);
 
 	return port;
 }
diff -u --recursive --new-file v2.1.130/linux/drivers/char/joystick/joystick.c linux/drivers/char/joystick/joystick.c
--- v2.1.130/linux/drivers/char/joystick/joystick.c	Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/joystick/joystick.c	Tue Dec  1 19:05:05 1998
@@ -32,6 +32,7 @@
 
 #include <asm/io.h>
 #include <asm/system.h>
+#include <asm/segment.h>
 #include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -456,14 +457,14 @@
 	struct js_dev *curd = js_dev;
 	unsigned long flags;
 
-	while (curp) {
+	while (curp != NULL) {
 		curp->read(curp->info, curp->axes, curp->buttons);
 		curp = curp->next;
 	}
 
 	spin_lock_irqsave(&js_lock, flags);
 
-	while (curd) {
+	while (curd != NULL) {
 		if (data) {
 			js_process_data(curd);
 			js_sync_buff(curd);
@@ -643,12 +644,12 @@
 	if (orig_tail == jd->tail) {
 		new_tail = curl->tail;
 		curl = jd->list;
-		while (curl && curl->tail != jd->tail) {
+		while (curl != NULL && curl->tail != jd->tail) {
 			if (ROT(jd->bhead, new_tail, curl->tail) ||
 				(jd->bhead == curl->tail)) new_tail = curl->tail;
 			curl = curl->next;
 		}
-		if (!curl) jd->tail = new_tail;
+		if (curl == NULL) jd->tail = new_tail;
 	}
 
 	spin_unlock_irqrestore(&js_lock, flags);
@@ -855,42 +856,51 @@
 
 static int js_open(struct inode *inode, struct file *file)
 {
-	struct js_list *curl;
+	struct js_list *curl, *new;
 	struct js_dev *jd = js_dev;
 	int i = MINOR(inode->i_rdev);
 	unsigned long flags;
-	int result;
+	int result; 
 
 	if (MAJOR(inode->i_rdev) != JOYSTICK_MAJOR)
 		return -EINVAL;
 
-	while (i > 0 && jd) {
+	spin_lock_irqsave(&js_lock, flags);
+
+	while (i > 0 && jd != NULL) {
 		jd = jd->next;
 		i--;
 	}
 
-	if (!jd) return -ENODEV;
+	spin_unlock_irqrestore(&js_lock, flags);
+
+	if (jd == NULL) return -ENODEV;
 
 	if ((result = jd->open(jd))) return result;
 
 	MOD_INC_USE_COUNT;
 	if (!js_use_count++) js_do_timer(0);
 
-	curl = jd->list;
+	if ((new = kmalloc(sizeof(struct js_list), GFP_KERNEL)) != NULL) {
 
-	spin_lock_irqsave(&js_lock, flags);
+		spin_lock_irqsave(&js_lock, flags);
+
+		curl = jd->list;
 
-	jd->list = kmalloc(sizeof(struct js_list), GFP_KERNEL);
-	jd->list->next = curl;
-	jd->list->dev = jd;
-	jd->list->startup = 0;
-	jd->list->tail = GOB(jd->bhead);
+		jd->list = new;
+		jd->list->next = curl;
+		jd->list->dev = jd;
+		jd->list->startup = 0;
+		jd->list->tail = GOB(jd->bhead);
+		file->private_data = jd->list;
 
-	spin_unlock_irqrestore(&js_lock, flags);
+		spin_unlock_irqrestore(&js_lock, flags);
 
-	file->private_data = jd->list;
+	} else {
+		result = -ENOMEM;
+	}
 
-	return 0;
+	return result;
 }
 
 /*
@@ -915,11 +925,11 @@
 	while (*curp && (*curp != curl)) curp = &((*curp)->next);
 	*curp = (*curp)->next;
 
-	if (jd->list)
+	if (jd->list != NULL)
 	if (curl->tail == jd->tail) {
 		curl = jd->list;
 		new_tail = curl->tail;
-		while (curl && curl->tail != jd->tail) {
+		while (curl != NULL && curl->tail != jd->tail) {
 			if (ROT(jd->bhead, new_tail, curl->tail) ||
 			       (jd->bhead == curl->tail)) new_tail = curl->tail;
 			curl = curl->next;
@@ -957,7 +967,7 @@
 	printk(",--- Dumping Devices:\n");
 	printk("| js_dev = %x\n", (int) js_dev);
 
-	while (curd) {
+	while (curd != NULL) {
 		printk("|  %s-device %x, next %x axes %d, buttons %d, port %x - %#x\n",
 			curd->next ? "|":"`",
 			(int) curd, (int) curd->next, curd->num_axes, curd->num_buttons, (int) curd->port, curd->port->io);
@@ -967,7 +977,7 @@
 	printk(">--- Dumping ports:\n");
 	printk("| js_port = %x\n", (int) js_port);
 
-	while (curp) {
+	while (curp != NULL) {
 		printk("|  %s-port %x, next %x, io %#x, devices %d\n",
 			curp->next ? "|":"`",
 			(int) curp, (int) curp->next, curp->io, curp->ndevs);
@@ -995,35 +1005,39 @@
 {
 	struct js_port **ptrp = &js_port;
 	struct js_port *curp;
+	void *all;
 	int i;
 	unsigned long flags;
 
-	spin_lock_irqsave(&js_lock, flags);
+	if ((all = kmalloc(sizeof(struct js_port) + 4 * devs * sizeof(void*) + infos, GFP_KERNEL)) == NULL)
+		return NULL;
 
-	while (*ptrp) ptrp=&((*ptrp)->next);
-	*ptrp = curp = kmalloc(sizeof(struct js_port), GFP_KERNEL);
+	curp = all;
 
 	curp->next = NULL;
 	curp->prev = port;
 	curp->read = read;
 	curp->ndevs = devs;
 
-	curp->devs = kmalloc(devs * sizeof(struct js_dev*), GFP_KERNEL);
+	curp->devs = all += sizeof(struct js_port);
+	for (i = 0; i < devs; i++) curp->devs[i] = NULL;
 
-	for (i = 0; i < devs; i++)
-		curp->devs[i] = NULL;
-
-	curp->axes = kmalloc(devs * sizeof(int*), GFP_KERNEL);
-	curp->buttons = kmalloc(devs * sizeof(int*), GFP_KERNEL);
-	curp->corr = kmalloc(devs * sizeof(struct js_corr*), GFP_KERNEL);
+	curp->axes = all += devs * sizeof(void*);
+	curp->buttons = (void*) all += devs * sizeof(void*);
+	curp->corr = all += devs * sizeof(void*);
 
 	if (infos) {
-		curp->info = kmalloc(infos, GFP_KERNEL);
+		curp->info = all += devs * sizeof(void*); 
 		memcpy(curp->info, info, infos);
 	} else {
 		curp->info = NULL;
 	}
 
+	spin_lock_irqsave(&js_lock, flags);
+
+	while (*ptrp != NULL) ptrp=&((*ptrp)->next);
+	*ptrp = curp;
+
 	spin_unlock_irqrestore(&js_lock, flags);
 
 	return curp;
@@ -1037,19 +1051,14 @@
 
 	spin_lock_irqsave(&js_lock, flags);
 
-	while (*curp && (*curp != port)) curp = &((*curp)->next);
+	while (*curp != NULL && (*curp != port)) curp = &((*curp)->next);
 	*curp = (*curp)->next;
 
+	spin_unlock_irqrestore(&js_lock, flags);
+
 	prev = port->prev;
-	kfree(port->devs);
-	kfree(port->axes);
-	kfree(port->buttons);
-	kfree(port->corr);
-	if (port->info) kfree(port->info);
 	kfree(port);
 
-	spin_unlock_irqrestore(&js_lock, flags);
-
 	return prev;
 }
 
@@ -1058,17 +1067,16 @@
 {
 	struct js_dev **ptrd = &js_dev;
 	struct js_dev *curd;
+	void *all;
 	int i = 0;
 	unsigned long flags;
 
-	spin_lock_irqsave(&js_lock, flags);
-
-	while (*ptrd) {
-		ptrd=&(*ptrd)->next;
-		i++;
-	}
+	if ((all = kmalloc(sizeof(struct js_dev) + 2 * axes * sizeof(int) +
+			2 * (((buttons - 1) >> 5) + 1) * sizeof(int) +
+			axes * sizeof(struct js_corr) + strlen(name) + 1, GFP_KERNEL)) == NULL)
+		return -1;
 
-	*ptrd = curd = kmalloc(sizeof(struct js_dev), GFP_KERNEL);
+	curd = all;
 
 	curd->next = NULL;
 	curd->list = NULL;
@@ -1083,20 +1091,25 @@
 	curd->num_axes = axes;
 	curd->num_buttons = buttons;
 
-	curd->name = kmalloc(strlen(name) + 1, GFP_KERNEL);
-	strcpy(curd->name, name);
+	curd->cur.axes = all += sizeof(struct js_dev);
+	curd->cur.buttons = all += axes * sizeof(int);
+	curd->new.axes = all += (((buttons - 1) >> 5) + 1) * sizeof(int);
+	curd->new.buttons = all += axes * sizeof(int);
+	curd->corr = all += (((buttons -1 ) >> 5) + 1) * sizeof(int);
 
-	curd->cur.axes = kmalloc(axes * sizeof(int), GFP_KERNEL);
-	curd->cur.buttons = kmalloc((((buttons - 1) >> 5) + 1) * sizeof(int), GFP_KERNEL);
-	curd->new.axes = kmalloc(axes * sizeof(int), GFP_KERNEL);
-	curd->new.buttons = kmalloc((((buttons -1 ) >> 5) + 1) * sizeof(int), GFP_KERNEL);
-	curd->corr = kmalloc(axes * sizeof(struct js_corr), GFP_KERNEL);
+	curd->name = all += axes * sizeof(struct js_corr);
+	strcpy(curd->name, name);
 
 	port->devs[number] = curd;
 	port->axes[number] = curd->new.axes;
 	port->buttons[number] = curd->new.buttons;
 	port->corr[number] = curd->corr;
 
+	spin_lock_irqsave(&js_lock, flags);
+
+	while (*ptrd != NULL) { ptrd=&(*ptrd)->next; i++; }
+	*ptrd = curd;
+
 	spin_unlock_irqrestore(&js_lock, flags);	
 
 	return i;
@@ -1109,17 +1122,11 @@
 
 	spin_lock_irqsave(&js_lock, flags);
 
-	while (*curd && (*curd != dev)) curd = &((*curd)->next);
+	while (*curd != NULL && (*curd != dev)) curd = &((*curd)->next);
 	*curd = (*curd)->next;
 
 	spin_unlock_irqrestore(&js_lock, flags);	
 
-	kfree(dev->cur.axes);
-	kfree(dev->new.axes);
-	kfree(dev->cur.buttons);
-	kfree(dev->new.buttons);
-	kfree(dev->corr);
-	kfree(dev->name);
 	kfree(dev);
 }
 
diff -u --recursive --new-file v2.1.130/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v2.1.130/linux/drivers/char/keyboard.c	Tue Aug 18 22:02:03 1998
+++ linux/drivers/char/keyboard.c	Fri Nov 27 10:24:27 1998
@@ -201,7 +201,12 @@
 	add_keyboard_randomness(scancode);
 
 	tty = ttytab? ttytab[fg_console]: NULL;
- 	kbd = kbd_table + fg_console;
+	if (tty && (!tty->driver_data)) {
+		/* This is to workaround ugly bug in tty_io.c, which
+                   does not do locking when it should */
+		tty = NULL;
+	}
+	kbd = kbd_table + fg_console;
 	if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
  		put_queue(scancode);
 		/* we do not return yet, because we want to maintain
diff -u --recursive --new-file v2.1.130/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.1.130/linux/drivers/char/lp.c	Sun Nov  8 14:02:55 1998
+++ linux/drivers/char/lp.c	Fri Nov 27 10:23:11 1998
@@ -16,8 +16,17 @@
  * Parport sharing hacking by Andrea Arcangeli
  * Fixed kernel_(to/from)_user memory copy to check for errors
  * 				by Riccardo Facchetti <fizban@tin.it>
- * Interrupt handling workaround for printers with buggy handshake
- *				by Andrea Arcangeli, 11 May 98
+ * Redesigned interrupt handling for handle printers with buggy handshake
+ *				by Andrea Arcangeli, 11 May 1998
+ * Full efficient handling of printer with buggy irq handshake (now I have
+ * understood the meaning of the strange handshake). This is done sending new
+ * characters if the interrupt is just happened, even if the printer say to
+ * be still BUSY. This is needed at least with Epson Stylus Color. To enable
+ * the new TRUST_IRQ mode read the `LP OPTIMIZATION' section below...
+ * Fixed the irq on the rising edge of the strobe case.
+ * Obsoleted the CAREFUL flag since a printer that doesn' t work with
+ * CAREFUL will block a bit after in lp_check_status().
+ *				Andrea Arcangeli, 15 Oct 1998
  */
 
 /* This driver should, in theory, work with any parallel port that has an
@@ -49,6 +58,74 @@
  *	# insmod lp.o reset=1
  */
 
+/*
+ * LP OPTIMIZATIONS
+ *
+ * - TRUST_IRQ flag
+ * 
+ * Epson Stylus Color, HP and many other new printers want the TRUST_IRQ flag
+ * set when printing with interrupts. This is a long story. Such printers
+ * use a broken handshake (see the timing graph below) when printing with
+ * interrupts. The lp driver as default is just able to handle such bogus
+ * handshake, but setting such flag cause lp to go faster and probably do
+ * what such printers want (even if not documented).
+ *
+ * NOTE that setting the TRUST_IRQ flag in some printer can cause the irq
+ * printing to fail completly. You must try, to know if your printer
+ * will handle it. I suggest a graphics printing to force a major flow of
+ * characters to the printer for do the test. NOTE also that the TRUST_IRQ
+ * flag _should_ be fine everywhere but there is a lot of buggy hardware out
+ * there, so I am forced to implement it as a not-default thing.
+ * WARNING: before to do the test, be sure to have not played with the
+ * `-w' parameter of tunelp!
+ *
+ * Note also that lp automagically warn you (with a KERN_WARNING) if it
+ * detects that you could _try_ to set the TRUST_IRQ flag to speed up the
+ * printing and decrease the CPU load.
+ *
+ * To set the TRUST_IRQ flag you can use this command:
+ *
+ * tunelp /dev/lp? -T on
+ *
+ * If you have an old tunelp executable you can (hack and) use this simple
+ * C lazy proggy to set the flag in the lp driver:
+
+-------------------------- cut here -------------------------------------
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#define	LPTRUSTIRQ  0x060f
+
+int main(int argc, char **argv)
+{
+	int fd = open("/dev/lp0", O_RDONLY);
+	ioctl(fd, LPTRUSTIRQ, argc - 1);
+	if (argc - 1)
+		printf("trusting the irq\n");
+	else
+		printf("untrusting the irq\n");
+	return 0;
+}
+-------------------------- cut here -------------------------------------
+
+ * - LP_WAIT time
+ *
+ * You can use this setting if your printer is fast enough and/or your
+ * machine is slow enough ;-).
+ *
+ * tunelp /dev/lp? -w 0
+ *
+ * - LP_CHAR tries
+ *
+ * If you print with irqs probably you can decrease the CPU load a lot using
+ * this setting. This is not the default because the printing is reported to
+ * be jerky somewhere...
+ *
+ * tunelp /dev/lp? -c 1
+ *
+ *					11 Nov 1998, Andrea Arcangeli
+ */
+
 /* COMPATIBILITY WITH OLD KERNELS
  *
  * Under Linux 2.0 and previous versions, lp devices were bound to ports at
@@ -79,6 +156,12 @@
  *	ftp://e-mind.com/pub/linux/pscan/
  *
  *					11 May 98, Andrea Arcangeli
+ *
+ * My printer scanner run on an Epson Stylus Color show that such printer
+ * generates the irq on the _rising_ edge of the STROBE. Now lp handle
+ * this case fine too.
+ *
+ *					15 Oct 1998, Andrea Arcangeli
  */
 
 #include <linux/module.h>
@@ -95,7 +178,6 @@
 
 #include <linux/parport.h>
 #undef LP_STATS
-#undef LP_NEED_CAREFUL
 #include <linux/lp.h>
 
 #include <asm/irq.h>
@@ -115,16 +197,14 @@
 			   NULL, 0, 0, 0}
 };
 
-/* Test if printer is ready (and optionally has no error conditions) */
-#ifdef LP_NEED_CAREFUL
-#define LP_READY(minor, status) \
-  ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : ((status) & LP_PBUSY))
-#define _LP_CAREFUL_READY(status) \
-   ((status) & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
-      (LP_PBUSY|LP_PSELECD|LP_PERRORP)
-#else
-#define LP_READY(minor, status) ((status) & LP_PBUSY)
-#endif
+/* Test if printer is ready */
+#define	LP_READY(status)	((status) & LP_PBUSY)
+/* Test if the printer is not acking the strobe */
+#define	LP_NO_ACKING(status)	((status) & LP_PACK)
+/* Test if the printer has error conditions */
+#define LP_NO_ERROR(status)					\
+	 (((status) & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) ==	\
+	 (LP_PSELECD|LP_PERRORP))
 
 #undef LP_DEBUG
 #undef LP_READ_DEBUG
@@ -187,60 +267,124 @@
 	return retval;
 }
 
+#define	lp_wait(minor)	udelay(LP_WAIT(minor))
+
 static inline int lp_char(char lpchar, int minor)
 {
-	unsigned int wait = 0;
 	unsigned long count = 0;
 #ifdef LP_STATS
 	struct lp_stats *stats;
 #endif
 
+	if (signal_pending(current))
+		return 0;
+
 	for (;;)
 	{
+		unsigned char status;
+		int irq_ok = 0;
+
+		/*
+		 * Give a chance to other pardevice to run in the meantime.
+		 */
 		lp_yield(minor);
-		if (LP_READY(minor, r_str(minor)))
-			break;
- 		if (++count == LP_CHAR(minor) || signal_pending(current))
- 			return 0;
+
+		status = r_str(minor);
+		if (LP_NO_ERROR(status))
+		{
+			if (LP_READY(status))
+				break;
+
+			/*
+			 * This is a crude hack that should be well known
+			 * at least by Epson device driver developers. -arca
+			 */
+			irq_ok = (!LP_POLLED(minor) &&
+				  LP_NO_ACKING(status) &&
+				  lp_table[minor].irq_detected);
+			if ((LP_F(minor) & LP_TRUST_IRQ) && irq_ok)
+				break;
+		}
+		/*
+		 * NOTE: if you run with irqs you _must_ use
+		 * `tunelp /dev/lp? -c 1' to be rasonable efficient!
+		 */
+		if (++count == LP_CHAR(minor))
+		{
+			if (irq_ok)
+			{
+				static int first_time = 1;
+				/*
+				 * The printer is using a buggy handshake, so
+				 * revert to polling to not overload the
+				 * machine and warn the user that its printer
+				 * could get optimized trusting the irq. -arca
+				 */
+				lp_table[minor].irq_missed = 1;
+				if (first_time)
+				{
+					first_time = 0;
+					printk(KERN_WARNING "lp%d: the "
+					       "printing could be optimized "
+					       "using the TRUST_IRQ flag, "
+					       "see the top of "
+					       "linux/drivers/char/lp.c\n",
+					       minor);
+				}
+			}
+			return 0;
+		}
 	}
 
 	w_dtr(minor, lpchar);
+
 #ifdef LP_STATS
 	stats = &LP_STAT(minor);
 	stats->chars++;
 #endif
+
 	/* must wait before taking strobe high, and after taking strobe
 	   low, according spec.  Some printers need it, others don't. */
-#ifndef __sparc__
-	while (wait != LP_WAIT(minor)) /* FIXME: should be a udelay() */
-		wait++;
-#else
-	udelay(1);
-#endif
+	lp_wait(minor);
+
 	/* control port takes strobe high */
-	w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE);
-#ifndef __sparc__
-	while (wait)			/* FIXME: should be a udelay() */
-		wait--;
-#else
-	udelay(1);
-#endif
-	/* take strobe low */
 	if (LP_POLLED(minor))
-		/* take strobe low */
-		w_ctr(minor, LP_PSELECP | LP_PINITP);
-	else
 	{
+		w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE);
+		lp_wait(minor);
+		w_ctr(minor, LP_PSELECP | LP_PINITP);
+	} else {
+		/*
+		 * Epson Stylus Color generate the IRQ on the rising edge of
+		 * strobe so clean the irq's information before playing with
+		 * the strobe. -arca
+		 */
 		lp_table[minor].irq_detected = 0;
 		lp_table[minor].irq_missed = 0;
+		/*
+		 * Be sure that the CPU doesn' t reorder instructions. -arca
+		 */
+		mb();
+		w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE | LP_PINTEN);
+		lp_wait(minor);
 		w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN);
 	}
 
+	/*
+	 * Give to the printer a chance to put BUSY low. Really we could
+	 * remove this because we could _guess_ that we are slower to reach
+	 * again lp_char() than the printer to put BUSY low, but I' d like
+	 * to remove this variable from the function I go solve
+	 * when I read bug reports ;-). -arca
+	 */
+	lp_wait(minor);
+
 #ifdef LP_STATS
 	/* update waittime statistics */
 	if (count > stats->maxwait) {
 #ifdef LP_DEBUG
-		printk(KERN_DEBUG "lp%d success after %d counts.\n", minor, count);
+		printk(KERN_DEBUG "lp%d success after %d counts.\n",
+		       minor, count);
 #endif
 		stats->maxwait = count;
 	}
@@ -325,7 +469,10 @@
 	lp_table[minor].irq_detected = 0;
 	lp_table[minor].irq_missed = 1;
 
-	w_ctr(minor, LP_PSELECP | LP_PINITP);
+	if (LP_POLLED(minor))
+		w_ctr(minor, LP_PSELECP | LP_PINITP);
+	else
+		w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN);
 
 	do {
 		bytes_written = 0;
@@ -396,9 +543,7 @@
 						goto lp_polling;
 					}
 					if (!lp_table[minor].irq_detected)
-					{
 						interruptible_sleep_on_timeout(&lp->wait_q, LP_TIMEOUT_INTERRUPT);
-					}
 					sti();
 				}
 			}
@@ -453,101 +598,97 @@
 	return (i & 0x0f);
 }
 
-static inline void lp_select_in_high(int minor) 
-{
-	parport_frob_control(lp_table[minor].dev->port, 8, 8);
+static void lp_read_terminate(struct parport *port) {
+	parport_write_control(port, (parport_read_control(port) & ~2) | 8);
+	/* SelectIN high, AutoFeed low */
+	if (parport_wait_peripheral(port, 0x80, 0)) 
+		/* timeout, SelectIN high, Autofeed low */
+		return;
+	parport_write_control(port, parport_read_control(port) | 2);
+	/* AutoFeed high */
+	parport_wait_peripheral(port, 0x80, 0x80);
+	/* no timeout possible, Autofeed low, SelectIN high */
+	parport_write_control(port, (parport_read_control(port) & ~2) | 8);
 }
 
 /* Status readback confirming to ieee1284 */
 static ssize_t lp_read(struct file * file, char * buf,
-		       size_t count, loff_t *ppos)
+		       size_t length, loff_t *ppos)
 {
-	unsigned char z=0, Byte=0, status;
-	char *temp;
-	ssize_t retval;
-	unsigned int counter=0;
-	unsigned int i;
+	int i;
 	unsigned int minor=MINOR(file->f_dentry->d_inode->i_rdev);
-	
- 	/* Claim Parport or sleep until it becomes available
- 	 */
- 	lp_parport_claim (minor);
+	char *temp = buf;
+	ssize_t count = 0;
+	unsigned char z = 0;
+	unsigned char Byte = 0;
+	struct parport *port = lp_table[minor].dev->port;
 
-	temp=buf;	
-#ifdef LP_READ_DEBUG 
-	printk(KERN_INFO "lp%d: read mode\n", minor);
-#endif
+	lp_parport_claim (minor);
 
-	retval = verify_area(VERIFY_WRITE, buf, count);
-	if (retval)
-		return retval;
-	if (parport_ieee1284_nibble_mode_ok(lp_table[minor].dev->port, 0)==0) {
-#ifdef LP_READ_DEBUG
-		printk(KERN_INFO "lp%d: rejected IEEE1284 negotiation.\n",
-		       minor);
-#endif
-		lp_select_in_high(minor);
-		parport_release(lp_table[minor].dev);
-		return temp-buf;          /*  End of file */
-	}
-	for (i=0; i<=(count*2); i++) {
-		parport_frob_control(lp_table[minor].dev->port, 2, 2); /* AutoFeed high */
-		do {
-			status = (r_str(minor) & 0x40);
-			udelay(50);
-			counter++;
-			if (current->need_resched)
-				schedule ();
-		} while ((status == 0x40) && (counter < 20));
-		if (counter == 20) { 
-			/* Timeout */
+	switch (parport_ieee1284_nibble_mode_ok(port, 0))
+	{
+	case 0:
+		/* Handshake failed. */
+		lp_read_terminate(port);
+		lp_parport_release (minor);
+		return -EIO;
+	case 1:
+		/* No data. */
+		lp_read_terminate(port);
+		lp_parport_release (minor);
+		return 0;
+	default:
+		/* Data available. */
+
+		/* Hack: Wait 10ms (between events 6 and 7) */
+                schedule_timeout((HZ+99)/100);
+                break;
+	}
+
+	for (i=0; ; i++) {
+		parport_frob_control(port, 2, 2); /* AutoFeed high */
+		if (parport_wait_peripheral(port, 0x40, 0)) {
 #ifdef LP_READ_DEBUG
-			printk(KERN_DEBUG "lp_read: (Autofeed high) timeout\n");
+			/* Some peripherals just time out when they've sent
+			   all their data.  */
+			printk("%s: read1 timeout.\n", port->name);
 #endif
-			parport_frob_control(lp_table[minor].dev->port, 2, 0);
-			lp_select_in_high(minor);
-			parport_release(lp_table[minor].dev);
-			return temp-buf; /* end the read at timeout */
+			parport_frob_control(port, 2, 0); /* AutoFeed low */
+			break;
 		}
-		counter=0;
 		z = lp_read_nibble(minor);
-		parport_frob_control(lp_table[minor].dev->port, 2, 0); /* AutoFeed low */
-		do {
-			status=(r_str(minor) & 0x40);
-			udelay(20);
-			counter++;
-			if (current->need_resched)
-				schedule ();
-		} while ( (status == 0) && (counter < 20) );
-		if (counter == 20) { /* Timeout */
-#ifdef LP_READ_DEBUG
-			printk(KERN_DEBUG "lp_read: (Autofeed low) timeout\n");
-#endif
-			if (signal_pending(current)) {
-				lp_select_in_high(minor);
-				parport_release(lp_table[minor].dev);
-				if (temp !=buf)
-					return temp-buf;
-				else 
-					return -EINTR;
-			}
-			current->state=TASK_INTERRUPTIBLE;
-			schedule_timeout(LP_TIME(minor));
+		parport_frob_control(port, 2, 0); /* AutoFeed low */
+		if (parport_wait_peripheral(port, 0x40, 0x40)) {
+			printk("%s: read2 timeout.\n", port->name);
+			break;
 		}
+		if ((i & 1) != 0) {
+			Byte |= (z<<4);
+			if (temp) {
+				if (__put_user (Byte, temp))
+				{
+					count = -EFAULT;
+					temp = NULL;
+				} else {
+					temp++;
 
-		counter=0;
-
-		if (( i & 1) != 0) {
-			Byte= (Byte | z<<4);
-			if (__put_user(Byte, (char *)temp))
-				return -EFAULT;
-			temp++;
-		} else Byte=z;
+					if (++count == length)
+						temp = NULL;
+				}
+			}
+			/* Does the error line indicate end of data? */
+			if ((parport_read_status(port) & LP_PERRORP) == 
+			    LP_PERRORP) 
+				break;
+		} else 
+			Byte=z;
 	}
 
-	lp_select_in_high(minor);
-	lp_parport_release(minor);
-	return temp-buf;	
+	lp_read_terminate(port);
+
+	lp_parport_release (minor);
+
+	return count;
 }
 
 #endif
@@ -645,7 +786,7 @@
 			else
 				LP_F(minor) &= ~LP_ABORTOPEN;
 			break;
-#ifdef LP_NEED_CAREFUL
+#ifdef OBSOLETED
 		case LPCAREFUL:
 			if (arg)
 				LP_F(minor) |= LP_CAREFUL;
@@ -653,6 +794,12 @@
 				LP_F(minor) &= ~LP_CAREFUL;
 			break;
 #endif
+		case LPTRUSTIRQ:
+			if (arg)
+				LP_F(minor) |= LP_TRUST_IRQ;
+			else
+				LP_F(minor) &= ~LP_TRUST_IRQ;
+			break;
 		case LPWAIT:
 			LP_WAIT(minor) = arg;
 			break;
@@ -695,7 +842,6 @@
 	}
 	return retval;
 }
-
 
 static struct file_operations lp_fops = {
 	lp_lseek,
diff -u --recursive --new-file v2.1.130/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.1.130/linux/drivers/char/tty_io.c	Fri Nov 27 13:09:23 1998
+++ linux/drivers/char/tty_io.c	Fri Nov 27 10:24:27 1998
@@ -868,7 +868,13 @@
 	 * Failures after this point use release_mem to clean up, so 
 	 * there's no need to null out the local pointers.
 	 */
-	driver->table[idx] = tty;
+	driver->table[idx] = tty;	/* FIXME: this is broken and
+	probably causes ^D bug. tty->private_date does not (yet) point
+	to a console, if keypress comes now, await armagedon. 
+
+	also, driver->table is accessed from interrupt for vt case,
+	and this does not look like atomic access at all. */
+	
 	if (!*tp_loc)
 		*tp_loc = tp;
 	if (!*ltp_loc)
diff -u --recursive --new-file v2.1.130/linux/drivers/scsi/ChangeLog.ncr53c8xx linux/drivers/scsi/ChangeLog.ncr53c8xx
--- v2.1.130/linux/drivers/scsi/ChangeLog.ncr53c8xx	Thu Nov 19 09:56:28 1998
+++ linux/drivers/scsi/ChangeLog.ncr53c8xx	Sun Nov 29 10:38:43 1998
@@ -1,3 +1,19 @@
+Thu Nov 26  22:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1d
+	- The SISL RAID change requires now remap_pci_mem() stuff to be 
+	  compiled for __i386__ when normal IOs are used.
+	- Minor spelling fixes in doc files.
+
+Sat Nov 21  18:00 1998 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1c
+	- Ignore chips that are driven by SISL RAID (DAC 960).
+	  Change sent by Leonard Zubkoff and slightly reworked.
+	- Still a buglet in the tags initial settings that needed to be fixed.
+	  It was not possible to disable TGQ at system startup for devices 
+	  that claim TGQ support. The driver used at least 2 for the queue 
+	  depth but did'nt keep track of user settings for tags depth lower 
+	  than 2.
+
 Wed Nov 11  10:00 1998 Gerard Roudier (groudier@club-internet.fr)
 	* revision 3.1b
 	- The driver was unhappy when configured with default_tags > MAX_TAGS
diff -u --recursive --new-file v2.1.130/linux/drivers/scsi/README.ncr53c8xx linux/drivers/scsi/README.ncr53c8xx
--- v2.1.130/linux/drivers/scsi/README.ncr53c8xx	Sun Nov  8 14:03:02 1998
+++ linux/drivers/scsi/README.ncr53c8xx	Sun Nov 29 10:38:43 1998
@@ -4,7 +4,7 @@
 21 Rue Carnot
 95170 DEUIL LA BARRE - FRANCE
 
-18 October 1998
+22 November 1998
 ===============================================================================
 
 1.  Introduction
@@ -853,7 +853,7 @@
         For 810A, 860, 825A, 875 and 895 scsi chips, this option enables 
 	support of features that reduce load of PCI bus and memory accesses 
 	during  scsi transfer processing: burst op-code fetch, read multiple, 
-        read line, prefetch, cache line line, write and invalidate, 
+        read line, prefetch, cache line, write and invalidate, 
         burst 128 (875 only), large dma fifo (875 only), offset 16 (875 only).
 	Can be changed by the following boot setup command:
 		ncr53c8xx=specf:n
diff -u --recursive --new-file v2.1.130/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.1.130/linux/drivers/scsi/ncr53c8xx.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/scsi/ncr53c8xx.c	Sun Nov 29 10:38:43 1998
@@ -73,7 +73,7 @@
 */
 
 /*
-**	November 11 1998, version 3.1b
+**	November 26 1998, version 3.1d
 **
 **	Supported SCSI-II features:
 **	    Synchronous negotiation
@@ -582,7 +582,7 @@
 #define bus_dvma_to_mem(p)		(p)
 #endif
 
-#ifndef NCR_IOMAPPED
+#if defined(__i386__) || !defined(NCR_IOMAPPED)
 __initfunc(
 static vm_offset_t remap_pci_mem(u_long base, u_long size)
 )
@@ -601,7 +601,7 @@
 	if (vaddr)
 		iounmap((void *) (vaddr & PAGE_MASK));
 }
-#endif	/* !NCR_IOMAPPED */
+#endif	/* __i386__ || !NCR_IOMAPPED */
 
 /*
 **	Insert a delay in micro-seconds and milli-seconds.
@@ -2145,7 +2145,6 @@
 				(ncb_p np, ncrcmd *src, ncrcmd *dst, int len);
 static  void    ncr_script_fill (struct script * scr, struct scripth * scripth);
 static	int	ncr_scatter	(ccb_p cp, Scsi_Cmnd *cmd);
-static	void	ncr_setmaxtags	(ncb_p np, tcb_p tp, u_long numtags);
 static	void	ncr_getsync	(ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p);
 static	void	ncr_setsync	(ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer);
 static	void	ncr_setup_tags	(ncb_p np, u_char tn, u_char ln);
@@ -5837,7 +5836,7 @@
 		**	If tags was reduced due to queue full,
 		**	increase tags if 1000 good status received.
 		*/
-		if (lp && lp->numtags < lp->maxtags) {
+		if (lp && lp->usetags && lp->numtags < lp->maxtags) {
 			++lp->num_good;
 			if (lp->num_good >= 1000) {
 				lp->num_good = 0;
@@ -6537,24 +6536,6 @@
 **==========================================================
 */
 
-static void ncr_setmaxtags (ncb_p np, tcb_p tp, u_long numtags)
-{
-	if (numtags > tp->usrtags)
-		numtags = tp->usrtags;
-
-	if (tp) {
-		int ln;
-		for (ln = 0; ln < MAX_LUN; ln++) {
-			lcb_p lp = tp->lp[ln];
-
-			if (!lp)
-				continue;
-			lp->maxtags = lp->numtags = numtags;
-			ncr_setup_tags (np, (tp - np->target), ln);
-		}
-	}
-}
-
 static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln)
 {
 	tcb_p tp = &np->target[tn];
@@ -6671,10 +6652,17 @@
 
 	case UC_SETTAGS:
 		for (t=0; t<MAX_TARGET; t++) {
+			int ln;
 			if (!((np->user.target>>t)&1)) continue;
 			np->target[t].usrtags = np->user.data;
-			ncr_setmaxtags (np, &np->target[t], np->user.data);
-		};
+			for (ln = 0; ln < MAX_LUN; ln++) {
+				lcb_p lp = np->target[t].lp[ln];
+				if (!lp)
+					continue;
+				lp->maxtags = lp->numtags = np->user.data;
+				ncr_setup_tags (np, t, ln);
+			}
+ 		};
 		break;
 
 	case UC_SETDEBUG:
@@ -7824,7 +7812,7 @@
 **	field of the controller's struct ncb.
 **
 **	Possible cases:		   hs  sir   msg_in value  send   goto
-**	We try try to negotiate:
+**	We try to negotiate:
 **	-> target doesnt't msgin   NEG FAIL  noop   defa.  -      dispatch
 **	-> target rejected our msg NEG FAIL  reject defa.  -      dispatch
 **	-> target answered  (ok)   NEG SYNC  sdtr   set    -      clrack
@@ -8718,7 +8706,7 @@
 	*/
 	if ((inq_byte7 ^ lp->inq_byte7) & INQ7_QUEUE) {
 		lp->inq_byte7 = inq_byte7;
-		lp->numtags   = tp->usrtags;
+		lp->numtags   = lp->maxtags;
 		ncr_setup_tags (np, tn, ln);
 	}
 
@@ -9622,8 +9610,6 @@
 #endif
 	ncr_chip *chip;
 
-	printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n",
-		bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7);
 	/*
 	 * Read info from the PCI config space.
 	 * pcibios_read_config_xxx() functions are assumed to be used for 
@@ -9650,6 +9636,11 @@
 					PCI_BASE_ADDRESS_1, &base);
 	(void) pcibios_read_config_dword(bus, device_fn,
 					PCI_BASE_ADDRESS_2, &base_2);
+
+	/* Handle 64bit base adresses for 53C896. */
+	if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
+		(void) pcibios_read_config_dword(bus, device_fn,
+						 PCI_BASE_ADDRESS_3, &base_2);
 	(void) pcibios_read_config_byte(bus, device_fn,
 					PCI_INTERRUPT_LINE, &irq);
 #endif
@@ -9674,6 +9665,34 @@
 		chip->revision_id = revision;
 		break;
 	}
+
+#if defined(__i386__)
+	/*
+	 *	Ignore Symbios chips controlled by SISL RAID controller.
+	 */
+	if (chip && (base_2 & PCI_BASE_ADDRESS_MEM_MASK)) {
+		unsigned int ScriptsSize, MagicValue;
+		vm_offset_t ScriptsRAM;
+
+		if (chip->features & FE_RAM8K)
+			ScriptsSize = 8192;
+		else
+			ScriptsSize = 4096;
+
+		ScriptsRAM = remap_pci_mem(base_2 & PCI_BASE_ADDRESS_MEM_MASK,
+					   ScriptsSize);
+		if (ScriptsRAM) {
+			MagicValue = readl(ScriptsRAM + ScriptsSize - 16);
+			unmap_pci_mem(ScriptsRAM, ScriptsSize);
+			if (MagicValue == 0x52414944)
+				return -1;
+		}
+	}
+#endif
+
+	printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n",
+		bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7);
+
 	if (!chip) {
 		printk("ncr53c8xx: not initializing, device not supported\n");
 		return -1;
@@ -10069,6 +10088,7 @@
 		ncb_p np;
 		tcb_p tp;
 		lcb_p lp;
+		int numtags;
 
 		if (device->host != host)
 			continue;
@@ -10080,15 +10100,16 @@
 		/*
 		**	Select queue depth from driver setup.
 		**	Donnot use more than configured by user.
-		**	Use 2 for devices that donnot support tags.
 		**	Use at least 2.
 		**	Donnot use more than our maximum.
 		*/
-		device->queue_depth =
-			device_queue_depth(np, device->id, device->lun);
-		if (device->queue_depth > tp->usrtags)
-			device->queue_depth = tp->usrtags;
-		if (!device->tagged_supported || device->queue_depth < 2)
+		numtags = device_queue_depth(np, device->id, device->lun);
+		if (numtags > tp->usrtags)
+			numtags = tp->usrtags;
+		if (!device->tagged_supported)
+			numtags = 1;
+		device->queue_depth = numtags;
+		if (device->queue_depth < 2)
 			device->queue_depth = 2;
 		if (device->queue_depth > SCSI_NCR_MAX_TAGS)
 			device->queue_depth = SCSI_NCR_MAX_TAGS;
@@ -10098,8 +10119,10 @@
 		**	we need to know this value in order not to 
 		**	announce stupid things to user.
 		*/
-		if (lp)
+		if (lp) {
+			lp->numtags = lp->maxtags = numtags;
 			lp->scdev_depth = device->queue_depth;
+		}
 		ncr_setup_tags (np, device->id, device->lun);
 
 #ifdef DEBUG_NCR53C8XX
diff -u --recursive --new-file v2.1.130/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h
--- v2.1.130/linux/drivers/scsi/ncr53c8xx.h	Thu Nov 19 09:56:28 1998
+++ linux/drivers/scsi/ncr53c8xx.h	Tue Dec  1 22:10:48 1998
@@ -45,7 +45,7 @@
 /*
 **	Name and revision of the driver
 */
-#define SCSI_NCR_DRIVER_NAME		"ncr53c8xx - revision 3.1b"
+#define SCSI_NCR_DRIVER_NAME		"ncr53c8xx - revision 3.1d"
 
 /*
 **	Check supported Linux versions
@@ -424,6 +424,10 @@
 #define FE_LDSTR	(1<<13)
 #define FE_RAM		(1<<14)
 #define FE_CLK80	(1<<15)
+#define FE_RAM8K	(1<<16)
+#define FE_64BIT	(1<<17)
+#define FE_IO256	(1<<18)
+#define FE_NOPM		(1<<19)
 #define FE_CACHE_SET	(FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP)
 #define FE_SCSI_SET	(FE_WIDE|FE_ULTRA|FE_ULTRA2|FE_DBLR|FE_QUAD|F_CLK80)
 #define FE_SPECIAL_SET	(FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM)
@@ -484,7 +488,8 @@
  FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
  ,									\
  {PCI_DEVICE_ID_NCR_53C896, 0xff, "896",  7, 31, 7,			\
- FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
+ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM|\
+ FE_RAM8K|FE_64BIT|FE_IO256|FE_NOPM}\
 }
 
 /*
diff -u --recursive --new-file v2.1.130/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c
--- v2.1.130/linux/drivers/scsi/scsi_obsolete.c	Sun Nov  8 14:03:02 1998
+++ linux/drivers/scsi/scsi_obsolete.c	Sun Nov 29 10:40:31 1998
@@ -607,10 +607,9 @@
 	if ((++SCpnt->retries) < SCpnt->allowed)
 	{
 	    if ((SCpnt->retries >= (SCpnt->allowed >> 1))
-		/* FIXME: last_reset == 0 is allowed
-                 *  && !(SCpnt->host->last_reset > 0 */ &&
-		     time_before(jiffies, SCpnt->host->last_reset
-                                 + MIN_RESET_PERIOD)
+		/* FIXME: last_reset == 0 is allowed */
+                && time_after(jiffies, SCpnt->host->last_reset
+                              + MIN_RESET_PERIOD)
 		&& !(SCpnt->flags & WAS_RESET))
 	    {
 		printk("scsi%d channel %d : resetting for second half of retries.\n",
diff -u --recursive --new-file v2.1.130/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
--- v2.1.130/linux/drivers/sound/sb_common.c	Thu Nov 12 16:21:22 1998
+++ linux/drivers/sound/sb_common.c	Sun Nov 29 11:18:04 1998
@@ -878,6 +878,7 @@
 
 			if(!sb16_set_dma_hw(devc)) {
 				free_irq(devc->irq, devc);
+			        release_region(hw_config->io_base, 16);
 				return 0;
 			}
 
diff -u --recursive --new-file v2.1.130/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.1.130/linux/drivers/video/atyfb.c	Fri Nov 27 13:09:27 1998
+++ linux/drivers/video/atyfb.c	Sun Nov 29 11:18:04 1998
@@ -973,6 +973,11 @@
 #endif
 #endif
 
+	if (! cursor->ram) {
+		kfree(cursor);
+		return NULL;
+	}
+
 	if (curblink) {
 		init_timer(cursor->timer);
 		cursor->timer->expires = jiffies + (HZ / 50);
@@ -2917,6 +2922,11 @@
 	    info->ati_regbase = (unsigned long)
 				ioremap(info->ati_regbase_phys, 0x1000);
 
+	    if(!info->ati_regbase) {
+		    kfree(info);
+		    return;
+	    }
+
 	    info->ati_regbase_phys += 0xc00;
 	    info->ati_regbase += 0xc00;
 
@@ -2939,6 +2949,11 @@
 	    info->frame_buffer_phys = addr;
 	    info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
 
+	    if(!info->frame_buffer) {
+		    kfree(info);
+		    return;
+	    }
+
 #endif /* __sparc__ */
 
 	    if (!aty_init(info, "PCI")) {
@@ -3046,6 +3061,13 @@
     info->ati_regbase_phys = 0x7ff000+addr;
     info->ati_regbase = (unsigned long)ioremap(info->ati_regbase_phys,
 						   0x1000);
+
+    if(! info->ati_regbase) {
+	    printk("atyfb_init: ioremap() returned NULL\n");
+	    kfree(info);
+	    return;
+    }
+
     info->ati_regbase_phys += 0xc00;
     info->ati_regbase += 0xc00;
 
@@ -3066,6 +3088,12 @@
     /* Map in frame buffer */
     info->frame_buffer_phys = addr;
     info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
+
+    if(! info->frame_buffer) {
+	    printk("atyfb_init: ioremap() returned NULL\n");
+	    kfree(info);
+	    return;
+    }
 
     if (!aty_init(info, dp->full_name)) {
 	kfree(info);
diff -u --recursive --new-file v2.1.130/linux/fs/affs/namei.c linux/fs/affs/namei.c
--- v2.1.130/linux/fs/affs/namei.c	Fri May  8 23:14:50 1998
+++ linux/fs/affs/namei.c	Tue Dec  1 22:42:20 1998
@@ -242,8 +242,6 @@
 
 	inode  = dentry->d_inode;
 	retval = -EPERM;
-	if (S_ISDIR(inode->i_mode))
-		goto unlink_done;
 	if (current->fsuid != inode->i_uid &&
 	    current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
 		goto unlink_done;
@@ -376,13 +374,11 @@
 	/*
 	 * Make sure the directory is empty and the dentry isn't busy.
 	 */
-	if (dentry->d_count > 1)
-		shrink_dcache_parent(dentry);
 	retval = -ENOTEMPTY;
 	if (!empty_dir(bh,AFFS_I2HSIZE(inode)))
 		goto rmdir_done;
 	retval = -EBUSY;
-	if (dentry->d_count > 1)
+	if (!list_empty(&dentry->d_hash))
 		goto rmdir_done;
 
 	if ((retval = affs_remove_header(bh,inode)) < 0)
diff -u --recursive --new-file v2.1.130/linux/fs/coda/dir.c linux/fs/coda/dir.c
--- v2.1.130/linux/fs/coda/dir.c	Sat Sep  5 16:46:41 1998
+++ linux/fs/coda/dir.c	Tue Dec  1 22:37:20 1998
@@ -520,7 +520,7 @@
         struct coda_inode_info *dircnp;
 	const char *name = de->d_name.name;
 	int len = de->d_name.len;
-        int error, rehash = 0;
+        int error;
 
 	ENTRY;
 	coda_vfs_stat.rmdir++;
@@ -535,24 +535,13 @@
 	if (len > CFS_MAXNAMLEN)
 		return -ENAMETOOLONG;
 
-	error = -EBUSY;
-	if (de->d_count > 1) {
-		/* Attempt to shrink child dentries ... */
-		shrink_dcache_parent(de);
-		if (de->d_count > 1)
-			return error;
-	}
-	/* Drop the dentry to force a new lookup */
-	if (!list_empty(&de->d_hash)) {
-		d_drop(de);
-		rehash = 1;
-	}
+	if (!list_empty(&de->d_hash))
+		return -EBUSY;
 
 	/* update i_nlink and free the inode before unlinking;
 	   if rmdir fails a new lookup set i_nlink right.*/
 	if (de->d_inode->i_nlink)
 		de->d_inode->i_nlink --;
-	d_delete(de);
 
 	error = venus_rmdir(dir->i_sb, &(dircnp->c_fid), name, len);
 
@@ -560,10 +549,6 @@
                 CDEBUG(D_INODE, "upc returned error %d\n", error);
                 return error;
         }
-
-	if (rehash)
-		d_add(de, NULL);
-	/* XXX how can mtime be set? */
 
         return 0;
 }
diff -u --recursive --new-file v2.1.130/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.1.130/linux/fs/ext2/namei.c	Fri Oct 23 22:01:22 1998
+++ linux/fs/ext2/namei.c	Tue Dec  1 22:45:12 1998
@@ -661,32 +661,14 @@
 	if (le32_to_cpu(de->inode) != inode->i_ino)
 		goto end_rmdir;
 
-	down(&inode->i_sem);
-	/*
-	 * Prune any child dentries so that this dentry becomes negative.
-	 */
-	if (dentry->d_count > 1)
-		shrink_dcache_parent(dentry);
-
 	if (!empty_dir (inode))
 		retval = -ENOTEMPTY;
 	else if (le32_to_cpu(de->inode) != inode->i_ino)
 		retval = -ENOENT;
 	else {
-		if (dentry->d_count > 1) {
-		/*
-		 * Are we deleting the last instance of a busy directory?
-		 * Better clean up if so.
-		 *
-		 * Make directory empty (it will be truncated when finally
-		 * dereferenced).  This also inhibits ext2_add_entry.
-		 */
-			inode->i_size = 0;
-		}
 		retval = ext2_delete_entry (de, bh);
 		dir->i_version = ++event;
 	}
-	up(&inode->i_sem);
 	if (retval)
 		goto end_rmdir;
 	mark_buffer_dirty(bh, 1);
@@ -700,6 +682,7 @@
 			      inode->i_nlink);
 	inode->i_version = ++event;
 	inode->i_nlink = 0;
+	inode->i_size = 0;
 	mark_inode_dirty(inode);
 	dir->i_nlink--;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
@@ -733,8 +716,6 @@
 	DQUOT_INIT(inode);
 
 	retval = -EPERM;
-	if (S_ISDIR(inode->i_mode))
-		goto end_unlink;
 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 		goto end_unlink;
 	if ((dir->i_mode & S_ISVTX) &&
diff -u --recursive --new-file v2.1.130/linux/fs/hfs/dir.c linux/fs/hfs/dir.c
--- v2.1.130/linux/fs/hfs/dir.c	Sun Nov  8 14:03:06 1998
+++ linux/fs/hfs/dir.c	Tue Dec  1 22:52:06 1998
@@ -352,7 +352,7 @@
 		goto hfs_rmdir_put;
 
 	error = -EBUSY;
-	if (dentry->d_count > 1)
+	if (!list_empty(&dentry->d_hash))
 		goto hfs_rmdir_put;
 
 	if (/* we only have to worry about 2 and 3 for mount points */
diff -u --recursive --new-file v2.1.130/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v2.1.130/linux/fs/minix/namei.c	Mon Sep 28 10:51:34 1998
+++ linux/fs/minix/namei.c	Tue Dec  1 22:51:46 1998
@@ -452,7 +452,7 @@
 		retval = -ENOENT;
 		goto end_rmdir;
 	}
-	if (dentry->d_count > 1) {
+	if (!list_empty(&dentry->d_hash)) {
 		retval = -EBUSY;
 		goto end_rmdir;
 	}
@@ -490,8 +490,6 @@
 	inode = dentry->d_inode;
 
 	retval = -EPERM;
-	if (S_ISDIR(inode->i_mode))
-		goto end_unlink;
 	if (de->inode != inode->i_ino) {
 		brelse(bh);
 		current->counter = 0;
diff -u --recursive --new-file v2.1.130/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v2.1.130/linux/fs/msdos/namei.c	Thu Nov 19 09:56:28 1998
+++ linux/fs/msdos/namei.c	Tue Dec  1 22:48:22 1998
@@ -452,8 +452,7 @@
 	if (res)
 		goto rmdir_done;
 	res = -EBUSY;
-	shrink_dcache_parent(dentry);
-	if (dentry->d_count > 1) {
+	if (!list_empty(&dentry->d_hash)) {
 #ifdef MSDOS_DEBUG
 printk("msdos_rmdir: %s/%s busy, d_count=%d\n",
 dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count);
diff -u --recursive --new-file v2.1.130/linux/fs/namei.c linux/fs/namei.c
--- v2.1.130/linux/fs/namei.c	Thu Nov 19 09:56:28 1998
+++ linux/fs/namei.c	Tue Dec  1 22:09:48 1998
@@ -834,6 +834,37 @@
 	return error;
 }
 
+/*
+ * Whee.. Deadlock country. Happily there are only two VFS
+ * operations that do this..
+ */
+static inline void double_lock(struct dentry *d1, struct dentry *d2)
+{
+	struct semaphore *s1 = &d1->d_inode->i_sem;
+	struct semaphore *s2 = &d2->d_inode->i_sem;
+
+	if (s1 != s2) {
+		if ((unsigned long) s1 < (unsigned long) s2) {
+			struct semaphore *tmp = s2;
+			s2 = s1; s1 = tmp;
+		}
+		down(s1);
+	}
+	down(s2);
+}
+
+static inline void double_unlock(struct dentry *d1, struct dentry *d2)
+{
+	struct semaphore *s1 = &d1->d_inode->i_sem;
+	struct semaphore *s2 = &d2->d_inode->i_sem;
+
+	up(s1);
+	if (s1 != s2)
+		up(s2);
+	dput(d1);
+	dput(d2);
+}
+
 static inline int do_rmdir(const char * name)
 {
 	int error;
@@ -845,13 +876,20 @@
 	if (IS_ERR(dentry))
 		goto exit;
 
-	dir = lock_parent(dentry);
-	error = PTR_ERR(dir);
-	if (IS_ERR(dir))
-		goto exit_dput;
+	dir = dget(dentry->d_parent);
 
 	error = -ENOENT;
 	if (!dentry->d_inode)
+		goto exit;
+	/*
+	 * The dentry->d_count stuff confuses d_delete() enough to
+	 * not kill the inode from under us while it is locked. This
+	 * wouldn't be needed, except the dentry semaphore is really
+	 * in the inode, not in the dentry..
+	 */
+	dentry->d_count++;
+	double_lock(dir, dentry);
+	if (dentry->d_parent != dir)
 		goto exit_lock;
 
 	error = -EROFS;
@@ -880,15 +918,35 @@
 
 	DQUOT_INIT(dir->d_inode);
 
-	if (dentry->d_count > 1)
+	/*
+	 * We try to drop the dentry early: we should have
+	 * a usage count of 2 if we're the only user of this
+	 * dentry, and if that is true (possibly after pruning
+	 * the dcache), then we drop the dentry now.
+	 *
+	 * A low-level filesystem can, if it choses, legally
+	 * do a
+	 *
+	 *	if (!list_empty(&dentry->d_hash))
+	 *		return -EBUSY;
+	 *
+	 * if it cannot handle the case of removing a directory
+	 * that is still in use by something else..
+	 */
+	switch (dentry->d_count) {
+	default:
 		shrink_dcache_parent(dentry);
+		if (dentry->d_count != 2)
+			break;
+	case 2:
+		d_drop(dentry);
+	}
 
 	error = dir->d_inode->i_op->rmdir(dir->d_inode, dentry);
 
 exit_lock:
-        unlock_dir(dir);
-exit_dput:
-	dput(dentry);
+	dentry->d_count--;
+	double_unlock(dentry, dir);
 exit:
 	return error;
 }
@@ -943,13 +1001,16 @@
 		goto exit_lock;
 
 	/*
+	 * A directory can't be unlink'ed.
 	 * A file cannot be removed from an append-only directory.
 	 */
 	error = -EPERM;
+	if (S_ISDIR(dentry->d_inode->i_mode))
+		goto exit_lock;
+
 	if (IS_APPEND(dir->d_inode))
 		goto exit_lock;
 
-	error = -EPERM;
 	if (!dir->d_inode->i_op || !dir->d_inode->i_op->unlink)
 		goto exit_lock;
 
@@ -1142,37 +1203,6 @@
 	}
 	unlock_kernel();
 	return error;
-}
-
-/*
- * Whee.. Deadlock country. Happily there is only one VFS
- * operation that does this..
- */
-static inline void double_lock(struct dentry *d1, struct dentry *d2)
-{
-	struct semaphore *s1 = &d1->d_inode->i_sem;
-	struct semaphore *s2 = &d2->d_inode->i_sem;
-
-	if (s1 != s2) {
-		if ((unsigned long) s1 < (unsigned long) s2) {
-			struct semaphore *tmp = s2;
-			s2 = s1; s1 = tmp;
-		}
-		down(s1);
-	}
-	down(s2);
-}
-
-static inline void double_unlock(struct dentry *d1, struct dentry *d2)
-{
-	struct semaphore *s1 = &d1->d_inode->i_sem;
-	struct semaphore *s2 = &d2->d_inode->i_sem;
-
-	up(s1);
-	if (s1 != s2)
-		up(s2);
-	dput(d1);
-	dput(d2);
 }
 
 static inline int do_rename(const char * oldname, const char * newname)
diff -u --recursive --new-file v2.1.130/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.1.130/linux/fs/ncpfs/dir.c	Fri Nov 27 13:09:28 1998
+++ linux/fs/ncpfs/dir.c	Tue Dec  1 22:46:46 1998
@@ -24,11 +24,6 @@
 #include <linux/ncp_fs.h>
 #include "ncplib_kernel.h"
 
-#ifndef shrink_dcache_parent
-#define shrink_dcache_parent(dentry) shrink_dcache_sb((dentry)->d_sb)
-#endif
-
-
 struct ncp_dirent {
 	struct nw_info_struct i;
 	struct nw_search_sequence s;	/* given back for i */
@@ -999,17 +994,14 @@
 		printk(KERN_WARNING "ncp_rmdir: inode is NULL or not a directory\n");
 		goto out;
 	}
+
 	error = -EIO;
 	if (!ncp_conn_valid(NCP_SERVER(dir)))
 		goto out;
 
-	if (dentry->d_count > 1)
-	{
-		shrink_dcache_parent(dentry);
-		error = -EBUSY;
-		if (dentry->d_count > 1)
-			goto out;
-	}
+	error = -EBUSY;
+	if (!list_empty(&dentry->d_hash))
+		goto out;
 
 	strncpy(_name, dentry->d_name.name, dentry->d_name.len);
 	_name[dentry->d_name.len] = '\0';
@@ -1023,7 +1015,6 @@
 	if (!result)
 	{
 		ncp_invalid_dir_cache(dir);
-		d_delete(dentry);
 		error = 0;
     	}
 out:
diff -u --recursive --new-file v2.1.130/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.1.130/linux/fs/nfs/dir.c	Fri Nov 27 13:09:28 1998
+++ linux/fs/nfs/dir.c	Tue Dec  1 22:07:12 1998
@@ -721,7 +721,7 @@
  */
 static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-	int error, rehash = 0;
+	int error;
 
 	dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",
 		dir->i_dev, dir->i_ino, dentry->d_name.name);
@@ -731,39 +731,24 @@
 		goto out;
 
 	error = -EBUSY;
-	if (dentry->d_count > 1) {
-		/* Attempt to shrink child dentries ... */
-		shrink_dcache_parent(dentry);
-		if (dentry->d_count > 1)
-			goto out;
-	}
+	if (!list_empty(&dentry->d_hash))
+		goto out;
+
 #ifdef NFS_PARANOIA
 if (dentry->d_inode->i_count > 1)
 printk("nfs_rmdir: %s/%s inode busy?? i_count=%d, i_nlink=%d\n",
 dentry->d_parent->d_name.name, dentry->d_name.name,
 dentry->d_inode->i_count, dentry->d_inode->i_nlink);
 #endif
-	/*
-	 * Unhash the dentry while we remove the directory.
-	 */
-	if (!list_empty(&dentry->d_hash)) {
-		d_drop(dentry);
-		rehash = 1;
-	}
+
 	/*
 	 * Update i_nlink and free the inode before unlinking.
 	 */
 	if (dentry->d_inode->i_nlink)
 		dentry->d_inode->i_nlink --;
-	d_delete(dentry);
 	nfs_invalidate_dircache(dir);
 	error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
 				dentry->d_name.name);
-	if (!error) {
-		if (rehash)
-			d_add(dentry, NULL);
-		nfs_renew_times(dentry);
-	}
 out:
 	return error;
 }
diff -u --recursive --new-file v2.1.130/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v2.1.130/linux/fs/nfs/file.c	Fri Nov 27 13:09:28 1998
+++ linux/fs/nfs/file.c	Tue Dec  1 13:34:51 1998
@@ -240,22 +240,21 @@
 	if (!fl->fl_owner || (fl->fl_flags & (FL_POSIX|FL_BROKEN)) != FL_POSIX)
 		return -ENOLCK;
 
-	/* If unlocking a file region, flush dirty pages (unless we've
-	 * been killed by a signal, that is). */
-	if (cmd == F_SETLK && fl->fl_type == F_UNLCK
-	    && !signal_pending(current)) {
-		status = nfs_wb_area(inode, /* current->pid  ?*/
-			fl->fl_start, fl->fl_end == NLM_OFFSET_MAX? 0 :
-			fl->fl_end - fl->fl_start + 1);
-		if (status < 0)
-			return status;
-	}
+	/*
+	 * Flush all pending writes before doing anything
+	 * with locks..
+	 */
+	status = nfs_wb_all(inode);
+	if (status < 0)
+		return status;
 
 	if ((status = nlmclnt_proc(inode, cmd, fl)) < 0)
 		return status;
 
-	/* Here, we could turn off write-back of pages in the
-	 * locked file region */
-
+	/*
+	 * Make sure we re-validate anything we've got cached.
+	 * This makes locking act as a cache coherency point.
+	 */
+	NFS_CACHEINV(inode);
 	return 0;
 }
diff -u --recursive --new-file v2.1.130/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.1.130/linux/fs/nfs/write.c	Fri Nov 27 13:09:28 1998
+++ linux/fs/nfs/write.c	Wed Dec  2 09:45:25 1998
@@ -583,38 +583,6 @@
 	NFS_WB(inode, req->wb_pid == pid);
 }
 
-/*
- * Write back everything in a specific area for locking purposes..
- */
-int
-nfs_wb_area(struct inode *inode, off_t offset, off_t len)
-{
-	NFS_WB(inode, 1);
-}
-
-/*
- * Write back and invalidate. Sometimes we can't leave the stuff
- * hanging if we can't write it out.
- */
-int
-nfs_wbinval(struct inode *inode)
-{
-	int retval = nfs_wb_all(inode);
-
-	if (retval)
-		nfs_cancel_dirty(inode,0);
-	return retval;
-}
-
-int nfs_wbinval_pid(struct inode *inode, pid_t pid)
-{
-	int retval = nfs_wb_pid(inode, pid);
-	
-	if (retval)
-		nfs_cancel_dirty(inode,pid);
-	return retval;
-}
-
 void
 nfs_inval(struct inode *inode)
 {
diff -u --recursive --new-file v2.1.130/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.1.130/linux/fs/nfsd/vfs.c	Sun Nov  8 14:03:07 1998
+++ linux/fs/nfsd/vfs.c	Tue Dec  1 21:45:10 1998
@@ -1072,6 +1072,11 @@
 	if (IS_ERR(rdentry))
 		goto out_nfserr;
 
+	/*
+	 * FIXME!!
+	 *
+	 * This should do a double-lock on both rdentry and the parent
+	 */
 	err = fh_lock_parent(fhp, rdentry);
 	if (err)
 		goto out;
diff -u --recursive --new-file v2.1.130/linux/fs/open.c linux/fs/open.c
--- v2.1.130/linux/fs/open.c	Thu Nov 19 09:56:28 1998
+++ linux/fs/open.c	Tue Dec  1 11:03:25 1998
@@ -797,11 +797,11 @@
 		printk("VFS: Close: file count is 0\n");
 		return 0;
 	}
-	if (dentry->d_inode)
-		locks_remove_posix(filp, id);
 	retval = 0;
 	if (filp->f_op && filp->f_op->flush)
 		retval = filp->f_op->flush(filp);
+	if (dentry->d_inode)
+		locks_remove_posix(filp, id);
 	fput(filp);
 	return retval;
 }
diff -u --recursive --new-file v2.1.130/linux/fs/qnx4/namei.c linux/fs/qnx4/namei.c
--- v2.1.130/linux/fs/qnx4/namei.c	Sat Sep  5 16:46:41 1998
+++ linux/fs/qnx4/namei.c	Tue Dec  1 22:50:54 1998
@@ -199,7 +199,7 @@
 		goto end_rmdir;
 	}
 #endif
-	if (dentry->d_count > 1) {
+	if (!list_empty(&dentry->d_hash)) {
 		retval = -EBUSY;
 		goto end_rmdir;
 	}
@@ -245,9 +245,6 @@
 		goto end_unlink;
 	}
 	retval = -EPERM;
-	if (S_ISDIR(inode->i_mode)) {
-		goto end_unlink;
-	}
 	if ((dir->i_mode & S_ISVTX) &&
 	    current->fsuid != inode->i_uid &&
 	    current->fsuid != dir->i_uid && !capable(CAP_FOWNER)) {
diff -u --recursive --new-file v2.1.130/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v2.1.130/linux/fs/smbfs/dir.c	Wed Aug 26 11:37:43 1998
+++ linux/fs/smbfs/dir.c	Tue Dec  1 22:09:46 1998
@@ -479,22 +479,15 @@
 	smb_close(inode);
 
 	/*
-	 * Prune any child dentries so this dentry can become negative.
+	 * Check that nobody else is using the directory..
 	 */
-	if (dentry->d_count > 1) {
-		shrink_dcache_parent(dentry);
-		error = -EBUSY;
-		if (dentry->d_count > 1)
-			goto out;
- 	}
+	error = -EBUSY;
+	if (!list_empty(&dentry->d_hash))
+		goto out;
 
 	smb_invalid_dir_cache(dir);
 	error = smb_proc_rmdir(dentry);
-	if (!error)
-	{
-		smb_renew_times(dentry);
-		d_delete(dentry);
-	}
+
 out:
 	return error;
 }
diff -u --recursive --new-file v2.1.130/linux/fs/sysv/namei.c linux/fs/sysv/namei.c
--- v2.1.130/linux/fs/sysv/namei.c	Wed May 20 19:10:41 1998
+++ linux/fs/sysv/namei.c	Mon Nov 30 16:04:15 1998
@@ -476,8 +476,6 @@
 	inode = dentry->d_inode;
 
 	retval = -EPERM;
-	if (S_ISDIR(inode->i_mode))
-		goto end_unlink;
 	if (de->inode != inode->i_ino) {
 		brelse(bh);
 		current->counter = 0;
diff -u --recursive --new-file v2.1.130/linux/fs/ufs/namei.c linux/fs/ufs/namei.c
--- v2.1.130/linux/fs/ufs/namei.c	Fri Oct 23 22:01:22 1998
+++ linux/fs/ufs/namei.c	Tue Dec  1 13:52:19 1998
@@ -701,7 +701,6 @@
 	if (SWAB32(de->d_ino) != inode->i_ino)
 		goto end_rmdir;
 
-	down(&inode->i_sem);
 	/*
 	 * Prune any child dentries so that this dentry becomes negative.
 	 */
@@ -727,7 +726,6 @@
 		retval = ufs_delete_entry (dir, de, bh);
 		dir->i_version = ++event;
 	}
-	up(&inode->i_sem);
 	if (retval)
 		goto end_rmdir;
 	mark_buffer_dirty(bh, 1);
@@ -784,8 +782,6 @@
 		inode->i_sb->dq_op->initialize (inode, -1);
 
 	retval = -EPERM;
-	if (S_ISDIR(inode->i_mode))
-		goto end_unlink;
 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 		goto end_unlink;
 	if ((dir->i_mode & S_ISVTX) &&
diff -u --recursive --new-file v2.1.130/linux/fs/umsdos/README-WIP.txt linux/fs/umsdos/README-WIP.txt
--- v2.1.130/linux/fs/umsdos/README-WIP.txt	Sun Nov  8 14:03:08 1998
+++ linux/fs/umsdos/README-WIP.txt	Sun Nov 29 11:43:13 1998
@@ -2,21 +2,19 @@
 (started by Peter T. Waltenberg <peterw@karaka.chch.cri.nz>)
 (Final conversion to dentries Bill Hawes <whawes@star.net>)
 
----------- WARNING --------- WARNING --------- WARNING -----------
 There is no warning any more.
 Both read-only and read-write stuff is fixed, both in
 msdos-compatibile mode, and in umsdos EMD mode, and it seems stable.
-There are still few symlink/hardlink nuisances, but those are not fatal.
+There are still few hardlink nuisances, but those are not fatal.
 
-I'd call it wide beta, and ask for as many people as possible to
+I'd call it pre-release, and ask for as many people as possible to
 come and test it! See notes below for some more information, or if
 you are trying to use UMSDOS as root partition.
----------- WARNING --------- WARNING --------- WARNING -----------
 
 Legend: those lines marked with '+' on the beggining of line indicates it
 passed all of my tests, and performed perfect in all of them.
 
-Current status (981018) - UMSDOS dentry-Beta 0.83:
+Current status (981129) - UMSDOS dentry-pre 0.84:
 
 (1) pure MSDOS (no --linux-.--- EMD file):
 
@@ -51,13 +49,13 @@
 + resolve symlink		- works
 + dereference symlink		- works
 + dangling symlink		- works
-- hard links			- seems to work mostly
++ hard links			- works
 + special files (block/char devices, FIFOs, sockets...)	- works
-- various umsdos ioctls		- works
++ various umsdos ioctls		- works
 
 
 WRITE:
-- create symlink		- works mostly, but see WARNING below
++ create symlink		- works
 - create hardlink		- works, but see portability WARNING below
 + create file			- works
 + create special file		- works
@@ -66,16 +64,16 @@
 + rename file (dif. dir)	- works
 - rename hardlink (same dir)	-
 - rename hardlink (dif. dir)	-
-- rename symlink (same dir)	- 
-- rename symlink (dif. dir)	- problems sometimes. see warning below.
++ rename symlink (same dir)	- works
++ rename symlink (dif. dir)	- works
 + rename dir (same dir)		- works
 + rename dir (dif. dir)		- works
 + delete file			- works
 + notify_change (chown,perms)	- works
 + delete hardlink		- works
 + mkdir				- works
-- rmdir 			- HMMM. see with clean --linux-.--- files...
-- umssyncing (many ioctls)	- works
++ rmdir 			- works
++ umssyncing (many ioctls)	- works
 
 
 - CVF-FAT stuff (compressed DOS filesystem) - there is some support from Frank
@@ -91,13 +89,6 @@
 example is specs file about it. Specifically, moving directory which
 contains hardlinks will break them.
 
-Warning: moving symlinks around may break them until umount/remount.
-
-Warning: I seem to able to reproduce one problem with creting symlink after
-I rm -rf directory: it is manifested as symlink apperantly being regular
-file instead of symlink until next umount/mount pair. Tracking this one
-down...
-
 Note: (about pseudoroot) If you are currently trying to use UMSDOS as root
 partition (with linux installed in c:\linux) it will boot, but there are
 some problems. Volunteers ready to test pseudoroot are needed (preferably
@@ -105,7 +96,8 @@
 different interpretation of hard links in normal in pseudo-root modes,
 resulting is 'silent delete' of them sometimes. Also, '/DOS' pseudo
 directory is only partially re-implemented and buggy. It works most of the
-time, though.
+time, though. Update: should work ok in 0.84, although it still does not
+work correctly in combination with initrd featere. Working on this!
 
 Warning: (about creating hardlinks in pseudoroot mode) - hardlinks created in
 pseudoroot mode are not compatibile with 'normal' hardlinks, and vice versa.
@@ -114,6 +106,8 @@
 people either always use pseudoroot, or always use normal umsdos filesystem,
 this is no showstopper.
 
+Warning: (about hardlinks) - modifying hardlinks (esp. if there are in
+different directories) are currently somewhat broken, I'm working on it.
 
 ------------------------------------------------------------------------------
 
diff -u --recursive --new-file v2.1.130/linux/fs/umsdos/check.c linux/fs/umsdos/check.c
--- v2.1.130/linux/fs/umsdos/check.c	Sun Nov  8 14:03:08 1998
+++ linux/fs/umsdos/check.c	Sun Nov 29 11:43:13 1998
@@ -66,10 +66,10 @@
 void check_sb (struct super_block *sb, const char c)
 {
 	if (sb) {
-		Printk ((" (has %c_sb=%d, %d)", 
-			c, MAJOR (sb->s_dev), MINOR (sb->s_dev)));
+		printk (" (has %c_sb=%d, %d)", 
+			c, MAJOR (sb->s_dev), MINOR (sb->s_dev));
 	} else {
-		Printk ((" (%c_sb is NULL)", c));
+		printk (" (%c_sb is NULL)", c);
 	}
 } 
 
@@ -81,35 +81,37 @@
 void check_inode (struct inode *inode)
 {
 	if (inode) {
-		Printk ((KERN_DEBUG "*   inode is %lu (i_count=%d)",
-			 inode->i_ino, inode->i_count));
+		printk (KERN_DEBUG "*   inode is %lu (i_count=%d)",
+			 inode->i_ino, inode->i_count);
 		check_sb (inode->i_sb, 'i');
 		
 		if (inode->i_dentry.next) {	/* FIXME: does this work ? */
-			Printk ((" (has i_dentry)"));
+			printk (" (has i_dentry)");
 		} else {
-			Printk ((" (NO i_dentry)"));
+			printk (" (NO i_dentry)");
 		}
 		
+		printk (" (i_patched=%d)", inode->u.umsdos_i.i_patched);
+		
 		if (inode->i_op == NULL) {
-			Printk ((" (i_op is NULL)\n"));
+			printk (" (i_op is NULL)\n");
 		} else if (inode->i_op == &umsdos_dir_inode_operations) {
-			Printk ((" (i_op is umsdos_dir_inode_operations)\n"));
+			printk (" (i_op is umsdos_dir_inode_operations)\n");
 		} else if (inode->i_op == &umsdos_file_inode_operations) {
-			Printk ((" (i_op is umsdos_file_inode_operations)\n"));
+			printk (" (i_op is umsdos_file_inode_operations)\n");
 		} else if (inode->i_op == &umsdos_file_inode_operations_no_bmap) {
-			Printk ((" (i_op is umsdos_file_inode_operations_no_bmap)\n"));
+			printk (" (i_op is umsdos_file_inode_operations_no_bmap)\n");
 		} else if (inode->i_op == &umsdos_file_inode_operations_readpage) {
-			Printk ((" (i_op is umsdos_file_inode_operations_readpage)\n"));
+			printk (" (i_op is umsdos_file_inode_operations_readpage)\n");
 		} else if (inode->i_op == &umsdos_rdir_inode_operations) {
-			Printk ((" (i_op is umsdos_rdir_inode_operations)\n"));
+			printk (" (i_op is umsdos_rdir_inode_operations)\n");
 		} else if (inode->i_op == &umsdos_symlink_inode_operations) {
-			Printk ((" (i_op is umsdos_symlink_inode_operations)\n"));
+			printk (" (i_op is umsdos_symlink_inode_operations)\n");
 		} else {
-			Printk ((" (i_op is UNKNOWN: %p)\n", inode->i_op));
+			printk ((" (i_op is UNKNOWN: %p)\n", inode->i_op));
 		}
 	} else {
-		Printk ((KERN_DEBUG "*   inode is NULL\n"));
+		printk (KERN_DEBUG "*   inode is NULL\n");
 	}
 }
 
@@ -127,40 +129,40 @@
 		return;
 	}
 
-	Printk ((KERN_DEBUG "checkd_inode:  inode %lu\n", inode->i_ino));
+	printk (KERN_DEBUG "checkd_inode:  inode %lu\n", inode->i_ino);
 	cur = inode->i_dentry.next;
 	while (count++ < 10) {
 		PRINTK (("1..."));
 		if (!cur) {
-			Printk ((KERN_ERR "checkd_inode: *** NULL reached. exit.\n"));
+			printk (KERN_ERR "checkd_inode: *** NULL reached. exit.\n");
 			return;
 		}
 		PRINTK (("2..."));
 		ret = list_entry (cur, struct dentry, d_alias);
 		PRINTK (("3..."));
 		if (cur == cur->next) {
-			Printk ((KERN_DEBUG "checkd_inode: *** cur=cur->next: normal exit.\n"));
+			printk (KERN_DEBUG "checkd_inode: *** cur=cur->next: normal exit.\n");
 			return;
 		}
 		PRINTK (("4..."));
 		if (!ret) {
-			Printk ((KERN_ERR "checkd_inode: *** ret dentry is NULL. exit.\n"));
+			printk (KERN_ERR "checkd_inode: *** ret dentry is NULL. exit.\n");
 			return;
 		}
 		PRINTK (("5... (ret=%p)...", ret));
 		PRINTK (("5.1.. (ret->d_dname=%p)...", &(ret->d_name)));
 		PRINTK (("5.1.1. (ret->d_dname.len=%d)...", (int) ret->d_name.len));
 		PRINTK (("5.1.2. (ret->d_dname.name=%c)...", ret->d_name.name));
-		Printk ((KERN_DEBUG "checkd_inode:   i_dentry is %.*s\n", (int) ret->d_name.len, ret->d_name.name));
+		printk (KERN_DEBUG "checkd_inode:   i_dentry is %.*s\n", (int) ret->d_name.len, ret->d_name.name);
 		PRINTK (("6..."));
 		cur = cur->next;
 		PRINTK (("7..."));
 #if 1
-		Printk ((KERN_DEBUG "checkd_inode: *** finished after count 1 (operator forced)\n"));
+		printk (KERN_DEBUG "checkd_inode: *** finished after count 1 (operator forced)\n");
 		return;
 #endif		
 	}
-	Printk ((KERN_ERR "checkd_inode: *** OVER LIMIT (loop?) !\n"));
+	printk (KERN_ERR "checkd_inode: *** OVER LIMIT (loop?) !\n");
 	return;
 }
 
@@ -172,19 +174,19 @@
 void check_dent_int (struct dentry *dentry, int parent)
 {
 	if (parent) {
-		Printk ((KERN_DEBUG "*  parent(%d) dentry: %.*s\n", 
-			parent, (int) dentry->d_name.len, dentry->d_name.name));
+		printk (KERN_DEBUG "*  parent(%d) dentry: %.*s\n", 
+			parent, (int) dentry->d_name.len, dentry->d_name.name);
 	} else {
-		Printk ((KERN_DEBUG "*  checking dentry: %.*s\n",
-			 (int) dentry->d_name.len, dentry->d_name.name));
+		printk (KERN_DEBUG "*  checking dentry: %.*s\n",
+			 (int) dentry->d_name.len, dentry->d_name.name);
 	}
 	check_inode (dentry->d_inode);
-	Printk ((KERN_DEBUG "*   d_count=%d", dentry->d_count));
+	printk (KERN_DEBUG "*   d_count=%d", dentry->d_count);
 	check_sb (dentry->d_sb, 'd');
 	if (dentry->d_op == NULL) {
-		Printk ((" (d_op is NULL)\n"));
+		printk (" (d_op is NULL)\n");
 	} else {
-		Printk ((" (d_op is UNKNOWN: %p)\n", dentry->d_op));
+		printk (" (d_op is UNKNOWN: %p)\n", dentry->d_op);
 	}
 }
 
@@ -196,35 +198,35 @@
 void check_dentry_path (struct dentry *dentry, const char *desc)
 {
 	int count=0;
-	Printk ((KERN_DEBUG "*** check_dentry_path: %.60s\n", desc));
+	printk (KERN_DEBUG "*** check_dentry_path: %.60s\n", desc);
 
 	if (!dentry) {
-		Printk ((KERN_DEBUG "*** checking dentry... it is NULL !\n"));
+		printk (KERN_DEBUG "*** checking dentry... it is NULL !\n");
 		return;
 	}
 	if (IS_ERR(dentry)) {
-		Printk ((KERN_DEBUG "*** checking dentry... it is ERR(%ld) !\n",
-			 PTR_ERR(dentry)));
+		printk (KERN_DEBUG "*** checking dentry... it is ERR(%ld) !\n",
+			 PTR_ERR(dentry));
 		return;
 	}
 	
 	while (dentry && count < 10) {
 		check_dent_int (dentry, count++);
 		if (dentry == dentry->d_parent) {
-			Printk ((KERN_DEBUG "*** end checking dentry (root reached ok)\n"));
+			printk (KERN_DEBUG "*** end checking dentry (root reached ok)\n");
 			break;
 		}
 		dentry = dentry->d_parent;
 	}
 
 	if (count >= 10) {	/* if infinite loop detected */
-		Printk ((KERN_ERR 
-			"*** WARNING ! INFINITE LOOP ! check_dentry_path aborted !\n"));
+		printk (KERN_ERR 
+			"*** WARNING ! INFINITE LOOP ! check_dentry_path aborted !\n");
 	}
 	
 	if (!dentry) {
-		Printk ((KERN_ERR 
-			"*** WARNING ! NULL dentry ! check_dentry_path aborted !\n"));
+		printk (KERN_ERR 
+			"*** WARNING ! NULL dentry ! check_dentry_path aborted !\n");
 	}
 }
 #else
diff -u --recursive --new-file v2.1.130/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c
--- v2.1.130/linux/fs/umsdos/dir.c	Sun Nov  8 14:03:08 1998
+++ linux/fs/umsdos/dir.c	Sun Nov 29 11:43:13 1998
@@ -383,7 +383,6 @@
 	if (inode->u.umsdos_i.i_patched)
 		goto out;
 	inode->u.umsdos_i.i_patched = 1;
-
 	if (S_ISREG (entry->mode))
 		entry->mtime = inode->i_mtime;
 	inode->i_mode = entry->mode;
diff -u --recursive --new-file v2.1.130/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- v2.1.130/linux/fs/umsdos/inode.c	Sun Nov  8 14:03:08 1998
+++ linux/fs/umsdos/inode.c	Sun Nov 29 11:43:13 1998
@@ -60,6 +60,7 @@
 			" Notify jacques@solucorp.qc.ca\n");
 	}
 
+	inode->u.umsdos_i.i_patched = 0;
 	fat_put_inode (inode);
 }
 
@@ -125,15 +126,6 @@
 }
 
 
-/*
- * Tells if an Umsdos inode has been "patched" once.
- * Return != 0 if so.
- */
-int umsdos_isinit (struct inode *inode)
-{
-	return 0; /* inode->u.umsdos_i.i_emd_owner != 0; */
-}
-
 
 /*
  * Connect the proper tables in the inode and add some info.
@@ -200,7 +192,7 @@
  */
 void UMSDOS_read_inode (struct inode *inode)
 {
-	PRINTK ((KERN_DEBUG "UMSDOS_read_inode %p ino = %lu ",
+	Printk ((KERN_DEBUG "UMSDOS_read_inode %p ino = %lu ",
 		inode, inode->i_ino));
 	msdos_read_inode (inode);
 
@@ -235,8 +227,8 @@
 	struct file filp;
 	struct umsdos_dirent entry;
 
-Printk(("UMSDOS_notify_change: entering for %s/%s\n",
-dentry->d_parent->d_name.name, dentry->d_name.name));
+Printk(("UMSDOS_notify_change: entering for %s/%s (%d)\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, inode->u.umsdos_i.i_patched));
 
 	ret = inode_change_ok (inode, attr);
 	if (ret) {
@@ -348,7 +340,8 @@
 	 * But it has the side effect to re"dirt" the inode.
 	 */
 /*      
- * internal_notify_change (inode, &newattrs);
+ * UMSDOS_notify_change (inode, &newattrs);
+
  * inode->i_state &= ~I_DIRTY; / * FIXME: this doesn't work.  We need to remove ourselves from list on dirty inodes. /mn/ */
 }
 
@@ -385,7 +378,7 @@
 	if (!res)
 		goto out_fail;
 
-	printk (KERN_INFO "UMSDOS dentry-Beta 0.83 "
+	printk (KERN_INFO "UMSDOS dentry-pre 0.84 "
 		"(compatibility level %d.%d, fast msdos)\n", 
 		UMSDOS_VERSION, UMSDOS_RELEASE);
 
diff -u --recursive --new-file v2.1.130/linux/fs/umsdos/namei.c linux/fs/umsdos/namei.c
--- v2.1.130/linux/fs/umsdos/namei.c	Sun Nov  8 14:03:08 1998
+++ linux/fs/umsdos/namei.c	Tue Dec  1 22:40:52 1998
@@ -1008,8 +1008,7 @@
 		goto out;
 
 	ret = -EBUSY;
-	shrink_dcache_parent(dentry);
-	if (dentry->d_count > 1)
+	if (!list_empty(&dentry->d_hash))
 		goto out;
 
 	/* check the sticky bit */
@@ -1020,11 +1019,6 @@
 		goto out;
 	}
 
-	/*
-	 * Lock the directory, then check whether it's empty.
-	 */
-	down(&dentry->d_inode->i_sem);
-
 	/* check whether the EMD is empty */
 	ret = -ENOTEMPTY;
 	empty = umsdos_isempty (dentry);
@@ -1050,7 +1044,6 @@
 		}
 	} else if (empty == 2)
 		ret = 0;
-	up(&dentry->d_inode->i_sem);
 	if (ret)
 		goto out;
 
@@ -1071,15 +1064,6 @@
 	else
 		d_drop(temp);
 
-	/* Check again for a busy dentry */
-	ret = -EBUSY;
-	shrink_dcache_parent(dentry);
-	if (dentry->d_count > 1) {
-printk("umsdos_rmdir: %s/%s busy\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
-		goto out_dput;
-	}
-
 	/*
 	 * Attempt to remove the msdos name.
 	 */
@@ -1096,11 +1080,8 @@
 
 	/* dput() temp if we didn't do it above */
 out_dput:
-	if (temp != dentry) {
+	if (temp != dentry)
 		dput(temp);
-		if (!ret)
-			d_delete (dentry);
-	}
 
 out:
 	Printk (("umsdos_rmdir %d\n", ret));
diff -u --recursive --new-file v2.1.130/linux/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c
--- v2.1.130/linux/fs/umsdos/rdir.c	Sun Nov  8 14:03:08 1998
+++ linux/fs/umsdos/rdir.c	Tue Dec  1 22:47:18 1998
@@ -83,17 +83,17 @@
 {
 	int ret;
 
-	/* N.B. this won't work ... lookups of `..' are done by VFS */
-#ifdef BROKEN_TO_BITS
-	if (pseudo_root && len == 2 && name[0] == '.' && name[1] == '.' &&
-	    dir == saved_root->d_inode) {
-printk (KERN_WARNING "umsdos_rlookup_x: we are at pseudo-root thingy?\n");
-		pseudo_root->i_count++;
-		d_add(dentry, pseudo_root);
-		ret = 0;
+	if (saved_root && dir == saved_root->d_inode && !nopseudo &&
+	    dentry->d_name.len == UMSDOS_PSDROOT_LEN &&
+	    memcmp (dentry->d_name.name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) == 0) {
+		/* #Specification: pseudo root / DOS/linux
+		 * Even in the real root directory (c:\), the directory
+		 * /linux won't show
+		 */
+		 
+		ret = -ENOENT;
 		goto out;
 	}
-#endif
 
 	ret = msdos_lookup (dir, dentry);
 	if (ret) {
@@ -111,20 +111,6 @@
 dentry->d_parent->d_name.name, dentry->d_name.name));
 		umsdos_patch_dentry_inode(dentry, 0);
 
-		/* N.B. Won't work -- /linux dentry will already have
-		 * an inode, so we'll never get called here.
-		 */
-#ifdef BROKEN_TO_BITS
-		if (dentry->d_inode == pseudo_root && !nopseudo) {
-			/* #Specification: pseudo root / DOS/linux
-			 * Even in the real root directory (c:\), the directory
-			 * /linux won't show
-			 */
-printk(KERN_WARNING "umsdos_rlookup_x: do the pseudo-thingy...\n");
-			/* make the dentry negative */
-			d_delete(dentry);
-		}
-#endif
 	}
 out:
 	/* always install our dentry ops ... */
@@ -170,17 +156,13 @@
 		goto out;
 
 	ret = -EBUSY;
-	if (dentry->d_count > 1) {
-		shrink_dcache_parent(dentry);
-		if (dentry->d_count > 1)
-			goto out;
-	}
+	if (!list_empty(&dentry->d_hash))
+		goto out;
 
 	ret = msdos_rmdir (dir, dentry);
 	if (ret != -ENOTEMPTY)
 		goto out;
 
-	down(&dentry->d_inode->i_sem);
 	empty = umsdos_isempty (dentry);
 	if (empty == 1) {
 		struct dentry *demd;
@@ -194,7 +176,6 @@
 			dput(demd);
 		}
 	}
-	up(&dentry->d_inode->i_sem);
 	if (ret)
 		goto out;
 
diff -u --recursive --new-file v2.1.130/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.1.130/linux/fs/vfat/namei.c	Thu Nov 12 16:21:23 1998
+++ linux/fs/vfat/namei.c	Tue Dec  1 23:52:55 1998
@@ -1422,6 +1422,8 @@
 	if (dir->i_dev != dentry->d_inode->i_dev || dir == dentry->d_inode) {
 		return -EBUSY;
 	}
+	if (!list_empty(&dentry->d_hash))
+		return -EBUSY;
 
 	res = vfat_empty(dentry->d_inode);
 	if (res) {
@@ -1508,18 +1510,16 @@
 			tmp = next;
 			next = tmp->next;
 			alias = list_entry(tmp, struct dentry, d_alias);
+			if (alias == dentry)
+				continue;
+
 			if (inode) {
 				list_del(&alias->d_alias);
 				iput(alias->d_inode);
 				d_instantiate(alias, inode);
-				/* dentry is already accounted for */
-				if (alias != dentry) {
-					inode->i_count++;
-				}
-			}
-			if (alias != dentry) {
-				d_drop(alias);
+				inode->i_count++;
 			}
+			d_drop(alias);
 		}
 	}
 }
@@ -1551,10 +1551,12 @@
 {
 	int res;
 	PRINTK1(("vfat_rmdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
-	res = vfat_rmdirx(dir, dentry);
-	if (res >= 0) {
-		drop_replace_inodes(dentry, NULL);
-		d_delete(dentry);
+
+	res = -EBUSY;
+	if (list_empty(&dentry->d_hash)) {
+		res = vfat_rmdirx(dir, dentry);
+		if (res >= 0)
+			drop_replace_inodes(dentry, NULL);
 	}
 	return res;
 }
diff -u --recursive --new-file v2.1.130/linux/include/asm-i386/semaphore.h linux/include/asm-i386/semaphore.h
--- v2.1.130/linux/include/asm-i386/semaphore.h	Fri Nov 27 13:09:28 1998
+++ linux/include/asm-i386/semaphore.h	Tue Dec  1 13:34:47 1998
@@ -36,9 +36,9 @@
 asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
 asmlinkage void __up_wakeup(void /* special register calling convention */);
 
-extern void __down(struct semaphore * sem);
-extern int  __down_interruptible(struct semaphore * sem);
-extern void __up(struct semaphore * sem);
+asmlinkage void __down(struct semaphore * sem);
+asmlinkage int  __down_interruptible(struct semaphore * sem);
+asmlinkage void __up(struct semaphore * sem);
 
 extern spinlock_t semaphore_wake_lock;
 
diff -u --recursive --new-file v2.1.130/linux/include/linux/apm_bios.h linux/include/linux/apm_bios.h
--- v2.1.130/linux/include/linux/apm_bios.h	Fri Oct  9 13:27:15 1998
+++ linux/include/linux/apm_bios.h	Sat Nov 28 17:18:54 1998
@@ -77,6 +77,7 @@
 extern struct apm_bios_info	apm_bios_info;
 
 extern void		apm_bios_init(void);
+extern void		apm_setup(char *, int *);
 
 extern int		apm_register_callback(int (*callback)(apm_event_t));
 extern void		apm_unregister_callback(int (*callback)(apm_event_t));
diff -u --recursive --new-file v2.1.130/linux/include/linux/joystick.h linux/include/linux/joystick.h
--- v2.1.130/linux/include/linux/joystick.h	Fri Oct 23 22:01:26 1998
+++ linux/include/linux/joystick.h	Tue Dec  1 22:11:10 1998
@@ -34,7 +34,7 @@
  * Version
  */
 
-#define JS_VERSION		0x01020c
+#define JS_VERSION		0x01020d
 
 /*
  * Types and constants for reading from /dev/js
@@ -179,18 +179,23 @@
 
 #ifdef USE_PARPORT
 #include <linux/parport.h>
-#define JS_PAR_STATUS(y)	parport_read_status(y->port)
 #define JS_PAR_DATA_IN(y)	parport_read_data(y->port)
 #define JS_PAR_DATA_OUT(x,y)	parport_write_data(y->port, x)
+#define JS_PAR_STATUS(y)	parport_read_status(y->port)
+#define JS_PAR_CTRL_IN(y)	parport_read_control(y->port)
 #define JS_PAR_CTRL_OUT(x,y)	parport_write_control(y->port, x)
+#define JS_PAR_ECTRL_OUT(x,y)	parport_write_econtrol(y->port, x)
 #else
-#define JS_PAR_STATUS(y)	inb(y+1)
 #define JS_PAR_DATA_IN(y)	inb(y)
 #define JS_PAR_DATA_OUT(x,y)	outb(x,y)
+#define JS_PAR_STATUS(y)	inb(y+1)
+#define JS_PAR_CTRL_IN(y)	inb(y+2)
 #define JS_PAR_CTRL_OUT(x,y)	outb(x,y+2)
+#define JS_PAR_ECTRL_OUT(x,y)	outb(x,y+0x402)
 #endif
 
 #define JS_PAR_STATUS_INVERT	(0x80)
+#define JS_PAR_CTRL_INVERT	(0x04)
 
 /*
  * Internal types
diff -u --recursive --new-file v2.1.130/linux/include/linux/linkage.h linux/include/linux/linkage.h
--- v2.1.130/linux/include/linux/linkage.h	Fri Oct  9 13:27:16 1998
+++ linux/include/linux/linkage.h	Tue Dec  1 11:28:24 1998
@@ -2,9 +2,15 @@
 #define _LINUX_LINKAGE_H
 
 #ifdef __cplusplus
-#define asmlinkage extern "C"
+#define CPP_ASMLINKAGE extern "C"
 #else
-#define asmlinkage
+#define CPP_ASMLINKAGE
+#endif
+
+#if defined __i386__ && (__GNUC__ > 2 || __GNUC_MINOR__ > 7)
+#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
+#else
+#define asmlinkage CPP_ASMLINKAGE
 #endif
 
 #define SYMBOL_NAME_STR(X) #X
diff -u --recursive --new-file v2.1.130/linux/include/linux/lp.h linux/include/linux/lp.h
--- v2.1.130/linux/include/linux/lp.h	Thu Nov 19 09:56:29 1998
+++ linux/include/linux/lp.h	Fri Nov 27 10:23:11 1998
@@ -25,10 +25,9 @@
 #define LP_NOPA  0x0010
 #define LP_ERR   0x0020
 #define LP_ABORT 0x0040
-#ifdef LP_NEED_CAREFUL
-#define LP_CAREFUL 0x0080
-#endif
+#define LP_CAREFUL 0x0080 /* obsoleted -arca */
 #define LP_ABORTOPEN 0x0100
+#define	LP_TRUST_IRQ 0x0200
 
 /* timeout for each character.  This is relative to bus cycles -- it
  * is the count in a busy loop.  THIS IS THE VALUE TO CHANGE if you
@@ -41,13 +40,10 @@
 #define LP_INIT_CHAR 1000
 
 /* The parallel port specs apparently say that there needs to be
- * a .5usec wait before and after the strobe.  Since there are wildly
- * different computers running linux, I can't come up with a perfect
- * value so if 20 is not good for you use `tunelp /dev/lp? -w ?`.
- * You can also set it to 0 if your printer handle that.
+ * a .5usec wait before and after the strobe.
  */
 
-#define LP_INIT_WAIT 20
+#define LP_INIT_WAIT 1
 
 /* This is the amount of time that the driver waits for the printer to
  * catch up when the printer's buffer appears to be filled.  If you
@@ -70,11 +66,10 @@
 			    or 0 for polling (no IRQ) */
 #define LPGETIRQ 0x0606  /* get the current IRQ number */
 #define LPWAIT   0x0608  /* corresponds to LP_INIT_WAIT */
-#ifdef LP_NEED_CAREFUL
+/* NOTE: LPCAREFUL is obsoleted and it' s always the default right now -arca */
 #define LPCAREFUL   0x0609  /* call with TRUE arg to require out-of-paper, off-
 			    line, and error indicators good on all writes,
 			    FALSE to ignore them.  Default is ignore. */
-#endif
 #define LPABORTOPEN 0x060a  /* call with TRUE arg to abort open() on error,
 			    FALSE to ignore error.  Default is ignore.  */
 #define LPGETSTATUS 0x060b  /* return LP_S(minor) */
@@ -83,6 +78,7 @@
 #define LPGETSTATS  0x060d  /* get statistics (struct lp_stats) */
 #endif
 #define LPGETFLAGS  0x060e  /* get status flags */
+#define LPTRUSTIRQ  0x060f  /* set/unset the LP_TRUST_IRQ flag */
 
 /* timeout for printk'ing a timeout, in jiffies (100ths of a second).
    This is also used for re-checking error conditions if LP_ABORT is
@@ -96,7 +92,7 @@
 #define LP_TIME(minor)	lp_table[(minor)].time		/* wait time */
 #define LP_WAIT(minor)	lp_table[(minor)].wait		/* strobe wait */
 #define LP_IRQ(minor)	lp_table[(minor)].dev->port->irq /* interrupt # */
-							/* 0 means polled */
+					/* PARPORT_IRQ_NONE means polled */
 #ifdef LP_STATS
 #define LP_STAT(minor)	lp_table[(minor)].stats		/* statistics area */
 #endif
diff -u --recursive --new-file v2.1.130/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- v2.1.130/linux/include/linux/nfs_fs.h	Fri Nov 27 13:09:29 1998
+++ linux/include/linux/nfs_fs.h	Wed Dec  2 09:45:42 1998
@@ -222,16 +222,12 @@
 extern int  nfs_wb_all(struct inode *);
 extern int  nfs_wb_page(struct inode *, struct page *);
 extern int  nfs_wb_pid(struct inode *, pid_t);
-extern int  nfs_wb_area(struct inode *, off_t, off_t);
 
 /*
  * Invalidate write-backs, possibly trying to write them
  * back first..
  */
 extern void nfs_inval(struct inode *);
-extern int  nfs_wbinval(struct inode *);
-extern int  nfs_wbinval_pid(struct inode *, pid_t);
-
 extern int  nfs_truncate_dirty_pages(struct inode *, unsigned long);
 extern int  nfs_updatepage(struct file *, struct page *, unsigned long, unsigned int, int);
 
diff -u --recursive --new-file v2.1.130/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.1.130/linux/include/linux/pci.h	Fri Nov 27 13:09:29 1998
+++ linux/include/linux/pci.h	Tue Dec  1 22:10:07 1998
@@ -615,6 +615,7 @@
 #define PCI_DEVICE_ID_MADGE_C155S	0x1001
 
 #define PCI_VENDOR_ID_3COM		0x10b7
+#define PCI_DEVICE_ID_3COM_3C985	0x0001
 #define PCI_DEVICE_ID_3COM_3C339	0x3390
 #define PCI_DEVICE_ID_3COM_3C590	0x5900
 #define PCI_DEVICE_ID_3COM_3C595TX	0x5950
diff -u --recursive --new-file v2.1.130/linux/include/linux/swap.h linux/include/linux/swap.h
--- v2.1.130/linux/include/linux/swap.h	Mon Sep 28 10:51:35 1998
+++ linux/include/linux/swap.h	Tue Dec  1 11:28:24 1998
@@ -107,8 +107,8 @@
 	int next;	/* swapfile to be used next */
 };
 extern struct swap_list_t swap_list;
-int sys_swapoff(const char *);
-int sys_swapon(const char *, int);
+asmlinkage int sys_swapoff(const char *);
+asmlinkage int sys_swapon(const char *, int);
 
 /*
  * vm_ops not present page codes for shared memory.
diff -u --recursive --new-file v2.1.130/linux/include/linux/umsdos_fs.h linux/include/linux/umsdos_fs.h
--- v2.1.130/linux/include/linux/umsdos_fs.h	Wed Sep  9 14:51:13 1998
+++ linux/include/linux/umsdos_fs.h	Tue Dec  1 22:11:43 1998
@@ -1,7 +1,9 @@
 #ifndef LINUX_UMSDOS_FS_H
 #define LINUX_UMSDOS_FS_H
 
-/* #define UMSDOS_DEBUG 1 */
+
+#define UMS_DEBUG 1	/* define for check_* functions */
+/*#define UMSDOS_DEBUG 1*/
 #define UMSDOS_PARANOIA 1
 
 #define UMSDOS_VERSION	0
diff -u --recursive --new-file v2.1.130/linux/include/linux/umsdos_fs.p linux/include/linux/umsdos_fs.p
--- v2.1.130/linux/include/linux/umsdos_fs.p	Mon Sep 28 10:51:36 1998
+++ linux/include/linux/umsdos_fs.p	Sun Nov 29 11:43:13 1998
@@ -57,7 +57,6 @@
 
 void umsdos_setup_dir(struct dentry *);
 void umsdos_set_dirinfo_new(struct dentry *, off_t);
-int umsdos_isinit (struct inode *inode);
 void umsdos_patch_dentry_inode (struct dentry *, off_t);
 int umsdos_get_dirowner (struct inode *inode, struct inode **result);
 
diff -u --recursive --new-file v2.1.130/linux/init/main.c linux/init/main.c
--- v2.1.130/linux/init/main.c	Fri Nov 27 13:09:29 1998
+++ linux/init/main.c	Sun Nov 29 10:37:02 1998
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <linux/blk.h>
+#include <linux/hdreg.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -41,6 +42,10 @@
 #  include <asm/mtrr.h>
 #endif
 
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
+
 /*
  * Versions of gcc older than that listed below may actually compile
  * and link okay, but the end product can have subtle run time bugs.
@@ -864,6 +869,9 @@
 #endif
 #ifdef CONFIG_PARIDE_PG
         { "pg.", pg_setup },
+#endif
+#ifdef CONFIG_APM
+	{ "apm=", apm_setup },
 #endif
 	{ 0, 0 }
 };
diff -u --recursive --new-file v2.1.130/linux/kernel/fork.c linux/kernel/fork.c
--- v2.1.130/linux/kernel/fork.c	Fri Nov 27 13:09:29 1998
+++ linux/kernel/fork.c	Fri Nov 27 10:17:08 1998
@@ -137,7 +137,7 @@
 {
 	struct task_struct **tslot = NULL;
 
-	if (!current->uid || (nr_tasks < NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT))
+	if ((nr_tasks < NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT) || !current->uid)
 		tslot = get_free_taskslot();
 	return tslot;
 }
diff -u --recursive --new-file v2.1.130/linux/mm/filemap.c linux/mm/filemap.c
--- v2.1.130/linux/mm/filemap.c	Fri Nov 27 13:09:30 1998
+++ linux/mm/filemap.c	Fri Nov 27 10:29:12 1998
@@ -200,8 +200,8 @@
 	struct page * page;
 	int count_max, count_min;
 
-	count_max = (limit<<1) >> (priority>>1);
-	count_min = (limit<<1) >> (priority);
+	count_max = limit;
+	count_min = (limit<<2) >> (priority);
 
 	page = mem_map + clock;
 	do {
@@ -214,7 +214,15 @@
 		if (shrink_one_page(page, gfp_mask))
 			return 1;
 		count_max--;
-		if (page->inode || page->buffers)
+		/* 
+		 * If the page we looked at was recyclable but we didn't
+		 * reclaim it (presumably due to PG_referenced), don't
+		 * count it as scanned.  This way, the more referenced
+		 * page cache pages we encounter, the more rapidly we
+		 * will age them. 
+		 */
+		if (atomic_read(&page->count) != 1 ||
+		    (!page->inode && !page->buffers))
 			count_min--;
 		page++;
 		clock++;
diff -u --recursive --new-file v2.1.130/linux/mm/swap.c linux/mm/swap.c
--- v2.1.130/linux/mm/swap.c	Fri Nov 27 13:09:30 1998
+++ linux/mm/swap.c	Fri Nov 27 10:15:29 1998
@@ -62,13 +62,13 @@
 
 buffer_mem_t buffer_mem = {
 	5,	/* minimum percent buffer */
-	25,	/* borrow percent buffer */
+	10,	/* borrow percent buffer */
 	60	/* maximum percent buffer */
 };
 
 buffer_mem_t page_cache = {
 	5,	/* minimum percent page cache */
-	30,	/* borrow percent page cache */
+	15,	/* borrow percent page cache */
 	75	/* maximum */
 };
 
diff -u --recursive --new-file v2.1.130/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.1.130/linux/mm/vmscan.c	Fri Nov 27 13:09:31 1998
+++ linux/mm/vmscan.c	Mon Nov 30 16:05:40 1998
@@ -431,7 +431,7 @@
 	kmem_cache_reap(gfp_mask);
 
 	if (buffer_over_borrow() || pgcache_over_borrow())
-		shrink_mmap(i, gfp_mask);
+		state = 0;
 
 	switch (state) {
 		do {
diff -u --recursive --new-file v2.1.130/linux/net/ipv4/Config.in linux/net/ipv4/Config.in
--- v2.1.130/linux/net/ipv4/Config.in	Mon Oct  5 13:13:48 1998
+++ linux/net/ipv4/Config.in	Fri Nov 27 10:13:53 1998
@@ -31,21 +31,23 @@
 	    define_bool CONFIG_NETLINK_DEV y
 	fi
     fi
-    bool 'IP: transparent proxy support' CONFIG_IP_TRANSPARENT_PROXY
-    bool 'IP: always defragment' CONFIG_IP_ALWAYS_DEFRAG
+    bool 'IP: always defragment (required for masquerading)' CONFIG_IP_ALWAYS_DEFRAG
   fi
 fi
 if [ "$CONFIG_IP_FIREWALL" = "y" ]; then
-  bool 'IP: masquerading' CONFIG_IP_MASQUERADE
-  if [ "$CONFIG_IP_MASQUERADE" != "n" ]; then
-    comment 'Protocol-specific masquerading support will be built as modules.'
-    bool 'IP: ICMP masquerading' CONFIG_IP_MASQUERADE_ICMP
-    comment 'Protocol-specific masquerading support will be built as modules.'
-    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      bool 'IP: masquerading special modules support' CONFIG_IP_MASQUERADE_MOD 
-      if [ "$CONFIG_IP_MASQUERADE_MOD" = "y" ]; then
-        tristate 'IP: ipautofw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPAUTOFW
-        tristate 'IP: ipportfw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPPORTFW
+  if [ "$CONFIG_IP_ALWAYS_DEFRAG" != "n" ]; then
+    bool 'IP: transparent proxy support' CONFIG_IP_TRANSPARENT_PROXY
+    bool 'IP: masquerading' CONFIG_IP_MASQUERADE
+    if [ "$CONFIG_IP_MASQUERADE" != "n" ]; then
+      comment 'Protocol-specific masquerading support will be built as modules.'
+      bool 'IP: ICMP masquerading' CONFIG_IP_MASQUERADE_ICMP
+      comment 'Protocol-specific masquerading support will be built as modules.'
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+        bool 'IP: masquerading special modules support' CONFIG_IP_MASQUERADE_MOD 
+        if [ "$CONFIG_IP_MASQUERADE_MOD" = "y" ]; then
+          tristate 'IP: ipautofw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPAUTOFW
+          tristate 'IP: ipportfw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPPORTFW
+	fi
       fi
     fi
   fi
diff -u --recursive --new-file v2.1.130/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.1.130/linux/net/ipv4/tcp_ipv4.c	Sun Nov  8 14:03:15 1998
+++ linux/net/ipv4/tcp_ipv4.c	Mon Nov 30 16:43:32 1998
@@ -265,7 +265,7 @@
 	struct tcp_bind_bucket *tb;
 	int low = sysctl_local_port_range[0];
 	int high = sysctl_local_port_range[1];
-	int remaining = high - low;
+	int remaining = high - low + 1;
 	int rover;
 
 	SOCKHASH_LOCK();
diff -u --recursive --new-file v2.1.130/linux/scripts/mkdep.c linux/scripts/mkdep.c
--- v2.1.130/linux/scripts/mkdep.c	Tue Jun 23 10:01:31 1998
+++ linux/scripts/mkdep.c	Wed Dec  2 10:04:04 1998
@@ -31,7 +31,7 @@
 	int len;
 	char buffer[256-sizeof(int)];
 } path_array[2] = {
-	{ 23, "/usr/src/linux/include/" },
+	{  0, "" },
 	{  0, "" }
 };
 
@@ -462,8 +462,11 @@
 	char *hpath;
 
 	hpath = getenv("HPATH");
-	if (!hpath)
-		hpath = "/usr/src/linux/include";
+	if (!hpath) {
+		fputs("mkdep: HPATH not set in environment.  "
+		      "Don't bypass the top level Makefile.\n", stderr);
+		return 1;
+	}
 	len = strlen(hpath);
 	memcpy(path_array[0].buffer, hpath, len);
 	if (len && hpath[len-1] != '/')
