diff -u --recursive --new-file v2.2.1/linux/CREDITS linux/CREDITS
--- v2.2.1/linux/CREDITS	Thu Jan 28 12:58:02 1999
+++ linux/CREDITS	Sat Feb  6 12:46:20 1999
@@ -1403,6 +1403,13 @@
 S: FIN-00330 Helsingfors
 S: Finland
 
+N: Trond Myklebust
+E: trond.myklebust@fys.uio.no
+D: current NFS client hacker.
+S: Dagaliveien 31e
+S: N-0391 Oslo
+S: Norway
+
 N: Matija Nalis
 E: mnalis@jagor.srce.hr
 E: mnalis@voyager.hr
diff -u --recursive --new-file v2.2.1/linux/Documentation/00-INDEX linux/Documentation/00-INDEX
--- v2.2.1/linux/Documentation/00-INDEX	Tue Dec 22 14:16:53 1998
+++ linux/Documentation/00-INDEX	Mon Feb  1 12:03:20 1999
@@ -57,6 +57,8 @@
 	- info on the in-kernel binary support for Java(tm)
 joystick.txt
 	- info on using joystick devices (and driver) with linux.
+kbuild/
+	- directory with info about the kernel build process
 kmod.txt
 	- - info on the kernel module loader/unloader (kerneld replacement)
 locks.txt
diff -u --recursive --new-file v2.2.1/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.2.1/linux/Documentation/Configure.help	Wed Jan 20 23:14:04 1999
+++ linux/Documentation/Configure.help	Sun Feb  7 19:54:09 1999
@@ -2330,8 +2330,8 @@
 
 IP: firewall packet netlink device
 CONFIG_IP_FIREWALL_NETLINK
-  If you say Y here, then the first 128 bytes of each packet that hit
-  your Linux firewall and was blocked are passed on to optional user
+  If you say Y here, you can use the ipchains tool to copy all or part of
+  any packet you specify that hits your Linux firewall to optional user
   space monitoring software that can then look for attacks and take
   actions such as paging the administrator of the site.
 
@@ -2339,9 +2339,6 @@
   with major number 36 and minor number 3 using mknod ("man mknod"),
   and you need (to write) a program that reads from that device and
   takes appropriate action.
-
-  With the ipchains tool you can specify which packets you want to go
-  to this device, as well as how many bytes from each packet.
 
 IP: kernel level autoconfiguration
 CONFIG_IP_PNP
diff -u --recursive --new-file v2.2.1/linux/Documentation/fb/vesafb.txt linux/Documentation/fb/vesafb.txt
--- v2.2.1/linux/Documentation/fb/vesafb.txt	Tue Jan 19 11:32:50 1999
+++ linux/Documentation/fb/vesafb.txt	Sat Feb  6 12:47:42 1999
@@ -11,7 +11,7 @@
 This means we decide at boot time whenever we want to run in text or
 graphics mode.  Switching mode later on (in protected mode) is
 impossible; BIOS calls work in real mode only.  VESA BIOS Extentions
-Version 2.0 are required, becauce we need a linear frame buffer.
+Version 2.0 are required, because we need a linear frame buffer.
 
 Advantages:
 
@@ -75,7 +75,7 @@
 1. Note: LILO cannot handle hex, for booting directly with 
          "vga=mode-number" you have to transform the numbers to decimal.
 2. Note: Some newer versions of LILO appear to work with those hex values,
-         if you set the 0x infront of the numbers.
+         if you set the 0x in front of the numbers.
 
 X11
 ===
diff -u --recursive --new-file v2.2.1/linux/Documentation/kbuild/00-INDEX linux/Documentation/kbuild/00-INDEX
--- v2.2.1/linux/Documentation/kbuild/00-INDEX	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/kbuild/00-INDEX	Mon Feb  1 12:03:20 1999
@@ -0,0 +1,8 @@
+00-INDEX
+    	- this file: info on the kernel build process
+bug-list.txt
+	- known bugs in kbuild programs
+commands.txt
+	- overview of kbuild commands
+config-language.txt
+	- specification of Config Language, the language in Config.in files
diff -u --recursive --new-file v2.2.1/linux/Documentation/kbuild/bug-list.txt linux/Documentation/kbuild/bug-list.txt
--- v2.2.1/linux/Documentation/kbuild/bug-list.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/kbuild/bug-list.txt	Mon Feb  1 12:03:20 1999
@@ -0,0 +1,22 @@
+Bug List
+21 January 1999
+Michael Elizabeth Chastain, <mailto:mec@shout.net>
+
+- If a variable has a value of "m" in the previous .config file,
+  and a type of bool in the Config script, then all the interpreters
+  get confused.  This happens frequently when someone changes a
+  tristate option to a bool option and people in the field have
+  .config files with a value of 'm'.  For example: CONFIG_PSMOUSE.
+
+- CONFIG_MODVERSIONS has incorrect dependencies.  If you have a
+  problem building the kernel, and you have CONFIG_MODVERSIONS turned
+  on, do a 'make dep' followed by 'make clean' before you try anything
+  else.
+
+- 'make dep' uses multistage dependencies, so the .hdepend file contains
+  'touch' commands.  As a result, building a kernel often touches files
+  in include/linux/*.h.  This messes up CVS and other systems which like
+  to rely on file dates.
+
+- 'make dep' fails for C files which include other C files, such as
+  drivers/cdrom/sbpcd2.c.
diff -u --recursive --new-file v2.2.1/linux/Documentation/kbuild/commands.txt linux/Documentation/kbuild/commands.txt
--- v2.2.1/linux/Documentation/kbuild/commands.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/kbuild/commands.txt	Mon Feb  1 12:03:20 1999
@@ -0,0 +1,113 @@
+Overview of Kbuild Commands
+24 January 1999
+Michael Elizabeth Chastain, <mailto:mec@shout.net>
+
+
+
+=== Introduction
+
+Someday we'll get our arms around all this stuff and clean it up
+a little!  Meanwhile, this file describes the system as it is today.
+
+
+
+=== Quick Start
+
+If you are building a kernel for the first time, here are the commands
+you need:
+
+    make config
+    make dep
+    make bzImage
+
+Instead of 'make config', you can run 'make menuconfig' for a full-screen
+text interface, or 'make xconfig' for an X interface using TCL/TK.
+
+'make bzImage' will leave your new kernel image in arch/i386/boot/bzImage.
+You can also use 'make bzdisk' or 'make bzlilo'.
+
+See the lilo documentation for more information on how to use lilo.
+You can also use the 'loadlin' program to boot Linux from MS-DOS.
+
+Some computers won't work with 'make bzImage', either due to hardware
+problems or very old versions of lilo or loadlin.  If your kernel image
+is small, you may use 'make zImage', 'make zdisk', or 'make zlilo'
+on theses systems.
+
+If you find a file name 'vmlinux' in the top directory of the source tree,
+just ignore it.  This is an intermediate file and you can't boot from it.
+
+Other architectures: the information above is oriented towards the
+i386.  On other architectures, there are no 'bzImage' files; simply
+use 'zImage' or 'vmlinux' as appropriate for your architecture.
+
+Note: the difference between 'zImage' files and 'bzImage' files is that
+'bzImage' uses a different layout and a different loading algorithm,
+and thus has a larger capacity.  Both files use gzip compression.
+The 'bz' in 'bzImage' stands for 'big zImage', not for 'bzip'!
+
+
+
+=== Top Level Makefile targets
+
+Here are the targets available at the top level:
+
+    make config, make oldconfig, make menuconfig, make xconfig
+
+	Configure the Linux kernel.  You must do this before almost
+	anything else.
+
+	config		line-oriented interface
+	oldconfig	line-oriented interface, re-uses old values
+	menuconfig	curses-based full-screen interface
+	xconfig		X window system interface
+
+    make checkconfig
+
+	This runs a little perl script that checks the source tree for
+	missing instances of #include <linux/config.h>.  Someone needs to
+	do this occasionally, because the C preprocessor will silently give
+	bad results if these symbols haven't been included (it treats
+	undefined symbols in preprocessor directives as defined to 0).
+	Superfluous uses of #include <linux/config.h> are also reported,
+	but you can ignore these, because smart CONFIG_* dependencies
+	make them harmless.
+
+	You can run 'make checkconfig' without configuring the kernel.
+	Also, 'make checkconfig' does not modify any files.
+
+    make checkhelp
+
+	This runs another little perl script that checks the source tree
+	for options that are in Config.in files but are not documented
+	in scripts/Configure.help.  Again, someone needs to do this
+	occasionally.  If you are adding configuration options, it's
+	nice if you do it before you publish your patch!
+
+	You can run 'make checkhelp' withoug configuring the kernel.
+	Also, 'make checkhelp' does not modify any files.
+
+    make dep, make depend
+
+	'make dep' is a synonym for the long form, 'make depend'.
+
+	This command does two things.  First, it computes dependency
+	information about which .o files depend on which .h files.
+	It records this information in a top-level file named .hdepend
+	and in one file per source directory named .depend.
+
+	Second, if you have CONFIG_MODVERSIONS enabled, 'make dep'
+	computes symbol version information for all of the files that
+	export symbols (note that both resident and modular files may
+	export symbols).
+
+	If you do not enable CONFIG_MODVERSIONS, you only have to run
+	'make dep' once, right after the first time you configure
+	the kernel.  The .hdepend files and the .depend file are
+	independent of your configuration.
+
+	If you do enable CONFIG_MODVERSIONS, you must run 'make dep'
+	every time you change your configuration, because the module
+	symbol version information depends on the configuration.
+
+[to be continued ...]
diff -u --recursive --new-file v2.2.1/linux/Documentation/kbuild/config-language.txt linux/Documentation/kbuild/config-language.txt
--- v2.2.1/linux/Documentation/kbuild/config-language.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/kbuild/config-language.txt	Mon Feb  1 12:03:20 1999
@@ -0,0 +1,630 @@
+Config Language Specification
+21 January 1999
+Michael Elizabeth Chastain, <mailto:mec@shout.net>
+
+
+
+=== Introduction
+
+Config Language is not 'bash'.
+
+This document describes Config Language, the Linux Kernel Configuration
+Language.  config.in and Config.in files are written in this language.
+
+Although it looks, and usually acts, like a subset of the 'sh' language,
+Config Language has a restricted syntax and different semantics.
+
+Here is a basic guideline for Config Language programming: use only the
+programming idioms that you see in existing Config.in files.  People often
+draw on their shell programming experience to invent idioms that look
+reasonable to shell programmers, but silently fail in Config Language.
+
+Config Language is not 'bash'.
+
+
+
+=== Interpreters
+
+Four different configuration programs read Config Language:
+
+    scripts/Configure   make config, make oldconfig
+    scripts/Menuconfig  make menuconfig
+    scripts/tkparse     make xconfig
+    mconfig             (in development)
+
+'Configure' is a bash script which interprets Config.in files by sourcing
+them.  Some of the Config Language commands are native bash commands;
+simple bash functions implement the rest of the commands.
+
+'Menuconfig' is another bash script.  It scans the input files with a
+small awk script, builds a shell function for each menu, sources the
+shell functions that it builds, and then executes the shell functions
+in a user-driven order.  Menuconfig uses 'lxdialog', a back-end utility
+program, to perform actual screen output.  'lxdialog' is a C program
+which uses curses.
+
+'scripts/tkparse' is a C program with an ad hoc parser which translates
+a Config Language script to a huge TCL/TK program.  'make xconfig'
+then hands this TCL/TK program to 'wish', which executes it.
+
+'mconfig' is the next generation of Config Language interpreters.  It is a
+C program with a bison parser which translates a Config Language script
+into an internal syntax tree and then hands the syntax tree to one of
+several user-interface front ends.
+
+This document describes the behaviour of all four interpreters, even though
+mconfig has not been released at the time of writing.
+
+
+
+=== Statements
+
+A Config Language script is a list of statements.  There are 21 simple
+statements; an 'if' statement; menu blocks; and a 'source' statement.
+
+A '\' at the end of a line marks a line continuation.
+
+'#' usually introduces a comment, which continues to the end of the line.
+Lines of the form '# ... is not set', however, are not comments.  They
+are semantically meaningful, and all four config interpreters implement
+this meaning.
+
+Newlines are significant.  You may not substitute semicolons for newlines.
+The 'if' statement does accept a semicolon in one position; you may use
+a newline in that position instead.
+
+Here are the basic grammar elements.
+
+    A /prompt/ is a single-quoted string or a double-quoted string.
+    If the word is double-quoted, it may not have any $ substitutions.
+
+    A /word/ is a single unquoted word, a single-quoted string, or a
+    double-quoted string.  If the word is unquoted or double quoted,
+    then $-substition will be performed on the word.
+
+    A /symbol/ is a single unquoted word.
+
+    A /dep/ is a dependency.  Syntactically, it is a /word/.  At run
+    time, a /dep/ must evaluate to "y", "m", "n", or "".
+
+    An /expr/ is a bash-like expression using the operators
+    '=', '!=', '-a', '-o', and '!'.
+
+Here are all the statements:
+
+    Text statements:
+
+        mainmenu_name   /prompt/
+        comment         /prompt/
+        text            /prompt/
+
+    Ask statements:
+
+        bool            /prompt/ /symbol/
+        hex             /prompt/ /symbol/ /word/
+        int             /prompt/ /symbol/ /word/
+        string          /prompt/ /symbol/ /word/
+        tristate        /prompt/ /symbol/
+
+    Define statements:
+
+        define_bool     /symbol/ /word/
+        define_hex      /symbol/ /word/
+        define_int      /symbol/ /word/
+        define_string   /symbol/ /word/
+        define_tristate /symbol/ /word/
+
+    Dependent statements:
+
+        dep_bool        /prompt/ /symbol/ /dep/ ...
+        dep_hex         /prompt/ /symbol/ /word/ /dep/ ...
+        dep_int         /prompt/ /symbol/ /word/ /dep/ ...
+        dep_string      /prompt/ /symbol/ /word/ /dep/ ...
+        dep_tristate    /prompt/ /symbol/ /dep/ ...
+
+    Unset statement:
+
+        unset /symbol/ ...
+
+    Choice statements:
+
+        choice          /prompt/ /word/ /word/
+        nchoice         /prompt/ /symbol/ /prompt/ /symbol/ ...
+
+    If statements:
+
+        if [ /expr/ ] ; then
+	  /statement/
+	  ...
+        fi
+
+        if [ /expr/ ] ; then
+	  /statement/
+	  ...
+        else
+	  /statement/
+	  ...
+        fi
+
+    Menu block:
+
+        mainmenu_option next_comment
+        comment /prompt/
+          /statement/
+	  ...
+        endmenu
+
+    Source statement:
+
+        source /word/
+
+
+
+=== mainmenu_name /prompt/
+
+This verb is a lot less important than it looks.  It specifies the top-level
+name of this Config Language file.
+
+Configure:  ignores this line
+Menuconfig: ignores this line
+Xconfig:    uses /prompt/ for the label window.
+mconfig:    ignores this line (mconfig does a better job without it).
+
+Example:
+
+    # arch/sparc/config.in
+    mainmenu_name "Linux/SPARC Kernel Configuration"
+
+
+
+=== comment /prompt/
+
+This verb displays its prompt to the user during the configuration process
+and also echoes it to the output files during output.  Note that the
+prompt, like all prompts, is a quoted string with no dollar substitution.
+
+The 'comment' verb is not a Config Language comment.  It causes the
+user interface to display text, and it causes output to appear in the
+output files.
+
+Configure:  implemented
+Menuconfig: implemented
+Xconfig:    does not display, but writes to output files
+mconfig:    implemented
+
+Example:
+
+    # drivers/net/Config.in
+    comment 'CCP compressors for PPP are only built as modules.'
+
+
+
+=== text /prompt/
+
+This verb displays the prompt to the user with no adornment whatsoever.
+It does not echo the prompt to the output file.  mconfig uses this verb
+internally for its help facility.
+
+Configure:  not implemented
+Menuconfig: not implemented
+Xconfig:    not implemented
+mconfig:    implemented
+
+Example:
+
+    # mconfig internal help text
+    text 'Here are all the mconfig command line options.'
+
+
+
+=== bool /prompt/ /symbol/
+
+This verb displays /prompt/ to the user, accepts a value from the user,
+and assigns that value to /symbol/.  The legal input values are "n" and
+"y".
+
+Note that the bool verb does not have a default value.  People keep
+trying to write Config Language scripts with a default value for bool,
+but *all* of the existing language interpreters discard additional values.
+Feel free to submit a multi-interpreter patch to linux-kbuild if you
+want to implement this as an enhancment.
+
+Configure:  implemented
+Menuconfig: implemented
+Xconfig:    implemented
+mconfig:    implemented
+
+Example:
+
+    # arch/i386/config.in
+    bool 'Symmetric multi-processing support' CONFIG_SMP
+
+
+
+=== hex /prompt/ /symbol/ /word/
+
+This verb displays /prompt/ to the user, accepts a value from the user,
+and assigns that value to /symbol/.  Any hexadecimal number is a legal
+input value.  /word/ is the default value.
+
+The hex verb does not accept range parameters.
+
+Configure:  implemented
+Menuconfig: implemented
+Xconfig:    implemented
+mconfig:    implemented
+
+Example:
+
+    # drivers/sound/Config.in
+    hex 'I/O base for SB Check from manual of the card' CONFIG_SB_BASE 220
+
+
+
+=== int /prompt/ /symbol/ /word/
+
+This verb displays /prompt/ to the user, accepts a value from the user,
+and assigns that value to /symbol/.  /word/ is the default value.
+Any decimal number is a legal input value.
+
+The int verb does not accept range parameters.
+
+Configure:  implemented
+Menuconfig: implemented
+Xconfig:    implemented
+mconfig:    implemented
+
+Example:
+
+    # drivers/char/Config.in
+    int 'Maximum number of Unix98 PTYs in use (0-2048)' \
+        CONFIG_UNIX98_PTY_COUNT 256
+
+
+
+=== string /prompt/ /symbol/ /word/
+
+This verb displays /prompt/ to the user, accepts a value from the user,
+and assigns that value to /symbol/.  /word/ is the default value.  Legal
+input values are any ASCII string, except for the characters '"' and '\\'.
+
+The default value is mandatory.
+
+Configure:  implemented
+Menuconfig: implemented
+Xconfig:    implemented
+mconfig:    implemented
+
+Example:
+
+    # drivers/sound/Config.in
+    string '  Full pathname of DSPxxx.LD firmware file' \
+        CONFIG_PSS_BOOT_FILE /etc/sound/dsp001.ld
+
+
+
+=== tristate /prompt/ /symbol/
+
+This verb displays /prompt/ to the user, accepts a value from the user,
+and assigns that value to /symbol/.  Legal values are "n", "m", or "y".
+
+The value "m" stands for "module"; it indicates that /symbol/ should
+be built as a kernel module.  The value "m" is legal only if the symbol
+CONFIG_MODULES currently has the value "y".
+
+The tristate verb does not have a default value.
+
+Configure:  implemented
+Menuconfig: implemented
+Xconfig:    implemented
+mconfig:    implemented
+
+Example:
+
+    # fs/Config.in
+    tristate 'NFS filesystem support' CONFIG_NFS_FS
+
+
+
+=== define_bool /symbol/ /word/
+
+This verb the value of /word/ to /symbol/.  Legal values are "n" or "y".
+
+For compatibility reasons, the value of "m" is also legal, because it
+will be a while before define_tristate is implemented everywhere.
+
+Configure:  implemented
+Menuconfig: implemented
+Xconfig:    implemented
+mconfig:    implemented
+
+Example:
+
+    # arch/alpha/config.in
+    if [ "$CONFIG_ALPHA_GENERIC" = "y" ]
+    then
+            define_bool CONFIG_PCI y
+            define_bool CONFIG_ALPHA_NEED_ROUNDING_EMULATION y
+    fi
+
+
+
+=== define_hex /symbol/ /word/
+
+This verb assigns the value of /word/ to /symbol/.  Any hexadecimal
+number is a legal value.
+
+Configure:  implemented
+Menuconfig: not implemented
+Xconfig:    not implemented
+mconfig:    implemented
+
+Example:
+
+    # Not from the corpus
+    bool 'Specify custom serial port' CONFIG_SERIAL_PORT_CUSTOM
+    if [ "$CONFIG_SERIAL_PORT_CUSTOM" = "y" ]; then
+	hex 'Serial port number' CONFIG_SERIAL_PORT
+    else
+	define_hex CONFIG_SERIAL_PORT 0x3F8
+    fi
+
+
+
+=== define_int /symbol/ /word/
+
+This verb assigns /symbol/ the value /word/.  Any decimal number is a
+legal value.
+
+Configure:  implemented
+Menuconfig: not implemented
+Xconfig:    not implemented
+mconfig:    implemented
+
+Example:
+
+    # Not from the corpus
+    define_int CONFIG_UID_TORVALDS 2026
+
+
+
+=== define_string /symbol/ /word/
+
+This verb assigns the value of /word/ to /symbol/.  Legal input values
+are any ASCII string, except for the characters '"' and '\\'.
+
+Configure:  implemented
+Menuconfig: not implemented
+Xconfig:    not implemented
+mconfig:    implemented
+
+Example
+
+    # Not from the corpus
+    define_string CONFIG_VERSION "2.2.0"
+
+
+
+=== define_tristate /symbol/ /word/
+
+This verb assigns the value of /word/ to /symbol/.  Legal input values
+are "n", "m", and "y".
+
+As soon as this verb is implemented in all interpreters, please use it
+instead of define_bool to define tristate values.  This aids in static
+type checking.
+
+Configure:  not implemented
+Menuconfig: not implemented
+Xconfig:    not implemented
+mconfig:    implemented
+
+Example:
+
+    # not from the corpus
+    if [ "$CONFIG_ZFTAPE" != "n" ]; then
+      comment 'The compressor will be built as a module only!'
+      define_tristate CONFIG_ZFT_COMPRESSOR m
+    fi
+
+
+
+=== dep_bool /prompt/ /symbol/ /dep/ ...
+
+This verb evaluates all of the dependencies in the dependency list.
+Any dependency which has a value of "y" does not restrict the input
+range.  Any dependency which has a value of "n", or which has some
+other value, restricts the input range to "n".
+
+If the input range is restricted to the single choice "n", dep_bool
+silently assigns "n" to /symbol/.  If the input range has more than
+one choice, dep_bool displays /prompt/ to the user, accepts a value
+from the user, and assigns that value to /symbol/.
+
+Configure:  not implemented
+Menuconfig: not implemented
+XConfig:    not implemented
+mconfig:    implemented
+
+    # not from the corpus
+    dep_bool 'RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_PCI
+
+
+
+=== dep_hex /prompt/ /symbol/ /word/ /dep/ ...
+=== dep_int /prompt/ /symbol/ /word/ /dep/ ...
+=== dep_string /prompt/ /symbol/ /word/ /dep/ ...
+
+I am still thinking about the semantics of these verbs.
+
+Configure:  not implemented
+Menuconfig: not implemented
+XConfig:    not implemented
+mconfig:    not implemented
+
+
+
+=== dep_tristate /prompt/ /symbol /dep/ ...
+
+This verb evaluates all of the dependencies in the dependency list.
+Any dependency which as a value of "y" does not restrict the input range.
+Any dependency which has a value of "m" restricts the input range to
+"m" or "n".  Any dependency which has a value of "n", or which has some
+other value, restricts the input range to "n".
+
+If the input range is restricted to the single choice "n", dep_tristate
+silently assigns "n" to /symbol/.  If the input range has more than
+one choice, dep_tristate displays /prompt/ to the user, accepts a value
+from the user, and assigns that value to /symbol/.
+
+Configure:  implemented
+Menuconfig: implemented (but silently ignores dependencies after the first)
+Xconfig:    implemented (but silently ignores dependencies after the first)
+mconfig:    implemented
+
+
+
+=== unset /symbol/ ...
+
+This verb assigns the value "" to /symbol/, but does not cause /symbol/
+to appear in the output.  The existence of this verb is a hack; it covers
+up deeper problems with variable semantics in a random-execution language.
+
+Configure:  implemented
+Menuconfig: implemented
+Xconfig:    not implemented
+mconfig:    implemented
+
+
+
+=== choice /prompt/ /word/ /word/
+
+This verb implements a choice list or "radio button list" selection.
+It displays /prompt/ to the user, as well as a group of sub-prompts
+which have corresponding symbols.
+
+When the user selects a value, the choice verb sets the corresponding
+symbol to "y" and sets all the other symbols in the choice list to "n".
+
+The second argument is a single-quoted or double-quoted word that
+describes a series of sub-prompts and symbol names.  The interpreter
+breaks up the word at white space boundaries into a list of sub-words.
+The first sub-word is the first prompt; the second sub-word is the
+first symbol.  The third sub-word is the second prompt; the fourth
+sub-word is the second symbol.  And so on, for all the sub-words.
+
+The third word is a literal word.  Its value must be a unique abbreviation
+for exactly one of the prompts.  The symbol corresponding to this prompt
+is the default enabled symbol.
+
+Note that because of the syntax of the choice verb, the sub-prompts
+may not have spaces in them.
+
+Configure:  implemented
+Menuconfig: implemented
+Xconfig:    implemented
+mconfig:    implemented
+
+
+
+=== nchoice /prompt/ /symbol/ /prompt/ /symbol/ ...
+
+This verb has the same semantics as the choice verb, but with a sensible
+syntax.
+
+The first /prompt/ is the master prompt for the entire choice list.
+
+The first /symbol/ is the default symbol to enable (notice that this
+is a symbol, not a unique prompt abbreviation).
+
+The subsequent /prompt/ and /symbol/ pairs are the prompts and symbols
+for the choice list.
+
+Configure:  not implemented
+Menuconfig: not implemented
+XConfig:    not implemented
+mconfig:    implemented
+
+
+
+=== if [ /expr/ ] ; then
+
+This is a conditional statement, with an optional 'else' clause.  You may
+substitute a newline for the semicolon if you choose.
+
+/expr/ may contain the following atoms and operators.  Note that, unlike
+shell, you must use double quotes around every atom.
+
+    "..."		a literal
+    "$..."		a variable
+
+    /atom/  = /atom/	true if atoms have identical value
+    /atom/ != /atom/	true if atoms have different value
+
+    /expr/ -o /expr/	true if either expression is true
+    /expr/ -a /expr/	true if both expressions are true
+    ! /expr/		true if expression is not true
+
+Configure:  implemented
+Menuconfig: implemented
+XConfig:    implemented, with bugs
+mconfig:    implemented
+
+Xconfig has several known bugs, and probably some unknown bugs too:
+
+- In a comparison, if the left-hand atom is a variable and that variable
+  is from a choice list, the right-hand atom must be "y".
+
+- In a comparison, if the right-hand atom is a variable and that variable
+  is from a choice list, you lose.  tkparse will throw a segmentation
+  violation, silently generate bizarre TCL code, or something else.
+
+- tkparse gives the wrong precedence to -o, -a, and !.  Don't use both
+  -o and -a in an expression.  Don't use ! at all.
+
+
+
+=== mainmenu_option next_comment
+
+This verb introduces a new menu.  The next statement must have a comment
+verb.  The /prompt/ of that comment verb becomes the title of the menu.
+(I have no idea why the original designer didn't create a 'menu ...' verb).
+
+Statements outside the scope of any menu are in the implicit top menu.
+The title of the top menu comes from a variety of sources, depending on
+the interpreter.
+
+Configure:  implemented
+Menuconfig: implemented
+Xconfig:    implemented
+mconfig:    implemented
+
+
+
+=== endmenu
+
+This verb closes the scope of a menu.
+
+Configure:  implemented
+Menuconfig: implemented
+Xconfig:    implemented
+mconfig:    implemented
+
+
+
+=== source /word/
+
+This verb interprets the literal /word/ as a filename, and interpolates
+the contents of that file.  The word must be a single unquoted literal
+word.
+
+Some interpreters interpret this verb at run time; some interpreters
+interpret it at parse time.
+
+Inclusion is textual inclusion, like the C preprocessor #include facility.
+The source verb does not imply a submenu or any kind of block nesting.
+
+Configure:  implemented (run time)
+Menuconfig: implemented (parse time)
+Xconfig:    implemented (parse time)
+mconfig:    implemented (parse time)
diff -u --recursive --new-file v2.2.1/linux/Documentation/proc.txt linux/Documentation/proc.txt
--- v2.2.1/linux/Documentation/proc.txt	Thu Jan 28 12:58:02 1999
+++ linux/Documentation/proc.txt	Sat Feb  6 12:46:20 1999
@@ -50,7 +50,7 @@
 the work back to the Linux community. This work is based on the
 2.1.132 and 2.2.0-pre-kernel versions. I'm afraid it's still far from
 complete, but we hope it will be useful. As far as we know, it is the
-first 'all-in-one’ document about the /proc file system. It is
+first 'all-in-one' document about the /proc file system. It is
 focused on the Intel x86 hardware, so if you are looking for PPC, ARM,
 SPARC, APX, etc., features, you probably won't find what you are
 looking for. It also only covers IPv4 networking, not IPv6 nor other
@@ -657,7 +657,7 @@
 
 sg-big-buff
    This file shows the size of the generic SCSI (sg) buffer. At this
-   point, you can’t tune it yet, but you can change it at compile time
+   point, you can't tune it yet, but you can change it at compile time
    by editing include/scsi/sg.h and changing the value of
    SG_BIG_BUFF.
 
@@ -794,9 +794,9 @@
   swap_cluster
      This is probably the greatest influence on system
      performance. swap_cluster is the number of pages kswapd writes in
-     one turn. You’ll want this value to be large so that kswapd does
-     its I/O in large chunks and the disk doesn’t have to seek as
-     often., but you don’t want it to be too large since that would
+     one turn. You'll want this value to be large so that kswapd does
+     its I/O in large chunks and the disk doesn't have to seek as
+     often., but you don't want it to be too large since that would
      flood the request queue.
 
 overcommit_memory
@@ -1140,7 +1140,7 @@
 accept_source_route
    Should source routed packages be accepted or declined. The
    default is dependent on the kernel configuration. It's 'yes' for
-   routers and 'np' for hosts.
+   routers and 'no' for hosts.
 
 bootp_relay
    Accept packets with source address 0.b.c.d destined not to this
diff -u --recursive --new-file v2.2.1/linux/Documentation/sound/ESS linux/Documentation/sound/ESS
--- v2.2.1/linux/Documentation/sound/ESS	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/ESS	Mon Feb  1 14:04:39 1999
@@ -0,0 +1,33 @@
+Documentation for the ESS AudioDrive chips
+
+In 2.2 kernels the SoundBlaster driver not only tries to detect an ESS chip, it
+tries to detect the type of ESS chip too. The correct detection of the chip 
+doesn't always succeed however, so the default behaviour is 2.0 behaviour
+which means: only detect ES688 and ES1688.
+
+All ESS chips now have a recording level setting. This is a need-to-have for
+people who want to use their ESS for recording sound.
+
+Every chip that's detected as a later-than-es1688 chip has a 6 bits logarithmic
+master volume control.
+
+Every chip that's detected as a ES1887 now has Full Duplex support. Made a 
+little testprogram that showes that is works, haven't seen a real program that
+needs this however.
+
+For ESS chips an additional parameter "esstype" can be specified. This controls
+the (auto) detection of the ESS chips. It can have 3 kinds of values:
+
+-1   Act like 2.0 kernels: only detect ES688 or ES1688.
+0	 Try to auto-detect the chip (may fail for ES1688)
+688  The chip will be treated as  ES688
+1688  ,,  ,,   ,,  ,,    ,,   ,, ES1688
+1868  ,,  ,,   ,,  ,,    ,,   ,, ES1868
+1869  ,,  ,,   ,,  ,,    ,,   ,, ES1869
+1788  ,,  ,,   ,,  ,,    ,,   ,, ES1788
+1887  ,,  ,,   ,,  ,,    ,,   ,, ES1887
+1888  ,,  ,,   ,,  ,,    ,,   ,, ES1888
+
+Because Full Duplex is supported for ES1887 you can specify a second DMA
+channel by specifying module parameter dma16. It can be one of: 0, 1, 3 or 5.
+
diff -u --recursive --new-file v2.2.1/linux/Documentation/sound/OPL3-SA linux/Documentation/sound/OPL3-SA
--- v2.2.1/linux/Documentation/sound/OPL3-SA	Tue Aug 18 22:02:01 1998
+++ linux/Documentation/sound/OPL3-SA	Mon Feb  1 10:41:47 1999
@@ -2,8 +2,7 @@
 
 ---
 Note: This howto only describes how to setup the OPL3-SA1 chip; this info
-does not apply to the SA2, SA3, or SA4. Contact hannu@opensound.com for
-the support details of these other SAx chips.
+does not apply to the SA2, SA3, or SA4. 
 ---
 
 The Yamaha OPL3-SA1 sound chip is usually found built into motherboards, and
diff -u --recursive --new-file v2.2.1/linux/Documentation/video4linux/bttv/INSTALL linux/Documentation/video4linux/bttv/INSTALL
--- v2.2.1/linux/Documentation/video4linux/bttv/INSTALL	Thu Nov 12 16:21:17 1998
+++ linux/Documentation/video4linux/bttv/INSTALL	Sat Feb  6 12:46:20 1999
@@ -41,6 +41,9 @@
    10: Newer Hauppage (Bt878)
    11: Miro PCTV Pro
    12: ADS Tech Channel Surfer TV (and maybe TV+FM)
+   13: AVerMedia TVCapture 98
+   14: Aimslab VHX
+   15: Zoltrix TV-Max
 
   - You may have to adjust BTTV_MAJOR to a different number depending on your
     kernel version. The official number 81 does not work on some setups.
diff -u --recursive --new-file v2.2.1/linux/Documentation/video4linux/bttv/README.FIRST linux/Documentation/video4linux/bttv/README.FIRST
--- v2.2.1/linux/Documentation/video4linux/bttv/README.FIRST	Wed Aug 26 11:37:33 1998
+++ linux/Documentation/video4linux/bttv/README.FIRST	Sat Feb  6 12:46:20 1999
@@ -1,4 +1,4 @@
 o Please direct queries about the in kernel version of this driver to
   Alan Cox first not to Ralph, or better yet join the video4linux mailing
-  list (mail majordomo@phunk.org with "subscribe video4linux")
+  list (mail video4linux-list-request@redhat.com with "subscribe")
 
diff -u --recursive --new-file v2.2.1/linux/MAINTAINERS linux/MAINTAINERS
--- v2.2.1/linux/MAINTAINERS	Wed Jan 20 23:14:04 1999
+++ linux/MAINTAINERS	Sat Feb  6 12:46:20 1999
@@ -530,6 +530,12 @@
 L:	netdev@roxanne.nuclecu.unam.mx
 S:	Maintained
 
+NFS CLIENT
+P:      Trond Myklebust
+M:      trond.myklebust@fys.uio.no
+L:      linux-kernel@vger.rutgers.edu
+S:      Maintained
+
 NI5010 NETWORK DRIVER
 P:     Jan-Pascal van Best and Andreas Mohr
 M:     jvbest@qv3pluto.leidenuniv.nl (Best)
diff -u --recursive --new-file v2.2.1/linux/Makefile linux/Makefile
--- v2.2.1/linux/Makefile	Thu Jan 28 12:58:02 1999
+++ linux/Makefile	Mon Feb  1 12:03:19 1999
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 2
-SUBLEVEL = 1
+SUBLEVEL = 2
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -221,35 +221,27 @@
 		mkdir include/linux/modules; \
 	fi
 
-oldconfig: symlinks scripts/split-include
+oldconfig: symlinks
 	$(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
-	if [ -r include/linux/autoconf.h ]; then \
-	    scripts/split-include include/linux/autoconf.h include/config; \
-	fi
 
-xconfig: symlinks scripts/split-include
+xconfig: symlinks
 	$(MAKE) -C scripts kconfig.tk
 	wish -f scripts/kconfig.tk
-	if [ -r include/linux/autoconf.h ]; then \
-	    scripts/split-include include/linux/autoconf.h include/config; \
-	fi
 
-menuconfig: include/linux/version.h symlinks scripts/split-include
+menuconfig: include/linux/version.h symlinks
 	$(MAKE) -C scripts/lxdialog all
 	$(CONFIG_SHELL) scripts/Menuconfig arch/$(ARCH)/config.in
-	if [ -r include/linux/autoconf.h ]; then \
-	    scripts/split-include include/linux/autoconf.h include/config; \
-	fi
 
-config: symlinks scripts/split-include
+config: symlinks
 	$(CONFIG_SHELL) scripts/Configure arch/$(ARCH)/config.in
-	if [ -r include/linux/autoconf.h ]; then \
-	    scripts/split-include include/linux/autoconf.h include/config; \
-	fi
+
+include/config/MARKER: scripts/split-include include/linux/autoconf.h
+	scripts/split-include include/linux/autoconf.h include/config
+	@ touch include/config/MARKER
 
 linuxsubdirs: $(patsubst %, _dir_%, $(SUBDIRS))
 
-$(patsubst %, _dir_%, $(SUBDIRS)) : dummy
+$(patsubst %, _dir_%, $(SUBDIRS)) : dummy include/config/MARKER
 	$(MAKE) -C $(patsubst _dir_%, %, $@)
 
 $(TOPDIR)/include/linux/version.h: include/linux/version.h
@@ -286,10 +278,10 @@
 	@echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' >>.ver
 	@mv -f .ver $@
 
-init/version.o: init/version.c include/linux/compile.h
+init/version.o: init/version.c include/linux/compile.h include/config/MARKER
 	$(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c
 
-init/main.o: init/main.c
+init/main.o: init/main.c include/config/MARKER
 	$(CC) $(CFLAGS) $(PROFILING) -c -o $*.o $<
 
 fs lib mm ipc kernel drivers net: dummy
diff -u --recursive --new-file v2.2.1/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.2.1/linux/arch/alpha/config.in	Tue Jan 19 11:32:50 1999
+++ linux/arch/alpha/config.in	Mon Feb  1 12:03:20 1999
@@ -243,7 +243,7 @@
 endmenu
 
 mainmenu_option next_comment
-comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
+comment 'Old CD-ROM drivers (not SCSI, not IDE)'
 
 bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
 if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
diff -u --recursive --new-file v2.2.1/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.2.1/linux/arch/alpha/kernel/entry.S	Mon Jan 25 17:44:34 1999
+++ linux/arch/alpha/kernel/entry.S	Mon Feb  1 10:41:47 1999
@@ -186,6 +186,18 @@
 	jsr	$31,do_entIF
 .end entIF
 
+.align 3
+.globl	entDbg
+.ent	entDbg
+entDbg:
+	SAVE_ALL
+	lda	$8,0x3fff
+	bic	$30,$8,$8
+	lda	$26,ret_from_sys_call
+	jsr	$31,do_entDbg
+.end entDbg
+
+
 /*
  * Fork() is one of the special system calls: it needs to
  * save the callee-saved regs so that the regs can be found
diff -u --recursive --new-file v2.2.1/linux/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h
--- v2.2.1/linux/arch/alpha/kernel/proto.h	Wed Jan 13 15:00:41 1999
+++ linux/arch/alpha/kernel/proto.h	Mon Feb  1 10:41:47 1999
@@ -187,6 +187,7 @@
 extern void entMM(void);
 extern void entSys(void);
 extern void entUna(void);
+extern void entDbg(void);
 
 /* process.c */
 extern void generic_kill_arch (int mode, char *reboot_cmd);
diff -u --recursive --new-file v2.2.1/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v2.2.1/linux/arch/alpha/kernel/traps.c	Fri Oct 23 22:01:19 1998
+++ linux/arch/alpha/kernel/traps.c	Mon Feb  1 10:41:47 1999
@@ -121,9 +121,9 @@
 #endif
 
 asmlinkage void
-do_entArith(unsigned long summary, unsigned long write_mask, unsigned long a2,
-	    unsigned long a3, unsigned long a4, unsigned long a5,
-	    struct pt_regs regs)
+do_entArith(unsigned long summary, unsigned long write_mask,
+	    unsigned long a2, unsigned long a3, unsigned long a4,
+	    unsigned long a5, struct pt_regs regs)
 {
 	if ((summary & 1)) {
 		/*
@@ -145,9 +145,10 @@
 	unlock_kernel();
 }
 
-asmlinkage void do_entIF(unsigned long type, unsigned long a1,
-			 unsigned long a2, unsigned long a3, unsigned long a4,
-			 unsigned long a5, struct pt_regs regs)
+asmlinkage void
+do_entIF(unsigned long type, unsigned long a1,
+	 unsigned long a2, unsigned long a3, unsigned long a4,
+	 unsigned long a5, struct pt_regs regs)
 {
 	lock_kernel();
 	die_if_kernel("Instruction fault", &regs, type, 0);
@@ -230,6 +231,25 @@
 	unlock_kernel();
 }
 
+/* There is an ifdef in the PALcode in MILO that enables a 
+   "kernel debugging entry point" as an unprivilaged call_pal.
+
+   We don't want to have anything to do with it, but unfortunately
+   several versions of MILO included in distributions have it enabled,
+   and if we don't put something on the entry point we'll oops.  */
+
+asmlinkage void
+do_entDbg(unsigned long type, unsigned long a1,
+	  unsigned long a2, unsigned long a3, unsigned long a4,
+	  unsigned long a5, struct pt_regs regs)
+{
+	lock_kernel();
+	die_if_kernel("Instruction fault", &regs, type, 0);
+	force_sig(SIGILL, current);
+	unlock_kernel();
+}
+
+
 /*
  * entUna has a different register layout to be reasonably simple. It
  * needs access to all the integer registers (the kernel doesn't use
@@ -895,4 +915,5 @@
 	wrent(entIF, 3);
 	wrent(entUna, 4);
 	wrent(entSys, 5);
+	wrent(entDbg, 6);
 }
diff -u --recursive --new-file v2.2.1/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.2.1/linux/arch/i386/config.in	Wed Jan 20 23:14:04 1999
+++ linux/arch/i386/config.in	Mon Feb  1 12:03:20 1999
@@ -158,7 +158,7 @@
 endmenu
 
 mainmenu_option next_comment
-comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
+comment 'Old CD-ROM drivers (not SCSI, not IDE)'
 
 bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
 if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
diff -u --recursive --new-file v2.2.1/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.2.1/linux/arch/i386/kernel/io_apic.c	Mon Dec 28 15:00:52 1998
+++ linux/arch/i386/kernel/io_apic.c	Wed Feb  3 14:56:43 1999
@@ -202,7 +202,7 @@
 DO_ACTION( mask,    0, |= 0x00010000, io_apic_sync())		/* mask = 1 */
 DO_ACTION( unmask,  0, &= 0xfffeffff, )				/* mask = 0 */
 
-static void __init clear_IO_APIC_pin(unsigned int pin)
+static void clear_IO_APIC_pin(unsigned int pin)
 {
 	struct IO_APIC_route_entry entry;
 
@@ -215,6 +215,13 @@
 	io_apic_write(0x11 + 2 * pin, *(((int *)&entry) + 1));
 }
 
+static void clear_IO_APIC (void)
+{
+	int pin;
+
+	for (pin = 0; pin < nr_ioapic_registers; pin++)
+		clear_IO_APIC_pin(pin);
+}
 
 /*
  * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
@@ -625,7 +632,7 @@
 /*
  * Set up a certain pin as ExtINT delivered interrupt
  */
-void __init setup_ExtINT_pin(unsigned int pin)
+void __init setup_ExtINT_pin(unsigned int pin, int irq)
 {
 	struct IO_APIC_route_entry entry;
 
@@ -635,11 +642,16 @@
 	memset(&entry,0,sizeof(entry));
 
 	entry.delivery_mode = dest_ExtINT;
-	entry.dest_mode = 1;				/* logical delivery */
+	entry.dest_mode = 0;				/* physical delivery */
 	entry.mask = 0;					/* unmask IRQ now */
-	entry.dest.logical.logical_dest = 0x01;		/* logical CPU #0 */
+	/*
+	 * We use physical delivery to get the timer IRQ
+	 * to the boot CPU. 'boot_cpu_id' is the physical
+	 * APIC ID of the boot CPU.
+	 */
+	entry.dest.physical.physical_dest = boot_cpu_id;
 
-	entry.vector = 0;				/* it's ignored */
+	entry.vector = assign_irq_vector(irq);
 
 	entry.polarity = 0;
 	entry.trigger = 0;
@@ -754,7 +766,7 @@
 
 static void __init init_sym_mode(void)
 {
-	int i, pin;
+	int i;
 
 	for (i = 0; i < PIN_MAP_SIZE; i++) {
 		irq_2_pin[i].pin = -1;
@@ -784,8 +796,7 @@
 	/*
 	 * Do not trust the IO-APIC being empty at bootup
 	 */
-	for (pin = 0; pin < nr_ioapic_registers; pin++)
-		clear_IO_APIC_pin(pin);
+	clear_IO_APIC();
 }
 
 /*
@@ -793,6 +804,15 @@
  */
 void init_pic_mode(void)
 {
+	/*
+	 * Clear the IO-APIC before rebooting:
+	 */
+	clear_IO_APIC();
+
+	/*
+	 * Put it back into PIC mode (has an effect only on
+	 * certain boards)
+	 */
 	printk("disabling symmetric IO mode... ");
 		outb_p(0x70, 0x22);
 		outb_p(0x00, 0x23);
@@ -1178,7 +1198,7 @@
 
 		if (pin2 != -1) {
 			printk(".. (found pin %d) ...", pin2);
-			setup_ExtINT_pin(pin2);
+			setup_ExtINT_pin(pin2, 0);
 			make_8259A_irq(0);
 		}
 
diff -u --recursive --new-file v2.2.1/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.2.1/linux/arch/i386/kernel/smp.c	Mon Jan 25 17:44:34 1999
+++ linux/arch/i386/kernel/smp.c	Mon Feb  1 10:59:05 1999
@@ -147,6 +147,17 @@
 #define APIC_DEFAULT_PHYS_BASE 0xfee00000
 
 /*
+ * Reads and clears the Pentium Timestamp-Counter
+ */
+#define READ_TSC(x)	__asm__ __volatile__ (  "rdtsc" \
+				:"=a" (((unsigned long*)&(x))[0]),  \
+				 "=d" (((unsigned long*)&(x))[1]))
+
+#define CLEAR_TSC \
+	__asm__ __volatile__ ("\t.byte 0x0f, 0x30;\n"::\
+		"a"(0x00001000), "d"(0x00001000), "c"(0x10):"memory")
+
+/*
  *	Setup routine for controlling SMP activation
  *
  *	Command-line option of "nosmp" or "maxcpus=0" will disable SMP
@@ -710,24 +721,19 @@
 	value |= 0xff;			/* Set spurious IRQ vector to 0xff */
  	apic_write(APIC_SPIV,value);
 
- 	value = apic_read(APIC_TASKPRI);
- 	value &= ~APIC_TPRI_MASK;	/* Set Task Priority to 'accept all' */
- 	apic_write(APIC_TASKPRI,value);
-
 	/*
-	 * Set arbitrarion priority to 0
+	 * Set Task Priority to 'accept all'
 	 */
- 	value = apic_read(APIC_ARBPRI);
- 	value &= ~APIC_ARBPRI_MASK;
- 	apic_write(APIC_ARBPRI, value);
+ 	value = apic_read(APIC_TASKPRI);
+ 	value &= ~APIC_TPRI_MASK;
+ 	apic_write(APIC_TASKPRI,value);
 
 	/*
-	 * Set the logical destination ID to 'all', just to be safe.
+	 * Clear the logical destination ID, just to be safe.
 	 * also, put the APIC into flat delivery mode.
 	 */
  	value = apic_read(APIC_LDR);
 	value &= ~APIC_LDR_MASK;
-	value |= SET_APIC_LOGICAL_ID(0xff);
  	apic_write(APIC_LDR,value);
 
  	value = apic_read(APIC_DFR);
@@ -735,8 +741,6 @@
  	apic_write(APIC_DFR, value);
 
 	udelay(100);			/* B safe */
-	ack_APIC_irq();
-	udelay(100);
 }
 
 unsigned long __init init_smp_mappings(unsigned long memory_start)
@@ -1815,10 +1819,6 @@
  * closely follows bus clocks.
  */
 
-#define RDTSC(x)	__asm__ __volatile__ (  "rdtsc" \
-				:"=a" (((unsigned long*)&x)[0]),  \
-				 "=d" (((unsigned long*)&x)[1]))
-
 /*
  * The timer chip is already set up at HZ interrupts per second here,
  * but we do not accept timer interrupts yet. We only allow the BP
@@ -1937,7 +1937,7 @@
 	/*
 	 * We wrapped around just now. Let's start:
 	 */
-	RDTSC(t1);
+	READ_TSC(t1);
 	tt1=apic_read(APIC_TMCCT);
 
 #define LOOPS (HZ/10)
@@ -1948,7 +1948,7 @@
 		wait_8254_wraparound ();
 
 	tt2=apic_read(APIC_TMCCT);
-	RDTSC(t2);
+	READ_TSC(t2);
 
 	/*
 	 * The APIC bus clock counter is 32 bits only, it
diff -u --recursive --new-file v2.2.1/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.2.1/linux/arch/m68k/config.in	Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/config.in	Mon Feb  1 12:03:20 1999
@@ -346,13 +346,13 @@
 source fs/Config.in
 
 if [ "$CONFIG_VME" = "n" ]; then
+  mainmenu_option next_comment
+  comment 'Console drivers'
   if [ "$CONFIG_HP300" = "y" ]; then
     bool 'Frame buffer support' CONFIG_FB
   else
     define_bool CONFIG_FB y
   fi
-  mainmenu_option next_comment
-  comment 'Console drivers'
   source drivers/video/Config.in
   endmenu
 fi
diff -u --recursive --new-file v2.2.1/linux/arch/mips/config.in linux/arch/mips/config.in
--- v2.2.1/linux/arch/mips/config.in	Tue Jan 19 11:32:51 1999
+++ linux/arch/mips/config.in	Mon Feb  1 12:03:20 1999
@@ -179,7 +179,7 @@
 	endmenu
 
 	mainmenu_option next_comment
-	comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
+	comment 'Old CD-ROM drivers (not SCSI, not IDE)'
 
 	bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
 	if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
diff -u --recursive --new-file v2.2.1/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.2.1/linux/arch/ppc/config.in	Tue Jan 19 11:32:51 1999
+++ linux/arch/ppc/config.in	Mon Feb  1 12:03:20 1999
@@ -152,7 +152,7 @@
 endmenu
 
 mainmenu_option next_comment
-comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
+comment 'Old CD-ROM drivers (not SCSI, not IDE)'
 
 bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
 if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
diff -u --recursive --new-file v2.2.1/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.2.1/linux/drivers/block/genhd.c	Wed Jan 13 15:00:41 1999
+++ linux/drivers/block/genhd.c	Mon Feb  1 17:25:53 1999
@@ -130,6 +130,14 @@
 		SYS_IND(p) == LINUX_EXTENDED_PARTITION);
 }
 
+static int sector_partition_scale(kdev_t dev)
+{
+       if (hardsect_size[MAJOR(dev)] != NULL)
+               return (hardsect_size[MAJOR(dev)][MINOR(dev)]/512);
+       else
+               return (1);
+}
+
 static unsigned int get_ptable_blocksize(kdev_t dev)
 {
   int ret = 1024;
@@ -149,6 +157,7 @@
    * the natural blocksize for the device so that we don't have to try
    * and read partial sectors.  Anything smaller should be just fine.
    */
+
   switch( blksize_size[MAJOR(dev)][MINOR(dev)] )
     {
     case 2048:
@@ -196,6 +205,7 @@
 	struct partition *p;
 	unsigned long first_sector, first_size, this_sector, this_size;
 	int mask = (1 << hd->minor_shift) - 1;
+	int sector_size = sector_partition_scale(dev);
 	int i;
 
 	first_sector = hd->part[MINOR(dev)].start_sect;
@@ -233,22 +243,22 @@
 		 * First process the data partition(s)
 		 */
 		for (i=0; i<4; i++, p++) {
-		    if (!NR_SECTS(p) || is_extended_partition(p))
-		      continue;
+			if (!NR_SECTS(p) || is_extended_partition(p))
+				continue;
 
-		    /* Check the 3rd and 4th entries -
-		       these sometimes contain random garbage */
-		    if (i >= 2
-			&& START_SECT(p) + NR_SECTS(p) > this_size
-			&& (this_sector + START_SECT(p) < first_sector ||
-			    this_sector + START_SECT(p) + NR_SECTS(p) >
-			     first_sector + first_size))
-		      continue;
-
-		    add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
-		    current_minor++;
-		    if ((current_minor & mask) == 0)
-		      goto done;
+			/* Check the 3rd and 4th entries -
+			   these sometimes contain random garbage */
+			if (i >= 2
+				&& START_SECT(p) + NR_SECTS(p) > this_size
+				&& (this_sector + START_SECT(p) < first_sector ||
+				    this_sector + START_SECT(p) + NR_SECTS(p) >
+				     first_sector + first_size))
+				continue;
+
+			add_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
+			current_minor++;
+			if ((current_minor & mask) == 0)
+				goto done;
 		}
 		/*
 		 * Next, process the (first) extended partition, if present.
@@ -262,20 +272,21 @@
 		 */
 		p -= 4;
 		for (i=0; i<4; i++, p++)
-		  if(NR_SECTS(p) && is_extended_partition(p))
-		    break;
+			if(NR_SECTS(p) && is_extended_partition(p))
+				break;
 		if (i == 4)
-		  goto done;	 /* nothing left to do */
+			goto done;	 /* nothing left to do */
 
-		hd->part[current_minor].nr_sects = NR_SECTS(p);
-		hd->part[current_minor].start_sect = first_sector + START_SECT(p);
-		this_sector = first_sector + START_SECT(p);
+		hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; /* JSt */
+		hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
+		this_sector = first_sector + START_SECT(p) * sector_size;
 		dev = MKDEV(hd->major, current_minor);
 		brelse(bh);
 	}
 done:
 	brelse(bh);
 }
+
 #ifdef CONFIG_SOLARIS_X86_PARTITION
 static void
 solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) {
@@ -317,11 +328,13 @@
 #endif
 
 #ifdef CONFIG_BSD_DISKLABEL
-static void check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p)
+static void check_and_add_bsd_partition(struct gendisk *hd,
+					struct bsd_partition *bsd_p, kdev_t dev)
 {
 	struct hd_struct *lin_p;
 		/* check relative position of partitions.  */
-	for (lin_p = hd->part + 1; lin_p - hd->part < current_minor; lin_p++) {
+	for (lin_p = hd->part + 1 + MINOR(dev);
+	     lin_p - hd->part - MINOR(dev) < current_minor; lin_p++) {
 			/* no relationship -> try again */
 		if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset 
 			|| lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size)
@@ -383,7 +396,7 @@
 			break;
 
 		if (p->p_fstype != BSD_FS_UNUSED) 
-			check_and_add_bsd_partition(hd, p);
+			check_and_add_bsd_partition(hd, p, dev);
 	}
 	brelse(bh);
 
@@ -436,6 +449,7 @@
 	struct partition *p;
 	unsigned char *data;
 	int mask = (1 << hd->minor_shift) - 1;
+	int sector_size = sector_partition_scale(dev);
 #ifdef CONFIG_BSD_DISKLABEL
 	/* no bsd disklabel as a default */
 	kdev_t bsd_kdev = 0;
@@ -538,7 +552,7 @@
 	for (i=1 ; i<=4 ; minor++,i++,p++) {
 		if (!NR_SECTS(p))
 			continue;
-		add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
+               add_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
 		if (is_extended_partition(p)) {
 			printk(" <");
 			/*
@@ -790,7 +804,7 @@
 	struct sgi_partition *p;
 #define SGI_LABEL_MAGIC 0x0be5a941
 
-	if(!(bh = bread(dev, 0, 1024))) {
+	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
 		printk("Dev %s: unable to read partition table\n", kdevname(dev));
 		return -1;
 	}
@@ -854,11 +868,18 @@
 	int			 blk;
 	int			 part, res;
 
+	/*
+	 *	Don't bother touching M/O 2K media.
+	 */
+	 
+	if (get_ptable_blocksize(dev) != 1024)
+		return 0;
+		
 	set_blocksize(dev,512);
 	res = 0;
 
 	for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
-		if(!(bh = bread(dev,blk,512))) {
+		if(!(bh = bread(dev,blk,get_ptable_blocksize(dev)))) {
 			printk("Dev %s: unable to read RDB block %d\n",
 			       kdevname(dev),blk);
 			goto rdb_done;
@@ -875,7 +896,7 @@
 			blk = htonl(rdb->rdb_PartitionList);
 			brelse(bh);
 			for (part = 1; blk > 0 && part <= 16; part++) {
-				if (!(bh = bread(dev,blk,512))) {
+				if (!(bh = bread(dev,blk, get_ptable_blocksize(dev)))) {
 					printk("Dev %s: unable to read partition block %d\n",
 						       kdevname(dev),blk);
 					goto rdb_done;
@@ -908,6 +929,10 @@
 	}
 
 rdb_done:
+	/*
+	 *	FIXME: should restore the original size. Then we could clean
+	 *	up the M/O skip. Amiga people ?
+	 */
 	set_blocksize(dev,BLOCK_SIZE);
 	return res;
 }
@@ -1089,7 +1114,7 @@
 	      partsect = extensect = pi->st;
 	      while (1)
 		{
-		  xbh = bread (dev, partsect / 2, 1024);
+		  xbh = bread (dev, partsect / 2, get_ptable_blocksize(dev));
 		  if (!xbh)
 		    {
 		      printk (" block %ld read failed\n", partsect);
diff -u --recursive --new-file v2.2.1/linux/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c
--- v2.2.1/linux/drivers/block/ide-disk.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/block/ide-disk.c	Sat Jan 30 10:06:14 1999
@@ -101,20 +101,6 @@
 		id->cyls = lba_sects / (16 * 63); /* correct cyls */
 		return 1;	/* lba_capacity is our only option */
 	}
-	/*
-	 * This is a split test for drives less than 8 Gig only.
-	 * Drives less than 8GB sometimes declare that they have 15 heads.
-	 * This is an accounting trick (0-15) == (1-16), just an initial
-	 * zero point difference.
-	 */
-	if ((id->lba_capacity < 16514064) && (lba_sects > chs_sects) &&
-	    ((id->heads == 15) || (id->heads == 16)) && (id->sectors == 63)) {
-		if (id->heads == 15)
-			id->cyls = lba_sects / (15 * 63); /* correct cyls */
-		if (id->heads == 16)
-			id->cyls = lba_sects / (16 * 63); /* correct cyls */
-		return 1;	/* lba_capacity is our only option */
-	}
 	/* perform a rough sanity check on lba_sects:  within 10% is "okay" */
 	if ((lba_sects - chs_sects) < _10_percent) {
 		return 1;	/* lba_capacity is good */
diff -u --recursive --new-file v2.2.1/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c
--- v2.2.1/linux/drivers/block/ide-probe.c	Thu Jan  7 15:11:36 1999
+++ linux/drivers/block/ide-probe.c	Sat Feb  6 12:46:20 1999
@@ -124,6 +124,10 @@
 			case ide_tape:
 				printk ("TAPE");
 				break;
+			case ide_optical:
+				printk ("OPTICAL");
+				drive->removable = 1;
+				break;
 			default:
 				printk("UNKNOWN (type %d)", type);
 				break;
@@ -720,17 +724,39 @@
 	}
 	if (register_blkdev (hwif->major, hwif->name, ide_fops)) {
 		printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major);
-	} else if (init_irq (hwif)) {
-		printk("%s: UNABLE TO GET IRQ %d\n", hwif->name, hwif->irq);
-		(void) unregister_blkdev (hwif->major, hwif->name);
-	} else {
-		init_gendisk(hwif);
-		blk_dev[hwif->major].data = hwif;
-		blk_dev[hwif->major].request_fn = rfn;
-		blk_dev[hwif->major].queue = ide_get_queue;
-		read_ahead[hwif->major] = 8;	/* (4kB) */
-		hwif->present = 1;	/* success */
+		return (hwif->present = 0);
 	}
+	
+	if (init_irq (hwif)) {
+		int i = hwif->irq;
+		/*
+		 *	It failed to initialise. Find the default IRQ for 
+		 *	this port and try that.
+		 */
+		if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) 
+		{
+			printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i);
+			(void) unregister_blkdev (hwif->major, hwif->name);
+			return (hwif->present = 0);
+		}
+		if(init_irq (hwif)) 
+		{
+			printk("%s: probed IRQ %d and default IRQ %d failed.\n",
+				hwif->name, i, hwif->irq);
+			(void) unregister_blkdev (hwif->major, hwif->name);
+			return (hwif->present = 0);
+		}
+		printk("%s: probed IRQ %d failed, using default.\n",
+			hwif->name, hwif->irq);
+	}
+	
+	init_gendisk(hwif);
+	blk_dev[hwif->major].data = hwif;
+	blk_dev[hwif->major].request_fn = rfn;
+	blk_dev[hwif->major].queue = ide_get_queue;
+	read_ahead[hwif->major] = 8;	/* (4kB) */
+	hwif->present = 1;	/* success */
+
 #if (DEBUG_SPINLOCK > 0)
 {
 	static int done = 0;
diff -u --recursive --new-file v2.2.1/linux/drivers/block/ide.h linux/drivers/block/ide.h
--- v2.2.1/linux/drivers/block/ide.h	Thu Dec 31 10:28:59 1998
+++ linux/drivers/block/ide.h	Mon Feb  8 15:27:26 1999
@@ -182,6 +182,7 @@
 
 #define ide_scsi	0x21
 #define ide_disk	0x20
+#define ide_optical	0x7
 #define ide_cdrom	0x5
 #define ide_tape	0x1
 #define ide_floppy	0x0
diff -u --recursive --new-file v2.2.1/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.2.1/linux/drivers/char/bttv.c	Mon Jan 25 17:44:34 1999
+++ linux/drivers/char/bttv.c	Sat Feb  6 12:46:20 1999
@@ -537,6 +537,8 @@
 	{ 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
         /* Aimslab VHX */
         { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
+        /* Zoltrix TV-Max */
+        { 3, 1, 0, 2,15, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
 };
 #define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
 
@@ -2880,9 +2882,6 @@
 
 		} else if (I2CRead(&(btv->i2c), I2C_STBEE)>=0) {
 			btv->type=BTTV_STB;
-		} else 
-		        if (I2CRead(&(btv->i2c), I2C_VHX)>=0) {
-			        btv->type=BTTV_VHX;
 		} else {
 			if (I2CRead(&(btv->i2c), 0x80)>=0) /* check for msp34xx */
 				btv->type = BTTV_MIROPRO;
@@ -2907,8 +2906,8 @@
         }
         if(btv->type==BTTV_AVERMEDIA98)
         {
-          btv->pll.pll_ifreq=28636363;
-          btv->pll.pll_crystal=BT848_IFORM_XT0;
+        	btv->pll.pll_ifreq=28636363;
+        	btv->pll.pll_crystal=BT848_IFORM_XT0;
         }
           
 	if (btv->have_tuner && btv->tuner_type != -1) 
diff -u --recursive --new-file v2.2.1/linux/drivers/char/bttv.h linux/drivers/char/bttv.h
--- v2.2.1/linux/drivers/char/bttv.h	Mon Jan 25 17:44:34 1999
+++ linux/drivers/char/bttv.h	Mon Feb  1 14:04:42 1999
@@ -206,7 +206,8 @@
 #define BTTV_MIROPRO       0x0b
 #define BTTV_ADSTECH_TV    0x0c
 #define BTTV_AVERMEDIA98   0x0d
-#define BTTV_VHX   	   0x0e
+#define BTTV_VHX           0x0e
+#define BTTV_ZOLTRIX       0x0f
 
 #define AUDIO_TUNER        0x00
 #define AUDIO_RADIO        0x01
diff -u --recursive --new-file v2.2.1/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.2.1/linux/drivers/char/pc_keyb.c	Mon Jan 25 17:44:34 1999
+++ linux/drivers/char/pc_keyb.c	Sun Feb  7 00:23:04 1999
@@ -10,6 +10,9 @@
  * because they share the same hardware.
  * Johan Myreen <jem@iki.fi> 1998-10-08.
  *
+ * Code fixes to handle mouse ACKs properly.
+ * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
+ *
  */
 
 #include <linux/config.h>
@@ -74,6 +77,8 @@
 
 static struct aux_queue *queue;	/* Mouse data buffer. */
 static int aux_count = 0;
+/* used when we send commands to the mouse that expect an ACK. */
+static unsigned char mouse_reply_expected = 0;
 
 #define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
 #define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
@@ -99,7 +104,7 @@
  * Controller Status register are set 0."
  */
 
-static inline void kb_wait(void)
+static void kb_wait(void)
 {
 	unsigned long timeout = KBC_TIMEOUT;
 
@@ -400,6 +405,33 @@
 	    return 0200;
 }
 
+static inline void handle_mouse_event(unsigned char scancode)
+{
+#ifdef CONFIG_PSMOUSE
+	if (mouse_reply_expected) {
+		if (scancode == AUX_ACK) {
+			mouse_reply_expected--;
+			return;
+		}
+		mouse_reply_expected = 0;
+	}
+
+	add_mouse_randomness(scancode);
+	if (aux_count) {
+		int head = queue->head;
+
+		queue->buf[head] = scancode;
+		head = (head + 1) & (AUX_BUF_SIZE-1);
+		if (head != queue->tail) {
+			queue->head = head;
+			if (queue->fasync)
+				kill_fasync(queue->fasync, SIGIO);
+			wake_up_interruptible(&queue->proc_list);
+		}
+	}
+#endif
+}
+
 /*
  * This reads the keyboard status port, and does the
  * appropriate action.
@@ -417,21 +449,7 @@
 		scancode = inb(KBD_DATA_REG);
 
 		if (status & KBD_STAT_MOUSE_OBF) {
-#ifdef CONFIG_PSMOUSE
-			/* Mouse data. */
-			if (aux_count) {
-				int head = queue->head;
-				queue->buf[head] = scancode;
-				add_mouse_randomness(scancode);
-				head = (head + 1) & (AUX_BUF_SIZE-1);
-				if (head != queue->tail) {
-					queue->head = head;
-					if (queue->fasync)
-						kill_fasync(queue->fasync, SIGIO);
-					wake_up_interruptible(&queue->proc_list);
-				}
-			}
-#endif
+			handle_mouse_event(scancode);
 		} else {
 			if (do_acknowledge(scancode))
 				handle_scancode(scancode);
@@ -716,9 +734,7 @@
 static int __init detect_auxiliary_port(void)
 {
 	unsigned long flags;
-	unsigned char status;
-	unsigned char val;
-	int loops = 5;
+	int loops = 10;
 	int retval = 0;
 
 	spin_lock_irqsave(&kbd_controller_lock, flags);
@@ -736,20 +752,19 @@
 	kb_wait();
 	outb(0x5a, KBD_DATA_REG); /* 0x5a is a random dummy value. */
 
-	status = inb(KBD_STATUS_REG);
-	while (!(status & KBD_STAT_OBF) && loops--) {
-		mdelay(1);
-		status = inb(KBD_STATUS_REG);
-	}
+	do {
+		unsigned char status = inb(KBD_STATUS_REG);
 
-	if (status & KBD_STAT_OBF) {
-		val = inb(KBD_DATA_REG);
-		if (status & KBD_STAT_MOUSE_OBF) {
-			printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
-			retval = 1;
+		if (status & KBD_STAT_OBF) {
+			(void) inb(KBD_DATA_REG);
+			if (status & KBD_STAT_MOUSE_OBF) {
+				printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
+				retval = 1;
+			}
+			break;
 		}
-	}
-
+		mdelay(1);
+	} while (--loops);
 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
 
 	return retval;
@@ -770,16 +785,33 @@
 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
 }
 
-static unsigned int get_from_queue(void)
+/*
+ * Send a byte to the mouse & handle returned ack
+ */
+static void aux_write_ack(int val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	kb_wait();
+	outb(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG);
+	kb_wait();
+	outb(val, KBD_DATA_REG);
+	/* we expect an ACK in response. */
+	mouse_reply_expected++;
+	kb_wait();
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+}
+
+static unsigned char get_from_queue(void)
 {
-	unsigned int result;
+	unsigned char result;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&kbd_controller_lock, flags);
 	result = queue->buf[queue->tail];
 	queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
 	return result;
 }
 
@@ -834,7 +866,7 @@
 	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE);	/* Enable the
 							   auxiliary port on
 							   controller. */
-	aux_write_dev(AUX_ENABLE_DEV); /* Enable aux device */
+	aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
 	kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
 
 	return 0;
@@ -951,11 +983,11 @@
 
 #ifdef INITIALIZE_MOUSE
 	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE);	/* Enable Aux. */
-	aux_write_dev(AUX_SET_SAMPLE);
-	aux_write_dev(100);			/* 100 samples/sec */
-	aux_write_dev(AUX_SET_RES);
-	aux_write_dev(3);			/* 8 counts per mm */
-	aux_write_dev(AUX_SET_SCALE21);		/* 2:1 scaling */
+	aux_write_ack(AUX_SET_SAMPLE);
+	aux_write_ack(100);			/* 100 samples/sec */
+	aux_write_ack(AUX_SET_RES);
+	aux_write_ack(3);			/* 8 counts per mm */
+	aux_write_ack(AUX_SET_SCALE21);		/* 2:1 scaling */
 #endif /* INITIALIZE_MOUSE */
 	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
 	kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
diff -u --recursive --new-file v2.2.1/linux/drivers/char/pc_keyb.h linux/drivers/char/pc_keyb.h
--- v2.2.1/linux/drivers/char/pc_keyb.h	Tue Jan 19 11:32:51 1999
+++ linux/drivers/char/pc_keyb.h	Sat Feb  6 12:46:20 1999
@@ -114,8 +114,12 @@
 #define AUX_ENABLE_DEV		0xF4	/* Enable aux device */
 #define AUX_DISABLE_DEV		0xF5	/* Disable aux device */
 #define AUX_RESET		0xFF	/* Reset aux device */
+#define AUX_ACK			0xFA	/* Command byte ACK. */
 
-#define AUX_BUF_SIZE		2048
+#define AUX_BUF_SIZE		2048	/* This might be better divisible by
+					   three to make overruns stay in sync
+					   but then the read function would need
+					   a lock etc - ick */
 
 struct aux_queue {
 	unsigned long head;
diff -u --recursive --new-file v2.2.1/linux/drivers/char/pty.c linux/drivers/char/pty.c
--- v2.2.1/linux/drivers/char/pty.c	Mon Oct  5 13:13:39 1998
+++ linux/drivers/char/pty.c	Sat Feb  6 17:28:37 1999
@@ -84,7 +84,6 @@
 	wake_up_interruptible(&tty->link->write_wait);
 	set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
 	if (tty->driver.subtype == PTY_TYPE_MASTER) {
-		tty_hangup(tty->link);
 		set_bit(TTY_OTHER_CLOSED, &tty->flags);
 #ifdef CONFIG_UNIX98_PTYS
 		{
@@ -95,6 +94,7 @@
 			}
 		}
 #endif
+		tty_vhangup(tty->link);
 	}
 }
 
diff -u --recursive --new-file v2.2.1/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v2.2.1/linux/drivers/char/vt.c	Wed Jan 13 15:00:41 1999
+++ linux/drivers/char/vt.c	Wed Feb  3 22:57:41 1999
@@ -165,7 +165,7 @@
 			val = K_HOLE;
 		} else
 		    val = (i ? K_HOLE : K_NOSUCHMAP);
-		return __put_user(val, &user_kbe->kb_value);
+		return put_user(val, &user_kbe->kb_value);
 	case KDSKBENT:
 		if (!perm)
 			return -EPERM;
@@ -244,7 +244,7 @@
 	case KDGETKEYCODE:
 		kc = getkeycode(tmp.scancode);
 		if (kc >= 0)
-			kc = __put_user(kc, &user_kbkc->keycode);
+			kc = put_user(kc, &user_kbkc->keycode);
 		break;
 	case KDSETKEYCODE:
 		if (!perm)
@@ -282,8 +282,8 @@
 		p = func_table[i];
 		if(p)
 			for ( ; *p && sz; p++, sz--)
-				__put_user(*p, q++);
-		__put_user('\0', q);
+				put_user(*p, q++);
+		put_user('\0', q);
 		return ((p && *p) ? -EOVERFLOW : 0);
 	case KDSKBSENT:
 		if (!perm)
@@ -603,12 +603,10 @@
 	{
 		struct kbdiacrs *a = (struct kbdiacrs *)arg;
 
-		i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
-		if (i)
-			return i;
-		__put_user(accent_table_size, &a->kb_cnt);
-		__copy_to_user(a->kbdiacr, accent_table,
-			    accent_table_size*sizeof(struct kbdiacr));
+		if (put_user(accent_table_size, &a->kb_cnt))
+			return -EFAULT;
+		if (copy_to_user(a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr)))
+			return -EFAULT;
 		return 0;
 	}
 
@@ -619,14 +617,13 @@
 
 		if (!perm)
 			return -EPERM;
-		i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
-		if (i)
-			return i;
-		__get_user(ct,&a->kb_cnt);
+		if (get_user(ct,&a->kb_cnt))
+			return -EFAULT;
 		if (ct >= MAX_DIACR)
 			return -EINVAL;
 		accent_table_size = ct;
-		__copy_from_user(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
+		if (copy_from_user(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr)))
+			return -EFAULT;
 		return 0;
 	}
 
@@ -717,12 +714,12 @@
 		i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
 		if (i)
 			return i;
-		__put_user(fg_console + 1, &vtstat->v_active);
+		put_user(fg_console + 1, &vtstat->v_active);
 		state = 1;	/* /dev/tty0 is always open */
 		for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
 			if (VT_IS_IN_USE(i))
 				state |= mask;
-		return __put_user(state, &vtstat->v_state);
+		return put_user(state, &vtstat->v_state);
 	}
 
 	/*
@@ -856,8 +853,8 @@
 		i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
 		if (i)
 			return i;
-		__get_user(ll, &vtsizes->v_rows);
-		__get_user(cc, &vtsizes->v_cols);
+		get_user(ll, &vtsizes->v_rows);
+		get_user(cc, &vtsizes->v_cols);
 		return vc_resize_all(ll, cc);
 	}
 
@@ -870,12 +867,12 @@
 		i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize));
 		if (i)
 			return i;
-		__get_user(ll, &vtconsize->v_rows);
-		__get_user(cc, &vtconsize->v_cols);
-		__get_user(vlin, &vtconsize->v_vlin);
-		__get_user(clin, &vtconsize->v_clin);
-		__get_user(vcol, &vtconsize->v_vcol);
-		__get_user(ccol, &vtconsize->v_ccol);
+		get_user(ll, &vtconsize->v_rows);
+		get_user(cc, &vtconsize->v_cols);
+		get_user(vlin, &vtconsize->v_vlin);
+		get_user(clin, &vtconsize->v_clin);
+		get_user(vcol, &vtconsize->v_vcol);
+		get_user(ccol, &vtconsize->v_ccol);
 		vlin = vlin ? vlin : video_scan_lines;
 		if ( clin )
 		  {
diff -u --recursive --new-file v2.2.1/linux/drivers/net/defxx.c linux/drivers/net/defxx.c
--- v2.2.1/linux/drivers/net/defxx.c	Fri May  8 23:14:48 1998
+++ linux/drivers/net/defxx.c	Sat Feb  6 12:46:21 1999
@@ -2881,6 +2881,22 @@
 	return(DFX_K_SUCCESS);
 	}
 
+
+/*
+ *	Align an sk_buff to a boundary power of 2
+ *
+ */
+ 
+void my_skb_align(struct sk_buff *skb, int n)
+{
+	u32 x=(u32)skb->data;	/* We only want the low bits .. */
+	u32 v;
+	
+	v=(x+n-1)&~(n-1);	/* Where we want to be */
+	
+	skb_reserve(skb, v-x);
+}
+
 
 /*
  * ================
@@ -2950,8 +2966,8 @@
 			 * align to 128 bytes for compatibility with
 			 * the old EISA boards.
 			 */
-			newskb->data = (char *)((unsigned long)
-						(newskb->data+127) & ~127);
+			 
+			my_skb_align(newskb,128);
 			bp->descr_block_virt->rcv_data[i+j].long_1 = virt_to_bus(newskb->data);
 			/*
 			 * p_rcv_buff_va is only used inside the
@@ -3062,10 +3078,10 @@
 					newskb = dev_alloc_skb(NEW_SKB_SIZE);
 					if (newskb){
 						rx_in_place = 1;
-
-						newskb->data = (char *)((unsigned long)(newskb->data+127) & ~127);
+						
+						my_skb_align(newskb, 128);
 						skb = (struct sk_buff *)bp->p_rcv_buff_va[entry];
-						skb->data += RCV_BUFF_K_PADDING;
+						skb_reserve(skb, RCV_BUFF_K_PADDING);
 						bp->p_rcv_buff_va[entry] = (char *)newskb;
 						bp->descr_block_virt->rcv_data[entry].long_1 = virt_to_bus(newskb->data);
 					} else
@@ -3088,9 +3104,9 @@
 
 						memcpy(skb->data, p_buff + RCV_BUFF_K_PADDING, pkt_len+3);
 					}
-
-					skb->data += 3;			/* adjust data field so that it points to FC byte */
-					skb->len = pkt_len;		/* pass up packet length, NOT including CRC */
+					
+					skb_reserve(skb,3);		/* adjust data field so that it points to FC byte */
+					skb_put(skb, pkt_len);		/* pass up packet length, NOT including CRC */
 					skb->dev = bp->dev;		/* pass up device pointer */
 
 					skb->protocol = fddi_type_trans(skb, bp->dev);
diff -u --recursive --new-file v2.2.1/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- v2.2.1/linux/drivers/net/eepro100.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/net/eepro100.c	Sat Feb  6 12:46:21 1999
@@ -842,9 +842,6 @@
 
 	wait_for_cmd_done(ioaddr + SCBCmd);
 	outw(CU_DUMPSTATS, ioaddr + SCBCmd);
-	/* No need to wait for the command unit to accept here. */
-	if ((sp->phy[0] & 0x8000) == 0)
-		mdio_read(ioaddr, sp->phy[0] & 0x1f, 0);
 
 	/*
 	 * Request the IRQ last, after we have set up all data structures.
@@ -854,6 +851,10 @@
 					"Intel EtherExpress Pro 10/100 Ethernet", dev)) {
 		return -EAGAIN;
 	}
+
+	/* No need to wait for the command unit to accept here. */
+	if ((sp->phy[0] & 0x8000) == 0)
+		mdio_read(ioaddr, sp->phy[0] & 0x1f, 0);
 
 	MOD_INC_USE_COUNT;
 
diff -u --recursive --new-file v2.2.1/linux/drivers/net/hamradio/baycom_epp.c linux/drivers/net/hamradio/baycom_epp.c
--- v2.2.1/linux/drivers/net/hamradio/baycom_epp.c	Fri Nov 27 13:09:24 1998
+++ linux/drivers/net/hamradio/baycom_epp.c	Mon Feb  1 10:41:47 1999
@@ -1075,6 +1075,7 @@
 	if (!(pp->modes & (PARPORT_MODE_PCECPEPP|PARPORT_MODE_PCEPP))) {
                 printk(KERN_ERR "%s: parport at 0x%lx does not support any EPP mode\n",
 		       bc_drvname, pp->base);
+		parport_release(bc->pdev);
                 parport_unregister_device(bc->pdev);
                 return -EIO;		
 	}
diff -u --recursive --new-file v2.2.1/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- v2.2.1/linux/drivers/net/smc-ultra.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/net/smc-ultra.c	Sat Feb  6 12:46:21 1999
@@ -440,6 +440,8 @@
 MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i");
 MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i");
 
+EXPORT_NO_SYMBOLS;
+
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
 int
diff -u --recursive --new-file v2.2.1/linux/drivers/net/syncppp.c linux/drivers/net/syncppp.c
--- v2.2.1/linux/drivers/net/syncppp.c	Fri Nov 27 13:09:24 1998
+++ linux/drivers/net/syncppp.c	Sat Feb  6 12:46:21 1999
@@ -380,6 +380,7 @@
 			if_down (dev);
 			if (! (sp->pp_flags & PP_CISCO)) {
 				/* Shut down the PPP link. */
+				sp->lcp.magic = jiffies;
 				sp->lcp.state = LCP_STATE_CLOSED;
 				sp->ipcp.state = IPCP_STATE_CLOSED;
 				sppp_clear_timeout (sp);
@@ -841,6 +842,25 @@
 }
 
 EXPORT_SYMBOL(sppp_open);
+
+int sppp_reopen (struct device *dev)
+{
+	struct sppp *sp = &((struct ppp_device *)dev)->sppp;
+	sppp_close(dev);
+	dev->flags |= IFF_RUNNING;
+	if (!(sp->pp_flags & PP_CISCO))
+	{
+		sp->lcp.magic = jiffies;
+		++sp->pp_seq;
+		sp->lcp.state = LCP_STATE_CLOSED;
+		sp->ipcp.state = IPCP_STATE_CLOSED;
+		/* Give it a moment for the line to settle then go */
+		sppp_set_timeout (sp, 1);
+	}
+	return 0;
+}
+
+EXPORT_SYMBOL(sppp_reopen);
 
 int sppp_change_mtu(struct device *dev, int new_mtu)
 {
diff -u --recursive --new-file v2.2.1/linux/drivers/net/syncppp.h linux/drivers/net/syncppp.h
--- v2.2.1/linux/drivers/net/syncppp.h	Fri Oct 23 22:01:21 1998
+++ linux/drivers/net/syncppp.h	Sat Feb  6 12:46:21 1999
@@ -80,6 +80,7 @@
 int sppp_isempty (struct device *dev);
 void sppp_flush (struct device *dev);
 int sppp_open (struct device *dev);
+int sppp_reopen (struct device *dev);
 int sppp_close (struct device *dev);
 #endif
 
diff -u --recursive --new-file v2.2.1/linux/drivers/net/tlan.c linux/drivers/net/tlan.c
--- v2.2.1/linux/drivers/net/tlan.c	Fri Jan  8 22:36:08 1999
+++ linux/drivers/net/tlan.c	Sat Feb  6 12:46:21 1999
@@ -29,6 +29,8 @@
  *
  *	Tigran Aivazian <tigran@sco.com>:	TLan_PciProbe() now uses
  *						new PCI BIOS interface.
+ *	Alan Cox	<alan@redhat.com>:	Fixed the out of memory
+ *						handling.
  *
  ********************************************************************/
 
@@ -1250,28 +1252,36 @@
 			netif_rx( skb );
 		}
 	} else {
-		skb = (struct sk_buff *) head_list->buffer[9].address;
-		head_list->buffer[9].address = 0;
-		skb_trim( skb, head_list->frameSize );
-
+		struct sk_buff *new_skb;
+		
+		/*
+		 *	I changed the algorithm here. What we now do
+		 *	is allocate the new frame. If this fails we
+		 *	simply recycle the frame.
+		 */
+		
+		new_skb = dev_alloc_skb( TLAN_MAX_FRAME_SIZE + 7 );
+		if ( new_skb != NULL ) {
+			/* If this ever happened it would be a problem */
+			/* not any more - ac */
+			skb = (struct sk_buff *) head_list->buffer[9].address;
+			head_list->buffer[9].address = 0;
+			skb_trim( skb, head_list->frameSize );
 #if LINUX_KERNEL_VERSION > 0x20100
 			priv->stats->rx_bytes += head_list->frameSize;
 #endif
 
-		skb->protocol = eth_type_trans( skb, dev );
-		netif_rx( skb );
-
-		skb = dev_alloc_skb( TLAN_MAX_FRAME_SIZE + 7 );
-		if ( skb == NULL ) {
-			printk( "TLAN:  Couldn't allocate memory for received data.\n" );
-			/* If this ever happened it would be a problem */
-		} else {
-			skb->dev = dev;
-			skb_reserve( skb, 2 );
-			t = (void *) skb_put( skb, TLAN_MAX_FRAME_SIZE );
+			skb->protocol = eth_type_trans( skb, dev );
+			netif_rx( skb );
+	
+			new_skb->dev = dev;
+			skb_reserve( new_skb, 2 );
+			t = (void *) skb_put( new_skb, TLAN_MAX_FRAME_SIZE );
 			head_list->buffer[0].address = virt_to_bus( t );
-			head_list->buffer[9].address = (u32) skb;
+			head_list->buffer[9].address = (u32) new_skb;
 		}
+		else
+			printk(KERN_WARNING "TLAN:  Couldn't allocate memory for received data.\n" );
 	}
 
 	head_list->forward = 0;
diff -u --recursive --new-file v2.2.1/linux/drivers/net/z85230.c linux/drivers/net/z85230.c
--- v2.2.1/linux/drivers/net/z85230.c	Fri Jan  8 22:36:08 1999
+++ linux/drivers/net/z85230.c	Sat Feb  6 12:46:21 1999
@@ -349,6 +349,7 @@
 	if(status&TxEOM)
 	{
 /*		printk("%s: Tx underrun.\n", chan->dev->name); */
+		chan->stats.tx_fifo_errors++;
 		write_zsctrl(chan, ERR_RES);
 		z8530_tx_done(chan);
 	}
@@ -359,6 +360,8 @@
 		{
 			printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
 			write_zsreg(chan, R3, chan->regs[3]|RxENABLE);
+			if(chan->netdevice)
+				sppp_reopen(chan->netdevice);
 		}
 		else
 		{
@@ -450,6 +453,8 @@
 		{
 			printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
 			write_zsreg(chan, R3, chan->regs[3]|RxENABLE);
+			if(chan->netdevice)
+				sppp_reopen(chan->netdevice);
 		}
 		else
 		{
@@ -1107,6 +1112,14 @@
 		{
 			flags=claim_dma_lock();
 			disable_dma(c->txdma);
+			/*
+			 *	Check if we crapped out.
+			 */
+			if(get_dma_residue(c->txdma))
+			{
+				c->stats.tx_dropped++;
+				c->stats.tx_fifo_errors++;
+			}
 			release_dma_lock(flags);
 		}
 		c->txcount=0;
@@ -1133,6 +1146,7 @@
 			set_dma_count(c->txdma, c->txcount);
 			enable_dma(c->txdma);
 			release_dma_lock(flags);
+			write_zsctrl(c, RES_EOM_L);
 			write_zsreg(c, R5, c->regs[R5]|TxENAB);
 		}
 		else
@@ -1173,6 +1187,8 @@
 	c->tx_skb=NULL;
 	z8530_tx_begin(c);
 	spin_unlock_irqrestore(&z8530_buffer_lock, flags);
+	c->stats.tx_packets++;
+	c->stats.tx_bytes+=skb->len;
 	dev_kfree_skb(skb);
 }
 
@@ -1255,11 +1271,16 @@
 		 
 		skb=dev_alloc_skb(ct);
 		if(skb==NULL)
-			printk("%s: Memory squeeze.\n", c->netdevice->name);
+		{
+			c->stats.rx_dropped++;
+			printk(KERN_WARNING "%s: Memory squeeze.\n", c->netdevice->name);
+		}
 		else
 		{
 			skb_put(skb, ct);
 			memcpy(skb->data, rxb, ct);
+			c->stats.rx_packets++;
+			c->stats.rx_bytes+=ct;
 		}
 		c->dma_ready=1;
 	}
@@ -1305,6 +1326,9 @@
 		{
 			skb_put(c->skb2,c->mtu);
 		}
+		c->stats.rx_packets++;
+		c->stats.rx_bytes+=ct;
+		
 	}
 	/*
 	 *	If we received a frame we must now process it.
@@ -1315,7 +1339,10 @@
 		c->rx_function(c,skb);
 	}
 	else
-		printk("Lost a frame\n");
+	{
+		c->stats.rx_dropped++;
+		printk(KERN_ERR "%s: Lost a frame\n", c->netdevice->name);
+	}
 }
 
 /*
diff -u --recursive --new-file v2.2.1/linux/drivers/scsi/atp870u.c linux/drivers/scsi/atp870u.c
--- v2.2.1/linux/drivers/scsi/atp870u.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/scsi/atp870u.c	Mon Feb  8 09:44:08 1999
@@ -1720,8 +1720,8 @@
     h=0;
     while ( devid[h] != 0 )
     {
-      pci_find_device(0x1191,devid[h],pdev);
-      if (pdev == NULL); {
+      pdev = pci_find_device(0x1191,devid[h],pdev);
+      if (pdev == NULL) {
 	  h++;
 	  index=0;
 	  continue;
diff -u --recursive --new-file v2.2.1/linux/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
--- v2.2.1/linux/drivers/scsi/ide-scsi.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/scsi/ide-scsi.c	Sat Feb  6 12:46:21 1999
@@ -23,8 +23,9 @@
  * Ver 0.6   Jan 27 98   Allow disabling of SCSI command translation layer
  *                        for access through /dev/sg.
  *                       Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation.
- * Ver 0.7   Dev 04 98   Ignore commands where lun != 0 to avoid multiple
+ * Ver 0.7   Dec 04 98   Ignore commands where lun != 0 to avoid multiple
  *                        detection of devices with CONFIG_SCSI_MULTI_LUN
+ * Ver 0.8   Feb 05 99   Optical media need translation too. 
  */
 
 #define IDESCSI_VERSION "0.6"
@@ -178,7 +179,7 @@
 
 	if (!test_bit(PC_TRANSFORM, &pc->flags))
 		return;
-	if (drive->media == ide_cdrom) {
+	if (drive->media == ide_cdrom || drive->media == ide_optical) {
 		if (c[0] == READ_6 || c[0] == WRITE_6) {
 			c[8] = c[4];		c[5] = c[3];		c[4] = c[2];
 			c[3] = c[1] & 0x1f;	c[2] = 0;		c[1] &= 0xe0;
@@ -217,7 +218,7 @@
 
 	if (!test_bit(PC_TRANSFORM, &pc->flags))
 		return;
-	if (drive->media == ide_cdrom) {
+	if (drive->media == ide_cdrom || drive->media == ide_optical) {
 		if (pc->c[0] == MODE_SENSE_10 && sc[0] == MODE_SENSE) {
 			scsi_buf[0] = atapi_buf[1];		/* Mode data length */
 			scsi_buf[1] = atapi_buf[2];		/* Medium type */
@@ -794,7 +795,7 @@
 
 int idescsi_reset (Scsi_Cmnd *cmd, unsigned int resetflags)
 {
-	return SCSI_RESET_PUNT;
+	return SCSI_RESET_SUCCESS;
 }
 
 int idescsi_bios (Disk *disk, kdev_t dev, int *parm)
diff -u --recursive --new-file v2.2.1/linux/drivers/scsi/imm.c linux/drivers/scsi/imm.c
--- v2.2.1/linux/drivers/scsi/imm.c	Wed Jan 13 15:00:42 1999
+++ linux/drivers/scsi/imm.c	Sun Feb 14 23:17:31 1999
@@ -1204,19 +1204,16 @@
 	    status = imm_out(host_no, &cmd[l << 1], 2);
 
 	if (!status) {
-	    imm_disconnect(host_no);
-	    imm_connect(host_no, CONNECT_EPP_MAYBE);
-	    w_dtr(ppb, 0x40);
-	    w_ctr(ppb, 0x08);
-	    udelay(30);
-	    w_ctr(ppb, 0x0c);
-	    udelay(1000);
-	    imm_disconnect(host_no);
-	    udelay(1000);
-	    if (imm_hosts[host_no].mode == IMM_EPP_32) {
-		imm_hosts[host_no].mode = old_mode;
-		goto second_pass;
-	    }
+            imm_disconnect(host_no);
+            imm_connect(host_no, CONNECT_EPP_MAYBE);
+            imm_reset_pulse(IMM_BASE(host_no));
+            udelay(1000);
+            imm_disconnect(host_no);
+            udelay(1000);
+            if (imm_hosts[host_no].mode == IMM_EPP_32) {
+                imm_hosts[host_no].mode = old_mode;
+                goto second_pass;
+            }
 	    printk("imm: Unable to establish communication, aborting driver load.\n");
 	    return 1;
 	}
diff -u --recursive --new-file v2.2.1/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.2.1/linux/drivers/scsi/ncr53c8xx.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/scsi/ncr53c8xx.c	Sun Feb 14 23:17:31 1999
@@ -9633,6 +9633,8 @@
 	base = pdev->base_address[1];
 	base_2 = pdev->base_address[2];
 	irq = pdev->irq;
+	if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
+		base_2 = pdev->base_address[3];
 #else
 	(void) pcibios_read_config_dword(bus, device_fn,
 					PCI_BASE_ADDRESS_0, &io_port);	
diff -u --recursive --new-file v2.2.1/linux/drivers/scsi/ppa.h linux/drivers/scsi/ppa.h
--- v2.2.1/linux/drivers/scsi/ppa.h	Fri Jan  8 22:36:10 1999
+++ linux/drivers/scsi/ppa.h	Mon Feb  8 15:27:42 1999
@@ -10,7 +10,7 @@
 #ifndef _PPA_H
 #define _PPA_H
 
-#define   PPA_VERSION   "2.03 (for Linux 2.0.0)"
+#define   PPA_VERSION   "2.03 (for Linux 2.2.x)"
 
 /* 
  * this driver has been hacked by Matteo Frigo (athena@theory.lcs.mit.edu)
diff -u --recursive --new-file v2.2.1/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c
--- v2.2.1/linux/drivers/scsi/scsi_error.c	Fri Jan  8 22:36:10 1999
+++ linux/drivers/scsi/scsi_error.c	Fri Jan 29 10:30:04 1999
@@ -1972,6 +1972,7 @@
 	     */
             SCSI_LOG_ERROR_RECOVERY(1,printk("Error handler sleeping\n"));
 	    down_interruptible (&sem);
+	    sem.owner = 0;
 
 	    if (signal_pending(current) )
 	      break;
diff -u --recursive --new-file v2.2.1/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.2.1/linux/drivers/scsi/sd.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/scsi/sd.c	Sat Feb  6 12:46:21 1999
@@ -708,14 +708,14 @@
      */
     if (rscsi_disks[dev].sector_size == 1024)
 	if((block & 1) || (SCpnt->request.nr_sectors & 1)) {
-	    printk("sd.c:Bad block number requested");
+	    printk("sd.c:Bad block number/count requested");
 	    SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
 	    goto repeat;
 	}
 
      if (rscsi_disks[dev].sector_size == 2048)
  	if((block & 3) || (SCpnt->request.nr_sectors & 3)) {
- 	    printk("sd.c:Bad block number requested");
+ 	    printk("sd.c:Bad block number/count requested");
  	    SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
  	    goto repeat;
  	}
diff -u --recursive --new-file v2.2.1/linux/drivers/sound/midi_synth.c linux/drivers/sound/midi_synth.c
--- v2.2.1/linux/drivers/sound/midi_synth.c	Thu May 14 19:47:42 1998
+++ linux/drivers/sound/midi_synth.c	Mon Feb  1 14:04:42 1999
@@ -12,6 +12,7 @@
  */
 /*
  * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed)
+ * Andrew Veliath  : fixed running status in MIDI input state machine
  */
 #include <linux/config.h>
 
@@ -196,13 +197,19 @@
 				      inc->m_left = len_tab[(data >> 4) - 8];
 				      inc->m_buf[0] = inc->m_prev_status = data;
 			      }
-		  } else if (inc->m_prev_status & 0x80)		/* Ignore if no previous status (yet) */
-		    {		/* Data byte (use running status) */
-			    inc->m_state = MST_DATA;
+		    } else if (inc->m_prev_status & 0x80) {
+			    /* Data byte (use running status) */
 			    inc->m_ptr = 2;
-			    inc->m_left = len_tab[(data >> 4) - 8] - 1;
-			    inc->m_buf[0] = inc->m_prev_status;
 			    inc->m_buf[1] = data;
+			    inc->m_buf[0] = inc->m_prev_status;
+			    inc->m_left = len_tab[(inc->m_buf[0] >> 4) - 8] - 1;
+			    if (inc->m_left > 0)
+				    inc->m_state = MST_DATA; /* Not done yet */
+			    else {
+				    inc->m_state = MST_INIT;
+				    do_midi_msg(dev, inc->m_buf, inc->m_ptr);
+				    inc->m_ptr = 0;
+			    }
 		    }
 		  break;	/* MST_INIT */
 
diff -u --recursive --new-file v2.2.1/linux/drivers/sound/sb.h linux/drivers/sound/sb.h
--- v2.2.1/linux/drivers/sound/sb.h	Tue Jan 19 11:32:52 1999
+++ linux/drivers/sound/sb.h	Mon Feb  1 14:04:42 1999
@@ -48,12 +48,6 @@
 #define MDL_ES1868MIDI	14	/* MIDI port of ESS1868 */
 #define MDL_AEDSP	15	/* Audio Excel DSP 16 */
 
-#define SUBMDL_ES1788	0x10	/* Subtype ES1788 for specific handling */
-#define SUBMDL_ES1868	0x11	/* Subtype ES1868 for specific handling */
-#define SUBMDL_ES1869	0x12	/* Subtype ES1869 for specific handling */
-#define SUBMDL_ES1878	0x13	/* Subtype ES1878 for specific handling */
-#define SUBMDL_ES1887	0x14	/* Subtype ES1887 for specific handling */
-#define SUBMDL_ES1888	0x14	/* Subtype ES1888 for specific handling */
 #define SUBMDL_ALS007	42	/* ALS-007 differs from SB16 only in mixer */
 				/* register assignment */
 #define SUBMDL_ALS100	43	/* ALS-100 allows sampling rates of up */
diff -u --recursive --new-file v2.2.1/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.2.1/linux/drivers/sound/sb_card.c	Thu Jan 28 12:58:02 1999
+++ linux/drivers/sound/sb_card.c	Mon Feb  1 14:04:42 1999
@@ -113,7 +113,7 @@
 }
 
 int sb_be_quiet=0;
-int esstype = 0;	/* ESS chip type */
+extern int esstype;	/* ESS chip type */
 
 #ifdef MODULE
 
@@ -130,13 +130,13 @@
 int io = -1;
 int irq = -1;
 int dma = -1;
-int dma16 = -1;	/* Set this for modules that need it */
-int type = 0;	/* Can set this to a specific card type */
-int mad16 = 0;	/* Set mad16=1 to load this as support for mad16 */
-int trix = 0;	/* Set trix=1 to load this as support for trix */
-int pas2 = 0;	/* Set pas2=1 to load this as support for pas2 */
+int dma16 = -1;		/* Set this for modules that need it */
+int type = 0;		/* Can set this to a specific card type */
+int mad16 = 0;		/* Set mad16=1 to load this as support for mad16 */
+int trix = 0;		/* Set trix=1 to load this as support for trix */
+int pas2 = 0;		/* Set pas2=1 to load this as support for pas2 */
 int sm_games = 0;	/* Mixer - see sb_mixer.c */
-int acer = 0;	/* Do acer notebook init */
+int acer = 0;		/* Do acer notebook init */
 
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
diff -u --recursive --new-file v2.2.1/linux/drivers/sound/sb_ess.c linux/drivers/sound/sb_ess.c
--- v2.2.1/linux/drivers/sound/sb_ess.c	Mon Jan 25 17:44:34 1999
+++ linux/drivers/sound/sb_ess.c	Sat Feb  6 12:46:21 1999
@@ -1,9 +1,38 @@
+#undef FKS_LOGGING
+#undef FKS_TEST
+
 /*
- * Created: 9-Jan-1999
+ * tabs should be 4 spaces, in vi(m): set tabstop=4
  *
  * TODO: 	consistency speed calculations!!
+ *			cleanup!
  * ????:	Did I break MIDI support?
  *
+ * History:
+ *
+ * Rolf Fokkens	(Dec 20 1998):	ES188x recording level support on a per
+ *								input basis.
+ *				(Dec 24 1998):	Recognition of ES1788, ES1887, ES1888,
+ *								ES1868, ES1869 and ES1878. Could be used for
+ *								specific handling in the future. All except
+ *								ES1887 and ES1888 and ES688 are handled like
+ *								ES1688.
+ *				(Dec 27 1998):	RECLEV for all (?) ES1688+ chips. ES188x now
+ *								have the "Dec 20" support + RECLEV
+ *				(Jan  2 1999):	Preparation for Full Duplex. This means
+ *								Audio 2 is now used for playback when dma16
+ *								is specified. The next step would be to use
+ *								Audio 1 and Audio 2 at the same time.
+ *				(Jan  9 1999):	Put all ESS stuff into sb_ess.[ch], this
+ *								includes both the ESS stuff that has been in
+ *								sb_*[ch] before I touched it and the ESS support
+ *								I added later
+ *				(Jan 23 1999):	Full Duplex seems to work. I wrote a small
+ *								test proggy which works OK. Haven't found
+ *								any applications to test it though. So why did
+ *								I bother to create it anyway?? :) Just for
+ *								fun.
+ *
  * This files contains ESS chip specifics. It's based on the existing ESS
  * handling as it resided in sb_common.c, sb_mixer.c and sb_audio.c. This
  * file adds features like:
@@ -19,27 +48,13 @@
  *
  * ESS detection isn't full proof (yet). If it fails an additional module
  * parameter esstype can be specified to be one of the following:
- * 688, 1688, 1868, 1869, 1788, 1887, 1888
- *
- * History:
- *
- * Rolf Fokkens	(Dec 20 1998):	ES188x recording level support on a per
- *								input basis.
- *				(Dec 24 1998):	Recognition of ES1788, ES1887, ES1888,
- *								ES1868, ES1869 and ES1878. Could be used for
- *								specific handling in the future. All except
- *								ES1887 and ES1888 and ES688 are handled like
- *								ES1688.
- *				(Dec 27 1998):	RECLEV for all (?) ES1688+ chips. ES188x now
- *								have the "Dec 20" support + RECLEV
- *				(jan  2 1999):	Preparation for Full Duplex. This means
- *								Audio 2 is now used for playback when dma16
- *								is specified. The next step would be to use
- *								Audio 1 and Audio 2 at the same time.
+ * -1, 0, 688, 1688, 1868, 1869, 1788, 1887, 1888
+ * -1 means: mimic 2.0 behaviour, 
+ *  0 means: auto detect.
+ *   others: explicitly specify chip
+ * -1 is default, cause auto detect still doesn't work.
  */
 
-#undef FKS_LOGGING
-
 /*
  * About the documentation
  *
@@ -156,13 +171,25 @@
  * ES1946	yes		This is a PCI chip; not handled by this driver
  */
 
+#include <linux/delay.h>
+
 #include "sound_config.h"
 #include "sb_mixer.h"
 #include "sb.h"
 
 #include "sb_ess.h"
 
-extern int esstype; /* module parameter in sb_card.c */
+#define ESSTYPE_LIKE20	-1		/* Mimic 2.0 behaviour					*/
+#define ESSTYPE_DETECT	0		/* Mimic 2.0 behaviour					*/
+
+int esstype = ESSTYPE_LIKE20; /* module parameter in sb_card.c */
+
+#define SUBMDL_ES1788	0x10	/* Subtype ES1788 for specific handling */
+#define SUBMDL_ES1868	0x11	/* Subtype ES1868 for specific handling */
+#define SUBMDL_ES1869	0x12	/* Subtype ES1869 for specific handling */
+#define SUBMDL_ES1878	0x13	/* Subtype ES1878 for specific handling */
+#define SUBMDL_ES1887	0x14	/* Subtype ES1887 for specific handling */
+#define SUBMDL_ES1888	0x15	/* Subtype ES1888 for specific handling */
 
 #ifdef FKS_LOGGING
 static void ess_show_mixerregs (sb_devc *devc);
@@ -370,45 +397,6 @@
 	}
 }
 
-#if 0
-static void ess_speed(sb_devc * devc)
-{
-	int divider;
-	unsigned char bits = 0;
-	int speed = devc->speed;
-
-	if (speed < 4000)
-		speed = 4000;
-	else if (speed > 48000)
-		speed = 48000;
-
-	if (speed > 22000)
-	{
-		bits = 0x80;
-		divider = 256 - (795500 + speed / 2) / speed;
-	}
-	else
-	{
-		divider = 128 - (397700 + speed / 2) / speed;
-	}
-
-	bits |= (unsigned char) divider;
-
-	ess_write (devc, 0xa1, bits);
-
-	/*
-	* Set filter divider register
-	*/
-
-	speed = (speed * 9) / 20;	/* Set filter roll-off to 90% of speed/2 */
-	divider = 256 - 7160000 / (speed * 82);
-
-	ess_write (devc, 0xa2, divider);
-
-	return;
-}
-#endif
-
 static int ess_audio_prepare_for_input(int dev, int bsize, int bcount)
 {
 	sb_devc *devc = audio_devs[dev]->devc;
@@ -931,6 +919,29 @@
 	return ess_common_set_irq_hw (devc);
 }
 
+#ifdef FKS_TEST
+
+/*
+ * FKS_test:
+ *	for ES1887: 00, 18, non wr bits: 0001 1000
+ *	for ES1868: 00, b8, non wr bits: 1011 1000
+ *	for ES1888: 00, f8, non wr bits: 1111 1000
+ *	for ES1688: 00, f8, non wr bits: 1111 1000
+ *	+   ES968
+ */
+
+static void FKS_test (sb_devc * devc)
+{
+	int val1, val2;
+	val1 = ess_getmixer (devc, 0x64);
+	ess_setmixer (devc, 0x64, ~val1);
+	val2 = ess_getmixer (devc, 0x64) ^ ~val1;
+	ess_setmixer (devc, 0x64, val1);
+	val1 ^= ess_getmixer (devc, 0x64);
+printk (KERN_INFO "FKS: FKS_test %02x, %02x\n", (val1 & 0x0ff), (val2 & 0x0ff));
+};
+#endif
+
 static unsigned int ess_identify (sb_devc * devc)
 {
 	unsigned int val;
@@ -1025,42 +1036,55 @@
 
 	if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) {
 		char *chip = NULL;
+		int submodel = -1;
 
-		if (esstype) {
-			int submodel = -1;
-
-			switch (esstype) {
-			case 688:
-				submodel = 0x00;
-				break;
-			case 1688:
-				submodel = 0x08;
-				break;
-			case 1868:
-				submodel = SUBMDL_ES1868;
-				break;
-			case 1869:
-				submodel = SUBMDL_ES1869;
-				break;
-			case 1788:
-				submodel = SUBMDL_ES1788;
-				break;
-			case 1887:
-				submodel = SUBMDL_ES1887;
-				break;
-			case 1888:
-				submodel = SUBMDL_ES1888;
-				break;
-			};
-			if (submodel != -1) {
-				devc->submodel = submodel;
-				sprintf (modelname, "ES%d", esstype);
-				chip = modelname;
-			};
+		switch (esstype) {
+		case ESSTYPE_DETECT:
+		case ESSTYPE_LIKE20:
+			break;
+		case 688:
+			submodel = 0x00;
+			break;
+		case 1688:
+			submodel = 0x08;
+			break;
+		case 1868:
+			submodel = SUBMDL_ES1868;
+			break;
+		case 1869:
+			submodel = SUBMDL_ES1869;
+			break;
+		case 1788:
+			submodel = SUBMDL_ES1788;
+			break;
+		case 1887:
+			submodel = SUBMDL_ES1887;
+			break;
+		case 1888:
+			submodel = SUBMDL_ES1888;
+			break;
+		default:
+			printk (KERN_ERR "Invalid esstype=%d specified\n", esstype);
+			return 0;
+		};
+		if (submodel != -1) {
+			devc->submodel = submodel;
+			sprintf (modelname, "ES%d", esstype);
+			chip = modelname;
 		};
 		if (chip == NULL && (ess_minor & 0x0f) < 8) {
 			chip = "ES688";
 		};
+#ifdef FKS_TEST
+FKS_test (devc);
+#endif
+		/*
+		 * If Nothing detected yet, and we want 2.0 behaviour...
+		 * Then let's assume it's ES1688.
+		 */
+		if (chip == NULL && esstype == ESSTYPE_LIKE20) {
+			chip = "ES1688";
+		};
 
 		if (chip == NULL) {
 			int type;
@@ -1080,6 +1104,10 @@
 				chip = "ES1878";
 				devc->submodel = SUBMDL_ES1878;
 				break;
+			default:
+				if ((type & 0x00ff) != ((type >> 8) & 0x00ff)) {
+					printk ("ess_init: Unrecognized %04x\n", type);
+				}
 			};
 		};
 #if 0
diff -u --recursive --new-file v2.2.1/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c
--- v2.2.1/linux/drivers/sound/sound_core.c	Tue Jan 19 11:32:52 1999
+++ linux/drivers/sound/sound_core.c	Sat Feb  6 12:46:21 1999
@@ -63,6 +63,10 @@
 	int n=low;
 
 	if (index < 0) {	/* first free */
+
+		while (*list && (*list)->unit_minor<n)
+			list=&((*list)->next);
+
 		while(n<top)
 		{
 			/* Found a hole ? */
@@ -73,7 +77,7 @@
 		}
 
 		if(n>=top)
-			return -ENOMEM;
+			return -ENOENT;
 	} else {
 		n = low+(index*16);
 		while (*list) {
@@ -141,13 +145,13 @@
 	int r;
 	struct sound_unit *s=(struct sound_unit *)kmalloc(sizeof(struct sound_unit), GFP_KERNEL);
 	if(s==NULL)
-		return -1;
+		return -ENOMEM;
 		
 	spin_lock(&sound_loader_lock);
 	r=__sound_insert_unit(s,list,fops,index,low,top);
 	spin_unlock(&sound_loader_lock);
 	
-	if(r==-1)
+	if(r<0)
 		kfree(s);
 	return r;
 }
diff -u --recursive --new-file v2.2.1/linux/drivers/sound/sys_timer.c linux/drivers/sound/sys_timer.c
--- v2.2.1/linux/drivers/sound/sys_timer.c	Thu May 14 19:47:42 1998
+++ linux/drivers/sound/sys_timer.c	Mon Feb  1 14:04:42 1999
@@ -13,6 +13,7 @@
  */
 /*
  * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed)
+ * Andrew Veliath  : adapted tmr2ticks from level 1 sequencer (avoid overflow)
  */
 #include <linux/config.h>
 
@@ -39,11 +40,17 @@
 tmr2ticks(int tmr_value)
 {
 	/*
-	 *    Convert system timer ticks (HZ) to MIDI ticks
-	 *    (divide # of MIDI ticks/minute by # of system ticks/minute).
+	 *    Convert timer ticks to MIDI ticks
 	 */
 
-	return ((tmr_value * curr_tempo * curr_timebase) + (30 * 100)) / (60 * HZ);
+	unsigned long tmp;
+	unsigned long scale;
+
+	/* tmr_value (ticks per sec) *
+	   1000000 (usecs per sec) / HZ (ticks per sec) -=> usecs */
+	tmp = tmr_value * (1000000 / HZ);
+	scale = (60 * 1000000) / (curr_tempo * curr_timebase);	/* usecs per MIDI tick */
+	return (tmp + scale / 2) / scale;
 }
 
 static void
diff -u --recursive --new-file v2.2.1/linux/fs/affs/inode.c linux/fs/affs/inode.c
--- v2.2.1/linux/fs/affs/inode.c	Tue Dec 22 14:16:57 1998
+++ linux/fs/affs/inode.c	Sat Feb  6 12:46:21 1999
@@ -293,7 +293,7 @@
 
 	sb = dir->i_sb;
 	inode->i_sb    = sb;
-	inode->i_flags = sb->s_flags;
+	inode->i_flags = 0;
 
 	if (!(block = affs_new_header((struct inode *)dir))) {
 		iput(inode);
diff -u --recursive --new-file v2.2.1/linux/fs/buffer.c linux/fs/buffer.c
--- v2.2.1/linux/fs/buffer.c	Tue Jan 19 11:32:52 1999
+++ linux/fs/buffer.c	Sat Feb  6 11:32:09 1999
@@ -74,6 +74,7 @@
 
 static int nr_buffers = 0;
 static int nr_buffers_type[NR_LIST] = {0,};
+static int size_buffers_type[NR_LIST] = {0,};
 static int nr_buffer_heads = 0;
 static int nr_unused_buffer_heads = 0;
 
@@ -99,7 +100,8 @@
 				each time we call refill */
 		int nref_dirt; /* Dirty buffer threshold for activating bdflush
 				  when trying to refill buffers. */
-		int dummy1;    /* unused */
+		int pct_dirt;    /* Max %age of mem for dirty buffers before
+				    activating bdflush */
 		int age_buffer;  /* Time for normal buffer to age before 
 				    we flush it */
 		int age_super;  /* Time for superblock to age before we 
@@ -478,6 +480,7 @@
 		return;
 	}
 	nr_buffers_type[bh->b_list]--;
+	size_buffers_type[bh->b_list] -= bh->b_size;
 	remove_from_hash_queue(bh);
 	remove_from_lru_list(bh);
 }
@@ -551,6 +554,7 @@
 		(*bhp)->b_prev_free = bh;
 
 		nr_buffers_type[bh->b_list]++;
+		size_buffers_type[bh->b_list] += bh->b_size;
 
 		/* Put the buffer in new hash-queue if it has a device. */
 		bh->b_next = NULL;
@@ -802,13 +806,19 @@
 		file_buffer(buf, dispose);
 		if(dispose == BUF_DIRTY) {
 			int too_many = (nr_buffers * bdf_prm.b_un.nfract/100);
+			int too_large = (num_physpages * bdf_prm.b_un.pct_dirt/100);
 
 			/* This buffer is dirty, maybe we need to start flushing.
 			 * If too high a percentage of the buffers are dirty...
 			 */
-			if (nr_buffers_type[BUF_DIRTY] > too_many)
-				wakeup_bdflush(0);
-
+			if (nr_buffers_type[BUF_DIRTY] > too_many ||
+			    (size_buffers_type[BUF_DIRTY] + size_buffers_type[BUF_LOCKED])/PAGE_SIZE > too_large) {
+				if (nr_buffers_type[BUF_LOCKED] > 2 * bdf_prm.b_un.ndirty)
+					wakeup_bdflush(1);
+				else
+					wakeup_bdflush(0);
+			}
+			
 			/* If this is a loop device, and
 			 * more than half of the buffers are dirty...
 			 * (Prevents no-free-buffers deadlock with loop device.)
@@ -1604,7 +1614,7 @@
 #ifdef DEBUG
 	for(nlist = 0; nlist < NR_LIST; nlist++)
 #else
-	for(nlist = BUF_DIRTY; nlist <= BUF_DIRTY; nlist++)
+	for(nlist = BUF_LOCKED; nlist <= BUF_DIRTY; nlist++)
 #endif
 	{
 		ndirty = 0;
@@ -1623,8 +1633,13 @@
 				 }
 				 
 				 /* Clean buffer on dirty list?  Refile it */
-				 if (nlist == BUF_DIRTY && !buffer_dirty(bh) && !buffer_locked(bh))
-				  {
+				 if (nlist == BUF_DIRTY && !buffer_dirty(bh) && !buffer_locked(bh)) {
+					 refile_buffer(bh);
+					 continue;
+				 }
+				  
+				  /* Unlocked buffer on locked list?  Refile it */
+				  if (nlist == BUF_LOCKED && !buffer_locked(bh)) {
 					  refile_buffer(bh);
 					  continue;
 				  }
diff -u --recursive --new-file v2.2.1/linux/fs/coda/sysctl.c linux/fs/coda/sysctl.c
--- v2.2.1/linux/fs/coda/sysctl.c	Tue Dec 22 14:16:57 1998
+++ linux/fs/coda/sysctl.c	Sat Feb  6 12:46:21 1999
@@ -24,6 +24,8 @@
 #include <asm/segment.h>
 #include <asm/uaccess.h>
 #include <linux/utsname.h>
+#define __NO_VERSION__
+#include <linux/module.h>
 
 #include <linux/coda.h>
 #include <linux/coda_linux.h>
@@ -491,6 +493,14 @@
                 coda_cache_inv_stats_get_info
         };
 
+static void coda_proc_modcount(struct inode *inode, int fill)
+{
+	if (fill)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
+}
+
 #endif
 
 
@@ -504,6 +514,7 @@
 
 #ifdef CONFIG_PROC_FS
 	proc_register(&proc_root_fs,&proc_fs_coda);
+	proc_fs_coda.fill_inode = &coda_proc_modcount;
 	proc_register(&proc_fs_coda,&proc_coda_vfs);
 	proc_register(&proc_fs_coda,&proc_coda_upcall);
 	proc_register(&proc_fs_coda,&proc_coda_permission);
diff -u --recursive --new-file v2.2.1/linux/fs/inode.c linux/fs/inode.c
--- v2.2.1/linux/fs/inode.c	Mon Jan 25 17:44:34 1999
+++ linux/fs/inode.c	Mon Feb 15 10:48:10 1999
@@ -62,9 +62,8 @@
 struct {
 	int nr_inodes;
 	int nr_free_inodes;
-	int preshrink;		/* pre-shrink dcache? */
-	int dummy[4];
-} inodes_stat = {0, 0, 0,};
+	int dummy[5];
+} inodes_stat = {0, 0,};
 
 int max_inodes;
 
@@ -196,6 +195,19 @@
 }
 
 /*
+ * Called with the spinlock already held..
+ */
+static void sync_all_inodes(void)
+{
+	struct super_block * sb = sb_entry(super_blocks.next);
+	for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) {
+		if (!sb->s_dev)
+			continue;
+		sync_list(&sb->s_dirty);
+	}
+}
+
+/*
  * Needed by knfsd
  */
 void write_inode_now(struct inode *inode)
@@ -232,13 +244,15 @@
 
 /*
  * Dispose-list gets a local list, so it doesn't need to
- * worry about list corruption.
+ * worry about list corruption. It releases the inode lock
+ * while clearing the inodes.
  */
 static void dispose_list(struct list_head * head)
 {
 	struct list_head *next;
 	int count = 0;
 
+	spin_unlock(&inode_lock);
 	next = head->next;
 	for (;;) {
 		struct list_head * tmp = next;
@@ -256,7 +270,6 @@
 	spin_lock(&inode_lock);
 	list_splice(head, &inode_unused);
 	inodes_stat.nr_free_inodes += count;
-	spin_unlock(&inode_lock);
 }
 
 /*
@@ -305,65 +318,53 @@
 	spin_lock(&inode_lock);
 	busy = invalidate_list(&inode_in_use, sb, &throw_away);
 	busy |= invalidate_list(&sb->s_dirty, sb, &throw_away);
-	spin_unlock(&inode_lock);
-
 	dispose_list(&throw_away);
+	spin_unlock(&inode_lock);
 
 	return busy;
 }
 
 /*
  * This is called with the inode lock held. It searches
- * the in-use for the specified number of freeable inodes.
- * Freeable inodes are moved to a temporary list and then
- * placed on the unused list by dispose_list.
+ * the in-use for freeable inodes, which are moved to a
+ * temporary list and then placed on the unused list by
+ * dispose_list. 
+ *
+ * We don't expect to have to call this very often.
  *
- * Note that we do not expect to have to search very hard:
- * the freeable inodes will be at the old end of the list.
- * 
- * N.B. The spinlock is released to call dispose_list.
+ * N.B. The spinlock is released during the call to
+ *      dispose_list.
  */
 #define CAN_UNUSE(inode) \
-	(((inode)->i_count == 0) && \
-	 (!(inode)->i_state))
+	(((inode)->i_count | (inode)->i_state) == 0)
+#define INODE(entry)	(list_entry(entry, struct inode, i_list))
 
-static int free_inodes(int goal)
+static int free_inodes(void)
 {
-	struct list_head *tmp, *head = &inode_in_use;
-	LIST_HEAD(freeable);
-	int found = 0, depth = goal << 1;
+	struct list_head list, *entry, *freeable = &list;
+	int found = 0;
 
-	while ((tmp = head->prev) != head && depth--) {
-		struct inode * inode = list_entry(tmp, struct inode, i_list);
+	INIT_LIST_HEAD(freeable);
+	entry = inode_in_use.next;
+	while (entry != &inode_in_use) {
+		struct list_head *tmp = entry;
+
+		entry = entry->next;
+		if (!CAN_UNUSE(INODE(tmp)))
+			continue;
 		list_del(tmp);
-		if (CAN_UNUSE(inode)) {
-			list_del(&inode->i_hash);
-			INIT_LIST_HEAD(&inode->i_hash);
-			list_add(tmp, &freeable);
-			if (++found < goal)
-				continue;
-			break;
-		}
-		list_add(tmp, head);
+		list_del(&INODE(tmp)->i_hash);
+		INIT_LIST_HEAD(&INODE(tmp)->i_hash);
+		list_add(tmp, freeable);
+		found = 1;
 	}
+
 	if (found) {
-		spin_unlock(&inode_lock);
-		dispose_list(&freeable);
-		spin_lock(&inode_lock);
+		dispose_list(freeable);
+		found = 1;	/* silly compiler */
 	}
-	return found;
-}
 
-static void shrink_dentry_inodes(int goal)
-{
-	int found;
-
-	spin_unlock(&inode_lock);
-	found = select_dcache(goal, 0);
-	if (found < goal)
-		found = goal;
-	prune_dcache(found);
-	spin_lock(&inode_lock);
+	return found;
 }
 
 /*
@@ -373,9 +374,22 @@
  */
 static void try_to_free_inodes(int goal)
 {
-	shrink_dentry_inodes(goal);
-	if (!free_inodes(goal))
-		shrink_dentry_inodes(goal);
+	/*
+	 * First stry to just get rid of unused inodes.
+	 *
+	 * If we can't reach our goal that way, we'll have
+	 * to try to shrink the dcache and sync existing
+	 * inodes..
+	 */
+	free_inodes();
+	goal -= inodes_stat.nr_free_inodes;
+	if (goal > 0) {
+		spin_unlock(&inode_lock);
+		prune_dcache(goal);
+		spin_lock(&inode_lock);
+		sync_all_inodes();
+		free_inodes();
+	}
 }
 
 /*
@@ -385,7 +399,7 @@
 void free_inode_memory(int goal)
 {
 	spin_lock(&inode_lock);
-	free_inodes(goal);
+	free_inodes();
 	spin_unlock(&inode_lock);
 }
 
@@ -403,9 +417,9 @@
 	/*
 	 * Check whether to restock the unused list.
 	 */
-	if (inodes_stat.preshrink) {
+	if (inodes_stat.nr_inodes > max_inodes) {
 		struct list_head *tmp;
-		try_to_free_inodes(8);
+		try_to_free_inodes(inodes_stat.nr_inodes >> 2);
 		tmp = inode_unused.next;
 		if (tmp != &inode_unused) {
 			inodes_stat.nr_free_inodes--;
@@ -436,9 +450,6 @@
 		 */
 		inodes_stat.nr_inodes += INODES_PER_PAGE;
 		inodes_stat.nr_free_inodes += INODES_PER_PAGE - 1;
-		inodes_stat.preshrink = 0;
-		if (inodes_stat.nr_inodes > max_inodes)
-			inodes_stat.preshrink = 1;
 		return inode;
 	}
 
@@ -447,10 +458,9 @@
 	 * the dcache and then try again to free some inodes.
 	 */
 	prune_dcache(inodes_stat.nr_inodes >> 2);
-	inodes_stat.preshrink = 1;
 
 	spin_lock(&inode_lock);
-	free_inodes(inodes_stat.nr_inodes >> 2);
+	free_inodes();
 	{
 		struct list_head *tmp = inode_unused.next;
 		if (tmp != &inode_unused) {
diff -u --recursive --new-file v2.2.1/linux/fs/lockd/clntproc.c linux/fs/lockd/clntproc.c
--- v2.2.1/linux/fs/lockd/clntproc.c	Thu Dec 31 10:29:02 1998
+++ linux/fs/lockd/clntproc.c	Sat Feb  6 12:46:21 1999
@@ -30,6 +30,14 @@
  */
 static u32	nlm_cookie = 0x1234;
 
+static inline void nlmclnt_next_cookie(struct nlm_cookie *c)
+{
+	memcpy(c->data, &nlm_cookie, 4);
+	memset(c->data+4, 0, 4);
+	c->len=4;
+	nlm_cookie++;
+}
+
 /*
  * Initialize arguments for TEST/LOCK/UNLOCK/CANCEL calls
  */
@@ -40,7 +48,7 @@
 	struct nlm_lock	*lock = &argp->lock;
 
 	memset(argp, 0, sizeof(*argp));
-	argp->cookie  = nlm_cookie++;
+	nlmclnt_next_cookie(&argp->cookie);
 	argp->state   = nsm_local_state;
 	lock->fh      = *NFS_FH(fl->fl_file->f_dentry);
 	lock->caller  = system_utsname.nodename;
@@ -57,7 +65,7 @@
 int
 nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
 {
-	call->a_args.cookie  = nlm_cookie++;
+	nlmclnt_next_cookie(&call->a_args.cookie);
 	call->a_args.lock    = *lock;
 	call->a_args.lock.caller = system_utsname.nodename;
 
@@ -230,9 +238,24 @@
 		/* Perform the RPC call. If an error occurs, try again */
 		if ((status = rpc_call(clnt, proc, argp, resp, 0)) < 0) {
 			dprintk("lockd: rpc_call returned error %d\n", -status);
-			if (status == -ERESTARTSYS)
-				return status;
-			nlm_rebind_host(host);
+			switch (status) {
+			case -EPROTONOSUPPORT:
+				status = -EINVAL;
+				break;
+			case -ECONNREFUSED:
+			case -ETIMEDOUT:
+			case -ENOTCONN:
+				status = -EAGAIN;
+				break;
+			case -ERESTARTSYS:
+				return signalled () ? -EINTR : status;
+			default:
+				break;
+			}
+			if (req->a_args.block)
+				nlm_rebind_host(host);
+			else
+				break;
 		} else
 		if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) {
 			dprintk("lockd: server in grace period\n");
@@ -248,9 +271,18 @@
 
 		/* Back off a little and try again */
 		interruptible_sleep_on_timeout(&host->h_gracewait, 15*HZ);
-	} while (!signalled());
 
-	return -ERESTARTSYS;
+		/* When the lock requested by F_SETLKW isn't available,
+		   we will wait until the request can be satisfied. If
+		   a signal is received during wait, we should return
+		   -EINTR. */
+		if (signalled ()) {
+			status = -EINTR;
+			break;
+		}
+	} while (1);
+
+	return status;
 }
 
 /*
@@ -446,7 +478,7 @@
 	int		status = req->a_res.status;
 
 	if (RPC_ASSASSINATED(task))
-		goto die;
+		return;
 
 	if (task->tk_status < 0) {
 		dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status);
@@ -458,9 +490,6 @@
 	 && status != NLM_LCK_DENIED_GRACE_PERIOD) {
 		printk("lockd: unexpected unlock status: %d\n", status);
 	}
-
-die:
-	rpc_release_task(task);
 }
 
 /*
@@ -536,7 +565,6 @@
 	}
 
 die:
-	rpc_release_task(task);
 	nlm_release_host(req->a_host);
 	kfree(req);
 	return;
diff -u --recursive --new-file v2.2.1/linux/fs/lockd/svc.c linux/fs/lockd/svc.c
--- v2.2.1/linux/fs/lockd/svc.c	Thu Dec 31 10:29:02 1998
+++ linux/fs/lockd/svc.c	Sat Feb  6 12:46:21 1999
@@ -64,6 +64,7 @@
 {
 	struct svc_serv	*serv = rqstp->rq_server;
 	int		err = 0;
+	unsigned long grace_period_expire;
 
 	/* Lock module and set up kernel thread */
 	MOD_INC_USE_COUNT;
@@ -111,7 +112,7 @@
 	}
 #endif
 
-	nlmsvc_grace_period += jiffies;
+	grace_period_expire = nlmsvc_grace_period + jiffies;
 	nlmsvc_timeout = nlm_timeout * HZ;
 
 	/*
diff -u --recursive --new-file v2.2.1/linux/fs/lockd/svclock.c linux/fs/lockd/svclock.c
--- v2.2.1/linux/fs/lockd/svclock.c	Thu Nov 12 16:21:22 1998
+++ linux/fs/lockd/svclock.c	Sat Feb  6 12:46:21 1999
@@ -111,16 +111,25 @@
 	return NULL;
 }
 
+static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b)
+{
+	if(a->len != b->len)
+		return 0;
+	if(memcmp(a->data,b->data,a->len))
+		return 0;
+	return 1;
+}
+
 /*
  * Find a block with a given NLM cookie.
  */
 static inline struct nlm_block *
-nlmsvc_find_block(u32 cookie)
+nlmsvc_find_block(struct nlm_cookie *cookie)
 {
 	struct nlm_block *block;
 
 	for (block = nlm_blocked; block; block = block->b_next) {
-		if (block->b_call.a_args.cookie == cookie)
+		if (nlm_cookie_match(&block->b_call.a_args.cookie,cookie))
 			break;
 	}
 
@@ -139,7 +148,7 @@
  */
 static inline struct nlm_block *
 nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
-				struct nlm_lock *lock, u32 cookie)
+				struct nlm_lock *lock, struct nlm_cookie *cookie)
 {
 	struct nlm_block	*block;
 	struct nlm_host		*host;
@@ -160,7 +169,7 @@
 	lock->fl.fl_notify = nlmsvc_notify_blocked;
 	if (!nlmclnt_setgrantargs(&block->b_call, lock))
 		goto failed_free;
-	block->b_call.a_args.cookie = cookie;	/* see above */
+	block->b_call.a_args.cookie = *cookie;	/* see above */
 
 	dprintk("lockd: created block %p...\n", block);
 
@@ -267,7 +276,7 @@
  */
 u32
 nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
-			struct nlm_lock *lock, int wait, u32 cookie)
+			struct nlm_lock *lock, int wait, struct nlm_cookie *cookie)
 {
 	struct file_lock	*conflock;
 	struct nlm_block	*block;
@@ -529,8 +538,8 @@
 	unsigned long		timeout;
 
 	dprintk("lockd: GRANT_MSG RPC callback\n");
-	if (!(block = nlmsvc_find_block(call->a_args.cookie))) {
-		dprintk("lockd: no block for cookie %x\n", call->a_args.cookie);
+	if (!(block = nlmsvc_find_block(&call->a_args.cookie))) {
+		dprintk("lockd: no block for cookie %x\n", *(u32 *)(call->a_args.cookie.data));
 		return;
 	}
 
@@ -552,7 +561,6 @@
 	block->b_incall = 0;
 
 	nlm_release_host(call->a_host);
-	rpc_release_task(task);
 }
 
 /*
@@ -560,7 +568,7 @@
  * block.
  */
 void
-nlmsvc_grant_reply(u32 cookie, u32 status)
+nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status)
 {
 	struct nlm_block	*block;
 	struct nlm_file		*file;
diff -u --recursive --new-file v2.2.1/linux/fs/lockd/svcproc.c linux/fs/lockd/svcproc.c
--- v2.2.1/linux/fs/lockd/svcproc.c	Thu Dec 31 10:29:02 1998
+++ linux/fs/lockd/svcproc.c	Sat Feb  6 12:46:21 1999
@@ -151,7 +151,7 @@
 
 	/* Now try to lock the file */
 	resp->status = nlmsvc_lock(rqstp, file, &argp->lock,
-					argp->block, argp->cookie);
+					argp->block, &argp->cookie);
 
 	dprintk("lockd: LOCK          status %ld\n", ntohl(resp->status));
 	nlm_release_host(host);
@@ -492,7 +492,6 @@
 					task->tk_pid, -task->tk_status);
 	}
 	nlm_release_host(call->a_host);
-	rpc_release_task(task);
 	kfree(call);
 }
 
diff -u --recursive --new-file v2.2.1/linux/fs/lockd/xdr.c linux/fs/lockd/xdr.c
--- v2.2.1/linux/fs/lockd/xdr.c	Tue Mar 10 10:03:34 1998
+++ linux/fs/lockd/xdr.c	Sat Feb  6 12:46:21 1999
@@ -53,28 +53,38 @@
 /*
  * XDR functions for basic NLM types
  */
-static inline u32 *
-nlm_decode_cookie(u32 *p, u32 *c)
+static inline u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c)
 {
 	unsigned int	len;
 
-	if ((len = ntohl(*p++)) == 4) {
-		*c = ntohl(*p++);
-	} else if (len == 0) {		/* hockeypux brain damage */
-		*c = 0;
-	} else {
+	len = ntohl(*p++);
+	
+	if(len==0)
+	{
+		c->len=4;
+		memset(c->data, 0, 4);	/* hockeypux brain damage */
+	}
+	else if(len<=8)
+	{
+		c->len=len;
+		memcpy(c->data, p, len);
+		p+=(len+3)>>2;
+	}
+	else 
+	{
 		printk(KERN_NOTICE
-			"lockd: bad cookie size %d (should be 4)\n", len);
+			"lockd: bad cookie size %d (only cookies under 8 bytes are supported.)\n", len);
 		return NULL;
 	}
 	return p;
 }
 
 static inline u32 *
-nlm_encode_cookie(u32 *p, u32 c)
+nlm_encode_cookie(u32 *p, struct nlm_cookie *c)
 {
-	*p++ = htonl(sizeof(c));
-	*p++ = htonl(c);
+	*p++ = htonl(c->len);
+	memcpy(p, c->data, c->len);
+	p+=(c->len+3)>>2;
 	return p;
 }
 
@@ -168,7 +178,7 @@
 static u32 *
 nlm_encode_testres(u32 *p, struct nlm_res *resp)
 {
-	if (!(p = nlm_encode_cookie(p, resp->cookie)))
+	if (!(p = nlm_encode_cookie(p, &resp->cookie)))
 		return 0;
 	*p++ = resp->status;
 
@@ -308,7 +318,7 @@
 int
 nlmsvc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
 {
-	if (!(p = nlm_encode_cookie(p, resp->cookie)))
+	if (!(p = nlm_encode_cookie(p, &resp->cookie)))
 		return 0;
 	*p++ = resp->status;
 	*p++ = xdr_zero;		/* sequence argument */
@@ -318,7 +328,7 @@
 int
 nlmsvc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
 {
-	if (!(p = nlm_encode_cookie(p, resp->cookie)))
+	if (!(p = nlm_encode_cookie(p, &resp->cookie)))
 		return 0;
 	*p++ = resp->status;
 	return xdr_ressize_check(rqstp, p);
@@ -388,7 +398,7 @@
 {
 	struct nlm_lock	*lock = &argp->lock;
 
-	if (!(p = nlm_encode_cookie(p, argp->cookie)))
+	if (!(p = nlm_encode_cookie(p, &argp->cookie)))
 		return -EIO;
 	*p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero;
 	if (!(p = nlm_encode_lock(p, lock)))
@@ -429,7 +439,7 @@
 {
 	struct nlm_lock	*lock = &argp->lock;
 
-	if (!(p = nlm_encode_cookie(p, argp->cookie)))
+	if (!(p = nlm_encode_cookie(p, &argp->cookie)))
 		return -EIO;
 	*p++ = argp->block? xdr_one : xdr_zero;
 	*p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero;
@@ -446,7 +456,7 @@
 {
 	struct nlm_lock	*lock = &argp->lock;
 
-	if (!(p = nlm_encode_cookie(p, argp->cookie)))
+	if (!(p = nlm_encode_cookie(p, &argp->cookie)))
 		return -EIO;
 	*p++ = argp->block? xdr_one : xdr_zero;
 	*p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero;
@@ -461,7 +471,7 @@
 {
 	struct nlm_lock	*lock = &argp->lock;
 
-	if (!(p = nlm_encode_cookie(p, argp->cookie)))
+	if (!(p = nlm_encode_cookie(p, &argp->cookie)))
 		return -EIO;
 	if (!(p = nlm_encode_lock(p, lock)))
 		return -EIO;
@@ -472,7 +482,7 @@
 static int
 nlmclt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
 {
-	if (!(p = nlm_encode_cookie(p, resp->cookie)))
+	if (!(p = nlm_encode_cookie(p, &resp->cookie)))
 		return -EIO;
 	*p++ = resp->status;
 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
@@ -501,7 +511,7 @@
  * Buffer requirements for NLM
  */
 #define NLM_void_sz		0
-#define NLM_cookie_sz		2
+#define NLM_cookie_sz		3	/* 1 len , 2 data */
 #define NLM_caller_sz		1+QUADLEN(sizeof(system_utsname.nodename))
 #define NLM_netobj_sz		1+QUADLEN(XDR_MAX_NETOBJ)
 /* #define NLM_owner_sz		1+QUADLEN(NLM_MAXOWNER) */
diff -u --recursive --new-file v2.2.1/linux/fs/nfsd/nfsproc.c linux/fs/nfsd/nfsproc.c
--- v2.2.1/linux/fs/nfsd/nfsproc.c	Sun Jul 26 11:57:18 1998
+++ linux/fs/nfsd/nfsproc.c	Fri Jan 29 11:09:56 1999
@@ -515,7 +515,7 @@
   PROC(symlink,	 symlinkargs,	void,		none,		RC_REPLSTAT),
   PROC(mkdir,	 createargs,	diropres,	fhandle,	RC_REPLBUFF),
   PROC(rmdir,	 diropargs,	void,		none,		RC_REPLSTAT),
-  PROC(readdir,	 readdirargs,	readdirres,	none,		RC_REPLSTAT),
+  PROC(readdir,	 readdirargs,	readdirres,	none,		RC_REPLBUFF),
   PROC(statfs,	 fhandle,	statfsres,	none,		RC_NOCACHE),
 };
 
diff -u --recursive --new-file v2.2.1/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.2.1/linux/include/linux/fs.h	Wed Jan 20 23:14:06 1999
+++ linux/include/linux/fs.h	Mon Feb  8 15:20:30 1999
@@ -150,6 +150,7 @@
 #define BLKFRAGET  _IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */
 #define BLKSECTSET _IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */
 #define BLKSECTGET _IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
+#define BLKSSZGET  _IO(0x12,104)/* get block device sector size (reserved for) */
 
 #define BMAP_IOCTL 1		/* obsolete - kept for compatibility */
 #define FIBMAP	   _IO(0x00,1)	/* bmap access */
diff -u --recursive --new-file v2.2.1/linux/include/linux/lockd/lockd.h linux/include/linux/lockd/lockd.h
--- v2.2.1/linux/include/linux/lockd/lockd.h	Fri Jul 31 17:10:16 1998
+++ linux/include/linux/lockd/lockd.h	Mon Feb  8 15:20:59 1999
@@ -145,7 +145,7 @@
  * Server-side lock handling
  */
 u32		  nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
-					struct nlm_lock *, int, u32);
+					struct nlm_lock *, int, struct nlm_cookie *);
 u32		  nlmsvc_unlock(struct nlm_file *, struct nlm_lock *);
 u32		  nlmsvc_testlock(struct nlm_file *, struct nlm_lock *,
 					struct nlm_lock *);
diff -u --recursive --new-file v2.2.1/linux/include/linux/lockd/xdr.h linux/include/linux/lockd/xdr.h
--- v2.2.1/linux/include/linux/lockd/xdr.h	Fri Jul 31 17:10:16 1998
+++ linux/include/linux/lockd/xdr.h	Mon Feb  8 15:20:57 1999
@@ -25,10 +25,21 @@
 };
 
 /*
+ *	NLM cookies. Technically they can be 1K, Nobody uses over 8 bytes
+ *	however.
+ */
+ 
+struct nlm_cookie
+{
+	unsigned char data[8];
+	unsigned int len;
+};
+
+/*
  * Generic lockd arguments for all but sm_notify
  */
 struct nlm_args {
-	u32			cookie;
+	struct nlm_cookie	cookie;
 	struct nlm_lock		lock;
 	u32			block;
 	u32			reclaim;
@@ -42,7 +53,7 @@
  * Generic lockd result
  */
 struct nlm_res {
-	u32			cookie;
+	struct nlm_cookie	cookie;
 	u32			status;
 	struct nlm_lock		lock;
 };
diff -u --recursive --new-file v2.2.1/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.2.1/linux/include/linux/sched.h	Tue Jan 19 11:32:53 1999
+++ linux/include/linux/sched.h	Mon Feb  8 15:20:32 1999
@@ -174,6 +174,8 @@
 	unsigned long rss, total_vm, locked_vm;
 	unsigned long def_flags;
 	unsigned long cpu_vm_mask;
+	unsigned long swap_cnt;	/* number of pages to swap on next pass */
+	unsigned long swap_address;
 	/*
 	 * This is an architecture-specific pointer: the portable
 	 * part of Linux does not know about any segments.
@@ -191,7 +193,7 @@
 		0, 0, 0, 				\
 		0, 0, 0, 0,				\
 		0, 0, 0,				\
-		0, 0, NULL }
+		0, 0, 0, 0, NULL }
 
 struct signal_struct {
 	atomic_t		count;
@@ -276,8 +278,6 @@
 /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
 	unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
 	int swappable:1;
-	unsigned long swap_address;
-	unsigned long swap_cnt;		/* number of pages to swap on next pass */
 /* process credentials */
 	uid_t uid,euid,suid,fsuid;
 	gid_t gid,egid,sgid,fsgid;
@@ -361,7 +361,7 @@
 /* utime */	{0,0,0,0},0, \
 /* per CPU times */ {0, }, {0, }, \
 /* flt */	0,0,0,0,0,0, \
-/* swp */	0,0,0, \
+/* swp */	0, \
 /* process credentials */					\
 /* uid etc */	0,0,0,0,0,0,0,0,				\
 /* suppl grps*/ 0, {0,},					\
diff -u --recursive --new-file v2.2.1/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h
--- v2.2.1/linux/include/linux/smb_fs.h	Thu Aug 27 19:56:30 1998
+++ linux/include/linux/smb_fs.h	Mon Feb  8 15:21:37 1999
@@ -14,7 +14,7 @@
 /*
  * ioctl commands
  */
-#define	SMB_IOC_GETMOUNTUID		_IOR('u', 1, uid_t)
+#define	SMB_IOC_GETMOUNTUID		_IOR('u', 1, __kernel_uid_t)
 #define SMB_IOC_NEWCONN                 _IOW('u', 2, struct smb_conn_opt)
 
 #ifdef __KERNEL__
diff -u --recursive --new-file v2.2.1/linux/init/main.c linux/init/main.c
--- v2.2.1/linux/init/main.c	Wed Jan 20 23:14:07 1999
+++ linux/init/main.c	Fri Feb  5 09:29:35 1999
@@ -64,6 +64,7 @@
 static int init(void *);
 extern int bdflush(void *);
 extern int kswapd(void *);
+extern int kpiod(void *);
 extern void kswapd_setup(void);
 
 extern void init_IRQ(void);
@@ -1271,6 +1272,7 @@
 	kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
 	/* Start the background pageout daemon. */
 	kswapd_setup();
+	kernel_thread(kpiod, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
 	kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
 
 #if CONFIG_AP1000
diff -u --recursive --new-file v2.2.1/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.2.1/linux/kernel/ksyms.c	Wed Jan 20 23:14:07 1999
+++ linux/kernel/ksyms.c	Thu Feb  4 13:00:32 1999
@@ -37,6 +37,7 @@
 #include <linux/file.h>
 #include <linux/console.h>
 #include <linux/poll.h>
+#include <linux/mm.h>
 
 #if defined(CONFIG_PROC_FS)
 #include <linux/proc_fs.h>
@@ -105,6 +106,8 @@
 EXPORT_SYMBOL(high_memory);
 EXPORT_SYMBOL(update_vm_cache);
 EXPORT_SYMBOL(vmtruncate);
+EXPORT_SYMBOL(find_vma);
+EXPORT_SYMBOL(get_unmapped_area);
 
 /* filesystem internal functions */
 EXPORT_SYMBOL(in_group_p);
diff -u --recursive --new-file v2.2.1/linux/kernel/sched.c linux/kernel/sched.c
--- v2.2.1/linux/kernel/sched.c	Wed Jan 20 23:14:07 1999
+++ linux/kernel/sched.c	Sun Feb  7 12:03:40 1999
@@ -639,6 +639,8 @@
 	struct task_struct * prev, * next;
 	int this_cpu;
 
+	run_task_queue(&tq_scheduler);
+
 	prev = current;
 	this_cpu = prev->processor;
 	/*
@@ -654,7 +656,6 @@
 	/* Do "administrative" work here while we don't hold any locks */
 	if (bh_active & bh_mask)
 		do_bottom_half();
-	run_task_queue(&tq_scheduler);
 
 	spin_lock(&scheduler_lock);
 	spin_lock_irq(&runqueue_lock);
@@ -680,8 +681,18 @@
 
 	sched_data->prevstate = prev->state;
 
+/* this is the scheduler proper: */
 	{
 		struct task_struct * p = init_task.next_run;
+		int c = -1000;
+
+		/* Default process to select.. */
+		next = idle_task;
+		if (prev->state == TASK_RUNNING) {
+			c = goodness(prev, prev, this_cpu);
+			next = prev;
+		}
+
 		/*
 		 * This is subtle.
 		 * Note how we can enable interrupts here, even
@@ -693,36 +704,27 @@
 		 * the scheduler lock
 		 */
 		spin_unlock_irq(&runqueue_lock);
-#ifdef __SMP__
-		prev->has_cpu = 0;
-#endif
-	
 /*
  * Note! there may appear new tasks on the run-queue during this, as
  * interrupts are enabled. However, they will be put on front of the
  * list, so our list starting at "p" is essentially fixed.
  */
-/* this is the scheduler proper: */
-		{
-			int c = -1000;
-			next = idle_task;
-			while (p != &init_task) {
-				if (can_schedule(p)) {
-					int weight = goodness(p, prev, this_cpu);
-					if (weight > c)
-						c = weight, next = p;
-				}
-				p = p->next_run;
+		while (p != &init_task) {
+			if (can_schedule(p)) {
+				int weight = goodness(p, prev, this_cpu);
+				if (weight > c)
+					c = weight, next = p;
 			}
+			p = p->next_run;
+		}
 
-			/* Do we need to re-calculate counters? */
-			if (!c) {
-				struct task_struct *p;
-				read_lock(&tasklist_lock);
-				for_each_task(p)
-					p->counter = (p->counter >> 1) + p->priority;
-				read_unlock(&tasklist_lock);
-			}
+		/* Do we need to re-calculate counters? */
+		if (!c) {
+			struct task_struct *p;
+			read_lock(&tasklist_lock);
+			for_each_task(p)
+				p->counter = (p->counter >> 1) + p->priority;
+			read_unlock(&tasklist_lock);
 		}
 	}
 
@@ -751,10 +753,8 @@
 	 * thus we have to lock the previous process from getting
 	 * rescheduled during switch_to().
 	 */
-	prev->has_cpu = 1;
-
- 	next->has_cpu = 1;
  	next->processor = this_cpu;
+ 	next->has_cpu = 1;
 	spin_unlock(&scheduler_lock);
 #endif /* __SMP__ */
  	if (prev != next) {
diff -u --recursive --new-file v2.2.1/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.2.1/linux/kernel/sysctl.c	Wed Jan 13 15:00:44 1999
+++ linux/kernel/sysctl.c	Sat Feb  6 12:22:24 1999
@@ -557,14 +557,19 @@
 				continue;
 			}
 			unregister_proc_table(table->child, de);
+
+			/* Don't unregister directories which still have entries.. */
+			if (de->subdir)
+				continue;
 		}
-		/* Don't unregister proc directories which still have
-		   entries... */
-		if (!((de->mode & S_IFDIR) && de->subdir)) {
-			proc_unregister(root, de->low_ino);
-			table->de = NULL;
-			kfree(de);
-		} 
+
+		/* Don't unregoster proc entries that are still being used.. */
+		if (de->count)
+			continue;
+
+		proc_unregister(root, de->low_ino);
+		table->de = NULL;
+		kfree(de);
 	}
 }
 
diff -u --recursive --new-file v2.2.1/linux/mm/filemap.c linux/mm/filemap.c
--- v2.2.1/linux/mm/filemap.c	Mon Jan 25 17:44:34 1999
+++ linux/mm/filemap.c	Mon Feb  8 15:25:49 1999
@@ -19,6 +19,7 @@
 #include <linux/blkdev.h>
 #include <linux/file.h>
 #include <linux/swapctl.h>
+#include <linux/slab.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -39,6 +40,26 @@
 
 #define release_page(page) __free_page((page))
 
+/* 
+ * Define a request structure for outstanding page write requests
+ * to the background page io daemon
+ */
+
+struct pio_request 
+{
+	struct pio_request *	next;
+	struct file *		file;
+	unsigned long		offset;
+	unsigned long		page;
+};
+static struct pio_request *pio_first = NULL, **pio_last = &pio_first;
+static kmem_cache_t *pio_request_cache;
+static struct wait_queue *pio_wait = NULL;
+
+static inline void 
+make_pio_request(struct file *, unsigned long, unsigned long);
+
+
 /*
  * Invalidate the pages of an inode, removing all pages that aren't
  * locked down (those are sure to be up-to-date anyway, so we shouldn't
@@ -1079,8 +1100,9 @@
 }
 
 static int filemap_write_page(struct vm_area_struct * vma,
-	unsigned long offset,
-	unsigned long page)
+			      unsigned long offset,
+			      unsigned long page,
+			      int wait)
 {
 	int result;
 	struct file * file;
@@ -1098,6 +1120,17 @@
 	 * and file could be released ... increment the count to be safe.
 	 */
 	file->f_count++;
+
+	/* 
+	 * If this is a swapping operation rather than msync(), then
+	 * leave the actual IO, and the restoration of the file count,
+	 * to the kpiod thread.  Just queue the request for now.
+	 */
+	if (!wait) {
+		make_pio_request(file, offset, page);
+		return 0;
+	}
+	
 	down(&inode->i_sem);
 	result = do_write_page(inode, file, (const char *) page, offset);
 	up(&inode->i_sem);
@@ -1113,7 +1146,7 @@
  */
 int filemap_swapout(struct vm_area_struct * vma, struct page * page)
 {
-	return filemap_write_page(vma, page->offset, page_address(page));
+	return filemap_write_page(vma, page->offset, page_address(page), 0);
 }
 
 static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
@@ -1150,7 +1183,7 @@
 			return 0;
 		}
 	}
-	error = filemap_write_page(vma, address - vma->vm_start + vma->vm_offset, page);
+	error = filemap_write_page(vma, address - vma->vm_start + vma->vm_offset, page, 1);
 	free_page(page);
 	return error;
 }
@@ -1568,4 +1601,128 @@
 	clear_bit(PG_locked, &page->flags);
 	wake_up(&page->wait);
 	__free_page(page);
+}
+
+
+/* Add request for page IO to the queue */
+
+static inline void put_pio_request(struct pio_request *p)
+{
+	*pio_last = p;
+	p->next = NULL;
+	pio_last = &p->next;
+}
+
+/* Take the first page IO request off the queue */
+
+static inline struct pio_request * get_pio_request(void)
+{
+	struct pio_request * p = pio_first;
+	pio_first = p->next;
+	if (!pio_first)
+		pio_last = &pio_first;
+	return p;
+}
+
+/* Make a new page IO request and queue it to the kpiod thread */
+
+static inline void make_pio_request(struct file *file,
+				    unsigned long offset,
+				    unsigned long page)
+{
+	struct pio_request *p;
+
+	atomic_inc(&mem_map[MAP_NR(page)].count);
+
+	/* 
+	 * We need to allocate without causing any recursive IO in the
+	 * current thread's context.  We might currently be swapping out
+	 * as a result of an allocation made while holding a critical
+	 * filesystem lock.  To avoid deadlock, we *MUST* not reenter
+	 * the filesystem in this thread.
+	 *
+	 * We can wait for kswapd to free memory, or we can try to free
+	 * pages without actually performing further IO, without fear of
+	 * deadlock.  --sct
+	 */
+
+	while ((p = kmem_cache_alloc(pio_request_cache, GFP_BUFFER)) == NULL) {
+		if (try_to_free_pages(__GFP_WAIT))
+			continue;
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(HZ/10);
+	}
+	
+	p->file   = file;
+	p->offset = offset;
+	p->page   = page;
+
+	put_pio_request(p);
+	wake_up(&pio_wait);
+}
+
+
+/*
+ * This is the only thread which is allowed to write out filemap pages
+ * while swapping.
+ * 
+ * To avoid deadlock, it is important that we never reenter this thread.
+ * Although recursive memory allocations within this thread may result
+ * in more page swapping, that swapping will always be done by queuing
+ * another IO request to the same thread: we will never actually start
+ * that IO request until we have finished with the current one, and so
+ * we will not deadlock.  
+ */
+
+int kpiod(void * unused)
+{
+	struct task_struct *tsk = current;
+	struct wait_queue wait = { tsk, };
+	struct inode * inode;
+	struct dentry * dentry;
+	struct pio_request * p;
+	
+	tsk->session = 1;
+	tsk->pgrp = 1;
+	strcpy(tsk->comm, "kpiod");
+	sigfillset(&tsk->blocked);
+	init_waitqueue(&pio_wait);
+	/*
+	 * Mark this task as a memory allocator - we don't want to get caught
+	 * up in the regular mm freeing frenzy if we have to allocate memory
+	 * in order to write stuff out.
+	 */
+	tsk->flags |= PF_MEMALLOC;
+
+	lock_kernel();
+	
+	pio_request_cache = kmem_cache_create("pio_request", 
+					      sizeof(struct pio_request),
+					      0, SLAB_HWCACHE_ALIGN, 
+					      NULL, NULL);
+	if (!pio_request_cache)
+		panic ("Could not create pio_request slab cache");
+
+	while (1) {
+		tsk->state = TASK_INTERRUPTIBLE;
+		add_wait_queue(&pio_wait, &wait);
+		if (!pio_first)
+			schedule();
+		remove_wait_queue(&pio_wait, &wait);
+		tsk->state = TASK_RUNNING;
+
+		while (pio_first) {
+			p = get_pio_request();
+			dentry = p->file->f_dentry;
+			inode = dentry->d_inode;
+			
+			down(&inode->i_sem);
+			do_write_page(inode, p->file,
+				      (const char *) p->page, p->offset);
+			up(&inode->i_sem);
+			fput(p->file);
+			free_page(p->page);
+			kmem_cache_free(pio_request_cache, p);
+		}
+	}
 }
diff -u --recursive --new-file v2.2.1/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.2.1/linux/mm/vmscan.c	Mon Jan 25 17:44:34 1999
+++ linux/mm/vmscan.c	Fri Feb  5 09:29:36 1999
@@ -202,7 +202,7 @@
 
 	do {
 		int result;
-		tsk->swap_address = address + PAGE_SIZE;
+		tsk->mm->swap_address = address + PAGE_SIZE;
 		result = try_to_swap_out(tsk, vma, address, pte, gfp_mask);
 		if (result)
 			return result;
@@ -274,7 +274,7 @@
 	/*
 	 * Go through process' page directory.
 	 */
-	address = p->swap_address;
+	address = p->mm->swap_address;
 
 	/*
 	 * Find the proper vm-area
@@ -296,8 +296,8 @@
 	}
 
 	/* We didn't find anything for the process */
-	p->swap_cnt = 0;
-	p->swap_address = 0;
+	p->mm->swap_cnt = 0;
+	p->mm->swap_address = 0;
 	return 0;
 }
 
@@ -345,9 +345,9 @@
 				continue;
 			/* Refresh swap_cnt? */
 			if (assign)
-				p->swap_cnt = p->mm->rss;
-			if (p->swap_cnt > max_cnt) {
-				max_cnt = p->swap_cnt;
+				p->mm->swap_cnt = p->mm->rss;
+			if (p->mm->swap_cnt > max_cnt) {
+				max_cnt = p->mm->swap_cnt;
 				pbest = p;
 			}
 		}
diff -u --recursive --new-file v2.2.1/linux/net/Makefile linux/net/Makefile
--- v2.2.1/linux/net/Makefile	Tue Dec 22 14:16:59 1998
+++ linux/net/Makefile	Sat Feb  6 12:46:21 1999
@@ -127,6 +127,8 @@
 
 ifeq ($(CONFIG_IRDA),y)
 SUB_DIRS += irda
+# There might be some irda features that are compiled as modules
+MOD_SUB_DIRS += irda
 else
   ifeq ($(CONFIG_IRDA),m)
   MOD_SUB_DIRS += irda
diff -u --recursive --new-file v2.2.1/linux/net/core/skbuff.c linux/net/core/skbuff.c
--- v2.2.1/linux/net/core/skbuff.c	Thu Sep 17 17:53:39 1998
+++ linux/net/core/skbuff.c	Sat Feb  6 12:46:21 1999
@@ -304,6 +304,9 @@
 	n->stamp=skb->stamp;
 	n->destructor = NULL;
 	n->security=skb->security;
+#ifdef CONFIG_IP_FIREWALL
+        n->fwmark = skb->fwmark;
+#endif
 	return n;
 }
 
@@ -350,6 +353,9 @@
 	n->stamp=skb->stamp;
 	n->destructor = NULL;
 	n->security=skb->security;
+#ifdef CONFIG_IP_FIREWALL
+        n->fwmark = skb->fwmark;
+#endif
 
 	return n;
 }
diff -u --recursive --new-file v2.2.1/linux/net/ipv4/fib_semantics.c linux/net/ipv4/fib_semantics.c
--- v2.2.1/linux/net/ipv4/fib_semantics.c	Mon Jan 25 17:44:34 1999
+++ linux/net/ipv4/fib_semantics.c	Mon Feb  8 09:26:29 1999
@@ -5,7 +5,7 @@
  *
  *		IPv4 Forwarding Information Base: semantics.
  *
- * Version:	$Id: fib_semantics.c,v 1.11 1998/10/03 09:37:12 davem Exp $
+ * Version:	$Id: fib_semantics.c,v 1.12 1999/01/26 05:33:44 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
diff -u --recursive --new-file v2.2.1/linux/net/ipv4/ip_masq_mfw.c linux/net/ipv4/ip_masq_mfw.c
--- v2.2.1/linux/net/ipv4/ip_masq_mfw.c	Mon Jan 25 17:44:34 1999
+++ linux/net/ipv4/ip_masq_mfw.c	Mon Feb  8 09:26:29 1999
@@ -3,7 +3,7 @@
  *
  *	Does (reverse-masq) forwarding based on skb->fwmark value
  *
- *	$Id: ip_masq_mfw.c,v 1.2 1998/12/12 02:40:42 davem Exp $
+ *	$Id: ip_masq_mfw.c,v 1.3 1999/01/26 05:33:47 davem Exp $
  *
  * Author:	Juan Jose Ciarlante   <jjciarla@raiz.uncu.edu.ar>
  *		  based on Steven Clarke's portfw
diff -u --recursive --new-file v2.2.1/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- v2.2.1/linux/net/ipv4/ip_output.c	Wed Jan 20 23:14:07 1999
+++ linux/net/ipv4/ip_output.c	Mon Feb  8 09:26:29 1999
@@ -5,7 +5,7 @@
  *
  *		The Internet Protocol (IP) output module.
  *
- * Version:	$Id: ip_output.c,v 1.64 1999/01/04 20:05:33 davem Exp $
+ * Version:	$Id: ip_output.c,v 1.65 1999/01/21 13:37:34 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
diff -u --recursive --new-file v2.2.1/linux/net/ipv4/proc.c linux/net/ipv4/proc.c
--- v2.2.1/linux/net/ipv4/proc.c	Sun Nov  8 14:03:14 1998
+++ linux/net/ipv4/proc.c	Mon Feb  8 09:26:29 1999
@@ -7,7 +7,7 @@
  *		PROC file system.  It is mainly used for debugging and
  *		statistics.
  *
- * Version:	$Id: proc.c,v 1.33 1998/10/21 05:44:35 davem Exp $
+ * Version:	$Id: proc.c,v 1.34 1999/02/08 11:20:34 davem Exp $
  *
  * Authors:	Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
@@ -184,6 +184,8 @@
 
 			for (req = sp->tp_pinfo.af_tcp.syn_wait_queue; req;
 			     i++, req = req->dl_next) {
+				if (req->sk)
+					continue;
 				pos += 128;
 				if (pos < offset) 
 					continue;
diff -u --recursive --new-file v2.2.1/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.2.1/linux/net/ipv4/tcp_input.c	Mon Jan 25 17:44:34 1999
+++ linux/net/ipv4/tcp_input.c	Mon Feb  8 09:26:29 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.153 1999/01/20 07:20:03 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.155 1999/01/26 05:33:50 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
diff -u --recursive --new-file v2.2.1/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.2.1/linux/net/ipv4/tcp_ipv4.c	Thu Jan  7 15:11:42 1999
+++ linux/net/ipv4/tcp_ipv4.c	Mon Feb  8 09:26:29 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.164 1999/01/04 20:36:55 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.165 1999/02/08 11:19:56 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -751,7 +751,6 @@
 	if (sk->ip_pmtudisc != IP_PMTUDISC_DONT && sk->dst_cache) {
 		if (tp->pmtu_cookie > sk->dst_cache->pmtu &&
 		    !atomic_read(&sk->sock_readers)) {
-			lock_sock(sk); 
 			tcp_sync_mss(sk, sk->dst_cache->pmtu);
 
 			/* Resend the TCP packet because it's  
@@ -760,7 +759,6 @@
 			 * discovery.
 			 */
 			tcp_simple_retransmit(sk);
-			release_sock(sk);
 		} /* else let the usual retransmit timer handle it */
 	}
 }
@@ -1563,12 +1561,6 @@
 	}
 #endif /* CONFIG_FILTER */
 
-	/*
-	 *	socket locking is here for SMP purposes as backlog rcv
-	 *	is currently called with bh processing disabled.
-	 */
-	lock_sock(sk); 
-
 	/* 
 	 * This doesn't check if the socket has enough room for the packet.
 	 * Either process the packet _without_ queueing it and then free it,
@@ -1579,7 +1571,6 @@
 	if (sk->state == TCP_ESTABLISHED) { /* Fast path */
 		if (tcp_rcv_established(sk, skb, skb->h.th, skb->len))
 			goto reset;
-		release_sock(sk);
 		return 0; 
 	} 
 
@@ -1590,14 +1581,21 @@
 		nsk = tcp_v4_hnd_req(sk, skb);
 		if (!nsk) 
 			goto discard;
-		lock_sock(nsk);
-		release_sock(sk);
+
+		/*
+		 * Queue it on the new socket if the new socket is active,
+		 * otherwise we just shortcircuit this and continue with
+		 * the new socket..
+		 */
+		if (atomic_read(&nsk->sock_readers)) {
+			__skb_queue_tail(&nsk->back_log, skb);
+			return 0;
+		}
 		sk = nsk;
 	}
 	
 	if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len))
 		goto reset;
-	release_sock(sk); 
 	return 0;
 
 reset:
@@ -1609,7 +1607,6 @@
 	 * might be destroyed here. This current version compiles correctly,
 	 * but you have been warned.
 	 */
-	release_sock(sk);  
 	return 0;
 }
 
diff -u --recursive --new-file v2.2.1/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.2.1/linux/net/ipv6/tcp_ipv6.c	Sun Nov  8 14:03:15 1998
+++ linux/net/ipv6/tcp_ipv6.c	Mon Feb  8 09:26:30 1999
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.94 1998/11/07 11:50:33 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.95 1999/02/08 11:20:03 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -641,10 +641,8 @@
 			sk->err_soft = -dst->error;
 		} else if (tp->pmtu_cookie > dst->pmtu
 			   && !atomic_read(&sk->sock_readers)) {
-			lock_sock(sk); 
 			tcp_sync_mss(sk, dst->pmtu);
 			tcp_simple_retransmit(sk);
-			release_sock(sk);
 		} /* else let the usual retransmit timer handle it */
 		dst_release(dst);
 		return;
@@ -1210,11 +1208,6 @@
 
   	ipv6_statistics.Ip6InDelivers++;
 
-	/* XXX We need to think more about socket locking
-	 * XXX wrt. backlog queues, __release_sock(), etc.  -DaveM
-	 */
-	lock_sock(sk); 
-
 	/* 
 	 * This doesn't check if the socket has enough room for the packet.
 	 * Either process the packet _without_ queueing it and then free it,
@@ -1255,8 +1248,16 @@
 		nsk = tcp_v6_hnd_req(sk, skb);
 		if (!nsk)
 			goto discard;
-		lock_sock(nsk);
-		release_sock(sk);
+
+		/*
+		 * Queue it on the new socket if the new socket is active,
+		 * otherwise we just shortcircuit this and continue with
+		 * the new socket..
+		 */
+		if (atomic_read(&nsk->sock_readers)) {
+			__skb_queue_tail(&nsk->back_log, skb);
+			return 0;
+		}
 		sk = nsk;
 	}
 
@@ -1264,7 +1265,6 @@
 		goto reset;
 	if (users)
 		goto ipv6_pktoptions;
-	release_sock(sk);
 	return 0;
 
 reset:
@@ -1273,7 +1273,6 @@
 	if (users)
 		kfree_skb(skb);
 	kfree_skb(skb);
-	release_sock(sk);  
 	return 0;
 
 ipv6_pktoptions:
@@ -1303,7 +1302,6 @@
 
 	if (skb)
 		kfree_skb(skb);
-	release_sock(sk);
 	return 0;
 }
 
diff -u --recursive --new-file v2.2.1/linux/net/netsyms.c linux/net/netsyms.c
--- v2.2.1/linux/net/netsyms.c	Fri Jan  8 22:36:27 1999
+++ linux/net/netsyms.c	Mon Feb  1 14:04:39 1999
@@ -382,6 +382,9 @@
 EXPORT_SYMBOL(ipv4_config);
 EXPORT_SYMBOL(dev_open);
 
+/* Used by other modules */
+EXPORT_SYMBOL(in_ntoa);
+
 EXPORT_SYMBOL(ip_rcv);
 EXPORT_SYMBOL(arp_rcv);
 EXPORT_SYMBOL(arp_tbl);
diff -u --recursive --new-file v2.2.1/linux/net/sunrpc/svcsock.c linux/net/sunrpc/svcsock.c
--- v2.2.1/linux/net/sunrpc/svcsock.c	Sun Nov  8 14:03:16 1998
+++ linux/net/sunrpc/svcsock.c	Sat Feb  6 12:46:22 1999
@@ -24,6 +24,7 @@
 #include <linux/fcntl.h>
 #include <linux/net.h>
 #include <linux/in.h>
+#include <linux/inet.h>
 #include <linux/udp.h>
 #include <linux/version.h>
 #include <linux/unistd.h>
@@ -546,14 +547,14 @@
 	 * we just punt connects from unprivileged ports. */
 	if (ntohs(sin.sin_port) >= 1024) {
 		printk(KERN_WARNING
-			"%s: connect from unprivileged port: %08lx:%d",
+			"%s: connect from unprivileged port: %s:%d",
 			serv->sv_name, 
-			ntohl(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+			in_ntoa(sin.sin_addr.s_addr), ntohs(sin.sin_port));
 		goto failed;
 	}
 
-	dprintk("%s: connect from %08lx:%04x\n", serv->sv_name,
-			ntohl(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+	dprintk("%s: connect from %s:%04x\n", serv->sv_name,
+			in_ntoa(sin.sin_addr.s_addr), ntohs(sin.sin_port));
 
 	if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0)))
 		goto failed;
diff -u --recursive --new-file v2.2.1/linux/scripts/Configure linux/scripts/Configure
--- v2.2.1/linux/scripts/Configure	Fri Nov 27 13:09:31 1998
+++ linux/scripts/Configure	Mon Feb  1 12:03:20 1999
@@ -1,4 +1,3 @@
-
 #! /bin/sh
 #
 # This script is used to configure the Linux kernel.
@@ -8,18 +7,8 @@
 # something better'' because the old configure script wasn't flexible
 # enough.
 #
-# Please send comments / questions / bug fixes to raymondc@microsoft.com.
-#
-#              ***** IMPORTANT COMPATIBILITY NOTE ****
-# If configuration changes are made which might adversely effect 
-# Menuconfig or xconfig, please notify the respective maintainers so that 
-# those utilities can be updated in parallel.
-#
-# Menuconfig:  <mec@shout.net>
-# xconfig:     <apenwarr@foxnet.net>  <eric@aib.com>
-#              ****************************************
-#
-# Each line in the config file is a command.
+# Raymond Chen was the original author of Configure.
+# Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
 #
 # 050793 - use IFS='@' to get around a bug in a pre-version of bash-1.13
 # with an empty IFS.
@@ -56,6 +45,9 @@
 #
 # 102598 Michael Chastain (mec@shout.net) - put temporary files in
 # current directory, not in /tmp.
+#
+# 24 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+# - Improve the exit message (Jeff Ronne).
 
 #
 # Make sure we're really running bash.
@@ -528,10 +520,13 @@
 mv .tmpconfig.h include/linux/autoconf.h
 
 echo
-echo "The Linux kernel should now be configured for your setup."
-echo "Check the top-level Makefile for additional configuration,"
-echo "and do a 'make dep ; make clean' if you want to be sure all"
-echo "the files are correctly re-made"
+echo "*** End of Linux kernel configuration."
+echo "*** Check the top-level Makefile for additional configuration."
+if [ ! -f .hdepend -o "$CONFIG_MODVERSIONS" = "y" ] ; then
+    echo "*** Next, you must run 'make dep'."
+else
+    echo "*** Next, you may run 'make zImage', 'make zdisk', or 'make zlilo'."
+fi
 echo
 
 exit 0
diff -u --recursive --new-file v2.2.1/linux/scripts/Menuconfig linux/scripts/Menuconfig
--- v2.2.1/linux/scripts/Menuconfig	Wed Jan 13 15:00:45 1999
+++ linux/scripts/Menuconfig	Mon Feb  1 12:03:20 1999
@@ -65,6 +65,9 @@
 # 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
 # Blow away lxdialog.scrltmp on entry to activate_menu.  This protects
 # against people who use commands like ' ' to select menus.
+#
+# 24 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+# - Improve the exit message (Jeff Ronne).
 
 
 #
@@ -1290,9 +1293,19 @@
 then
 	save_configuration
 	echo
-	echo The linux kernel is now configured for your setup.
+	echo
+	echo "*** End of Linux kernel configuration."
+	echo "*** Check the top-level Makefile for additional configuration."
+	if [ ! -f .hdepend -o "$CONFIG_MODVERSIONS" = "y" ] ; then
+	    echo "*** Next, you must run 'make dep'."
+	else
+	    echo "*** Next, you may run 'make zImage', 'make zdisk', or 'make zlilo.'"
+	fi
+	echo
 else
+	echo
     	echo 
 	echo Your kernel configuration changes were NOT saved.
+	echo
 fi
 exit 0
diff -u --recursive --new-file v2.2.1/linux/scripts/header.tk linux/scripts/header.tk
--- v2.2.1/linux/scripts/header.tk	Tue Jan 19 11:32:53 1999
+++ linux/scripts/header.tk	Mon Feb  1 12:03:20 1999
@@ -4,12 +4,17 @@
 # CHANGES
 # =======
 #
-# 8 January 1998, Michael Elizabeth Chastain, <mec@shout.net>
-# Remove unused do_cmd function (part of the 2.0 sound support).
-# Arrange buttons in three columns for better screen fitting.
-# Add CONSTANT_Y, CONSTANT_M, CONSTANT_N for commands like:
-#   dep_tristate 'foo' CONFIG_FOO m
+# 8 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+# - Remove unused do_cmd function (part of the 2.0 sound support).
+# - Arrange buttons in three columns for better screen fitting.
+# - Add CONSTANT_Y, CONSTANT_M, CONSTANT_N for commands like:
+#     dep_tristate 'foo' CONFIG_FOO m
 #
+# 23 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+# - Shut vfix the hell up.
+#
+# 24 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+# - Improve the exit message (Jeff Ronne).
 
 #
 # This is a handy replacement for ".widget cget" that requires neither tk4
@@ -27,7 +32,6 @@
 proc vfix { var } {
 	global $var
 	if [ catch {eval concat $$var} ] {
-		puts stdout "WARNING - broken Config.in!  $var was not declared!"
 		set $var 0
 	}
 }
@@ -428,8 +432,15 @@
 proc wrapup {w }  {
 	catch {destroy $w}
 	toplevel $w -class Dialog
-	message $w.m -width 400 -aspect 300 -text \
-		"The Linux kernel should now be configured for your setup. Check the top-level Makefile for additional configuration, and do a 'make dep ; make clean' if you want to be sure all the files are correctly re-made."  -relief raised 
+
+	global CONFIG_MODVERSIONS; vfix CONFIG_MODVERSIONS
+	if { ([file exists .hdepend] != 1) || ($CONFIG_MODVERSIONS == 1) } then {
+	    message $w.m -width 400 -aspect 300 -relief raised -text \
+		"End of Linux kernel configuration.  Check the top-level Makefile for additional configuration.  Next, you must run 'make dep'."
+	} else {
+	    message $w.m -width 400 -aspect 300 -relief raised -text \
+		"End of Linux kernel configuration.  Check the top-level Makefile for additional configuration.  Next, you may 'make bzImage', 'make bzdisk', or 'make bzlilo.'"
+	}
 	label $w.bm -bitmap info
 	pack $w.bm $w.m -pady 10 -side top -padx 10
 	wm title $w "Kernel build instructions" 
diff -u --recursive --new-file v2.2.1/linux/scripts/lxdialog/checklist.c linux/scripts/lxdialog/checklist.c
--- v2.2.1/linux/scripts/lxdialog/checklist.c	Tue Mar 10 10:03:37 1998
+++ linux/scripts/lxdialog/checklist.c	Mon Feb  1 12:03:20 1999
@@ -157,6 +157,14 @@
     wattrset (dialog, dialog_attr);
     waddch (dialog, ACS_RTEE);
 
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
     if (title != NULL) {
 	wattrset (dialog, title_attr);
 	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
diff -u --recursive --new-file v2.2.1/linux/scripts/lxdialog/inputbox.c linux/scripts/lxdialog/inputbox.c
--- v2.2.1/linux/scripts/lxdialog/inputbox.c	Sun Mar 24 10:02:36 1996
+++ linux/scripts/lxdialog/inputbox.c	Mon Feb  1 12:03:20 1999
@@ -69,6 +69,14 @@
     wattrset (dialog, dialog_attr);
     waddch (dialog, ACS_RTEE);
 
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
     if (title != NULL) {
 	wattrset (dialog, title_attr);
 	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
diff -u --recursive --new-file v2.2.1/linux/scripts/lxdialog/menubox.c linux/scripts/lxdialog/menubox.c
--- v2.2.1/linux/scripts/lxdialog/menubox.c	Wed Jan 13 15:00:45 1999
+++ linux/scripts/lxdialog/menubox.c	Mon Feb  1 12:03:20 1999
@@ -189,6 +189,14 @@
     wbkgdset (dialog, dialog_attr & A_COLOR);
     waddch (dialog, ACS_RTEE);
 
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
     if (title != NULL) {
 	wattrset (dialog, title_attr);
 	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
diff -u --recursive --new-file v2.2.1/linux/scripts/lxdialog/msgbox.c linux/scripts/lxdialog/msgbox.c
--- v2.2.1/linux/scripts/lxdialog/msgbox.c	Tue Feb  6 23:47:28 1996
+++ linux/scripts/lxdialog/msgbox.c	Mon Feb  1 12:03:20 1999
@@ -43,6 +43,14 @@
 
     draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
 
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
     if (title != NULL) {
 	wattrset (dialog, title_attr);
 	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
diff -u --recursive --new-file v2.2.1/linux/scripts/lxdialog/textbox.c linux/scripts/lxdialog/textbox.c
--- v2.2.1/linux/scripts/lxdialog/textbox.c	Thu Nov 12 16:21:25 1998
+++ linux/scripts/lxdialog/textbox.c	Mon Feb  1 12:03:20 1999
@@ -106,6 +106,14 @@
     wbkgdset (dialog, dialog_attr & A_COLOR);
     waddch (dialog, ACS_RTEE);
 
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
     if (title != NULL) {
 	wattrset (dialog, title_attr);
 	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
diff -u --recursive --new-file v2.2.1/linux/scripts/lxdialog/yesno.c linux/scripts/lxdialog/yesno.c
--- v2.2.1/linux/scripts/lxdialog/yesno.c	Sat Mar  2 23:22:25 1996
+++ linux/scripts/lxdialog/yesno.c	Mon Feb  1 12:03:20 1999
@@ -63,6 +63,14 @@
     wattrset (dialog, dialog_attr);
     waddch (dialog, ACS_RTEE);
 
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
     if (title != NULL) {
 	wattrset (dialog, title_attr);
 	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
diff -u --recursive --new-file v2.2.1/linux/scripts/tkgen.c linux/scripts/tkgen.c
--- v2.2.1/linux/scripts/tkgen.c	Wed Jan 20 23:14:07 1999
+++ linux/scripts/tkgen.c	Mon Feb  1 12:03:19 1999
@@ -89,6 +89,9 @@
  *   drives/net/Config.in and other places.
  * - Fix menu line wraparound at 128 menus (some fool used a 'char' for
  *   a counter).
+ *
+ * 23 January 1999, Michael Elizabeth Chastain <mec@shout.net>
+ * - Remove bug-compatible code.
  */
 
 #include <stdio.h>
@@ -749,11 +752,9 @@
 	    break;
 
 	case token_endmenu:
-#if ! defined(BUG_COMPATIBLE)
 	    /* flatten menus with proper scoping */
 	    if ( --menu_depth < 0 )
 		{ fprintf( stderr, "unmatched endmenu\n" ); exit( 1 ); }
-#endif
 	    break;
 
 	case token_bool:
diff -u --recursive --new-file v2.2.1/linux/scripts/tkparse.c linux/scripts/tkparse.c
--- v2.2.1/linux/scripts/tkparse.c	Wed Jan 20 23:14:07 1999
+++ linux/scripts/tkparse.c	Mon Feb  1 12:03:19 1999
@@ -26,6 +26,9 @@
  *   every architecture and comparing it character-for-character against
  *   the output of the old tkparse.
  *
+ * 23 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+ * - Remove bug-compatible code.
+ *
  * TO DO:
  * - xconfig is at the end of its life cycle.  Contact <mec@shout.net> if
  *   you are interested in working on the replacement.
@@ -434,25 +437,14 @@
 
     case token_define_bool:
 	pnt = get_string( pnt, &cfg->optionname );
-#if ! defined(BUG_COMPATIBLE)
 	while ( *pnt == ' ' || *pnt == '\t' )
 	    pnt++;
-#endif
 	if      ( *pnt == 'n' || *pnt == 'N' ) cfg->value = "0";
 	else if ( *pnt == 'y' || *pnt == 'Y' ) cfg->value = "1";
 	else if ( *pnt == 'm' || *pnt == 'M' ) cfg->value = "2";
 	else
 	{
-#if ! defined(BUG_COMPATIBLE)
 	    syntax_error( "unknown define_bool value" );
-#else
-	    /*
-	     * This ought to give the same output as printf'ing
-	     * through the null pointer ... I don't want to be
-	     * SIGSEGV compatible!
-	     */
-	    cfg->value = "(null)";
-#endif
 	}
 	break;
 
@@ -558,12 +550,7 @@
     if ( infile == NULL )
     {
 	sprintf( buffer, "unable to open %s", filename );
-#if defined(BUG_COMPATIBLE)
-	fprintf( stderr, "%s\n", buffer );
-	return;
-#else
 	syntax_error( buffer );
-#endif
     }
 
     /* push the new file name and line number */
diff -u --recursive --new-file v2.2.1/linux/scripts/tkparse.h linux/scripts/tkparse.h
--- v2.2.1/linux/scripts/tkparse.h	Wed Jan 20 23:14:07 1999
+++ linux/scripts/tkparse.h	Mon Feb  1 12:03:19 1999
@@ -3,14 +3,6 @@
  */
 
 /*
- * Define this symbol to generate exactly the same output, byte for byte,
- * as the previous version of xconfig.  I need to do this to make sure I
- * I don't break anything in my moby edit. -- mec
- */
-
-#define BUG_COMPATIBLE
-
-/*
  * Token types (mostly statement types).
  */
 
diff -u --recursive --new-file v2.2.1/linux/scripts/ver_linux linux/scripts/ver_linux
--- v2.2.1/linux/scripts/ver_linux	Tue Jan 19 11:32:54 1999
+++ linux/scripts/ver_linux	Sat Feb  6 12:46:22 1999
@@ -4,6 +4,7 @@
 # /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may
 # differ on your system.
 #
+PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH
 echo '-- Versions installed: (if some fields are empty or looks'
 echo '-- unusual then possibly you have very old versions)'
 uname -a
