diff -u --recursive --new-file v2.1.17/linux/CREDITS linux/CREDITS
--- v2.1.17/linux/CREDITS	Sun Dec 22 16:37:16 1996
+++ linux/CREDITS	Tue Dec 24 11:48:03 1996
@@ -767,6 +767,13 @@
 D: Author of the dialog utility, foundation
 D: for Menuconfig's lxdialog.
 
+N: David van Leeuwen
+E: david@tm.tno.nl
+D: Philips/LMS cm206 cdrom driver, generic cdrom driver
+S: Scheltemalaan 14
+S: 3817 KS Amersfoort
+S: The Netherlands
+
 N: Volker Lendecke
 E: lendecke@namu01.Num.Math.Uni-Goettingen.de
 D: Kernel smbfs (to mount WfW, NT and OS/2 network drives.)
@@ -1148,6 +1155,11 @@
 S: 1407 Broad Street
 S: Waynesboro, Virginia  22980
 S: USA
+
+N: Andrew J. Robinson
+E: arobinso@nyx.net
+W: http://www.nyx.net/~arobinso
+D: Hayes ESP serial port driver
 
 N: Florian La Roche
 E: rzsfl@rz.uni-sb.de
diff -u --recursive --new-file v2.1.17/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.17/linux/Documentation/Configure.help	Sun Dec 22 16:37:17 1996
+++ linux/Documentation/Configure.help	Tue Dec 24 11:39:07 1996
@@ -3553,22 +3553,21 @@
   whenever you want), say M here and read Documentation/modules.txt.
 
 Hayes ESP serial port support
-CONFIG_ESP
+CONFIG_ESPSERIAL
   This is a driver which supports Hayes ESP serial ports.  It uses DMA
   to transfer data to and from the host.  Make sure to read
   drivers/char/README.esp. To compile this driver as a module ( = code
   which can be inserted in and removed from the running kernel
   whenever you want), say M here and read Documentation/modules.txt.
-  This driver may be compiled as a loadable module.
 
 Hayes ESP serial port DMA channel
-CONFIG_ESP_DMA_CHANNEL
+CONFIG_ESPSERIAL_DMA_CHANNEL
   This is the DMA channel to be used to transfer data to and from the host.
   One DMA channel is shared between all the ESP ports.   Valid values are
   1 and 3.
 
 Hayes ESP serial port trigger level
-CONFIG_ESP_TRIGGER_LEVEL
+CONFIG_ESPSERIAL_TRIGGER_LEVEL
   This is the trigger level (in bytes) of the transmit FIFO and the receive
   FIFO.  Larger values may result in fewer interrupts; however, a value too
   high could result in data loss.  Valid values are 1 through 1015.
@@ -4567,6 +4566,20 @@
   sharing a hard disk between i386 and m68k Linux boxes, for example.
   Say Y if you need this feature; users who are only using their
   system-native partitioning scheme can say N here.
+
+Sparc ESP SCSI support
+CONFIG_SCSI_SUNESP
+  This is the driver for the Sun ESP SCSI host adapter. The ESP
+  chipset is present in most SPARC-based computers.
+
+Sparc /dev/openprom compatibility driver
+CONFIG_SUN_OPENPROMIO
+  This driver provides user programs with an interface to the Sparc
+  PROM device tree. The driver implements a SunOS-compatible
+  interface and a NetBSD-compatible interface. If you want to
+  compile this as a module ( = code which can be inserted in and
+  removed from the running kernel whenever you want), say M and read
+  Documentation/modules.txt. If unsure, say Y.
 
 # need an empty line after last entry, for sed script in Configure.
 
diff -u --recursive --new-file v2.1.17/linux/Documentation/cdrom/cdrom-standard.tex linux/Documentation/cdrom/cdrom-standard.tex
--- v2.1.17/linux/Documentation/cdrom/cdrom-standard.tex	Tue Nov 12 15:56:01 1996
+++ linux/Documentation/cdrom/cdrom-standard.tex	Tue Dec 24 11:48:03 1996
@@ -1,5 +1,5 @@
 \documentclass{article}
-\def\version{$Id: cdrom-standard.tex,v 1.2 1996/09/22 20:18:00 david Exp $}
+\def\version{$Id: cdrom-standard.tex,v 1.6 1996/12/23 21:17:44 david Exp $}
 
 \evensidemargin=0pt
 \oddsidemargin=0pt
@@ -128,12 +128,14 @@
 one of the cheapest \cdrom\ drives was a Philips cm206, a double-speed
 proprietary drive. In the months that I was busy writing a \linux\ 
 driver for it, proprietary drives became old-fashioned and IDE/ATAPI
-drives became standard. At the time of writing (April 1996) the
-cheapest double speed drive is IDE and at one fifth of the price of
-its predecessor. Eight speed drives are available now.)
-
-This document defines (in pre-release versions: proposes) the various
-$ioctl$s, and the way the drivers should implement this.
+drives became standard. At the time of writing (December 1996) the
+cheapest drive is quadruple speed IDE and at less than half the price
+of its predecessor. Twelve speed drives are available now.)
+
+This document defines the various $ioctl$s, and the way the drivers
+should implement this. Currently (in the kernel 2.1.$n$ development
+line) three low-level \cdrom\ drivers use this interface, among
+which are the most important drivers for IDE and SCSI. 
 
 \section{Standardizing through another software level}
 \label{cdrom.c}
@@ -166,7 +168,7 @@
 \halign{$#$\ \hfil&$#$\ \hfil&$/*$ \rm# $*/$\hfil\cr
 struct& file_operations\ cdrom_fops = \{\hidewidth\cr
         &NULL,                  & lseek \cr
-        &block_read,            & read---general\ block-dev\ read \cr
+        &block_read,            & read---general block-dev read \cr
         &block_write,           & write---general block-dev write \cr
         &NULL,                  & readdir \cr
         &NULL,                  & select \cr
@@ -176,7 +178,7 @@
         &cdrom_release,         & release \cr
         &NULL,                  & fsync \cr
         &NULL,                  & fasync \cr
-        &cdrom_media_changed,   & media_change \cr
+        &cdrom_media_changed,   & media change \cr
         &NULL                   & revalidate \cr
 \};\cr
 }
@@ -193,11 +195,11 @@
 routines in \cdromc, not to the VFS any more. The interfacing with
 \cdromc\ is implemented trough two general structures, that contain
 information about the capabilities of the driver, and the specific
-drives on which the driver operates. The structures are seperated to
+drives on which the driver operates. The structures are separated to
 contain information about
 \begin{description}
 \item[the low-level driver] It lists the routines that actually
-  implement cdrom operations, and hence the structure is called
+  implement \cdrom\ operations, and hence the structure is called
   $cdrom_device_ops$. The structure is conceptually connected to the
   major number of the device (although some drivers may have have
   different major numbers, as is the case for the IDE driver).
@@ -209,20 +211,20 @@
 
 The registration is done for each drive found by the driver (and hence
 for each minor number) though the call
-$$register_cdrom(kdev_t\ dev, char * name, 
-  struct\ cdrom_device_info\ <device>_info)
+$$register_cdrom(struct\ cdrom_device_info * <device>_info, char * name)  
 $$
-This device information structure (described shortly) contains all
-information needed for the kernel to interface with the low-level
-cdrom device driver. One of the main entries of this structure is a
-pointer to the $cdrom_device_ops$ structure of the driver.
-
-This device operations structure lists the implemented routines for
-interfacing to the hardware. [It is impossible to come up with a
-complete list of all capabilities of (future) \cdrom\ drives, as the
-developments in technology follow-up at an incredible rate. Maybe
-write-operation (WORM devices) will become very popular in the
-future.]  The list now is:
+This device information structure $<device>_info$ (described
+shortly) contains all information needed for the kernel to interface
+with the low-level \cdrom\ device driver. One of the main entries of
+this structure is a pointer to the $cdrom_device_ops$ structure of the
+driver.
+
+This device operations structure $cdrom_device_ops$ lists the
+implemented routines for interfacing to the hardware. [It is
+impossible to come up with a complete list of all capabilities of
+(future) \cdrom\ drives, as the developments in technology follow-up
+at an incredible rate. Maybe write-operation (WORM devices) will
+become very popular in the future.]  The list now is:
 $$
 \halign{$#$\ \hfil&$#$\ \hfil&\hbox to 10em{$#$\hss}&
   $/*$ \rm# $*/$\hfil\cr
@@ -236,14 +238,17 @@
   &int& (* lock_door)(struct\ cdrom_device_info *, int);\cr
   &int& (* select_speed)(struct\ cdrom_device_info *, int);\cr
   &int& (* select_disc)(struct\ cdrom_device_info *, int);\cr
-  &int& (* get_last_session) (struct\ cdrom_device_info *, struct\ cdrom_multisession *{});\cr
+  &int& (* get_last_session) (struct\ cdrom_device_info *, 
+        struct\ cdrom_multisession *{});\cr
   &int& (* get_mcn)(struct\ cdrom_device_info *, struct\ cdrom_mcn *{});\cr
   &int& (* reset)(struct\ cdrom_device_info *);\cr
-  &int& (* audio_ioctl)(struct\ cdrom_device_info *, unsigned\ int, void *{});\cr 
-  &int& (* dev_ioctl)(struct\ cdrom_device_info *, unsigned\ int, unsigned\ long);\cr
+  &int& (* audio_ioctl)(struct\ cdrom_device_info *, unsigned\ int, 
+        void *{});\cr 
+  &int& (* dev_ioctl)(struct\ cdrom_device_info *, unsigned\ int, 
+        unsigned\ long);\cr
 \noalign{\medskip}
   &\llap{const\ }int& capability;&  capability flags \cr
-  &int& n_minors;& number of supported minor devices \cr
+  &int& n_minors;& number of active minor devices \cr
 }
 $$
 The \cdrom-driver should simply implement (some of) these
@@ -254,14 +259,14 @@
 value indicating the number of minor devices that are supported by the
 driver, normally~1. Although these two variables are `informative'
 rather than `operational,' they are included in $cdrom_device_ops$
-because they describe the cabability of the {\em driver\/} rather than
+because they describe the capability of the {\em driver\/} rather than
 the {\em drive}. Nomenclature has always been difficult in computer
 programming. 
 
 Note that most functions have fewer parameters than their
 $blkdev_fops$ counterparts. This is because very little of the
 information in the structures $inode$ and $file$ are used, the main
-parameter is the device $dev$, from which the minor-number can be
+parameter is the first, from which the major and minor number can be
 extracted. (Most low-level \cdrom\ drivers don't even look at that value
 as only one device is supported.) This will be available through $dev$
 in $cdrom_device_info$ described below. 
@@ -272,11 +277,11 @@
 \halign{$#$\ \hfil&$#$\ \hfil&\hbox to 10em{$#$\hss}&
   $/*$ \rm# $*/$\hfil\cr
 struct& cdrom_device_info\ \{ \hidewidth\cr
-  & \llap{$const\ $}struct\ cdrom_device_ops *& ops;& device operations for this major\cr
+  & struct\ cdrom_device_ops *& ops;& device operations for this major\cr
   & struct\ cdrom_device_info *& next;& next device_info for this major\cr
   & void *&  handle;& driver-dependent data\cr
 \noalign{\medskip}
-  & \llap{$const\ $}kdev_t&  dev;& device number (incorporates minor)/\cr
+  & kdev_t&  dev;& device number (incorporates minor)/\cr
   & int& mask;& mask of capability: disables them \cr
   &\llap{$const\ $}int& speed;&  maximum speed for reading data \cr
   &\llap{$const\ $}int& n_discs;& number of discs in jukebox \cr
@@ -287,7 +292,7 @@
 \}\cr
 }$$
 
-With this $struct$, a linked list of minor devices registrered with
+With this $struct$, a linked list of minor devices registered with
 the same low-level driver is built, though the field $next$.  The
 device number, the device operations struct and specifications of
 properties of the drive are stored in this structure.
@@ -296,7 +301,7 @@
 listed in $ops\to capability$, if a specific drive doesn't support a
 feature of the driver. The value $speed$ specifies the maximum
 head-rate of the drive, measured in units of normal audio speed
-(176\,kB/sec raw data or 150\,kB/sec filesystem data).  The value
+(176\,kB/sec raw data or 150\,kB/sec file system data).  The value
 $n_discs$ should reflect the number of discs the drive can hold
 simultaneously, if it is designed as a juke-box, or otherwise~1.
 The parameters are declared $const$ because they describe properties
@@ -453,10 +458,16 @@
 rate. If the drive doesn't have this `auto-selection' capability, the
 decision should be made on the current disc loaded and the return
 value should be positive. A negative return value indicates an
-error. (Although the audio-low-pass filters probably aren't designed
-for it, more than real-time playback of audio might be used for
-high-speed copying of audio tracks). Badly pressed \cdrom s may
-benefit from less-than-maximum head rate.
+error. 
+
+There are a few reasons for having the speed to be selectable. Badly
+pressed \cdrom s may benefit from less-than-maximum head rate. Modern
+\cdrom\ drives can obtain very high head rates (up to twelve times
+audio speed is common), but these drives tend to make an annoyingly
+loud noise. A lower speed may reduce this. Finally, although the
+audio-low-pass filters probably aren't designed for it, more than
+real-time playback of audio might be used for high-speed copying of
+audio tracks.
 
 \subsection{$Select_disc(struct\ cdrom_device_info * cdi, int\ number)$}
 
@@ -573,10 +584,10 @@
 accidentally tampering with the contents. The capability fags actually
 inform \cdromc\ on what the driver is capable of. If the drive found
 by the driver does not have the capability, is can be masked out by
-the $cdrom_device_info$ variable $mask$. For instance, the SCSI cdrom
-driver has implemeted the code for loading and ejecting cdrom's, and
+the $cdrom_device_info$ variable $mask$. For instance, the SCSI \cdrom\
+driver has implemented the code for loading and ejecting \cdrom's, and
 hence its corresponding flags in $capability$ will be set. But a SCSI
-cdrom drive might be a caddy system, which can't load the tray, and
+\cdrom\ drive might be a caddy system, which can't load the tray, and
 hence for this drive the $cdrom_device_info$ struct will have set
 the $CDC_CLOSE_TRAY$ bit in $mask$.
 
@@ -690,7 +701,7 @@
 control both the hardware and software of their supported products,
 and are large enough to set their own standard. They do not have to
 deal with a dozen or more different, competing hardware
-configurations.\footnote{Personally, I think that SUN's approach to
+configurations.\footnote{Incidentally, I think that SUN's approach to
 mounting \cdrom s is very good in origin: under Solaris a
 volume-daemon automatically mounts a newly inserted \cdrom\ under {\tt
 /cdrom/$<volume-name>$/}. In my opinion they should have pushed this
@@ -750,7 +761,7 @@
 belonging to \cdromc\ is called \ucdrom, but may be included in {\tt
 cdrom.h} in the future.
 
-\subsection{$struct\ file_operations\ cdrom_fops$}
+\subsection{$Struct\ file_operations\ cdrom_fops$}
 
 The contents of this structure has been described in
 section~\ref{cdrom.c}, and this structure should be used in
@@ -759,15 +770,15 @@
 register_blkdev(major, <name>, \&cdrom_fops);
 $$
 
-\subsection{$Int\ register_cdrom(kdev_t\ dev, char * name, struct\
-cdrom_device_info\ * cdi)$}
+\subsection{$Int\ register_cdrom( struct\ cdrom_device_info\ * cdi, 
+  char * name,)$}
 
 Similar to registering $cdrom_fops$ to the kernel, the device
 operations and information structures, as described in
 section~\ref{cdrom.c}, should be registered to the general \cdrom\ 
 interface:
 $$
-register_cdrom(dev, <name>, \&<device>_info);
+register_cdrom(\&<device>_info), <name>);
 $$
 This function returns zero upon success, and non-zero upon
 failure. The structure $<device>_info$ should have a pointer the
@@ -853,7 +864,7 @@
 \item[CDROMPLAYMSF] Play audio fragment specified in Minute, Second,
 Frame format, delimited by $arg$ of type $struct\ cdrom_msf *{}$.
 \item[CDROMPLAYTRKIND] Play audio fragment in track-index format
-delimited by $arg$ of type $struct\ cdrom_ti *{}$.
+delimited by $arg$ of type $struct\ \penalty-1000 cdrom_ti *{}$.
 \item[CDROMVOLCTRL] Set volume specified by $arg$ of type $struct\
 cdrom_volctrl *{}$.
 \item[CDROMVOLREAD] Read volume into by $arg$ of type $struct\
@@ -886,16 +897,23 @@
 \item[CDROM_MEDIA_CHANGED] Returns 1 if a disc has been changed since
   the last call. Note that calls to $cdrom_media_changed$ by the VFS
   are treated by an independent queue, so both mechanisms will detect
-  a media change once. Currently, \cdromc\ implements maximum 16 minors
-  per major device.
+  a media change once. For Juke-boxes, an extra argument $arg$
+  specifies the slot for which the information is given. The special
+  value $CDSL_CURRENT$ requests that information about the currently
+  selected slot is returned.
 \item[CDROM_DRIVE_STATUS] Returns the status of the drive by a call to
   $drive_status()$. Return values are as defined in section~\ref{drive
     status}. Note that this call doesn't return information on the
   current playing activity of the drive; this can be polled through an
-  $ioctl$ call to $CDROMSUBCHNL$.
+  $ioctl$ call to $CDROMSUBCHNL$. For Juke-boxes, an extra argument
+  $arg$ specifies the slot for which (possibly limited) information is
+  given. The special value $CDSL_CURRENT$ requests that information
+  about the currently selected slot is returned.
 \item[CDROM_DISC_STATUS] Returns the type of the disc currently in the
   drive by a call to $disc_status()$. Return values are as defined in
   section~\ref{disc status}.
+\item[CDROM_CHANGER_NSLOTS] Returns the number of slots in a
+  juke-box. 
 \end{description}
 
 \subsubsection{Device dependent $ioct$s}
@@ -908,48 +926,53 @@
 \begin{enumerate}
 \item Make a backup of your current driver. 
 \item Get hold of the files \cdromc\ and \ucdrom, they should be in
-the directory tree that came with this documentation. 
+  the directory tree that came with this documentation.
 \item Include {\tt \char`\<linux/ucdrom.h>} just after {\tt cdrom.h}.
 \item Change the 3rd argument of $register_blkdev$ from
 $\&<your-drive>_fops$ to $\&cdrom_fops$. 
-\item Just after that line, add a line to register to the \cdrom\
-routines: 
-$$register_cdrom(major, <name>, <your-drive>_dops);$$
-Similarly, add a call to $unregister_cdrom()$. 
-\item Copy an example of the device-operations $struct$ to your source,
-e.g., from {\tt cm206.c} $cm206_dops$, and change all entries to names
-corresponding to your driver, or names you just happen to like. If
-your driver doesn't support a certain function, make the entry
-$NULL$. At the entry $capability$ you should list all capabilities
-your drive could support, in principle. If your drive has a capability
-that is not listed, please send me a message.
+\item Just after that line, add a line to register to the \cdrom\ 
+  routines:
+  $$register_cdrom(\&<your-drive>_info, <name>);$$
+  Similarly, add a
+  call to $unregister_cdrom()$.
+\item Copy an example of the device-operations $struct$ to your
+  source, e.g., from {\tt cm206.c} $cm206_dops$, and change all
+  entries to names corresponding to your driver, or names you just
+  happen to like. If your driver doesn't support a certain function,
+  make the entry $NULL$. At the entry $capability$ you should list all
+  capabilities your drive could support, in principle. If your drive
+  has a capability that is not listed, please send me a message.
+\item Copy the $cdrom_device_info$ declaration from the same example
+  driver, and modify the entries according to your needs. If your
+  driver dynamically determines the capabilities of the hardware, this
+  structure should also be declared dynamically. 
 \item Implement all functions in your $<device>_dops$ structure,
-according to prototypes listed in \ucdrom, and specifications given in
-section~\ref{cdrom.c}. Most likely you have already implemented
-the code in a large part, and you may just have to adapt the prototype
-and return values. 
+  according to prototypes listed in \ucdrom, and specifications given
+  in section~\ref{cdrom.c}. Most likely you have already implemented
+  the code in a large part, and you may just have to adapt the
+  prototype and return values.
 \item Rename your $<device>_ioctl()$ function to $audio_ioctl$ and
-change the prototype a little. Remove entries listed in the first part
-in section~\ref{cdrom-ioctl}, if your code was OK, these are just calls
-to the routines you adapted in the previous step. 
+  change the prototype a little. Remove entries listed in the first
+  part in section~\ref{cdrom-ioctl}, if your code was OK, these are
+  just calls to the routines you adapted in the previous step.
 \item You may remove all remaining memory checking code in the
-$audio_ioctl()$ function that deals with audio commands (these are
-listed in the second part of section~\ref{cdrom-ioctl}). There is no
-need for memory allocation either, so most $case$s in the $switch$
-statement look similar to:
-$$
-case\ CDROMREADTOCENTRY\colon
-get_toc_entry\bigl((struct\ cdrom_tocentry *{})\ arg\bigr);
-$$
+  $audio_ioctl()$ function that deals with audio commands (these are
+  listed in the second part of section~\ref{cdrom-ioctl}). There is no
+  need for memory allocation either, so most $case$s in the $switch$
+  statement look similar to:
+  $$
+  case\ CDROMREADTOCENTRY\colon get_toc_entry\bigl((struct\ 
+  cdrom_tocentry *{})\ arg\bigr);
+  $$
 \item All remaining $ioctl$ cases must be moved to a separate
-function, $<device>_ioctl$, the device-dependent $ioctl$s. Note that
-memory checking and allocation must be kept in this code!
+  function, $<device>_ioctl$, the device-dependent $ioctl$s. Note that
+  memory checking and allocation must be kept in this code!
 \item Change the prototypes of $<device>_open()$ and
-$<device>_release()$, and remove any strategic code (i.e., tray
-movement, door locking, etc.). 
+  $<device>_release()$, and remove any strategic code (i.e., tray
+  movement, door locking, etc.).
 \item Try to recompile the drivers. We advice you to use modules, both
-for {\tt cdrom.o} and your driver, as debugging is much easier this
-way.
+  for {\tt cdrom.o} and your driver, as debugging is much easier this
+  way.
 \end{enumerate} 
 
 \section{Thanks}
@@ -965,7 +988,87 @@
 place.
 
 \vfill
-$\version$
+$ \version\ $
 \eject
 \end{document}
 
+\def\versionlog{
+$Log: cdrom-standard.tex,v $
+Revision 1.6  1996/12/23 21:17:44  david
+Added reasons for speed selection.
+
+Revision 1.5  1996/12/22 21:54:25  david
+Repared version definition.
+
+Revision 1.4  1996/12/22 21:40:26  david
+Added older version log at end of text.
+
+Revision 1.3  1996/12/22 21:31:58  david
+Adapted text to fit kernel changes up to 2.1.15.
+
+Sun Dec 22 21:31:58 1996  David A. van Leeuwen  <david@ElseWare>
+
+        * cdrom-standard.tex: Adapted text to fit kernel changes up to 2.1.15.
+
+Sun Sep 22 20:18:00 1996  David
+
+        * cdrom-standard.tex:
+        Documentation adapted to align with developments started by Scott
+        Snyder, Gerd Knorr and myself.
+
+        Split _ops in _info (minor stuff) and _ops (major stuff).
+        Moved capability back to _ops, added n_minors.
+        Implemented use_count in _info.
+        Removed open_files().
+
+Sat Aug 10 10:57:16 1996  David 
+
+        * cdrom-standard.tex:
+        Weakened Eberhard's annoying comments by making it a quotation and
+        having it appear smaal-type. He doesn't react to my email-messages.
+
+        Changed float speed to int speed.
+
+Tue May 21 15:27:10 1996  David 
+
+        * cdrom-standard.tex:
+        Typographic errors introduced by Eberhard Moenkeberg were corrected,
+        as well one of my own typos. I deepfully respect the person that
+        corrects all typos i make in code and documentation!
+
+        Linux version 1.99.6.
+
+        * cdrom-standard.tex:
+        Changes made by Eberhard Moenkeberg, much to my annoyance. The
+        contents of the introduction were altered completely so that it now
+        says the opposite of what I wrote before: that there is no need for an
+        additional unform cdrom layer. This makes the whole document and the
+        project for that matter worthless.
+
+        ---david
+
+        * cdrom-standard.tex:
+        Version as it appeared first in the official kernel documentation
+        tree, Linux 1.99.2, Documentation/cdrom/cdrom-standard.tex.
+
+        Some improvements in use of English language have been made by people
+        that know better English than me.
+
+Wed Apr 17 20:46:34 1996  David 
+
+        * cdrom-standard.tex: changed #minors from 4 to 16.
+
+Sun Apr 14 20:53:17 1996  David 
+
+        * cdrom-standard.tex:
+        Update to go with cdrom.c version 0.3. More ioctl stuff.
+
+Wed Apr 10 18:00:28 1996  David 
+
+        * cdrom-standard.tex:
+        Version as first distributed among CDrom device driver authors.
+
+Mon Apr  8 18:25:21 1996  David A. van Leeuwen  <david@ElseWare>
+
+        * cdrom-standard.tex: *** empty log message ***
+}
diff -u --recursive --new-file v2.1.17/linux/Makefile linux/Makefile
--- v2.1.17/linux/Makefile	Sun Dec 22 16:37:20 1996
+++ linux/Makefile	Fri Dec 27 12:03:19 1996
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 17
+SUBLEVEL = 18
 
 ARCH = i386
 
@@ -176,7 +176,7 @@
 		$(FILESYSTEMS) \
 		$(DRIVERS) \
 		$(LIBS) -o vmlinux
-	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | sort > System.map
+	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)\|\(\.\.ng$$\)' | sort > System.map
 
 symlinks:
 	rm -f include/asm
diff -u --recursive --new-file v2.1.17/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.1.17/linux/arch/alpha/defconfig	Wed Dec 18 15:58:34 1996
+++ linux/arch/alpha/defconfig	Sun Dec 22 17:29:27 1996
@@ -62,6 +62,7 @@
 CONFIG_BLK_DEV_RAM=y
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_EZ is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -164,7 +165,6 @@
 # CONFIG_PLIP is not set
 # CONFIG_PPP is not set
 # CONFIG_NET_RADIO is not set
-# CONFIG_NET_HAM is not set
 # CONFIG_SLIP is not set
 # CONFIG_TR is not set
 
diff -u --recursive --new-file v2.1.17/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.1.17/linux/arch/alpha/kernel/entry.S	Tue Nov 19 15:53:53 1996
+++ linux/arch/alpha/kernel/entry.S	Fri Dec 27 12:03:19 1996
@@ -648,10 +648,14 @@
 	ldq	$20,72($30)	/* .. and this a3 */
 	subq	$31,$0,$0	/* with error in v0 */
 	addq	$31,1,$1	/* set a3 for errno return */
-	bis	$31,$31,$26	/* tell "ret_from_sys_call" that we can restart */
+	stq	$0,0($30)
+	bis	$31,$31,$26	/* tell "ret_from_sys_call" we can restart */
 	stq	$1,72($30)	/* a3 for return */
+	br	$31,ret_from_sys_call
+
 ret_success:
 	stq	$0,0($30)
+	stq	$31,72($30)	/* a3=0 => no error */
 	br	$31,ret_from_sys_call
 
 .align 3
@@ -777,4 +781,5 @@
 	.quad sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler, sys_sched_yield
 	.quad sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, do_entSys /* sys_afs_syscall */, sys_newuname
 	.quad sys_nanosleep, sys_mremap, do_entSys, sys_setresuid, sys_getresuid
-	.quad sys_pciconfig_read, sys_pciconfig_write, do_entSys, do_entSys, do_entSys
+	.quad sys_pciconfig_read, sys_pciconfig_write, sys_query_module
+	.quad do_entSys, do_entSys
diff -u --recursive --new-file v2.1.17/linux/arch/alpha/kernel/ksyms.c linux/arch/alpha/kernel/ksyms.c
--- v2.1.17/linux/arch/alpha/kernel/ksyms.c	Thu Oct 10 19:10:54 1996
+++ linux/arch/alpha/kernel/ksyms.c	Fri Dec 27 12:03:19 1996
@@ -12,6 +12,7 @@
 #include <linux/elfcore.h>
 #include <asm/io.h>
 #include <asm/hwrpb.h>
+#include <asm/uaccess.h>
 
 extern void bcopy (const char *src, char *dst, int len);
 extern struct hwrpb_struct *hwrpb;
@@ -30,83 +31,71 @@
 extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
 
 
-static struct symbol_table arch_symbol_table = {
-#include <linux/symtab_begin.h>
-	/* platform dependent support */
-
-	X(_inb),
-	X(_inw),
-	X(_inl),
-	X(_outb),
-	X(_outw),
-	X(_outl),
-	X(_readb),
-	X(_readw),
-	X(_readl),
-	X(_writeb),
-	X(_writew),
-	X(_writel),
-	X(__divl),
-	X(__reml),
-	X(__divq),
-	X(__remq),
-	X(__divlu),
-	X(__remlu),
-	X(__divqu),
-	X(__remqu),
-	X(insb),
-	X(insw),
-	X(insl),
-	X(outsb),
-	X(outsw),
-	X(outsl),
-	X(strcat),
-	X(strcmp),
-	X(strcpy),
-	X(strlen),
-	X(strncmp),
-	X(strncpy),
-	X(strnlen),
-	X(strstr),
-	X(strtok),
-	X(strchr),
-	X(memcmp),
-	X(memmove),
-	X(__memcpy),
-	X(__constant_c_memset),
-
-	X(dump_thread),
-	X(dump_fpu),
-	X(hwrpb),
-	X(wrusp),
-
-	/*
-	 * The following are special because they're not called
-	 * explicitly (the C compiler or assembler generates them in
-	 * response to division operations).  Fortunately, their
-	 * interface isn't gonna change any time soon now, so it's OK
-	 * to leave it out of version control.
-	 */
+/* platform dependent support */
+EXPORT_SYMBOL(_inb);
+EXPORT_SYMBOL(_inw);
+EXPORT_SYMBOL(_inl);
+EXPORT_SYMBOL(_outb);
+EXPORT_SYMBOL(_outw);
+EXPORT_SYMBOL(_outl);
+EXPORT_SYMBOL(_readb);
+EXPORT_SYMBOL(_readw);
+EXPORT_SYMBOL(_readl);
+EXPORT_SYMBOL(_writeb);
+EXPORT_SYMBOL(_writew);
+EXPORT_SYMBOL(_writel);
+EXPORT_SYMBOL(insb);
+EXPORT_SYMBOL(insw);
+EXPORT_SYMBOL(insl);
+EXPORT_SYMBOL(outsb);
+EXPORT_SYMBOL(outsw);
+EXPORT_SYMBOL(outsl);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(strtok);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(__memcpy);
+EXPORT_SYMBOL(__memset);
+EXPORT_SYMBOL(__constant_c_memset);
+
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(hwrpb);
+EXPORT_SYMBOL(wrusp);
+
+/*
+ * The following are specially called from the uaccess assembly stubs.
+ */
+EXPORT_SYMBOL_NOVERS(__copy_user);
+EXPORT_SYMBOL_NOVERS(__clear_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(__strlen_user);
+
+/*
+ * The following are special because they're not called
+ * explicitly (the C compiler or assembler generates them in
+ * response to division operations).  Fortunately, their
+ * interface isn't gonna change any time soon now, so it's OK
+ * to leave it out of version control.
+ */
 # undef bcopy
 # undef memcpy
 # undef memset
-	XNOVERS(__divl),
-	XNOVERS(__divlu),
-	XNOVERS(__divq),
-	XNOVERS(__divqu),
-	XNOVERS(__reml),
-	XNOVERS(__remlu),
-	XNOVERS(__remq),
-	XNOVERS(__remqu),
-	XNOVERS(memcpy),
-	XNOVERS(memset),
-	/* these shouldn't be necessary---they should be versioned: */
-	XNOVERS(__memcpy),
-	XNOVERS(__memset),
-#include <linux/symtab_end.h>
-};
-
-void arch_syms_export(void)
-{
-	register_symtab(&arch_symbol_table);
-}
+EXPORT_SYMBOL_NOVERS(__divl);
+EXPORT_SYMBOL_NOVERS(__divlu);
+EXPORT_SYMBOL_NOVERS(__divq);
+EXPORT_SYMBOL_NOVERS(__divqu);
+EXPORT_SYMBOL_NOVERS(__reml);
+EXPORT_SYMBOL_NOVERS(__remlu);
+EXPORT_SYMBOL_NOVERS(__remq);
+EXPORT_SYMBOL_NOVERS(__remqu);
+EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL_NOVERS(memset);
diff -u --recursive --new-file v2.1.17/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v2.1.17/linux/arch/alpha/kernel/traps.c	Fri Nov  1 17:13:14 1996
+++ linux/arch/alpha/kernel/traps.c	Fri Dec 27 12:03:19 1996
@@ -17,7 +17,8 @@
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
-void die_if_kernel(char * str, struct pt_regs * regs, long err)
+void die_if_kernel(char * str, struct pt_regs * regs, long err,
+		   unsigned long *r9_15)
 {
 	long i;
 	unsigned long sp;
@@ -27,19 +28,30 @@
 		return;
 	printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
 	sp = (unsigned long) (regs+1);
-	printk("pc = [<%lx>] ps = %04lx\n", regs->pc, regs->ps);
-	printk("rp = [<%lx>] sp = %lx\n", regs->r26, sp);
-	printk("r0=%lx r1=%lx r2=%lx r3=%lx\n",
-		regs->r0, regs->r1, regs->r2, regs->r3);
-	printk("r8=%lx\n", regs->r8);
-	printk("r16=%lx r17=%lx r18=%lx r19=%lx\n",
-		regs->r16, regs->r17, regs->r18, regs->r19);
-	printk("r20=%lx r21=%lx r22=%lx r23=%lx\n",
-		regs->r20, regs->r21, regs->r22, regs->r23);
-	printk("r24=%lx r25=%lx r26=%lx r27=%lx\n",
-		regs->r24, regs->r25, regs->r26, regs->r27);
-	printk("r28=%lx r29=%lx r30=%lx\n",
-		regs->r28, regs->gp, sp);
+	printk("pc = [<%016lx>] ps = %04lx\n", regs->pc, regs->ps);
+	printk("rp = [<%016lx>] sp = %016lx\n", regs->r26, sp);
+	printk("r0 = %016lx  r1 = %016lx\n", regs->r0, regs->r1);
+	printk("r2 = %016lx  r3 = %016lx\n", regs->r2, regs->r3);
+	printk("r4 = %016lx  r5 = %016lx\n", regs->r4, regs->r5);
+	printk("r6 = %016lx  r7 = %016lx\n", regs->r6, regs->r7);
+
+	if (r9_15) {
+		printk("r8 = %016lx  r9 = %016lx\n", regs->r8, r9_15[9]);
+		printk("r10= %016lx  r11= %016lx\n", r9_15[10], r9_15[11]);
+		printk("r12= %016lx  r13= %016lx\n", r9_15[12], r9_15[13]);
+		printk("r14= %016lx  r15= %016lx\n", r9_15[14], r9_15[15]);
+	} else {
+		printk("r8 = %016lx\n", regs->r8);
+	}
+
+	printk("r16= %016lx  r17= %016lx\n", regs->r16, regs->r17);
+	printk("r18= %016lx  r19= %016lx\n", regs->r18, regs->r19);
+	printk("r20= %016lx  r21= %016lx\n", regs->r20, regs->r21);
+	printk("r22= %016lx  r23= %016lx\n", regs->r22, regs->r23);
+	printk("r24= %016lx  r25= %016lx\n", regs->r24, regs->r25);
+	printk("r26= %016lx  r27= %016lx\n", regs->r26, regs->r27);
+	printk("r28= %016lx  r29= %016lx\n", regs->r28, regs->gp);
+
 	printk("Code:");
 	pc = (unsigned int *) regs->pc;
 	for (i = -3; i < 6; i++)
@@ -66,7 +78,7 @@
 	}
 	printk("%s: arithmetic trap at %016lx: %02lx %016lx\n",
 		current->comm, regs.pc, summary, write_mask);
-	die_if_kernel("Arithmetic fault", &regs, 0);
+	die_if_kernel("Arithmetic fault", &regs, 0, 0);
 	force_sig(SIGFPE, current);
 }
 
@@ -76,7 +88,7 @@
 {
 	extern int ptrace_cancel_bpt (struct task_struct *who);
 
-	die_if_kernel("Instruction fault", &regs, type);
+	die_if_kernel("Instruction fault", &regs, type, 0);
 	switch (type) {
 	      case 0: /* breakpoint */
 		if (ptrace_cancel_bpt(current)) {
diff -u --recursive --new-file v2.1.17/linux/arch/alpha/lib/strncpy_from_user.S linux/arch/alpha/lib/strncpy_from_user.S
--- v2.1.17/linux/arch/alpha/lib/strncpy_from_user.S	Fri Nov  1 17:13:14 1996
+++ linux/arch/alpha/lib/strncpy_from_user.S	Fri Dec 27 12:03:19 1996
@@ -313,12 +313,12 @@
 	stq_u	t0, 0(a0)	# e0    :
 
 $finish_up:
-	zapnot	t0, t10, t4	# was last byte written null?
+	zapnot	t0, t8, t4	# was last byte written null?
 	cmovne	t4, 1, t4
 
-	and	t10, 0xf0, t3	# binary search for the address of the
-	and	t10, 0xcc, t2	# last byte written
-	and	t10, 0xaa, t1
+	and	t8, 0xf0, t3	# binary search for the address of the
+	and	t8, 0xcc, t2	# last byte written
+	and	t8, 0xaa, t1
 	bic	a0, 7, t0
 	cmovne	t3, 4, t3
 	cmovne	t2, 2, t2
diff -u --recursive --new-file v2.1.17/linux/arch/alpha/mm/extable.c linux/arch/alpha/mm/extable.c
--- v2.1.17/linux/arch/alpha/mm/extable.c	Fri Nov  1 17:13:14 1996
+++ linux/arch/alpha/mm/extable.c	Fri Dec 27 12:03:19 1996
@@ -2,6 +2,8 @@
  * linux/arch/alpha/mm/extable.c
  */
 
+#include <linux/config.h>
+#include <linux/module.h>
 #include <asm/uaccess.h>
 
 extern const struct exception_table_entry __start___ex_table[];
@@ -10,8 +12,12 @@
 static inline unsigned
 search_one_table(const struct exception_table_entry *first,
 		 const struct exception_table_entry *last,
-		 signed int value)
+		 signed long value)
 {
+	/* Abort early if the search value is out of range.  */
+	if (value != (signed int)value)
+		return 0;
+
         while (first <= last) {
 		const struct exception_table_entry *mid;
 		long diff;
@@ -32,19 +38,24 @@
 search_exception_table(unsigned long addr)
 {
 	unsigned ret;
-	signed int reladdr;
 
-	/* Search the kernel's table first.  */
-	{
-		register unsigned long gp __asm__("$29");
-		reladdr = addr - gp;
+#ifndef CONFIG_MODULE
+	/* There is only the kernel to search.  */
+	register unsigned long gp __asm__("$29");
+	ret = search_one_table(__start___ex_table, __stop___ex_table - 1,
+			       addr - gp);
+	if (ret) return ret;
+#else
+	/* The kernel is the last "module" -- no need to treat it special. */
+	struct module *mp;
+	for (mp = module_list; mp ; mp = mp->next) {
+		if (!mp->ex_table_start)
+			continue;
+		ret = search_one_table(mp->ex_table_start,
+				       mp->ex_table_end - 1, addr - mp->gp);
+		if (ret) return ret;
 	}
-	ret = search_one_table(__start___ex_table,
-			       __stop___ex_table-1, reladdr);
-	if (ret)
-		return ret;
-
-	/* FIXME -- search the module's tables here */
+#endif
 
 	return 0;
 }
diff -u --recursive --new-file v2.1.17/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c
--- v2.1.17/linux/arch/alpha/mm/fault.c	Wed Dec 18 15:58:34 1996
+++ linux/arch/alpha/mm/fault.c	Fri Dec 27 12:03:19 1996
@@ -35,7 +35,7 @@
 }
 #endif
 
-extern void die_if_kernel(char *,struct pt_regs *,long);
+extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *);
 
 /*
  * This routine handles page faults.  It determines the address,
@@ -121,7 +121,7 @@
 		printk("%s: memory violation at pc=%08lx ra=%08lx "
 		       "(bad address = %08lx)\n",
 			tsk->comm, regs->pc, regs->r26, address);
-		die_if_kernel("oops", regs, cause);
+		die_if_kernel("oops", regs, cause, (unsigned long*)regs - 16);
 		force_sig(SIGSEGV, tsk);
 		return;
 	}
@@ -131,6 +131,6 @@
  */
 	printk(KERN_ALERT "Unable to handle kernel paging request at "
 	       "virtual address %016lx\n", address);
-	die_if_kernel("Oops", regs, cause);
+	die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16);
 	do_exit(SIGKILL);
 }
diff -u --recursive --new-file v2.1.17/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- v2.1.17/linux/arch/i386/kernel/bios32.c	Wed Dec 18 15:58:34 1996
+++ linux/arch/i386/kernel/bios32.c	Mon Dec 23 19:25:31 1996
@@ -105,6 +105,7 @@
 	char chars[16];
 };
 
+#ifdef CONFIG_PCI
 /*
  * Physical address of the service directory.  I don't know if we're
  * allowed to have more than one of these or not, so just in case
@@ -118,7 +119,6 @@
 	unsigned short segment;
 } bios32_indirect = { 0, KERNEL_CS };
 
-#ifdef CONFIG_PCI
 
 /*
  * function table for accessing PCI configuration space
@@ -619,7 +619,6 @@
       pci_conf2_write_config_dword
 };
 
-#endif
 
 struct pci_access *check_direct_pci(void)
 {
@@ -773,9 +772,11 @@
     return mem_start;
 }
 
+#endif
 
 unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
 {
+#ifdef CONFIG_PCI
 	union bios32 *check;
 	unsigned char sum;
 	int i, length;
@@ -818,7 +819,6 @@
 			}
 		}
 	}
-#ifdef CONFIG_PCI
 	if (bios32_entry) {
 		memory_start = check_pcibios (memory_start, memory_end);
 	}
diff -u --recursive --new-file v2.1.17/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.1.17/linux/arch/i386/kernel/entry.S	Thu Dec 12 19:36:57 1996
+++ linux/arch/i386/kernel/entry.S	Fri Dec 27 12:03:19 1996
@@ -17,7 +17,7 @@
  *
  * Stack layout in 'ret_from_system_call':
  * 	ptrace needs to have all regs on the stack.
- *	if the order here is changed, it needs to be 
+ *	if the order here is changed, it needs to be
  *	updated in fork.c:copy_process, signal.c:do_signal,
  *	ptrace.c and ptrace.h
  *
@@ -133,7 +133,7 @@
 
 /* macro ENTER_KERNEL waits for entering the kernel, increments
    kernel_counter, and reloads the processor variables if necessary
-   uses : %eax, %edx (pushed and popped) 
+   uses : %eax, %edx (pushed and popped)
 
    Note: We go to great pains to minimise the number of locked operations.
    We want to spin without locking, and lock when we attempt an update.
@@ -146,7 +146,7 @@
 #ifndef __SMP_PROF__
 
 #define SMP_PROF_A
-#define SMP_PROF_B 
+#define SMP_PROF_B
 
 #else
 
@@ -627,8 +627,9 @@
 	.long SYMBOL_NAME(sys_nanosleep)
 	.long SYMBOL_NAME(sys_mremap)
 	.long SYMBOL_NAME(sys_setresuid)
-	.long SYMBOL_NAME(sys_getresuid)
+	.long SYMBOL_NAME(sys_getresuid)	/* 165 */
 	.long SYMBOL_NAME(sys_vm86)
-	.rept NR_syscalls-166
+	.long SYMBOL_NAME(sys_query_module)
+	.rept NR_syscalls-167
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
diff -u --recursive --new-file v2.1.17/linux/arch/i386/kernel/ksyms.c linux/arch/i386/kernel/ksyms.c
--- v2.1.17/linux/arch/i386/kernel/ksyms.c	Wed Dec 18 15:58:34 1996
+++ linux/arch/i386/kernel/ksyms.c	Fri Dec 27 12:03:19 1996
@@ -13,43 +13,36 @@
 extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(elf_fpregset_t *);
 
-static struct symbol_table arch_symbol_table = {
-#include <linux/symtab_begin.h>
-	/* platform dependent support */
-	X(EISA_bus),
-	X(MCA_bus),
-	X(wp_works_ok),
-	X(__verify_write),
-	X(dump_thread),
-	X(dump_fpu),
-	X(ioremap),
-	X(iounmap),
-	XNOVERS(__down_failed),
-	XNOVERS(__up_wakeup),
+/* platform dependent support */
+EXPORT_SYMBOL(EISA_bus);
+EXPORT_SYMBOL(MCA_bus);
+EXPORT_SYMBOL(wp_works_ok);
+EXPORT_SYMBOL(__verify_write);
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(ioremap);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL_NOVERS(__down_failed);
+EXPORT_SYMBOL_NOVERS(__up_wakeup);
+
 #ifdef __SMP__
-	X(apic_reg),		/* Needed internally for the I386 inlines */
-	X(cpu_data),
-	X(syscall_count),
-	X(kernel_flag),
-	X(kernel_counter),
-	X(active_kernel_processor),
-	X(smp_invalidate_needed),
+EXPORT_SYMBOL(apic_reg);	/* Needed internally for the I386 inlines */
+EXPORT_SYMBOL(cpu_data);
+EXPORT_SYMBOL(syscall_count);
+EXPORT_SYMBOL(kernel_flag);
+EXPORT_SYMBOL(kernel_counter);
+EXPORT_SYMBOL(active_kernel_processor);
+EXPORT_SYMBOL(smp_invalidate_needed);
 #endif
+
 #ifdef CONFIG_MCA
-	/* Adapter probing and info methods. */
-	X(mca_write_pos),
-	X(mca_read_pos),
-	X(mca_read_stored_pos),
-	X(mca_set_adapter_name),
-	X(mca_get_adapter_name),
-	X(mca_set_adapter_procfn),
-	X(mca_isenabled),
-	X(mca_isadapter),
+/* Adapter probing and info methods. */
+EXPORT_SYMBOL(mca_write_pos);
+EXPORT_SYMBOL(mca_read_pos);
+EXPORT_SYMBOL(mca_read_stored_pos);
+EXPORT_SYMBOL(mca_set_adapter_name);
+EXPORT_SYMBOL(mca_get_adapter_name);
+EXPORT_SYMBOL(mca_set_adapter_procfn);
+EXPORT_SYMBOL(mca_isenabled);
+EXPORT_SYMBOL(mca_isadapter);
 #endif
-#include <linux/symtab_end.h>
-};
-
-void arch_syms_export(void)
-{
-	register_symtab(&arch_symbol_table);
-}
diff -u --recursive --new-file v2.1.17/linux/arch/i386/mm/extable.c linux/arch/i386/mm/extable.c
--- v2.1.17/linux/arch/i386/mm/extable.c	Sun Nov 10 20:12:08 1996
+++ linux/arch/i386/mm/extable.c	Fri Dec 27 12:03:19 1996
@@ -14,11 +14,6 @@
 		 const struct exception_table_entry *last,
 		 unsigned long value)
 {
-	/* Some versions of the linker are buggy and do not align the
-	   __start pointer along with the section, thus we may be low.  */
-	if ((long)first & 3)
-		(long)first = ((long)first | 3) + 1;
-
         while (first <= last) {
 		const struct exception_table_entry *mid;
 		long diff;
@@ -39,25 +34,22 @@
 search_exception_table(unsigned long addr)
 {
 	unsigned long ret;
-#ifdef CONFIG_MODULES
-	struct module *mp;
-#endif
 
-	/* Search the kernel's table first.  */
-	ret = search_one_table(__start___ex_table,
-			       __stop___ex_table-1, addr);
-	if (ret)
-		return ret;
-
-#ifdef CONFIG_MODULES
+#ifndef CONFIG_MODULES
+	/* There is only the kernel to search.  */
+	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
+	if (ret) return ret;
+#else
+	/* The kernel is the last "module" -- no need to treat it special.  */
+	struct module *mp;
 	for (mp = module_list; mp != NULL; mp = mp->next) {
-		if (mp->exceptinfo.start != NULL) {
-			ret = search_one_table(mp->exceptinfo.start,
-				mp->exceptinfo.stop-1, addr);
-			if (ret)
-				return ret;
-		}
+		if (mp->ex_table_start == NULL)
+			continue;
+		ret = search_one_table(mp->ex_table_start,
+				       mp->ex_table_end - 1, addr);
+		if (ret) return ret;
 	}
 #endif
+
 	return 0;
 }
diff -u --recursive --new-file v2.1.17/linux/arch/m68k/amiga/ksyms.c linux/arch/m68k/amiga/ksyms.c
--- v2.1.17/linux/arch/m68k/amiga/ksyms.c	Sun Dec 22 16:37:21 1996
+++ linux/arch/m68k/amiga/ksyms.c	Fri Dec 27 12:03:19 1996
@@ -6,37 +6,21 @@
 extern volatile u_short amiga_audio_min_period;
 extern u_short amiga_audio_period;
 
-static struct symbol_table amiga_symbol_table = {
-#include <linux/symtab_begin.h>
-
-  /*
-   * Add things here when you find the need for it.
-   */
-  X(amiga_model),
-  X(amiga_hw_present),
-  X(amiga_eclock),
-  X(amiga_colorclock),
-  X(amiga_chip_alloc),
-  X(amiga_chip_free),
-  X(amiga_chip_avail),
-  X(amiga_audio_period),
-  X(amiga_audio_min_period),
-
-  X(zorro_find),
-  X(zorro_get_board),
-  X(zorro_config_board),
-  X(zorro_unconfig_board),
-  X(zorro_unused_z2ram),
-
-  /* example
-  X(something_you_need),
-  */
-
-
-#include <linux/symtab_end.h>
-};
-
-void amiga_syms_export(void)
-{
-	register_symtab(&amiga_symbol_table);
-}
+/*
+ * Add things here when you find the need for it.
+ */
+EXPORT_SYMBOL(amiga_model);
+EXPORT_SYMBOL(amiga_hw_present);
+EXPORT_SYMBOL(amiga_eclock);
+EXPORT_SYMBOL(amiga_colorclock);
+EXPORT_SYMBOL(amiga_chip_alloc);
+EXPORT_SYMBOL(amiga_chip_free);
+EXPORT_SYMBOL(amiga_chip_avail);
+EXPORT_SYMBOL(amiga_audio_period);
+EXPORT_SYMBOL(amiga_audio_min_period);
+
+EXPORT_SYMBOL(zorro_find);
+EXPORT_SYMBOL(zorro_get_board);
+EXPORT_SYMBOL(zorro_config_board);
+EXPORT_SYMBOL(zorro_unconfig_board);
+EXPORT_SYMBOL(zorro_unused_z2ram);
diff -u --recursive --new-file v2.1.17/linux/arch/m68k/atari/ksyms.c linux/arch/m68k/atari/ksyms.c
--- v2.1.17/linux/arch/m68k/atari/ksyms.c	Sun Dec 22 16:37:21 1996
+++ linux/arch/m68k/atari/ksyms.c	Fri Dec 27 12:03:19 1996
@@ -9,35 +9,25 @@
 
 extern void atari_microwire_cmd( int cmd );
 
-static struct symbol_table atari_symbol_table = {
-#include <linux/symtab_begin.h>
 
-	X(atari_mch_cookie),
-	X(atari_hw_present),
-	X(is_medusa),
-	X(atari_register_vme_int),
-	X(atari_unregister_vme_int),
-	X(stdma_lock),
-	X(stdma_release),
-	X(stdma_others_waiting),
-	X(stdma_islocked),
+EXPORT_SYMBOL(atari_mch_cookie);
+EXPORT_SYMBOL(atari_hw_present);
+EXPORT_SYMBOL(is_medusa);
+EXPORT_SYMBOL(atari_register_vme_int);
+EXPORT_SYMBOL(atari_unregister_vme_int);
+EXPORT_SYMBOL(stdma_lock);
+EXPORT_SYMBOL(stdma_release);
+EXPORT_SYMBOL(stdma_others_waiting);
+EXPORT_SYMBOL(stdma_islocked);
 
-	X(atari_mouse_buttons),
-	X(atari_mouse_interrupt_hook),
-	X(atari_MIDI_interrupt_hook),
-	X(atari_mch_cookie),
-	X(ikbd_write),
-	X(ikbd_mouse_y0_top),
-	X(ikbd_mouse_thresh),
-	X(ikbd_mouse_rel_pos),
-	X(ikbd_mouse_disable),
+EXPORT_SYMBOL(atari_mouse_buttons);
+EXPORT_SYMBOL(atari_mouse_interrupt_hook);
+EXPORT_SYMBOL(atari_MIDI_interrupt_hook);
+EXPORT_SYMBOL(atari_mch_cookie);
+EXPORT_SYMBOL(ikbd_write);
+EXPORT_SYMBOL(ikbd_mouse_y0_top);
+EXPORT_SYMBOL(ikbd_mouse_thresh);
+EXPORT_SYMBOL(ikbd_mouse_rel_pos);
+EXPORT_SYMBOL(ikbd_mouse_disable);
 
-	X(atari_microwire_cmd),
-	
-#include <linux/symtab_end.h>
-};
-
-void atari_syms_export(void)
-{
-	register_symtab(&atari_symbol_table);
-}
+EXPORT_SYMBOL(atari_microwire_cmd);
diff -u --recursive --new-file v2.1.17/linux/arch/m68k/kernel/ksyms.c linux/arch/m68k/kernel/ksyms.c
--- v2.1.17/linux/arch/m68k/kernel/ksyms.c	Sun Dec 22 16:37:22 1996
+++ linux/arch/m68k/kernel/ksyms.c	Fri Dec 27 12:03:19 1996
@@ -18,47 +18,34 @@
 extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(elf_fpregset_t *);
 
-static struct symbol_table arch_symbol_table = {
-#include <linux/symtab_begin.h>
-	/* platform dependent support */
+/* platform dependent support */
 
-	X(memcmp),
-	X(m68k_machtype),
-	X(m68k_cputype),
-	X(m68k_is040or060),
-	X(cache_push),
-	X(cache_push_v),
-	X(cache_clear),
-	X(mm_vtop),
-	X(mm_ptov),
-	X(mm_end_of_chunk),
-	X(m68k_debug_device),
-	X(request_irq),
-	X(free_irq),
-	X(dump_fpu),
-	X(dump_thread),
-	X(strnlen),
-	X(strrchr),
-	X(strstr),
+EXPORT_SYMBOLS(memcmp);
+EXPORT_SYMBOLS(m68k_machtype);
+EXPORT_SYMBOLS(m68k_cputype);
+EXPORT_SYMBOLS(m68k_is040or060);
+EXPORT_SYMBOLS(cache_push);
+EXPORT_SYMBOLS(cache_push_v);
+EXPORT_SYMBOLS(cache_clear);
+EXPORT_SYMBOLS(mm_vtop);
+EXPORT_SYMBOLS(mm_ptov);
+EXPORT_SYMBOLS(mm_end_of_chunk);
+EXPORT_SYMBOLS(m68k_debug_device);
+EXPORT_SYMBOLS(request_irq);
+EXPORT_SYMBOLS(free_irq);
+EXPORT_SYMBOLS(dump_fpu);
+EXPORT_SYMBOLS(dump_thread);
+EXPORT_SYMBOLS(strnlen);
+EXPORT_SYMBOLS(strrchr);
+EXPORT_SYMBOLS(strstr);
+
+/* The following are special because they're not called
+   explicitly (the C compiler generates them).  Fortunately,
+   their interface isn't gonna change any time soon now, so
+   it's OK to leave it out of version control.  */
+EXPORT_SYMBOLS_NOVERS(__ashrdi3);
+EXPORT_SYMBOLS_NOVERS(memcpy);
+EXPORT_SYMBOLS_NOVERS(memset);
 
-	/* The following are special because they're not called
-	   explicitly (the C compiler generates them).  Fortunately,
-	   their interface isn't gonna change any time soon now, so
-	   it's OK to leave it out of version control.  */
-	XNOVERS(__ashrdi3),
-	XNOVERS(memcpy),
-	XNOVERS(memset),
-
-	XNOVERS(__down_failed),
-	XNOVERS(__up_wakeup),
-
-#include <linux/symtab_end.h>
-};
-
-void arch_syms_export(void)
-{
-	register_symtab(&arch_symbol_table);
-
-	if (mach_syms_export)
-	    mach_syms_export();
-}
+EXPORT_SYMBOLS_NOVERS(__down_failed);
+EXPORT_SYMBOLS_NOVERS(__up_wakeup);
diff -u --recursive --new-file v2.1.17/linux/arch/m68k/mm/extable.c linux/arch/m68k/mm/extable.c
--- v2.1.17/linux/arch/m68k/mm/extable.c	Fri Nov 22 18:28:17 1996
+++ linux/arch/m68k/mm/extable.c	Fri Dec 27 12:03:20 1996
@@ -34,24 +34,22 @@
 search_exception_table(unsigned long addr)
 {
 	unsigned long ret;
-#ifdef CONFIG_MODULES
-	struct module *mp;
-#endif
 
-	/* Search the kernel's table first.  */
+#ifndef CONFIG_MODULES
+	/* There is only the kernel to search.  */
 	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
-	if (ret)
-		return ret;
-
-#ifdef CONFIG_MODULES
+	if (ret) return ret;
+#else
+	/* The kernel is the last "module" -- no need to treat it special.  */
+	struct module *mp;
 	for (mp = module_list; mp != NULL; mp = mp->next) {
-		if (mp->exceptinfo.start != NULL) {
-			ret = search_one_table(mp->exceptinfo.start,
-				mp->exceptinfo.stop-1, addr);
-			if (ret)
-				return ret;
-		}
+		if (mp->ex_table_start == NULL)
+			continue;
+		ret = search_one_table(mp->ex_table_start,
+				       mp->ex_table_stop-1, addr);
+		if (ret) return ret;
 	}
 #endif
+
 	return 0;
 }
diff -u --recursive --new-file v2.1.17/linux/arch/ppc/kernel/ksyms.c linux/arch/ppc/kernel/ksyms.c
--- v2.1.17/linux/arch/ppc/kernel/ksyms.c	Mon May 27 12:00:58 1996
+++ linux/arch/ppc/kernel/ksyms.c	Fri Dec 27 12:03:20 1996
@@ -1,14 +1,4 @@
 #include <linux/module.h>
 #include <linux/smp.h>
 
-static struct symbol_table arch_symbol_table = {
-#include <linux/symtab_begin.h>
-	/* platform dependent support */
-#include <linux/symtab_end.h>
-};
-
-void arch_syms_export(void)
-{
-	register_symtab(&arch_symbol_table);
-}
-
+/* platform dependent support */
diff -u --recursive --new-file v2.1.17/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S
--- v2.1.17/linux/arch/sparc/kernel/head.S	Wed Dec 18 15:58:43 1996
+++ linux/arch/sparc/kernel/head.S	Mon Dec 23 10:13:52 1996
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.74 1996/12/08 08:18:59 davem Exp $
+/* $Id: head.S,v 1.75 1996/12/20 07:54:57 davem Exp $
  * head.S: The initial boot code for the Sparc port of Linux.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -409,7 +409,7 @@
  */
 	.globl C_LABEL(bootup_user_stack)
 	.globl C_LABEL(bootup_kernel_stack)
-	.globl C_LABEL(pg0)
+	.globl C_LABEL(pg0), C_LABEL(pg1), C_LABEL(pg2), C_LABEL(pg3)
 	.globl C_LABEL(empty_bad_page)
 	.globl C_LABEL(empty_bad_page_table)
 	.globl C_LABEL(empty_zero_page)
@@ -418,6 +418,9 @@
 C_LABEL(bootup_kernel_stack):		.skip 0x2000
 C_LABEL(swapper_pg_dir):		.skip 0x1000
 C_LABEL(pg0):				.skip 0x1000
+C_LABEL(pg1):				.skip 0x1000
+C_LABEL(pg2):				.skip 0x1000
+C_LABEL(pg3):				.skip 0x1000
 C_LABEL(empty_bad_page):		.skip 0x1000
 C_LABEL(empty_bad_page_table):		.skip 0x1000
 C_LABEL(empty_zero_page):		.skip 0x1000
diff -u --recursive --new-file v2.1.17/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c
--- v2.1.17/linux/arch/sparc/kernel/signal.c	Wed Dec 18 15:58:43 1996
+++ linux/arch/sparc/kernel/signal.c	Mon Dec 23 10:13:52 1996
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.64 1996/12/03 08:44:34 jj Exp $
+/*  $Id: signal.c,v 1.66 1996/12/20 07:54:58 davem Exp $
  *  linux/arch/sparc/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -26,7 +26,11 @@
 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
 
 asmlinkage int sys_waitpid(pid_t pid, unsigned long *stat_addr, int options);
+
+extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
+		   void *fpqueue, unsigned long *fpqdepth);
 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
+
 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs,
 			 unsigned long orig_o0, int ret_from_syscall);
 
@@ -64,7 +68,6 @@
 
 struct new_signal_frame {
 	struct      sparc_stackf ss;
-	struct      reg_window sig_window;
 	__siginfo_t info;
 	unsigned    long __pad;
 	unsigned    long insns [2];
@@ -140,11 +143,26 @@
 	up_psr = regs->psr;
 	memcpy (regs, &sf->info.si_regs, sizeof (struct pt_regs));
 
-	/* User can only change condition codes in %psr. */
-	regs->psr = (up_psr & ~(PSR_ICC)) | (regs->psr & PSR_ICC);
+	/* User can only change condition codes and FPU enabling in the %psr. */
+	regs->psr = (up_psr & ~(PSR_ICC | PSR_EF)) | (regs->psr & (PSR_ICC | PSR_EF));
 	
-	if (regs->psr & PSR_EF)
-		fpload (&sf->info.si_float_regs [0], &sf->info.si_fsr);
+	if (regs->psr & PSR_EF) {
+		regs->psr &= ~(PSR_EF);
+#ifndef __SMP__
+		if(current == last_task_used_math)
+			last_task_used_math = 0;
+#endif
+		current->used_math = 1;
+		current->flags &= ~(PF_USEDFPU);
+
+		/* Copy signal FPU state into thread struct FPU state. */
+		memcpy(&current->tss.float_regs[0], &sf->info.si_float_regs[0],
+		       (sizeof(unsigned long) * 64));
+		current->tss.fsr = sf->info.si_fsr;
+		if((current->tss.fpqdepth = sf->info.si_fpqdepth) != 0)
+		    memcpy(&current->tss.fpqueue[0], &sf->info.si_fpqueue[0],
+		           ((sizeof(unsigned long) + (sizeof(unsigned long *))) * 16));
+	}
 	current->blocked = sf->info.si_mask & _BLOCKABLE;
 }
 
@@ -287,17 +305,53 @@
 	}
 
 	if (current->tss.w_saved != 0){
-		printk ("Ay Caramba!  w_saved not zero!\n");
+		printk ("%s[%d]: Invalid user stack frame for signal delivery.\n",
+			current->comm, current->pid);
 		do_exit (SIGILL);
 		return;
 	}
 
-	/* 2. Save the state current process state */
+	/* 2. Save the current process state */
 	memcpy (&sf->info.si_regs, regs, sizeof (struct pt_regs));
-	if (regs->psr & PSR_EF){
+#ifdef __SMP__
+	if(current->flags & PF_USEDFPU) {
+		put_psr(get_psr() | PSR_EF);
+		fpsave (&sf->info.si_float_regs [0], &sf->info.si_fsr,
+			&sf->info.si_fpqueue[0], &sf->info.si_fpqdepth);
+
+		/* Save a copy into thread struct as well. */
+		memcpy(&current->tss.float_regs[0], &sf->info.si_float_regs[0],
+		       (sizeof(unsigned long) * 64));
+		current->tss.fsr = sf->info.si_fsr;
+		if((current->tss.fpqdepth = sf->info.si_fpqdepth) != 0)
+		    memcpy(&current->tss.fpqueue[0], &sf->info.si_fpqueue[0],
+			   ((sizeof(unsigned long) + (sizeof(unsigned long *))) * 16));
+
+		regs->psr &= ~(PSR_EF);
+		current->flags &= ~(PF_USEDFPU);
+	}
+#else
+	if(current == last_task_used_math) {
+		put_psr(get_psr() | PSR_EF);
 		fpsave (&sf->info.si_float_regs [0], &sf->info.si_fsr,
 			&sf->info.si_fpqueue[0], &sf->info.si_fpqdepth);
+
+		/* Save a copy into thread struct as well. */
+		memcpy(&current->tss.float_regs[0], &sf->info.si_float_regs[0],
+		       (sizeof(unsigned long) * 64));
+		current->tss.fsr = sf->info.si_fsr;
+		if((current->tss.fpqdepth = sf->info.si_fpqdepth) != 0)
+		    memcpy(&current->tss.fpqueue[0], &sf->info.si_fpqueue[0],
+			   ((sizeof(unsigned long) + (sizeof(unsigned long *))) * 16));
+
+		last_task_used_math = NULL;
+		regs->psr &= ~(PSR_EF);
 	}
+#endif
+
+	/* This new thread of control has not used the FPU. */
+	current->used_math = 0;
+
 	sf->info.si_mask = oldmask;
 	memcpy (sf, (char *) regs->u_regs [UREG_FP], sizeof (struct reg_window));
 	
@@ -315,7 +369,7 @@
 	regs->pc = (unsigned long) sa->sa_handler;
 	regs->npc = (regs->pc + 4);
 
-	/* Flush cache, replace this with a generic thingie */
+	/* Flush instruction space. */
 	flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
 }
 
diff -u --recursive --new-file v2.1.17/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.1.17/linux/arch/sparc/kernel/sparc_ksyms.c	Sun Dec 22 16:37:23 1996
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Fri Dec 27 12:03:20 1996
@@ -65,139 +65,128 @@
  * support routines are named is a mess, they all start with
  * a '.' which makes it a bitch to export, here is the trick:
  */
-#define DD(sym) extern int __sparc_dot_ ## sym (int) __asm__("." ## #sym)
-#define XD(sym) { (void *) & __sparc_dot_ ## sym, "." ## #sym }
 
-DD(rem);
-DD(urem);
-DD(div);
-DD(udiv);
-DD(mul);
-DD(umul);
+#define EXPORT_SYMBOL_DOT(sym)					\
+extern int __sparc_dot_ ## sym (int) __asm__("." ## #sym);	\
+const struct module_symbol __export_dot_##sym			\
+__attribute__((section("__ksymtab"))) =				\
+{ (unsigned long) &__sparc_dot_ ## sym, "." ## #sym }
 
-static struct symbol_table arch_symbol_table = {
-#include <linux/symtab_begin.h>
 
-	/* used by various drivers */
-	X(sparc_cpu_model),
+/* used by various drivers */
+EXPORT_SYMBOL(sparc_cpu_model);
 #ifdef __SMP__
-	X(kernel_flag),
-	X(kernel_counter),
-	X(active_kernel_processor),
-	X(syscall_count),
+EXPORT_SYMBOL(kernel_flag);
+EXPORT_SYMBOL(kernel_counter);
+EXPORT_SYMBOL(active_kernel_processor);
+EXPORT_SYMBOL(syscall_count);
 #endif
-	X(page_offset),
-	X(stack_top),
+EXPORT_SYMBOL(page_offset);
+EXPORT_SYMBOL(stack_top);
 
-	X(udelay),
-	X(mstk48t02_regs),
+EXPORT_SYMBOL(udelay);
+EXPORT_SYMBOL(mstk48t02_regs);
 #if CONFIG_SUN_AUXIO
-	X(auxio_register),
+EXPORT_SYMBOL(auxio_register);
 #endif
-	X(request_fast_irq),
-	X(sparc_alloc_io),
-	X(sparc_free_io),
-	X(mmu_v2p),
-	X(mmu_unlockarea),
-	X(mmu_lockarea),
-	X(mmu_get_scsi_sgl),
-	X(mmu_get_scsi_one),
-	X(mmu_release_scsi_sgl),
-	X(mmu_release_scsi_one),
-	X(sparc_dvma_malloc),
-	X(sun4c_unmapioaddr),
-	X(srmmu_unmapioaddr),
+EXPORT_SYMBOL(request_fast_irq);
+EXPORT_SYMBOL(sparc_alloc_io);
+EXPORT_SYMBOL(sparc_free_io);
+EXPORT_SYMBOL(mmu_v2p);
+EXPORT_SYMBOL(mmu_unlockarea);
+EXPORT_SYMBOL(mmu_lockarea);
+EXPORT_SYMBOL(mmu_get_scsi_sgl);
+EXPORT_SYMBOL(mmu_get_scsi_one);
+EXPORT_SYMBOL(mmu_release_scsi_sgl);
+EXPORT_SYMBOL(mmu_release_scsi_one);
+EXPORT_SYMBOL(sparc_dvma_malloc);
+EXPORT_SYMBOL(sun4c_unmapioaddr);
+EXPORT_SYMBOL(srmmu_unmapioaddr);
 #if CONFIG_SBUS
-	X(SBus_chain),
+EXPORT_SYMBOL(SBus_chain);
 #endif
-	/* Solaris/SunOS binary compatibility */
-	X(svr4_setcontext),
-	X(svr4_getcontext),
-	X(_sigpause_common),
-	X(sunos_mmap),
-	X(sunos_poll),
-
-	/* Should really be in linux/kernel/ksyms.c */
-	X(dump_thread),
-
-	/* prom symbols */
-	X(idprom),
-	X(prom_root_node),
-	X(prom_getchild),
-        X(prom_getsibling),
-	X(prom_searchsiblings),
-	X(prom_firstprop),
-        X(prom_nextprop),
-	X(prom_getproplen),
-	X(prom_getproperty),
-        X(prom_setprop),
-        X(prom_nodeops),
-	X(prom_getbootargs),
-	X(prom_apply_obio_ranges),
-	X(prom_getname),
-	X(prom_feval),
-	X(prom_getstring),
-	X(prom_apply_sbus_ranges),
-	X(prom_getint),
-	X(prom_getintdefault),
-	X(romvec),
-
-	/* sparc library symbols */
-	X(bcopy),
-	X(memmove),
-	X(memscan),
-	X(strlen),
-	X(strnlen),
-	X(strcpy),
-	X(strncpy),
-	X(strcat),
-	X(strncat),
-	X(strcmp),
-	X(strncmp),
-	X(strchr),
-	X(strrchr),
-	X(strpbrk),
-	X(strtok),
-	X(strstr),
-	X(strspn),
-
-	/* Special internal versions of library functions. */
-	X(__copy_1page),
-	X(__memcpy),
-	X(__memset),
-	X(bzero_1page),
-	X(__bzero),
-	X(__memscan_zero),
-	X(__memscan_generic),
-	X(__memcmp),
-	X(__strncmp),
-
-	/* Moving data to/from userspace. */
-	X(__copy_user),
-	X(__clear_user),
-	X(__strncpy_from_user),
-
-	/* No version information on this, heavily used in inline asm,
-	 * and will always be 'void __ret_efault(void)'.
-	 */
-	XNOVERS(__ret_efault),
-
-	/* No version information on these, as gcc produces such symbols. */
-	XNOVERS(memcmp),
-	XNOVERS(memcpy),
-	XNOVERS(memset),
-	XNOVERS(__ashrdi3),
-
-	XD(rem),
-	XD(urem),
-	XD(mul),
-	XD(umul),
-	XD(div),
-	XD(udiv),
-#include <linux/symtab_end.h>
-};
-
-void arch_syms_export(void)
-{
-	register_symtab(&arch_symbol_table);
-}
+
+/* Solaris/SunOS binary compatibility */
+EXPORT_SYMBOL(svr4_setcontext);
+EXPORT_SYMBOL(svr4_getcontext);
+EXPORT_SYMBOL(_sigpause_common);
+EXPORT_SYMBOL(sunos_mmap);
+EXPORT_SYMBOL(sunos_poll);
+
+/* Should really be in linux/kernel/ksyms.c */
+EXPORT_SYMBOL(dump_thread);
+
+/* prom symbols */
+EXPORT_SYMBOL(idprom);
+EXPORT_SYMBOL(prom_root_node);
+EXPORT_SYMBOL(prom_getchild);
+EXPORT_SYMBOL(prom_getsibling);
+EXPORT_SYMBOL(prom_searchsiblings);
+EXPORT_SYMBOL(prom_firstprop);
+EXPORT_SYMBOL(prom_nextprop);
+EXPORT_SYMBOL(prom_getproplen);
+EXPORT_SYMBOL(prom_getproperty);
+EXPORT_SYMOBL(prom_setprop);
+EXPORT_SYMBOL(prom_nodeops);
+EXPORT_SYMBOL(prom_getbootargs);
+EXPORT_SYMBOL(prom_apply_obio_ranges);
+EXPORT_SYMBOL(prom_getname);
+EXPORT_SYMBOL(prom_feval);
+EXPORT_SYMBOL(prom_getstring);
+EXPORT_SYMBOL(prom_apply_sbus_ranges);
+EXPORT_SYMBOL(prom_getint);
+EXPORT_SYMBOL(prom_getintdefault);
+EXPORT_SYMBOL(romvec);
+
+/* sparc library symbols */
+EXPORT_SYMBOL(bcopy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strtok);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(strspn);
+
+/* Special internal versions of library functions. */
+EXPORT_SYMBOL(__copy_1page);
+EXPORT_SYMBOL(__memcpy);
+EXPORT_SYMBOL(__memset);
+EXPORT_SYMBOL(bzero_1page);
+EXPORT_SYMBOL(__bzero);
+EXPORT_SYMBOL(__memscan_zero);
+EXPORT_SYMBOL(__memscan_generic);
+EXPORT_SYMBOL(__memcmp);
+EXPORT_SYMBOL(__strncmp);
+
+/* Moving data to/from userspace. */
+EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(__clear_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+
+/* No version information on this, heavily used in inline asm,
+ * and will always be 'void __ret_efault(void)'.
+ */
+EXPORT_SYMBOLNOVERS(__ret_efault);
+
+/* No version information on these, as gcc produces such symbols. */
+EXPORT_SYMBOL_NOVERS(memcmp);
+EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL_NOVERS(__ashrdi3);
+
+EXPORT_SYMBOL_DOT(rem);
+EXPORT_SYMBOL_DOT(urem);
+EXPORT_SYMBOL_DOT(mul);
+EXPORT_SYMBOL_DOT(umul);
+EXPORT_SYMBOL_DOT(div);
+EXPORT_SYMBOL_DOT(udiv);
diff -u --recursive --new-file v2.1.17/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.1.17/linux/arch/sparc/kernel/sys_sunos.c	Sun Dec 22 16:37:27 1996
+++ linux/arch/sparc/kernel/sys_sunos.c	Mon Dec 23 10:13:52 1996
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.68 1996/12/19 05:25:43 davem Exp $
+/* $Id: sys_sunos.c,v 1.69 1996/12/21 04:50:38 tridge Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -131,7 +131,7 @@
 }
 
 /* SunOS is completely broken... it returns 0 on success, otherwise
- * ENOMEM.  For sys_sbrk() it wants the new brk value as a return
+ * ENOMEM.  For sys_sbrk() it wants the old brk value as a return
  * on success and ENOMEM as before on failure.
  */
 asmlinkage int sunos_brk(unsigned long brk)
@@ -142,7 +142,7 @@
 
 	if(sparc_cpu_model == sun4c) {
 		if(brk >= 0x20000000 && brk < 0xe0000000)
-			return current->mm->brk;
+			return -ENOMEM;
 	}
 
 	if (brk < current->mm->end_code)
@@ -205,13 +205,14 @@
 asmlinkage unsigned long sunos_sbrk(int increment)
 {
 	int error;
+	unsigned long oldbrk = current->mm->brk;
 
 	/* This should do it hopefully... */
 	error = sunos_brk(((int) current->mm->brk) + increment);
 	if(error)
 		return error;
 	else
-		return current->mm->brk;
+		return oldbrk;
 }
 
 /* XXX Completely undocumented, and completely magic...
diff -u --recursive --new-file v2.1.17/linux/arch/sparc/mm/extable.c linux/arch/sparc/mm/extable.c
--- v2.1.17/linux/arch/sparc/mm/extable.c	Wed Dec 18 15:58:46 1996
+++ linux/arch/sparc/mm/extable.c	Fri Dec 27 12:03:20 1996
@@ -31,12 +31,13 @@
                 else
                         last = mid-1;
         }
-        if (last->insn < value && !last->fixup && (last + 1)->insn > value) {
+        if (last->insn < value && !last->fixup && last[1].insn > value) {
         	*g2 = (value - last->insn)/4;
-        	return (last + 1)->fixup;
+        	return last[1].fixup;
         }
-        if (first > start && (first-1)->insn < value && !(first-1)->fixup && first->insn < value) {
-        	*g2 = (value - (first-1)->insn)/4;
+        if (first > start && first[-1].insn < value
+	    && !first[-1].fixup && first->insn < value) {
+        	*g2 = (value - firstp[-1].insn)/4;
         	return first->fixup;
         }
         return 0;
@@ -46,25 +47,23 @@
 search_exception_table(unsigned long addr, unsigned long *g2)
 {
 	unsigned long ret;
-#ifdef CONFIG_MODULES
-	struct module *mp;
-#endif
 
-	/* Search the kernel's table first.  */
+#ifndef CONFIG_MODULES
+	/* There is only the kernel to search.  */
 	ret = search_one_table(__start___ex_table,
 			       __stop___ex_table-1, addr, g2);
-	if (ret)
-		return ret;
-
-#ifdef CONFIG_MODULES
+	if (ret) return ret;
+#else
+	/* The kernel is the last "module" -- no need to treat it special.  */
+	struct module *mp;
 	for (mp = module_list; mp != NULL; mp = mp->next) {
-		if (mp->exceptinfo.start != NULL) {
-			ret = search_one_table(mp->exceptinfo.start,
-				mp->exceptinfo.stop-1, addr, g2);
-			if (ret)
-				return ret;
-		}
+		if (mp->ex_table_start == NULL)
+			continue;
+		ret = search_one_table(mp->ex_table_start,
+				       mp->ex_table_stop-1, addr, g2);
+		if (ret) return ret;
 	}
 #endif
+
 	return 0;
 }
diff -u --recursive --new-file v2.1.17/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- v2.1.17/linux/arch/sparc/mm/sun4c.c	Sun Dec 22 16:37:29 1996
+++ linux/arch/sparc/mm/sun4c.c	Mon Dec 23 10:13:52 1996
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.133 1996/12/18 06:43:28 tridge Exp $
+/* $Id: sun4c.c,v 1.135 1996/12/23 05:27:50 davem Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -1862,10 +1862,11 @@
 /* Please take special note on the foo_kernel() routines below, our
  * fast in window fault handler wants to get at the pte's for vmalloc
  * area with traps off, therefore they _MUST_ be locked down to prevent
- * a watchdog from happening.  The lowest VMALLOC'd thing is the buffer
- * cache hash table, it is never free'd ever, so the pg0 we use for the
- * lowest most page of pte's will never be freed and is guarenteed to
- * be locked down.  Be careful with this code thanks.
+ * a watchdog from happening.  It only takes 4 pages of pte's to lock
+ * down the maximum vmalloc space possible on sun4c so we statically
+ * allocate these page table pieces in the kernel image.  Therefore
+ * we should never have to really allocate or free any kernel page
+ * table information.
  */
 
 /* Allocate and free page tables. The xxx_kernel() versions are
@@ -1874,39 +1875,16 @@
  */
 static void sun4c_pte_free_kernel(pte_t *pte)
 {
-	unsigned long pg0_addr = (unsigned long) pg0;
-	unsigned long this_addr = (unsigned long) pte;
-	unsigned long page = (unsigned long) pte;
-
-	pg0_addr &= PAGE_MASK;
-	this_addr &= PAGE_MASK;
-
-	/* See above comment. */
-	if(pg0_addr != this_addr) {
-		page = (PAGE_OFFSET + ((sun4c_get_pte(this_addr) & 0xffff)<<PAGE_SHIFT));
-		sun4c_unlockarea((char *)this_addr, PAGE_SIZE);
-	}
-
-	free_page(page);
+	/* This should never get called. */
+	panic("sun4c_pte_free_kernel called, can't happen...");
 }
 
 static pte_t *sun4c_pte_alloc_kernel(pmd_t *pmd, unsigned long address)
 {
-	address = (address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1);
-	if (sun4c_pmd_none(*pmd)) {
-		pte_t *page = (pte_t *) get_free_page(GFP_KERNEL);
-		if (sun4c_pmd_none(*pmd)) {
-			if (page) {
-				/* See above comment. */
-				page = (pte_t *) sun4c_lockarea((char *)page, PAGE_SIZE);
-				*pmd = __pmd(PGD_TABLE | (unsigned long) page);
-				return page + address;
-			}
-			*pmd = __pmd(PGD_TABLE | (unsigned long) BAD_PAGETABLE);
-			return NULL;
-		}
-		free_page((unsigned long) page);
-	}
+	if(address >= SUN4C_LOCK_VADDR)
+		return NULL;
+	if (sun4c_pmd_none(*pmd))
+		panic("sun4c_pmd_none for kernel pmd, can't happen...");
 	if (sun4c_pmd_bad(*pmd)) {
 		printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
 		*pmd = __pmd(PGD_TABLE | (unsigned long) BAD_PAGETABLE);
@@ -1921,7 +1899,6 @@
  */
 static void sun4c_pmd_free_kernel(pmd_t *pmd)
 {
-	*pmd = __pmd(0);
 }
 
 static pmd_t *sun4c_pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
@@ -2072,7 +2049,7 @@
 __initfunc(unsigned long sun4c_paging_init(unsigned long start_mem, unsigned long end_mem))
 {
 	int i, cnt;
-	unsigned long kernel_end;
+	unsigned long kernel_end, vaddr;
 	extern unsigned long sparc_iobase_vaddr;
 
 	kernel_end = (unsigned long) &end;
@@ -2093,8 +2070,19 @@
 	sun4c_set_context(0);
 	memset(swapper_pg_dir, 0, PAGE_SIZE);
 	memset(pg0, 0, PAGE_SIZE);
+	memset(pg1, 0, PAGE_SIZE);
+	memset(pg2, 0, PAGE_SIZE);
+	memset(pg3, 0, PAGE_SIZE);
+
 	/* Save work later. */
-	swapper_pg_dir[SUN4C_VMALLOC_START>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg0);
+	vaddr = SUN4C_VMALLOC_START;
+	swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg0);
+	vaddr += SUN4C_PGDIR_SIZE;
+	swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg1);
+	vaddr += SUN4C_PGDIR_SIZE;
+	swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg2);
+	vaddr += SUN4C_PGDIR_SIZE;
+	swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg3);
 	sun4c_init_ss2_cache_bug();
 	start_mem = PAGE_ALIGN(start_mem);
 	start_mem = sparc_context_init(start_mem, num_contexts);
diff -u --recursive --new-file v2.1.17/linux/drivers/block/README.fd linux/drivers/block/README.fd
--- v2.1.17/linux/drivers/block/README.fd	Thu May 30 15:56:07 1996
+++ linux/drivers/block/README.fd	Thu Dec 26 13:15:06 1996
@@ -4,7 +4,7 @@
 =========
 
  A FAQ list may be found in the fdutils package (see below), and also
-at ftp.imag.fr:pub/Linux/ZLIBC/floppy/FAQ
+at http://www.club.innet.lu/~year3160/floppy/FAQ.html
 
 
 Lilo config options (Thinkpad users, read this)
@@ -171,58 +171,25 @@
 allows to access high capacity disks (up to 1992K on a high density 3
 1/2 disk!). It also contains additional documentation about the floppy
 driver. It can be found at:
- ftp.imag.fr:pub/Linux/ZLIBC/fdutils/fdutils-4.1.src.tar.gz
- sunsite.unc.edu:/pub/Linux/system/Misc/fdutils-4.1.src.tar.gz
- tsx-11.mit.edu:/pub/linux/sources/sbin/fdutils-4.1.src.tar.gz
+ linux.wauug.org:/pub/knaff/fdutils/fdutils-4.3.src.tar.gz
+ sunsite.unc.edu:/pub/Linux/system/Misc/fdutils-4.3.src.tar.gz
+ tsx-11.mit.edu:/pub/linux/sources/sbin/fdutils-4.3.src.tar.gz
 
  Alpha patches to these utilities are at:
- ftp.imag.fr:pub/Linux/ZLIBC/fdutils/ALPHA
+ http://www.club.innet.lu/~year3160/fdutils/ALPHA
  All patches contained in this directory are directly against the base
 version, i.e. DON'T APPLY THEM ON TOP OF EACH OTHER. Only apply the
 most recent one.
 
-
-Alpha patches for the floppy driver:
-====================================
-
- You may find ALPHA patches of the driver itself in
-ftp.imag.fr:pub/Linux/ZLIBC/floppy/ALPHA. These patches are named
-fdp<kernel-version>-<day><month>.diff.gz
- WARNING: These _are_ ALPHA, and may introduce new problems! Some
-problems may only show up on certain hardware, or when trying weirdo
-things. So don't be misled by people claiming they are stable and
-should really be BETA. What works for one person, may not work for
-somebody else at all. This directory contains a RELEASES file
-describing the features of some of these patches.
-
- If after some testing these patches prove to be sufficiently stable,
-they'll move into ftp.imag.fr:pub/Linux/ZLIBC/floppy/BETA.
-
- You may find quick&dirty fixes to the driver in
-ftp.imag.fr:pub/Linux/ZLIBC/QDF. These patches are named
-fdp<kernel-version>-<day><month>.diff
- These patches fix only the most obvious problems, or provide trivial
-enhancements. The main objective is to keep these patches small and
-local, in order to keep the probability of introducing new problems as
-small as possible. However, they may not attack the root of the
-problem but only cure the symptoms. This directory contains a RELEASES
-file describing the features of these patches.
-
- The ALPHA, BETA and QDF directories are removed, and replaced by a
-README file when they get empty due to integration of the patches into
-the stock kernel. You may still find patches to old kernels in
-ftp.imag.fr:pub/Linux/ZLIBC/obsolete
-
-
 Reporting problems about the floppy driver
 ==========================================
 
  If you have a question or a bug report about the floppy driver, mail
-me at Alain.Knaff@imag.fr. If you post to the news, use preferably one
-of the groups comp.os.linux.help (for questions) or
-comp.os.linux.hardware (for bug reports). As the volume in these
-groups is rather high, be sure to include the word "floppy" (or
-"FLOPPY") in the subject line.
+me at Alain.Knaff@poboxes.com . If you post to Usenet, preferably use
+comp.os.linux.hardware. As the volume in these groups is rather high,
+be sure to include the word "floppy" (or "FLOPPY") in the subject
+line.  If the reported problem happens when mounting floppy disks, be
+sure to mention also the type of the filesystem in the subject line.
 
  Be sure to read the FAQ before mailing/posting any bug reports!
 
diff -u --recursive --new-file v2.1.17/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.1.17/linux/drivers/block/floppy.c	Fri Nov 15 23:49:07 1996
+++ linux/drivers/block/floppy.c	Fri Dec 27 12:03:20 1996
@@ -4061,8 +4061,10 @@
 static void floppy_release_irq_and_dma(void)
 {
 #ifdef FLOPPY_SANITY_CHECK
+#ifndef __sparc__
 	int drive;
 #endif
+#endif
 	long tmpsize;
 	unsigned long tmpaddr;
 	unsigned long flags;
@@ -4094,9 +4096,11 @@
 	}
 
 #ifdef FLOPPY_SANITY_CHECK
+#ifndef __sparc__
 	for (drive=0; drive < N_FDC * 4; drive++)
 		if (motor_off_timer[drive].next)
 			printk("motor off timer %d still active\n", drive);
+#endif
 
 	if (fd_timeout.next)
 		printk("floppy timer still active:%s\n", timeout_message);
@@ -4179,7 +4183,7 @@
 #endif
 int init_module(void)
 {
-	printk(KERN_INFO "inserting floppy driver for %s\n", kernel_version);
+	printk(KERN_INFO "inserting floppy driver for " UTS_RELEASE "\n");
 		
 	if(floppy)
 		parse_floppy_cfg_string(floppy);
diff -u --recursive --new-file v2.1.17/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v2.1.17/linux/drivers/block/ide-cd.c	Thu Dec 12 19:36:58 1996
+++ linux/drivers/block/ide-cd.c	Sun Dec 29 11:37:34 1996
@@ -144,6 +144,9 @@
  *                          to fix the drive door locking problems.
  *
  * 4.03  Dec 04, 1996  -- Added DSC overlap support.
+ * 4.04  Dec 29, 1996  -- Added CDROMREADRAW ioclt based on patch 
+ *                          by Ales Makarov (xmakarov@sun.felk.cvut.cz)
+ *
  *
  * MOSTLY DONE LIST:
  *  Query the drive to find what features are available
@@ -152,8 +155,8 @@
  * TO DO LIST:
  *  Avoid printing error messages for expected errors from the drive.
  *    (If you are using a cd changer, you may get errors in the kernel
-       logs that are completly expected.  Don't complpain to me about this,
-       unless you have a patch to fix it.  I am working on it...)
+ *     logs that are completly expected.  Don't complain to me about this,
+ *     unless you have a patch to fix it.  I am working on it...)
  *  Reset unlocks drive?
  *  Implement ide_cdrom_disc_status using the generic cdrom interface
  *  Implement ide_cdrom_select_speed using the generic cdrom interface
@@ -161,7 +164,7 @@
  *
  *  -- Suggestions are welcome.  Patches that work are more welcome though.
  *       For those wishing to work on this driver, please be sure you download
- *       and comply with the latest ATAPI standard.  This document can 
+ *       and comply with the latest ATAPI standard.  This document can be
  *       obtained by anonymous ftp from fission.dt.wdc.com in directory:
  *       /pub/standards/atapi/spec/SFF8020-r2.6/PDF/8020r26.pdf
  *
@@ -1834,7 +1837,7 @@
 	pc.c[7] = ((nblocks>>8) & 0xff);
 	pc.c[6] = ((nblocks>>16) & 0xff);
 	if (format <= 1)
-		pc.c[9] = 0xf0;
+		pc.c[9] = 0xf8;         /* returns 2352 for any format */
 	else
 		pc.c[9] = 0x10;
 
@@ -1956,6 +1959,7 @@
 
 
 	switch (cmd) {
+	case CDROMREADRAW:
 	case CDROMREADMODE1:
 	case CDROMREADMODE2: {
 		struct cdrom_msf msf;
@@ -1966,11 +1970,13 @@
 		if (cmd == CDROMREADMODE1) {
 			blocksize = CD_FRAMESIZE;
 			format = 2;
-		} else {
+		} else if (cmd == CDROMREADMODE2) {
 			blocksize = CD_FRAMESIZE_RAW0;
 			format = 3;
+		} else {
+			blocksize = CD_FRAMESIZE_RAW;
+			format = 0;
 		}
-
 		stat = verify_area (VERIFY_WRITE, (char *)arg, blocksize);
 		if (stat) return stat;
 
@@ -1989,7 +1995,7 @@
 		if (lba < 0 || lba >= toc->capacity)
 			return -EINVAL;
 
-		buf = (char *) kmalloc (CD_FRAMESIZE_RAW0, GFP_KERNEL);
+		buf = (char *) kmalloc (CD_FRAMESIZE_RAW, GFP_KERNEL);
 		if (buf == NULL)
 			return -ENOMEM;
 
diff -u --recursive --new-file v2.1.17/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.1.17/linux/drivers/block/ide.c	Thu Dec 12 19:36:59 1996
+++ linux/drivers/block/ide.c	Fri Dec 27 12:03:20 1996
@@ -2828,45 +2828,55 @@
 	ide_revalidate_disk	/* revalidate */
 }};
 
-static struct symbol_table ide_syms = {
-#include <linux/symtab_begin.h>
-	X(ide_hwifs),
-	X(ide_register_module),		X(ide_unregister_module),
-
-	/*
-	 * Probe module
-	 */
-	X(ide_timer_expiry),		X(ide_intr),
-	X(ide_geninit),			X(ide_fops),
-	X(ide_get_queue),
-	X(do_ide0_request),
+EXPORT_SYMBOL(ide_hwifs);
+EXPORT_SYMBOL(ide_register_module);
+EXPORT_SYMBOL(ide_unregister_module);
+
+/*
+ * Probe module
+ */
+EXPORT_SYMBOL(ide_timer_expiry);
+EXPORT_SYMBOL(ide_intr);
+EXPORT_SYMBOL(ide_geninit);
+EXPORT_SYMBOL(ide_fops);
+EXPORT_SYMBOL(ide_get_queue);
+EXPORT_SYMBOL(do_ide0_request);
 #if MAX_HWIFS > 1
-	X(do_ide1_request),
+EXPORT_SYMBOL(do_ide1_request);
 #endif /* MAX_HWIFS > 1 */
 #if MAX_HWIFS > 2
-	X(do_ide2_request),
+EXPORT_SYMBOL(do_ide2_request);
 #endif /* MAX_HWIFS > 2 */
 #if MAX_HWIFS > 3
-	X(do_ide3_request),
+EXPORT_SYMBOL(do_ide3_request);
 #endif /* MAX_HWIFS > 3 */
 
-	/*
-	 * Driver module
-	 */
-	X(ide_scan_devices),		X(ide_register_subdriver),
-	X(ide_unregister_subdriver),	X(ide_input_data),
-	X(ide_output_data),		X(atapi_input_bytes),
-	X(atapi_output_bytes),		X(ide_set_handler),
-	X(ide_dump_status),		X(ide_error),
-	X(ide_fixstring),		X(ide_wait_stat),
-	X(ide_do_reset),		X(ide_init_drive_cmd),
-	X(ide_do_drive_cmd),		X(ide_end_drive_cmd),
-	X(ide_end_request),		X(ide_revalidate_disk),
-	X(ide_cmd),			X(ide_stall_queue),
-
-	X(ide_register),		X(ide_unregister),
-#include <linux/symtab_end.h>
-};
+/*
+ * Driver module
+ */
+EXPORT_SYMBOL(ide_scan_devices);
+EXPORT_SYMBOL(ide_register_subdriver);
+EXPORT_SYMBOL(ide_unregister_subdriver);
+EXPORT_SYMBOL(ide_input_data);
+EXPORT_SYMBOL(ide_output_data);
+EXPORT_SYMBOL(atapi_input_bytes);
+EXPORT_SYMBOL(atapi_output_bytes);
+EXPORT_SYMBOL(ide_set_handler);
+EXPORT_SYMBOL(ide_dump_status);
+EXPORT_SYMBOL(ide_error);
+EXPORT_SYMBOL(ide_fixstring);
+EXPORT_SYMBOL(ide_wait_stat);
+EXPORT_SYMBOL(ide_do_reset);
+EXPORT_SYMBOL(ide_init_drive_cmd);
+EXPORT_SYMBOL(ide_do_drive_cmd);
+EXPORT_SYMBOL(ide_end_drive_cmd);
+EXPORT_SYMBOL(ide_end_request);
+EXPORT_SYMBOL(ide_revalidate_disk);
+EXPORT_SYMBOL(ide_cmd);
+EXPORT_SYMBOL(ide_stall_queue);
+
+EXPORT_SYMBOL(ide_register);
+EXPORT_SYMBOL(ide_unregister);
 
 /*
  * This is gets invoked once during initialization, to set *everything* up
@@ -2879,12 +2889,12 @@
 	ide_init_builtin_drivers();
 	initializing = 0;
 
-	(void) register_symtab(&ide_syms);
 	return 0;
 }
 
 #ifdef MODULE
 char *options = NULL;
+MODULE_PARM(options,"s");
 
 static void parse_options (char *line)
 {
diff -u --recursive --new-file v2.1.17/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.1.17/linux/drivers/block/ll_rw_blk.c	Sun Dec 22 16:37:30 1996
+++ linux/drivers/block/ll_rw_blk.c	Mon Dec 23 10:13:53 1996
@@ -375,7 +375,8 @@
 	req = *get_queue(bh->b_rdev);
 	if (!req) {
 		/* MD and loop can't handle plugging without deadlocking */
-		if (major != MD_MAJOR && major != LOOP_MAJOR)
+		if (major != MD_MAJOR && major != LOOP_MAJOR && 
+		    major != DDV_MAJOR)
 			plug_device(blk_dev + major);
 	} else switch (major) {
 	     case IDE0_MAJOR:	/* same as HD_MAJOR */
@@ -725,5 +726,11 @@
 #ifdef CONFIG_BLK_DEV_MD
 	md_init();
 #endif CONFIG_BLK_DEV_MD
+#ifdef CONFIG_APBLOCK
+	ap_init();
+#endif
+#ifdef CONFIG_DDV
+	ddv_init();
+#endif
 	return 0;
 }
diff -u --recursive --new-file v2.1.17/linux/drivers/block/md.c linux/drivers/block/md.c
--- v2.1.17/linux/drivers/block/md.c	Tue Nov 19 15:53:53 1996
+++ linux/drivers/block/md.c	Fri Dec 27 12:03:20 1996
@@ -431,17 +431,10 @@
   return;
 }  
 
-static struct symbol_table md_symbol_table=
-{
-#include <linux/symtab_begin.h>
-
-  X(md_size),
-  X(register_md_personality),
-  X(unregister_md_personality),
-  X(partition_name),
-
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(md_size);
+EXPORT_SYMBOL(register_md_personality);
+EXPORT_SYMBOL(unregister_md_personality);
+EXPORT_SYMBOL(partition_name);
 
 static struct proc_dir_entry proc_md = {
 	PROC_MD, 6, "mdstat",
@@ -461,7 +454,6 @@
   }
 
   blksize_size[MAJOR_NR] = md_blocksizes;
-  register_symtab (&md_symbol_table);
 
   proc_register(&proc_root, &proc_md);
 }
diff -u --recursive --new-file v2.1.17/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.1.17/linux/drivers/block/rd.c	Sun Dec 22 16:37:30 1996
+++ linux/drivers/block/rd.c	Mon Dec 23 10:13:53 1996
@@ -100,6 +100,7 @@
 #ifdef CONFIG_BLK_DEV_INITRD
 unsigned long initrd_start,initrd_end;
 int mount_initrd = 1;		/* zero if initrd should not be mounted */
+int initrd_below_start_ok = 0;
 #endif
 #endif
 
diff -u --recursive --new-file v2.1.17/linux/drivers/cdrom/aztcd.c linux/drivers/cdrom/aztcd.c
--- v2.1.17/linux/drivers/cdrom/aztcd.c	Tue Oct 29 19:58:03 1996
+++ linux/drivers/cdrom/aztcd.c	Fri Dec 27 12:03:20 1996
@@ -268,6 +268,7 @@
 static volatile int azt_read_count = 1;
 
 static int azt_port = AZT_BASE_ADDR;
+MODULE_PARM(azt_port, "i");
 
 static char  azt_cont = 0;
 static char  azt_init_end = 0;
diff -u --recursive --new-file v2.1.17/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c
--- v2.1.17/linux/drivers/cdrom/cdu31a.c	Thu Dec 12 19:36:59 1996
+++ linux/drivers/cdrom/cdu31a.c	Fri Dec 27 12:03:20 1996
@@ -255,6 +255,7 @@
 /* The base I/O address of the Sony Interface.  This is a variable (not a
    #define) so it can be easily changed via some future ioctl() */
 static unsigned int cdu31a_port = 0;
+MODULE_PARM(cdu31a_port, "i");
 
 /*
  * The following are I/O addresses of the various registers for the drive.  The
@@ -325,6 +326,7 @@
 
 /* What IRQ is the drive using?  0 if none. */
 static int cdu31a_irq = 0;
+MODULE_PARM(cdu31a_irq, "i");
 
 /* The interrupt handler will wake this queue up when it gets an
    interrupts. */
diff -u --recursive --new-file v2.1.17/linux/drivers/cdrom/cm206.c linux/drivers/cdrom/cm206.c
--- v2.1.17/linux/drivers/cdrom/cm206.c	Tue Nov 19 15:53:53 1996
+++ linux/drivers/cdrom/cm206.c	Fri Dec 27 12:03:20 1996
@@ -77,7 +77,33 @@
 	      Upgrade to Linux kernel 1.3.78. 
 
  11 apr 1996  0.98 Upgrade to Linux kernel 1.3.85
-              Made it more uniform.
+              More code moved to cdrom.c
+
+	      0.99 Some more small changes to decrease number
+	      of oopses at module load; 
+
+	      Branch from here:
+
+	      0.99.1.0 Update to kernel release 2.0.10 dev_t -> kdev_t
+	      (emoenke) various typos found by others.  extra
+	      module-load oops protection.
+
+	      0.99.1.1 Initialization constant cdrom_dops.speed
+	      changed from float (2.0) to int (2); Cli()-sti() pair
+	      around cm260_reset() in module initialization code.
+
+	      0.99.1.2 Changes literally as proposed by Scott Snyder
+	      <snyder@d0sgif.fnal.gov>, which have to do mainly with
+	      the poor minor support i had. The major new concept is
+	      to change a cdrom driver's operations struct from the
+	      capabilities struct. This reflects the fact that there
+	      is one major for a driver, whilst there can be many
+	      minors whith completely different capabilities.
+
+	      0.99.1.3 More changes for operations/info separation.
+
+	      0.99.1.4 Added speed selection (someone had to do this
+	      first).
  * 
  * Parts of the code are based upon lmscd.c written by Kai Petzke,
  * sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
@@ -98,7 +124,7 @@
  * - Philips/LMS cm260 product specification
  *
  *                       David van Leeuwen, david@tm.tno.nl.  */
-#define VERSION "$Id: cm206.c,v 0.99.1.1 1996/08/11 10:35:01 david Exp $"
+#define VERSION "$Id: cm206.c,v 0.99.1.4 1996/12/23 21:46:13 david Exp $"
 
 #include <linux/module.h>	
 
@@ -135,6 +161,8 @@
 
 static int cm206_base = CM206_BASE;
 static int cm206_irq = CM206_IRQ; 
+MODULE_PARM(cm206_base, "i");
+MODULE_PARM(cm206_irq, "i");
 
 #define POLLOOP 10000
 #define READ_AHEAD 1		/* defines private buffer, waste! */
@@ -580,7 +608,7 @@
 
 /* The new open. The real opening strategy is defined in cdrom.c. */
 
-static int cm206_open(struct cdrom_device_info *i, int purpose) 
+static int cm206_open(struct cdrom_device_info * cdi, int purpose) 
 {
   if (!cd->openfiles) {		/* reset only first time */
     cd->background=0;
@@ -593,7 +621,7 @@
   return 0;
 }
 
-static void cm206_release(struct cdrom_device_info *i)
+static void cm206_release(struct cdrom_device_info * cdi)
 {
   if (cd->openfiles==1) {
     if (cd->background) {
@@ -885,7 +913,8 @@
  * upon success. Memory checking has been done by cdrom_ioctl(), the
  * calling function, as well as LBA/MSF sanitization.
 */
-int cm206_audio_ioctl(struct cdrom_device_info *i, unsigned int cmd, void * arg)
+int cm206_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd, 
+		      void * arg)  
 {
   switch (cmd) {
   case CDROMREADTOCHDR: 
@@ -930,7 +959,8 @@
    some driver statistics accessible through ioctl calls.
  */
 
-static int cm206_ioctl(struct cdrom_device_info *i, unsigned int cmd, unsigned long arg)
+static int cm206_ioctl(struct cdrom_device_info * cdi, unsigned int cmd, 
+		       unsigned long arg)
 {
   switch (cmd) {
 #ifdef STATISTICS
@@ -947,7 +977,7 @@
   }
 }     
 
-int cm206_media_changed(struct cdrom_device_info *i, int n) 
+int cm206_media_changed(struct cdrom_device_info * cdi, int disc_nr) 
 {
   if (cd != NULL) {
     int r;
@@ -963,14 +993,14 @@
    the logic should be in cdrom.c */
 
 /* returns number of times device is in use */
-int cm206_open_files(struct cdrom_device_info *i)	
+int cm206_open_files(struct cdrom_device_info * cdi)	
 {
   if (cd) return cd->openfiles;
   return -1;
 }
 
 /* controls tray movement */
-int cm206_tray_move(struct cdrom_device_info *i, int position) 
+int cm206_tray_move(struct cdrom_device_info * cdi, int position) 
 {
   if (position) {		/* 1: eject */
     type_0_command(c_open_tray,1);
@@ -981,7 +1011,7 @@
 }
 
 /* gives current state of the drive */
-int cm206_drive_status(struct cdrom_device_info *i, int n)
+int cm206_drive_status(struct cdrom_device_info * cdi, int slot_nr)
 {
   get_drive_status();
   if (cd->dsb & dsb_tray_not_closed) return CDS_TRAY_OPEN;
@@ -991,7 +1021,7 @@
 }
  
 /* gives current state of disc in drive */
-int cm206_disc_status(struct cdrom_device_info *i)
+int cm206_disc_status(struct cdrom_device_info * cdi)
 {
   uch xa;
   get_drive_status();
@@ -1009,7 +1039,7 @@
 }
 
 /* locks or unlocks door lock==1: lock; return 0 upon success */
-int cm206_lock_door(struct cdrom_device_info *i, int lock)
+int cm206_lock_door(struct cdrom_device_info * cdi, int lock)
 {
   uch command = (lock) ? c_lock_tray : c_unlock_tray;
   type_0_command(command, 1);	/* wait and get dsb */
@@ -1020,7 +1050,8 @@
 /* Although a session start should be in LBA format, we return it in 
    MSF format because it is slightly easier, and the new generic ioctl
    will take care of the necessary conversion. */
-int cm206_get_last_session(struct cdrom_device_info *i, struct cdrom_multisession * mssp) 
+int cm206_get_last_session(struct cdrom_device_info * cdi, 
+			   struct cdrom_multisession * mssp) 
 {
   if (!FIRST_TRACK) get_disc_status();
   if (mssp != NULL) {
@@ -1038,7 +1069,7 @@
   return 0;
 }
 
-int cm206_get_upc(struct cdrom_device_info *info, struct cdrom_mcn * mcn)
+int cm206_get_upc(struct cdrom_device_info * cdi, struct cdrom_mcn * mcn)
 {
   uch upc[10];
   char * ret = mcn->medium_catalog_number;
@@ -1054,7 +1085,7 @@
   return 0;
 } 
 
-int cm206_reset(struct cdrom_device_info *i)
+int cm206_reset(struct cdrom_device_info * cdi)
 {
   stop_read();
   reset_cm260();
@@ -1067,6 +1098,26 @@
   return 0;
 }
 
+int cm206_select_speed(struct cdrom_device_info * cdi, int speed)
+{
+  int r;
+  switch (speed) {
+  case 0: 
+    r = type_0_command(c_auto_mode, 1);
+    break;
+  case 1:
+    r = type_0_command(c_force_1x, 1);
+    break;
+  case 2:
+    r = type_0_command(c_force_2x, 1);
+    break;
+  default:
+    return -1;
+  }
+  if (r<0) return r;
+  else return 1;
+}
+
 static struct cdrom_device_ops cm206_dops = {
   cm206_open,			/* open */
   cm206_release,		/* release */
@@ -1075,7 +1126,7 @@
   cm206_media_changed,		/* media changed */
   cm206_tray_move,		/* tray move */
   cm206_lock_door,		/* lock door */
-  NULL,				/* select speed */
+  cm206_select_speed,		/* select speed */
   NULL,				/* select disc */
   cm206_get_last_session,	/* get last session */
   cm206_get_upc,		/* get universal product code */
@@ -1087,22 +1138,22 @@
   1,				/* number of minor devices */
 };
 
-static struct cdrom_device_info cm206_info= {
-	&cm206_dops,
-	NULL,
-	NULL,
-	CM206_CDROM_MAJOR,
-	CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION |
-		CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO, /* capability */
-	2,				/* maximum speed */
-	1,				/* number of discs */
-	0,				/* options, ignored */
-	0,				/* mc_flags, ignored */
-	0
+
+static struct cdrom_device_info cm206_info = {
+  &cm206_dops,                  /* device operations */
+  NULL,				/* link */
+  NULL,				/* handle (not used by cm206) */
+  MKDEV(MAJOR_NR,0),		/* dev */
+  0,				/* mask */
+  2,				/* maximum speed */
+  1,				/* number of discs */
+  0,				/* options, not owned */
+  0,				/* mc_flags, not owned */
+  0				/* use count, not owned */
 };
-	
-/* This routine gets called during init if thing go wrong, can be used
- * in cleanup_module as well. */
+
+/* This routine gets called during initialization if thing go wrong,
+ * can be used in cleanup_module as well. */
 void cleanup(int level)
 {
   switch (level) {
@@ -1229,7 +1280,7 @@
     cleanup(3);
     return -EIO;
   }
-  if (register_cdrom(&cm206_info,"cm206") != 0) {
+  if (register_cdrom(&cm206_info, "cm206") != 0) {
     printk("Cannot register for cdrom %d!\n", MAJOR_NR);
     cleanup(3);
     return -EIO;
@@ -1304,6 +1355,6 @@
 #endif /* MODULE */
 /*
  * Local variables:
- * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/include/linux -Wall -Wstrict-prototypes -O2 -m486 -c cm206.c -o cm206.o"
+ * compile-command: "gcc -DMODULE -D__KERNEL__ -I. -I/usr/src/linux/include/linux -Wall -Wstrict-prototypes -O2 -m486 -c cm206.c -o cm206.o"
  * End:
  */
diff -u --recursive --new-file v2.1.17/linux/drivers/cdrom/gscd.c linux/drivers/cdrom/gscd.c
--- v2.1.17/linux/drivers/cdrom/gscd.c	Tue Oct 29 19:58:04 1996
+++ linux/drivers/cdrom/gscd.c	Fri Dec 27 12:03:20 1996
@@ -71,6 +71,7 @@
 static unsigned char gscd_buf[2048];    /* buffer for block size conversion */
 static int   gscd_bn              = -1;
 static short gscd_port            = GSCD_BASE_ADDR;
+MODULE_PARM(gscd, "h");
 
 /* Kommt spaeter vielleicht noch mal dran ...
  *    static struct wait_queue *gscd_waitq = NULL;
diff -u --recursive --new-file v2.1.17/linux/drivers/cdrom/isp16.c linux/drivers/cdrom/isp16.c
--- v2.1.17/linux/drivers/cdrom/isp16.c	Tue Apr  2 08:43:05 1996
+++ linux/drivers/cdrom/isp16.c	Fri Dec 27 12:03:21 1996
@@ -62,6 +62,11 @@
 static int isp16_cdrom_irq = ISP16_CDROM_IRQ;
 static int isp16_cdrom_dma = ISP16_CDROM_DMA;
 static char *isp16_cdrom_type = ISP16_CDROM_TYPE;
+MODULE_PARM(isp16_cdrom_base, "i");
+MODULE_PARM(isp16_cdrom_irq, "i");
+MODULE_PARM(isp16_cdrom_dma, "i");
+MODULE_PARM(isp16_cdrom_type, "s");
+
 #ifdef MODULE
 int init_module(void);
 void cleanup_module(void);
diff -u --recursive --new-file v2.1.17/linux/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c
--- v2.1.17/linux/drivers/cdrom/mcdx.c	Sun Nov 10 20:12:10 1996
+++ linux/drivers/cdrom/mcdx.c	Fri Dec 27 12:03:21 1996
@@ -3,15 +3,15 @@
  * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
  * VERSION: 2.14(hs)
  *
- * ... anyway, I'm back again, thanks to Marcin, he adopted 
+ * ... anyway, I'm back again, thanks to Marcin, he adopted
  * large portions of my code (at least the parts containing
  * my main thoughts ...)
  *
  ****************** H E L P *********************************
  * If you ever plan to update your CD ROM drive and perhaps
- * want to sell or simply give away your Mitsumi FX-001[DS] 
+ * want to sell or simply give away your Mitsumi FX-001[DS]
  * -- Please --
- * mail me (heiko@lotte.sax.de).  When my last drive goes 
+ * mail me (heiko@lotte.sax.de).  When my last drive goes
  * ballistic no more driver support will be available from me!
  *************************************************************
  *
@@ -19,12 +19,12 @@
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
  * any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; see the file COPYING.  If not, write to
  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -43,7 +43,7 @@
  *  Heiko Eissfeldt (VERIFY_READ/WRITE)
  *  Marcin Dalecki (improved performance, shortened code)
  *  ... somebody forgotten?
- *  
+ *
  */
 
 
@@ -70,11 +70,11 @@
 #define MAJOR_NR MITSUMI_X_CDROM_MAJOR
 #include <linux/blk.h>
 
-/* for compatible parameter passing with "insmod" */ 
-#define	mcdx_drive_map mcdx    
+/* for compatible parameter passing with "insmod" */
+#define	mcdx_drive_map mcdx
 #include <linux/mcdx.h>
 
-#ifndef HZ 
+#ifndef HZ
 #error HZ not defined
 #endif
 
@@ -121,7 +121,7 @@
 const unsigned char READ2X = 0xc1;
 
 
-/* DECLARATIONS ****************************************************/ 
+/* DECLARATIONS ****************************************************/
 struct s_subqcode {
 	unsigned char control;
 	unsigned char tno;
@@ -136,7 +136,7 @@
 	struct cdrom_msf0 msf_leadout;
 	struct cdrom_msf0 msf_first;
 };
-	
+
 struct s_multi {
 	unsigned char multi;
 	struct cdrom_msf0 msf_last;
@@ -161,7 +161,7 @@
     volatile int lock;		/* exclusive usage */
     int eject_sw;           /* 1 - eject on last close (default 0) */
     int autoclose;          /* 1 - close the door on open (default 1) */
-    
+
 	/* cd infos */
 	struct s_diskinfo di;
 	struct s_multi multi;
@@ -170,7 +170,7 @@
     struct s_subqcode stop;
 	int xa;					/* 1 if xa disk */
 	int audio;				/* 1 if audio disk */
-	int audiostatus;			
+	int audiostatus;
 
 	/* `buffer' control */
     volatile int valid;			/* pending, ..., values are valid */
@@ -204,7 +204,7 @@
 };
 
 
-/* Prototypes ******************************************************/ 
+/* Prototypes ******************************************************/
 
 /*	The following prototypes are already declared elsewhere.  They are
  	repeated here to show what's going on.  And to sense, if they're
@@ -219,7 +219,7 @@
 void mcdx_setup(char *, int *);
 
 /*	Indirect exported functions. These functions are exported by their
-	addresses, such as mcdx_open and mcdx_close in the 
+	addresses, such as mcdx_open and mcdx_close in the
 	structure fops. */
 
 /* ???  exported by the mcdx_sigaction struct */
@@ -256,9 +256,9 @@
 static int mcdx_requesttocdata(struct s_drive_stuff*, struct s_diskinfo*, int);
 static int mcdx_getstatus(struct s_drive_stuff*, int);
 static int mcdx_getval(struct s_drive_stuff*, int to, int delay, char*);
-static int mcdx_talk(struct s_drive_stuff*, 
-		const unsigned char* cmd, size_t, 
-        void *buffer, size_t size, 
+static int mcdx_talk(struct s_drive_stuff*,
+		const unsigned char* cmd, size_t,
+        void *buffer, size_t size,
         unsigned int timeout, int);
 static int mcdx_readtoc(struct s_drive_stuff*);
 static int mcdx_playtrk(struct s_drive_stuff*, const struct cdrom_ti*);
@@ -273,6 +273,7 @@
 static struct s_drive_stuff* mcdx_irq_map[16] =
 		{0, 0, 0, 0, 0, 0, 0, 0,
 		0, 0, 0, 0, 0, 0, 0, 0};
+MODULE_PARM(mcdx, "1-4i");
 
 static struct file_operations mcdx_fops = {
 	NULL,			/* lseek - use kernel default */
@@ -290,13 +291,13 @@
 	NULL                      /* revalidate */
 };
 
-/* KERNEL INTERFACE FUNCTIONS **************************************/ 
+/* KERNEL INTERFACE FUNCTIONS **************************************/
 
-static int 
+static int
 mcdx_ioctl(
-	struct inode* ip, struct file* fp, 
+	struct inode* ip, struct file* fp,
 	unsigned int cmd, unsigned long arg)
-{ 
+{
 	struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(ip->i_rdev)];
 
 	if (!stuffp->present) return -ENXIO;
@@ -344,7 +345,7 @@
                 && (-1 == mcdx_hold(stuffp, 1))) return -EIO;
 
             if ((ans = verify_area(
-                    VERIFY_READ, (void*) arg, sizeof(struct cdrom_msf)))) 
+                    VERIFY_READ, (void*) arg, sizeof(struct cdrom_msf))))
                 return ans;
 
             copy_from_user(&msf, (void*) arg, sizeof msf);
@@ -377,13 +378,13 @@
 			if ((ans = verify_area(VERIFY_WRITE, (void *) arg, sizeof(entry)))) return ans;
 			copy_from_user(&entry, (void *) arg, sizeof(entry));
 
-			if (entry.cdte_track == CDROM_LEADOUT) 
+			if (entry.cdte_track == CDROM_LEADOUT)
 				tp = &stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1];
-			else if (entry.cdte_track > stuffp->di.n_last 
+			else if (entry.cdte_track > stuffp->di.n_last
 					|| entry.cdte_track < stuffp->di.n_first) return -EINVAL;
 			else tp = &stuffp->toc[entry.cdte_track - stuffp->di.n_first];
 
-			if (NULL == tp) xwarn("FATAL.\n"); 
+			if (NULL == tp) xwarn("FATAL.\n");
 
 			entry.cdte_adr = tp->control;
 			entry.cdte_ctrl = tp->control >> 4;
@@ -422,7 +423,7 @@
 			sub.cdsc_trk = bcd2uint(q.tno);
 			sub.cdsc_ind = bcd2uint(q.index);
 
-            xtrace(SUBCHNL, "trk %d, ind %d\n", 
+            xtrace(SUBCHNL, "trk %d, ind %d\n",
                     sub.cdsc_trk, sub.cdsc_ind);
 
 			if (sub.cdsc_format == CDROM_LBA) {
@@ -482,10 +483,10 @@
 			int ans;
 			struct cdrom_multisession ms;
 			xtrace(IOCTL, "ioctl() MULTISESSION\n");
-			if (0 != (ans = verify_area(VERIFY_WRITE, (void*) arg, 
+			if (0 != (ans = verify_area(VERIFY_WRITE, (void*) arg,
 					sizeof(struct cdrom_multisession))))
 				return ans;
-				
+
 			copy_from_user(&ms, (void*) arg, sizeof(struct cdrom_multisession));
 			if (ms.addr_format == CDROM_MSF) {
 				ms.addr.msf.minute = bcd2uint(stuffp->multi.msf_last.minute);
@@ -499,9 +500,9 @@
 
 			copy_to_user((void*) arg, &ms, sizeof(struct cdrom_multisession));
 			if (ms.addr_format == CDROM_MSF) {
-				xtrace(MS, 
+				xtrace(MS,
 						"ioctl() (%d, %02x:%02x.%02x [%02x:%02x.%02x])\n",
-						ms.xa_flag, 
+						ms.xa_flag,
 						ms.addr.msf.minute,
 						ms.addr.msf.second,
 						ms.addr.msf.frame,
@@ -509,7 +510,7 @@
 						stuffp->multi.msf_last.second,
 						stuffp->multi.msf_last.frame);
 			} else {
-			    xtrace(MS, 
+			    xtrace(MS,
 					"ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",
 					ms.xa_flag,
 					ms.addr.lba,
@@ -538,7 +539,7 @@
 
             xtrace(IOCTL, "ioctl() VOLCTRL\n");
             if ((ans = verify_area(
-                    VERIFY_READ, 
+                    VERIFY_READ,
                     (void*) arg,
                     sizeof(volctrl))))
                 return ans;
@@ -581,11 +582,11 @@
     dev = MINOR(CURRENT->rq_dev);
     stuffp = mcdx_stuffp[dev];
 
-	if ((dev < 0) 
-		|| (dev >= MCDX_NDRIVES) 
-		|| !stuffp 
+	if ((dev < 0)
+		|| (dev >= MCDX_NDRIVES)
+		|| !stuffp
 		|| (!stuffp->present)) {
-		xwarn("do_request(): bad device: %s\n", 
+		xwarn("do_request(): bad device: %s\n",
 				kdevname(CURRENT->rq_dev));
 		xtrace(REQUEST, "end_request(0): bad device\n");
 		end_request(0); return;
@@ -639,12 +640,12 @@
     goto again;
 }
 
-static int 
+static int
 mcdx_open(struct inode *ip, struct file *fp)
 /*  actions done on open:
- *  1)  get the drives status 
+ *  1)  get the drives status
  *  2)  set the stuffp.readcmd if a CD is in.
- *  (return no error if no CD is found, since ioctl() 
+ *  (return no error if no CD is found, since ioctl()
  *  needs an opened device */
 {
     struct s_drive_stuff *stuffp;
@@ -680,7 +681,7 @@
 
 	/* close the door,
 	 * This should be explained ...
-	 * - If the door is open and its last close is too recent the 
+	 * - If the door is open and its last close is too recent the
 	 *   autoclose wouldn't probably be what we want.
 	 * - If we didn't try to close the door yet, close it and go on.
 	 * - If we autoclosed the door and couldn't succeed in find a valid
@@ -703,7 +704,7 @@
 	if (stuffp->xxx) {
 
 		xtrace(OPENCLOSE, "open() media changed\n");
-        /* but wait - the time of media change will be set at the 
+        /* but wait - the time of media change will be set at the
          * very last of this block - it seems, some of the following
          * talk() will detect a media change ... (I think, config()
          * is the reason. */
@@ -726,10 +727,10 @@
 			/* we succeeded, so on next open(2) we could try auto close
 			 * again */
 			stuffp->autoclose = 1;
-		
+
 #if !MCDX_QUIET
 			if (stuffp->multi.multi > 2)
-				xinfo("open() unknown multisession value (%d)\n", 
+				xinfo("open() unknown multisession value (%d)\n",
 						stuffp->multi.multi);
 #endif
 
@@ -752,7 +753,7 @@
 
 		} else {
 
-			stuffp->lastsector = (CD_FRAMESIZE / 512) 
+			stuffp->lastsector = (CD_FRAMESIZE / 512)
 					* msf2log(&stuffp->di.msf_leadout) - 1;
 
 			xtrace(OPENCLOSE, "open() start %d (%02x:%02x.%02x) %d\n",
@@ -772,7 +773,7 @@
 		if (stuffp->toc) {
 			xtrace(MALLOC, "open() free old toc @ %p\n", stuffp->toc);
 			kfree(stuffp->toc);
-		
+
 			stuffp->toc = NULL;
 		}
 
@@ -786,7 +787,7 @@
 		/* Set the read speed */
 		xwarn("AAA %x AAA\n", stuffp->readcmd);
 		if (stuffp->readerrs) stuffp->readcmd = READ1X;
-		else stuffp->readcmd = 
+		else stuffp->readcmd =
 				stuffp->present | SINGLE ? READ1X : READ2X;
 		xwarn("XXX %x XXX\n", stuffp->readcmd);
 #else
@@ -810,26 +811,26 @@
 					stuffp->xa ? "XA" : "normal");
 
 				/* set data mode */
-				if (-1 == (ans = mcdx_setdatamode(stuffp, 
+				if (-1 == (ans = mcdx_setdatamode(stuffp,
 						stuffp->xa ? MODE2 : MODE1, 1))) {
 					/* MOD_DEC_USE_COUNT, return -EIO; */
 					stuffp->xa = 0;
 					break;
 				}
 
-				if ((stuffp->audio = e_audio(ans))) break; 
+				if ((stuffp->audio = e_audio(ans))) break;
 
-				while (0 == (ans = mcdx_transfer(stuffp, buf, 0, 1))) 
+				while (0 == (ans = mcdx_transfer(stuffp, buf, 0, 1)))
 					;
 
 				if (ans == 1) break;
-				stuffp->xa = !stuffp->xa; 
+				stuffp->xa = !stuffp->xa;
 			}
 			/* if (!tries) MOD_DEC_USE_COUNT, return -EIO; */
 		}
 
 		/* xa disks will be read in raw mode, others not */
-		if (-1 == mcdx_setdrivemode(stuffp, 
+		if (-1 == mcdx_setdrivemode(stuffp,
 				stuffp->xa ? RAW : COOKED, 1)) {
 			MOD_DEC_USE_COUNT;
 			return -EIO;
@@ -841,7 +842,7 @@
 			xinfo("open() %s%s disk found\n",
 					stuffp->xa ? "XA / " : "",
 					stuffp->multi.multi ? "Multi Session" : "Single Session");
-		} 
+		}
 
         /* stuffp->xxx = 0; */
 	}
@@ -851,7 +852,7 @@
 		MOD_DEC_USE_COUNT;
         return -EIO;
 	}
-	} 
+	}
 
 	stuffp->xxx = 0;
     stuffp->users++;
@@ -859,7 +860,7 @@
 
 }
 
-static void 
+static void
 mcdx_close(struct inode *ip, struct file *fp)
 {
     struct s_drive_stuff *stuffp;
@@ -895,7 +896,7 @@
 /*	Return: 1 if media changed since last call to this function
 			0 otherwise */
 {
-    struct s_drive_stuff *stuffp; 
+    struct s_drive_stuff *stuffp;
 
     xinfo("check_mcdx_media_change called for device %s\n",
 	  kdevname(full_dev));
@@ -915,7 +916,7 @@
 	if (pi[0] > 1) mcdx_drive_map[0][1] = pi[2];
 }
 
-/* DIRTY PART ******************************************************/ 
+/* DIRTY PART ******************************************************/
 
 static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
 /* This routine is used for sleeping.
@@ -923,7 +924,7 @@
  *              =0 means minimal sleeping (let the kernel
  *                 run for other processes)
  *              >0 means at least sleep for that amount.
- *	May be we could use a simple count loop w/ jumps to itself, but 
+ *	May be we could use a simple count loop w/ jumps to itself, but
  *	I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */
 {
     unsigned long tout = jiffies + jifs;
@@ -931,12 +932,12 @@
 
 	/* If loaded during kernel boot no *_sleep_on is
 	 * allowed! */
-    if (current->pid == 0) {        
+    if (current->pid == 0) {
 		while (jiffies < tout) {
             current->timeout = jiffies;
             schedule();
         }
-    } else {  
+    } else {
         current->timeout = tout;
 		xtrace(SLEEP, "*** delay: sleepq\n");
 		interruptible_sleep_on(&stuff->sleepq);
@@ -944,10 +945,10 @@
 		if (current->signal & ~current->blocked) {
 			xtrace(SLEEP, "got signal\n");
 		}
-	} 
+	}
 }
 
-static void 
+static void
 mcdx_intr(int irq, void *dev_id, struct pt_regs* regs)
 {
     struct s_drive_stuff *stuffp;
@@ -969,7 +970,7 @@
 	b = inb((unsigned int) stuffp->rreg_status);
 	stuffp->introk = ~b & MCDX_RBIT_DTEN;
 
-	/* NOTE: We only should get interrupts if the data we 
+	/* NOTE: We only should get interrupts if the data we
 	 * requested are ready to transfer.
 	 * But the drive seems to generate ``asynchronous'' interrupts
 	 * on several error conditions too.  (Despite the err int enable
@@ -979,7 +980,7 @@
 	if (!stuffp->introk) {
 		xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b);
 		if (~b & MCDX_RBIT_STEN) {
-			xinfo(  "intr() irq %d    status 0x%02x\n", 
+			xinfo(  "intr() irq %d    status 0x%02x\n",
 					irq, inb((unsigned int) stuffp->rreg_data));
 		} else {
 			xinfo(  "intr() irq %d ambiguous hw status\n", irq);
@@ -993,11 +994,11 @@
 }
 
 
-static int 
+static int
 mcdx_talk (
-		struct s_drive_stuff *stuffp, 
+		struct s_drive_stuff *stuffp,
 		const unsigned char *cmd, size_t cmdlen,
-		void *buffer, size_t size, 
+		void *buffer, size_t size,
 		unsigned int timeout, int tries)
 /* Send a command to the drive, wait for the result.
  * returns -1 on timeout, drive status otherwise
@@ -1015,7 +1016,7 @@
 
     while (stuffp->lock) {
 		xtrace(SLEEP, "*** talk: lockq\n");
-		interruptible_sleep_on(&stuffp->lockq); 
+		interruptible_sleep_on(&stuffp->lockq);
 		xtrace(SLEEP, "talk: awoken\n");
 	}
 
@@ -1023,12 +1024,12 @@
 
 	/* An operation other then reading data destroys the
      * data already requested and remembered in stuffp->request, ... */
-    stuffp->valid = 0;	
+    stuffp->valid = 0;
 
 #if MCDX_DEBUG & TALK
-	{ 
+	{
 		unsigned char i;
-		xtrace(TALK, "talk() %d / %d tries, res.size %d, command 0x%02x", 
+		xtrace(TALK, "talk() %d / %d tries, res.size %d, command 0x%02x",
 				tries, timeout, size, (unsigned char) cmd[0]);
 		for (i = 1; i < cmdlen; i++) xtrace(TALK, " 0x%02x", cmd[i]);
 		xtrace(TALK, "\n");
@@ -1047,9 +1048,9 @@
 
         /* get the status byte */
         if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
-            xinfo("talk() %02x timed out (status), %d tr%s left\n", 
+            xinfo("talk() %02x timed out (status), %d tr%s left\n",
                     cmd[0], tries - 1, tries == 2 ? "y" : "ies");
-                continue; 
+                continue;
         }
         st = *bp;
         sz--;
@@ -1059,7 +1060,7 @@
 
         /* command error? */
         if (e_cmderr(st)) {
-            xwarn("command error cmd = %02x %s \n", 
+            xwarn("command error cmd = %02x %s \n",
                     cmd[0], cmdlen > 1 ? "..." : "");
             st = -1;
             continue;
@@ -1067,9 +1068,9 @@
 
         /* audio status? */
         if (stuffp->audiostatus == CDROM_AUDIO_INVALID)
-            stuffp->audiostatus = 
+            stuffp->audiostatus =
                     e_audiobusy(st) ? CDROM_AUDIO_PLAY : CDROM_AUDIO_NO_STATUS;
-        else if (stuffp->audiostatus == CDROM_AUDIO_PLAY 
+        else if (stuffp->audiostatus == CDROM_AUDIO_PLAY
                 && e_audiobusy(st) == 0)
             stuffp->audiostatus = CDROM_AUDIO_COMPLETED;
 
@@ -1082,7 +1083,7 @@
         /* now actually get the data */
         while (sz--) {
             if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
-                xinfo("talk() %02x timed out (data), %d tr%s left\n", 
+                xinfo("talk() %02x timed out (data), %d tr%s left\n",
                         cmd[0], tries - 1, tries == 2 ? "y" : "ies");
                 st = -1; break;
             }
@@ -1104,6 +1105,7 @@
 
 /* MODULE STUFF ***********************************************************/
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
 
 int init_module(void)
 {
@@ -1119,10 +1121,9 @@
 		}
 	}
 
-    if (!drives) 
+    if (!drives)
 		return -EIO;
 
-    register_symtab(0);
     return 0;
 }
 
@@ -1131,7 +1132,7 @@
     int i;
 
 	xinfo("cleanup_module called\n");
-	
+
     for (i = 0; i < MCDX_NDRIVES; i++) {
 		struct s_drive_stuff *stuffp;
 		stuffp = mcdx_stuffp[i];
@@ -1149,7 +1150,7 @@
 
     if (unregister_blkdev(MAJOR_NR, DEVICE_NAME) != 0) {
         xwarn("cleanup() unregister_blkdev() failed\n");
-    } 
+    }
 #if !MCDX_QUIET
 	else xinfo("cleanup() succeeded\n");
 #endif
@@ -1164,7 +1165,7 @@
 	int drive;
 
 #ifdef MODULE
-	xwarn("Version 2.14(hs) for %s\n", kernel_version);
+	xwarn("Version 2.14(hs) for " UTS_RELEASE "\n");
 #else
 	xwarn("Version 2.14(hs) \n");
 #endif
@@ -1176,7 +1177,7 @@
 		mcdx_stuffp[drive] = NULL;
 
 	/* do the initialisation */
-	for (drive = 0; drive < MCDX_NDRIVES; drive++) { 
+	for (drive = 0; drive < MCDX_NDRIVES; drive++) {
 		struct s_version version;
 		struct s_drive_stuff* stuffp;
         int size;
@@ -1184,14 +1185,14 @@
 		mcdx_blocksizes[drive] = 0;
 
         size = sizeof(*stuffp);
-		
+
 		xtrace(INIT, "init() try drive %d\n", drive);
 
         xtrace(INIT, "kmalloc space for stuffpt's\n");
 		xtrace(MALLOC, "init() malloc %d bytes\n", size);
 		if (!(stuffp = kmalloc(size, GFP_KERNEL))) {
 			xwarn("init() malloc failed\n");
-			break; 
+			break;
 		}
 
 		xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n", sizeof(*stuffp), stuffp);
@@ -1215,7 +1216,7 @@
             xwarn("0x%3p,%d: "
                     "Init failed. I/O ports (0x%3p..0x%3p) already in use.\n",
                     stuffp->wreg_data, stuffp->irq,
-                    stuffp->wreg_data, 
+                    stuffp->wreg_data,
                     stuffp->wreg_data + MCDX_IO_SIZE - 1);
 			xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
             kfree(stuffp);
@@ -1241,19 +1242,19 @@
 		}
 
 		switch (version.code) {
-		case 'D': 
-                stuffp->readcmd = READ2X; 
-                stuffp->present = DOUBLE | DOOR | MULTI; 
+		case 'D':
+                stuffp->readcmd = READ2X;
+                stuffp->present = DOUBLE | DOOR | MULTI;
                 break;
-		case 'F': 
-                stuffp->readcmd = READ1X; 
+		case 'F':
+                stuffp->readcmd = READ1X;
                 stuffp->present = SINGLE | DOOR | MULTI;
                 break;
-		case 'M': 
+		case 'M':
                 stuffp->readcmd = READ1X;
                 stuffp->present = SINGLE;
                 break;
-		default: 
+		default:
                 stuffp->present = 0; break;
 		}
 
@@ -1291,9 +1292,9 @@
 			kfree(stuffp);
 			continue;
 		}
-		request_region((unsigned int) stuffp->wreg_data, 
-                MCDX_IO_SIZE, 
-                DEVICE_NAME); 
+		request_region((unsigned int) stuffp->wreg_data,
+                MCDX_IO_SIZE,
+                DEVICE_NAME);
 
 		xtrace(INIT, "init() get garbage\n");
 		{
@@ -1324,12 +1325,12 @@
 	return 0;
 }
 
-static int 
+static int
 mcdx_transfer(struct s_drive_stuff *stuffp,
 		char *p, int sector, int nr_sectors)
 /*	This seems to do the actually transfer.  But it does more.  It
 	keeps track of errors occurred and will (if possible) fall back
-	to single speed on error. 
+	to single speed on error.
 	Return:	-1 on timeout or other error
 			else status byte (as in stuff->st) */
 {
@@ -1351,7 +1352,7 @@
 	stuffp->readcmd = READ1X;
 	return mcdx_transfer(stuffp, p, sector, nr_sectors);
 #endif
-	
+
 }
 
 
@@ -1363,7 +1364,7 @@
 {
     int border;
     int done = 0;
-	
+
 	if (stuffp->audio) {
 			xwarn("Attempt to read from audio CD.\n");
 			return -1;
@@ -1403,9 +1404,9 @@
 			interruptible_sleep_on(&stuffp->busyq);
 
 			if (!stuffp->introk) { xtrace(XFER, "error via interrupt\n"); }
-			else if (current->timeout == 0) { xtrace(XFER, "timeout\n"); } 
+			else if (current->timeout == 0) { xtrace(XFER, "timeout\n"); }
 			else if (current->signal & ~current->blocked) {
-				xtrace(XFER, "signal\n"); 
+				xtrace(XFER, "signal\n");
 			} else continue;
 
 			stuffp->lock = 0;
@@ -1428,8 +1429,8 @@
 			insb((unsigned int) stuffp->rreg_data, p, HEAD);
 		}
 
-		/* now actually read the data */ 
-	    insb((unsigned int) stuffp->rreg_data, p, 512); 
+		/* now actually read the data */
+	    insb((unsigned int) stuffp->rreg_data, p, 512);
 
 		/* test if it's the last sector of a block,
 		 * if so, we have to handle XA special */
@@ -1450,7 +1451,7 @@
 
     } else {
 
-		/* The requested sector(s) is/are out of the 
+		/* The requested sector(s) is/are out of the
 		 * already requested range, so we have to bother the drive
 		 * with a new request. */
 
@@ -1546,7 +1547,7 @@
     + bcd2uint(pmsf->minute) * 4500
     - CD_BLOCK_OFFSET;
 }
-	
+
 int mcdx_readtoc(struct s_drive_stuff* stuffp)
 /*  Read the toc entries from the CD,
  *  Return: -1 on failure, else 0 */
@@ -1584,15 +1585,15 @@
 		int trk;
 		int retries;
 
-		for (trk = 0; 
-				trk < (stuffp->di.n_last - stuffp->di.n_first + 1); 
+		for (trk = 0;
+				trk < (stuffp->di.n_last - stuffp->di.n_first + 1);
 				trk++)
 			stuffp->toc[trk].index = 0;
 
 		for (retries = 300; retries; retries--) { /* why 300? */
 			struct s_subqcode q;
 			unsigned int idx;
-		
+
 			if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) {
 				mcdx_setdrivemode(stuffp, DATA, 1);
 				return -EIO;
@@ -1600,8 +1601,8 @@
 
 			idx = bcd2uint(q.index);
 
-			if ((idx > 0) 
-					&& (idx <= stuffp->di.n_last) 
+			if ((idx > 0)
+					&& (idx <= stuffp->di.n_last)
 					&& (q.tno == 0)
 					&& (stuffp->toc[idx - stuffp->di.n_first].index == 0)) {
 				stuffp->toc[idx - stuffp->di.n_first] = q;
@@ -1610,7 +1611,7 @@
 			}
 			if (trk == 0) break;
 		}
-		memset(&stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1], 
+		memset(&stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1],
 				0, sizeof(stuffp->toc[0]));
 		stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1].dt
 				= stuffp->di.msf_leadout;
@@ -1623,8 +1624,8 @@
 
 #if MCDX_DEBUG && READTOC
 	{ int trk;
-	for (trk = 0; 
-			trk < (stuffp->di.n_last - stuffp->di.n_first + 2); 
+	for (trk = 0;
+			trk < (stuffp->di.n_last - stuffp->di.n_first + 2);
 			trk++)
 		xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x"
 				"  %02x:%02x.%02x  %02x:%02x.%02x\n",
@@ -1651,7 +1652,7 @@
 	}
 
     cmd[0] = stuffp->playcmd;
-    
+
     cmd[1] = msf->cdmsf_min0;
     cmd[2] = msf->cdmsf_sec0;
     cmd[3] = msf->cdmsf_frame0;
@@ -1662,12 +1663,12 @@
     xtrace(PLAYMSF, "ioctl(): play %x "
             "%02x:%02x:%02x -- %02x:%02x:%02x\n",
             cmd[0], cmd[1], cmd[2], cmd[3],
-            cmd[4], cmd[5], cmd[6]); 
+            cmd[4], cmd[5], cmd[6]);
 
     outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd);
 
     if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) {
-        xwarn("playmsf() timeout\n"); 
+        xwarn("playmsf() timeout\n");
         return -1;
     }
 
@@ -1675,7 +1676,7 @@
     return 0;
 }
 
-static int 
+static int
 mcdx_playtrk(struct s_drive_stuff* stuffp, const struct cdrom_ti* ti)
 {
     struct s_subqcode* p;
@@ -1705,7 +1706,7 @@
 
 /* Drive functions ************************************************/
 
-static int 
+static int
 mcdx_closedoor(struct s_drive_stuff *stuffp, int tries)
 {
 	if (stuffp->present & DOOR)
@@ -1714,7 +1715,7 @@
 		return 0;
 }
 
-static int 
+static int
 mcdx_stop(struct s_drive_stuff *stuffp, int tries)
 { return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries); }
 
@@ -1732,8 +1733,8 @@
 }
 
 static int
-mcdx_requestsubqcode(struct s_drive_stuff *stuffp, 
-        struct s_subqcode *sub, 
+mcdx_requestsubqcode(struct s_drive_stuff *stuffp,
+        struct s_subqcode *sub,
         int tries)
 {
 	char buf[11];
@@ -1741,7 +1742,7 @@
 
 	if (-1 == (ans = mcdx_talk(
             stuffp, "\x20", 1, buf, sizeof(buf),
-            2 * HZ, tries))) 
+            2 * HZ, tries)))
         return -1;
 	sub->control = buf[1];
 	sub->tno = buf[2];
@@ -1775,7 +1776,7 @@
     }
 }
 
-static int 
+static int
 mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info, int tries)
 {
 	char buf[9];
@@ -1860,7 +1861,7 @@
 	char buf[3];
 	int ans;
 
-	if (-1 == (ans = mcdx_talk(stuffp, "\xdc", 
+	if (-1 == (ans = mcdx_talk(stuffp, "\xdc",
 			1, buf, sizeof(buf), 2 * HZ, tries)))
 		return ans;
 
@@ -1872,7 +1873,7 @@
 
 static int
 mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
-{ 
+{
 	if (mode == HARD) {
 		outb(0, (unsigned int) stuffp->wreg_chn);		/* no dma, no irq -> hardware */
 		outb(0, (unsigned int) stuffp->wreg_reset);		/* hw reset */
@@ -1914,8 +1915,8 @@
 
 static int
 mcdx_setattentuator(
-        struct s_drive_stuff* stuffp, 
-        struct cdrom_volctrl* vol, 
+        struct s_drive_stuff* stuffp,
+        struct cdrom_volctrl* vol,
         int tries)
 {
     char cmd[5];
diff -u --recursive --new-file v2.1.17/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c
--- v2.1.17/linux/drivers/cdrom/optcd.c	Tue Nov 19 15:53:53 1996
+++ linux/drivers/cdrom/optcd.c	Fri Dec 27 12:03:21 1996
@@ -106,7 +106,7 @@
 
 #define optcd_port optcd			/* Needed for the modutils. */
 static short optcd_port = OPTCD_PORTBASE;	/* I/O base of drive. */
-
+MODULE_PARM(optcd_port, "h");
 /* Drive registers, read */
 #define DATA_PORT	optcd_port	/* Read data/status */
 #define STATUS_PORT	optcd_port+1	/* Indicate data/status availability */
diff -u --recursive --new-file v2.1.17/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- v2.1.17/linux/drivers/cdrom/sbpcd.c	Tue Oct 29 19:58:05 1996
+++ linux/drivers/cdrom/sbpcd.c	Fri Dec 27 12:03:21 1996
@@ -442,6 +442,7 @@
 #else
 static int sbpcd[] = {CDROM_PORT, SBPRO}; /* probe with user's setup only */
 #endif
+MODULE_PARM(sbpcd, "2i");
 
 #define NUM_PROBE  (sizeof(sbpcd) / sizeof(int))
 
diff -u --recursive --new-file v2.1.17/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c
--- v2.1.17/linux/drivers/cdrom/sjcd.c	Tue Oct 29 19:58:05 1996
+++ linux/drivers/cdrom/sjcd.c	Fri Dec 27 12:03:21 1996
@@ -106,6 +106,7 @@
 static struct sjcd_play_msf sjcd_playing;
 
 static int sjcd_base = SJCD_BASE_ADDR;
+MODULE_PARM(sjcd_base, "i");
 
 static struct wait_queue *sjcd_waitq = NULL;
 
diff -u --recursive --new-file v2.1.17/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- v2.1.17/linux/drivers/cdrom/sonycd535.c	Tue Oct 29 19:58:05 1996
+++ linux/drivers/cdrom/sonycd535.c	Fri Dec 27 12:03:21 1996
@@ -198,6 +198,7 @@
 /* The base I/O address of the Sony Interface.  This is a variable (not a
    #define) so it can be easily changed via some future ioctl() */
 static unsigned int sony535_cd_base_io = CDU535_ADDRESS;
+MODULE_PARM(sony535_cd_base_io, "i");
 
 /*
  * The following are I/O addresses of the various registers for the drive.  The
diff -u --recursive --new-file v2.1.17/linux/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c
--- v2.1.17/linux/drivers/char/apm_bios.c	Tue Oct 29 19:58:05 1996
+++ linux/drivers/char/apm_bios.c	Fri Dec 27 12:03:21 1996
@@ -73,12 +73,8 @@
 #include <linux/miscdevice.h>
 #include <linux/apm_bios.h>
 
-static struct symbol_table	apm_syms = {
-#include <linux/symtab_begin.h>
-	X(apm_register_callback),
-	X(apm_unregister_callback),
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(apm_register_callback);
+EXPORT_SYMBOL(apm_unregister_callback);
 
 extern unsigned long get_cmos_time(void);
 
@@ -89,7 +85,7 @@
 #define	APM_MINOR_DEV	134
 
 /* Configurable options:
- *  
+ *
  * CONFIG_APM_IGNORE_USER_SUSPEND: define to ignore USER SUSPEND requests.
  * This is necessary on the NEC Versa M series, which generates these when
  * resuming from SYSTEM SUSPEND.  However, enabling this on other laptops
@@ -564,7 +560,7 @@
 	*ptr = old->next;
 	kfree_s(old, sizeof(callback_list_t));
 }
-	
+
 static int queue_empty(struct apm_bios_struct * as)
 {
 	return as->event_head == as->event_tail;
@@ -579,7 +575,7 @@
 static int queue_event(apm_event_t event, struct apm_bios_struct *sender)
 {
 	struct apm_bios_struct *	as;
-	
+
 	if (user_list == NULL)
 		return 0;
 	for (as = user_list; as != NULL; as = as->next) {
@@ -635,7 +631,7 @@
 	clock_cmos_diff += CURRENT_TIME;
 	got_clock_diff = 1;
 	restore_flags(flags);
-	
+
 	err = apm_set_power_state(APM_STATE_SUSPEND);
 	if (err)
 		apm_error("suspend", err);
@@ -673,7 +669,7 @@
 {
 	callback_list_t *	call;
 	callback_list_t *	fix;
-    
+
 	for (call = callback_list; call != NULL; call = call->next) {
 		if (call->callback(event) && undo) {
 			for (fix = callback_list; fix != call; fix = fix->next)
@@ -796,7 +792,7 @@
 
 	if (!apm_enabled)
 		return;
-	
+
 #ifndef ALWAYS_CALL_BUSY
 	if (!clock_slowed)
 		return;
@@ -1054,7 +1050,7 @@
 	      Number of remaining minutes or seconds
 	      -1: Unknown
 	   8) min = minutes; sec = seconds */
-	    
+
 	p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
 		     driver_version,
 		     (apm_bios_info.version >> 8) & 0xff,
@@ -1176,7 +1172,7 @@
 			if (dx == 0xffff)
 				printk("unknown\n");
 			else {
-				if ((dx & 0x8000)) 
+				if ((dx & 0x8000))
 					printk("%d minutes\n", dx & 0x7ffe );
 				else
 					printk("%d seconds\n", dx & 0x7fff );
@@ -1201,8 +1197,6 @@
 	apm_timer.function = do_apm_timer;
 	apm_timer.expires = APM_CHECK_TIMEOUT + jiffies;
 	add_timer(&apm_timer);
-
-	register_symtab(&apm_syms);
 
 #ifdef CONFIG_PROC_FS
 	proc_register_dynamic(&proc_root, &apm_proc_entry);
diff -u --recursive --new-file v2.1.17/linux/drivers/char/esp.c linux/drivers/char/esp.c
--- v2.1.17/linux/drivers/char/esp.c	Wed Dec 18 15:58:47 1996
+++ linux/drivers/char/esp.c	Fri Dec 27 12:03:21 1996
@@ -28,6 +28,11 @@
  *     by Dennis J. Boylan).  Patches to allow use with 2.1.x contributed
  *     by Chris Faylor.
  *
+ * Most recent changes: (Andrew J. Robinson)
+ *     Remove tx_flowed_[on|off], since the ESP handles flow itself.
+ *     Enabled reinterrupt pacing to ensure all requests are serviced.
+ *     Decreased RX timeout to reduce latency.
+ *
  * This module exports the following rs232 io functions:
  *
  *	int esp_init(void);
@@ -68,8 +73,9 @@
 static int irq[NR_PRIMARY] = {0,0,0,0,0,0,0,0};	/* IRQ for each base port */
 static unsigned int divisor[NR_PRIMARY] = {0,0,0,0,0,0,0,0};
 	/* custom divisor for each port */
-static unsigned int dma = CONFIG_ESP_DMA_CHANNEL; /* DMA channel */
-static unsigned int trigger = CONFIG_ESP_TRIGGER_LEVEL; /* FIFO trigger level */
+static unsigned int dma = CONFIG_ESPSERIAL_DMA_CHANNEL; /* DMA channel */
+static unsigned int trigger = CONFIG_ESPSERIAL_TRIGGER_LEVEL;
+	/* FIFO trigger level */
 /* END */
 
 static char *dma_buffer;
@@ -78,8 +84,8 @@
 
 #define WAKEUP_CHARS 1024
 
-static char *serial_name = "ESP driver";
-static char *serial_version = "1.1";
+static char *serial_name = "ESP serial driver";
+static char *serial_version = "1.2";
 
 DECLARE_TASK_QUEUE(tq_esp);
 
@@ -574,31 +580,8 @@
 	}
 }
 
-static _INLINE_ void tx_flowed_on(struct esp_struct *info)
-{
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
-	printk("CTS tx start...");
-#endif
-	info->tty->hw_stopped = 0;
-	info->IER |= UART_IER_THRI;
-	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); /* set mask */
-	serial_out(info, UART_ESI_CMD2, info->IER);
-	rs_sched_event(info, ESP_EVENT_WRITE_WAKEUP);
-}
-
-static _INLINE_ void tx_flowed_off(struct esp_struct *info)
-{
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
-	printk("CTS tx stop...");
-#endif
-	info->tty->hw_stopped = 1;
-	info->IER &= ~UART_IER_THRI;
-	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); /* set mask */
-	serial_out(info, UART_ESI_CMD2, info->IER);
-}
-
 /*
- * This is the serial driver's interrupt routine for a single port
+ * This is the serial driver's interrupt routine
  */
 static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
 {
@@ -644,12 +627,6 @@
 
 			if (err_status & 0x8000)	/* Start break */
 				wake_up_interruptible(&info->break_wait);
-
-			if (err_status & 0x0002)	/* tx off */
-				tx_flowed_off(info);
-
-			if (err_status & 0x0004)	/* tx on */
-				tx_flowed_on(info);
 		}
 		
 		if ((scratch & 0x88)  || /* DMA completed or timed out */
@@ -777,7 +754,7 @@
 	/* set error status mask (check this) */
 	serial_out(info, UART_ESI_CMD1, ESI_SET_ERR_MASK);
 	serial_out(info, UART_ESI_CMD2, 0xbd);
-	serial_out(info, UART_ESI_CMD2, 0x06);
+	serial_out(info, UART_ESI_CMD2, 0x00);
 
 	/* set DMA timeout */
 	serial_out(info, UART_ESI_CMD1, ESI_SET_DMA_TMOUT);
@@ -793,6 +770,10 @@
 	/* Set clock scaling */
 	serial_out(info, UART_ESI_CMD1, ESI_SET_PRESCALAR);
 	serial_out(info, UART_ESI_CMD2, ESPC_SCALE);
+
+	/* set reinterrupt pacing */
+	serial_out(info, UART_ESI_CMD1, ESI_SET_REINTR);
+	serial_out(info, UART_ESI_CMD2, 0xff);
 }
 
 static int startup(struct esp_struct * info)
@@ -867,7 +848,7 @@
 
 	/* set receive character timeout */
 	serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
-	serial_out(info, UART_ESI_CMD2, 0xff);
+	serial_out(info, UART_ESI_CMD2, 0x80);
 
 	info->stat_flags = 0;
 
@@ -1417,7 +1398,7 @@
 	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
 	serial_out(info, UART_ESI_CMD2, info->IER);
 	serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
-	serial_out(info, UART_ESI_CMD2, 0xff);
+	serial_out(info, UART_ESI_CMD2, 0x80);
 	sti();
 }
 
@@ -2409,7 +2390,7 @@
 	}
 
 	if ((dma != 1) && (dma != 3))
-		dma = CONFIG_ESP_DMA_CHANNEL;
+		dma = 1;
 
 	if ((trigger < 1) || (trigger > 1015))
 		trigger = 768;
diff -u --recursive --new-file v2.1.17/linux/drivers/char/ftape/kernel-interface.c linux/drivers/char/ftape/kernel-interface.c
--- v2.1.17/linux/drivers/char/ftape/kernel-interface.c	Fri Nov  1 17:13:16 1996
+++ linux/drivers/char/ftape/kernel-interface.c	Fri Dec 27 12:03:21 1996
@@ -116,6 +116,7 @@
  */
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
 #define ftape_init init_module
 #endif
 
@@ -175,9 +176,7 @@
 	udelay_calibrate();	/* must be before fdc_wait_calibrate ! */
 	fdc_wait_calibrate();
 	TRACE_EXIT;
-#ifdef MODULE
-	register_symtab(0);	/* remove global ftape symbols */
-#endif
+
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.17/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.1.17/linux/drivers/char/mem.c	Sun Dec 22 16:37:31 1996
+++ linux/drivers/char/mem.c	Mon Dec 23 11:12:12 1996
@@ -34,27 +34,17 @@
 void pcwatchdog_init(void);
 #endif
 
-static long read_ram(struct inode * inode, struct file * file,
-	char * buf, unsigned long count)
-{
-	return -EIO;
-}
-
-static long write_ram(struct inode * inode, struct file * file,
-	const char * buf, unsigned long count)
-{
-	return -EIO;
-}
-
+/*
+ * This funcion reads the *physical* memory. The f_pos points directly to the 
+ * memory location. 
+ */
 static long read_mem(struct inode * inode, struct file * file,
 	char * buf, unsigned long count)
 {
 	unsigned long p = file->f_pos;
 	unsigned long end_mem;
-	int read;
+	unsigned long read;
 
-	if (count < 0)
-		return -EINVAL;
 	end_mem = __pa(high_memory);
 	if (p >= end_mem)
 		return 0;
@@ -82,10 +72,8 @@
 {
 	unsigned long p = file->f_pos;
 	unsigned long end_mem;
-	int written;
+	unsigned long written;
 
-	if (count < 0)
-		return -EINVAL;
 	end_mem = __pa(high_memory);
 	if (p >= end_mem)
 		return 0;
@@ -132,19 +120,70 @@
 	return 0;
 }
 
+/*
+ * This function reads the *virtual* memory as seen by the kernel.
+ */
 static long read_kmem(struct inode *inode, struct file *file,
 	char *buf, unsigned long count)
 {
-	int read1, read2;
+	unsigned long p = file->f_pos;
+	unsigned long read = 0;
+	long virtr;
+		
+	if (p < (unsigned long) high_memory) { 
+		unsigned long tmp;
+		
+		if (count > (unsigned long) high_memory - p)
+			tmp = (unsigned long) high_memory - p;
+		else
+			tmp = count;
+		read = tmp;
+#if defined(__sparc__) /* we don't have page 0 mapped on sparc.. */
+		while (p < PAGE_SIZE && tmp > 0) {
+			put_user(0,buf);
+			buf++;
+			p++;
+			tmp--;
+		}
+#endif
+		copy_to_user(buf, (char *) p, tmp);
+		buf += tmp;
+	}
+
+	virtr = vread(buf, (char *) (unsigned long) file->f_pos, count - read);
+	if (virtr < 0)
+		return virtr;
+	file->f_pos += virtr + read;
+	return virtr + read;
+}
+
+/*
+ * This function writes to the *virtual* memory as seen by the kernel.
+ */
+static long write_kmem(struct inode * inode, struct file * file,
+	const char * buf, unsigned long count)
+{
+	unsigned long p = file->f_pos;
+	unsigned long written;
 
-	read1 = read_mem(inode, file, buf, count);
-	if (read1 < 0)
-		return read1;
-	read2 = vread(buf + read1, (char *) ((unsigned long) file->f_pos), count - read1);
-	if (read2 < 0)
-		return read2;
-	file->f_pos += read2;
-	return read1 + read2;
+	if (p >= (unsigned long) high_memory)
+		return 0;
+	if (count > (unsigned long) high_memory - p)
+		count = (unsigned long) high_memory - p;
+	written = 0;
+#if defined(__sparc__) /* we don't have page 0 mapped on sparc.. */
+	while (p < PAGE_SIZE && count > 0) {
+		/* Hmm. Do something? */
+		buf++;
+		p++;
+		count--;
+		written++;
+	}
+#endif
+	copy_from_user((char *) p, buf, count);
+	written += count;
+	file->f_pos += written;
+	return count;
 }
 
 static long read_port(struct inode * inode, struct file * file,
@@ -298,24 +337,10 @@
 	return file->f_pos;
 }
 
-#define write_kmem	write_mem
 #define mmap_kmem	mmap_mem
 #define zero_lseek	null_lseek
 #define write_zero	write_null
 
-static struct file_operations ram_fops = {
-	memory_lseek,
-	read_ram,
-	write_ram,
-	NULL,		/* ram_readdir */
-	NULL,		/* ram_select */
-	NULL,		/* ram_ioctl */
-	NULL,		/* ram_mmap */
-	NULL,		/* no special open code */
-	NULL,		/* no special release code */
-	NULL		/* fsync */
-};
-
 static struct file_operations mem_fops = {
 	memory_lseek,
 	read_mem,
@@ -395,9 +420,6 @@
 static int memory_open(struct inode * inode, struct file * filp)
 {
 	switch (MINOR(inode->i_rdev)) {
-		case 0:
-			filp->f_op = &ram_fops;
-			break;
 		case 1:
 			filp->f_op = &mem_fops;
 			break;
diff -u --recursive --new-file v2.1.17/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.1.17/linux/drivers/char/misc.c	Sun Dec 22 16:37:31 1996
+++ linux/drivers/char/misc.c	Fri Dec 27 12:03:21 1996
@@ -175,17 +175,13 @@
 
 #endif
 
-static struct symbol_table misc_syms = {
 /* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
-#include <linux/symtab_begin.h>
-	X(misc_register),
-	X(misc_deregister),
+EXPORT_SYMBOL(misc_register);
+EXPORT_SYMBOL(misc_deregister);
 #ifndef MODULE
-	X(set_selection),   /* used by the kmouse module, can only */
-	X(paste_selection), /* be exported if misc.c is in linked in */
+EXPORT_SYMBOL(set_selection);   /* used by the kmouse module, can only */
+EXPORT_SYMBOL(paste_selection); /* be exported if misc.c is in linked in */
 #endif
-#include <linux/symtab_end.h>
-};
 
 #if defined(CONFIG_PROC_FS) && !defined(MODULE)
 static struct proc_dir_entry proc_misc = {
@@ -240,15 +236,10 @@
 #endif
 #endif /* !MODULE */
 	if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
-	  printk("unable to get major %d for misc devices\n",
-		 MISC_MAJOR);
+		printk("unable to get major %d for misc devices\n",
+		       MISC_MAJOR);
 		return -EIO;
 	}
 
-	if(register_symtab(&misc_syms)!=0)
-	{
-		unregister_chrdev(MISC_MAJOR, "misc");
-		return -EIO;
-	}
 	return 0;
 }
diff -u --recursive --new-file v2.1.17/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c
--- v2.1.17/linux/drivers/char/pcwd.c	Thu Dec 12 19:37:01 1996
+++ linux/drivers/char/pcwd.c	Fri Dec 27 12:03:21 1996
@@ -215,14 +215,13 @@
 	wdrst_stat |= WD_WDRST;
 
 	outb_p(wdrst_stat, current_readport + PORT_OFFSET);
-	return(1);
 }
 
 static int pcwd_ioctl(struct inode *inode, struct file *file,
 	unsigned int cmd, unsigned long arg)
 {
 	int i, cdat, rv;
-	static struct watchdog_ident ident=
+	static struct watchdog_info ident=
 	{
 		WDIOF_OVERHEAT|WDIOF_CARDRESET,
 #ifdef CONFIG_PCWD_REV_A	
@@ -238,61 +237,39 @@
 		return -ENOIOCTLCMD;
 
 	case WDIOC_GETSUPPORT:
-		i = verify_area(VERIFY_WRITE, (void*) arg, sizeof(struct watchdog_info));
-		if (i)
-			return i;
-		else
-			return copy_to_user(arg, &ident, sizeof(ident));
+		i = copy_to_user((void*)arg, &ident, sizeof(ident));
+		return i ? -EFAULT : 0;
 
 	case WDIOC_GETSTATUS:
-		i = verify_area(VERIFY_WRITE, (void*) arg, sizeof(int));
-		if (i)
-			return i;
-		else {
-			cdat = inb(current_readport);
-			rv = 0;
+		cdat = inb(current_readport);
+		rv = 0;
 
-			if (cdat & WD_WDRST)
-				rv |= WDIOF_CARDRESET;
+		if (cdat & WD_WDRST)
+			rv |= WDIOF_CARDRESET;
 
-			if (cdat & WD_T110)
-				rv |= WDIOF_OVERHEAT;
+		if (cdat & WD_T110)
+			rv |= WDIOF_OVERHEAT;
 
-			return put_user(rv, (int *) arg);
-		}
+		return put_user(rv, (int *) arg);
 		break;
 
 	case WDIOC_GETBOOTSTATUS:
-		i = verify_area(VERIFY_WRITE, (void*) arg, sizeof(int));
-		if (i)
-			return i;
-		else {
-			int rv;
-			rv = 0;
-
-			if (initial_status & WD_WDRST)
-				rv |= WDIOF_CARDRESET;
-
-			if (initial_status & WD_T110)
-				rv |= WDIOF_OVERHEAT;
-			return put_user(rv, (int *) arg);
-		}
-		break;
+		rv = 0;
+
+		if (initial_status & WD_WDRST)
+			rv |= WDIOF_CARDRESET;
+
+		if (initial_status & WD_T110)
+			rv |= WDIOF_OVERHEAT;
+		return put_user(rv, (int *) arg);
 
 	case WDIOC_GETTEMP:
-		i = verify_area(VERIFY_WRITE, (void*) arg, sizeof(int));
-		if (i)
-			return i;
-		else {
-			int rv;
-
-			rv = 0;
-			if ((supports_temp) && (mode_debug == 0)) {
-				rv = inb(current_readport);
-				return put_user(rv, (int*) arg);
-			} else
-				return put_user(rv, (int*) arg);
-		}
+		rv = 0;
+		if ((supports_temp) && (mode_debug == 0)) {
+			rv = inb(current_readport);
+			return put_user(rv, (int*) arg);
+		} else
+			return put_user(rv, (int*) arg);
 
 	case WDIOC_KEEPALIVE:
 		pcwd_send_heartbeat();
@@ -304,11 +281,12 @@
 
 static long pcwd_write(struct file *file, struct inode *inode, const char *buf, unsigned long len)
 {
-	if(len)
+	if (len)
 	{
 		pcwd_send_heartbeat();
 		return 1;
 	}
+	return 0;
 }
 
 static int pcwd_open(struct inode *ino, struct file *filep)
diff -u --recursive --new-file v2.1.17/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c
--- v2.1.17/linux/drivers/char/pcxx.c	Thu Dec 12 17:02:41 1996
+++ linux/drivers/char/pcxx.c	Sun Dec 22 15:07:11 1996
@@ -1111,6 +1111,7 @@
 	digi_channels = kmalloc(sizeof(struct channel) * nbdevs, GFP_KERNEL);
 	if (!digi_channels)
 		panic("Unable to allocate digi_channel struct");
+	memset(digi_channels, 0, sizeof(struct channel) * nbdevs);
 
 	pcxe_table =  kmalloc(sizeof(struct tty_struct *) * nbdevs, GFP_KERNEL);
 	if (!pcxe_table)
diff -u --recursive --new-file v2.1.17/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c
--- v2.1.17/linux/drivers/char/riscom8.c	Thu Dec 12 17:02:41 1996
+++ linux/drivers/char/riscom8.c	Fri Dec 27 12:03:22 1996
@@ -1857,6 +1857,10 @@
 int iobase1 = 0;
 int iobase2 = 0;
 int iobase3 = 0;
+MODULE_PARM(iobase, "i");
+MODULE_PARM(iobase1, "i");
+MODULE_PARM(iobase2, "i");
+MODULE_PARM(iobase3, "i");
 
 /*
  * You can setup up to 4 boards (current value of RC_NBOARD)
diff -u --recursive --new-file v2.1.17/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.1.17/linux/drivers/char/serial.c	Wed Dec 18 15:58:47 1996
+++ linux/drivers/char/serial.c	Fri Dec 27 12:03:22 1996
@@ -2955,12 +2955,8 @@
 int register_serial(struct serial_struct *req);
 void unregister_serial(int line);
 
-static struct symbol_table serial_syms = {
-#include <linux/symtab_begin.h>
-	X(register_serial),
-	X(unregister_serial),
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(register_serial);
+EXPORT_SYMBOL(unregister_serial);
 
 /*
  * The serial driver boot-time initialization code!
@@ -3062,7 +3058,7 @@
 		       state->port, state->irq,
 		       uart_config[state->type].name);
 	}
-	register_symtab(&serial_syms);
+
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.17/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.1.17/linux/drivers/char/tty_io.c	Thu Dec 12 19:37:02 1996
+++ linux/drivers/char/tty_io.c	Sat Dec 28 13:11:45 1996
@@ -1923,7 +1923,7 @@
 		panic("Couldn't register /dev/console driver\n");
 	
 	kbd_init();
-#ifdef CONFIG_ESP  /* init ESP before rs, so rs doesn't see the port */
+#ifdef CONFIG_ESPSERIAL  /* init ESP before rs, so rs doesn't see the port */
 	esp_init();
 #endif
 #ifdef CONFIG_SERIAL
diff -u --recursive --new-file v2.1.17/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c
--- v2.1.17/linux/drivers/isdn/icn/icn.c	Tue Nov 19 15:53:54 1996
+++ linux/drivers/isdn/icn/icn.c	Fri Dec 27 12:03:22 1996
@@ -16,7 +16,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: icn.c,v $
  * Revision 1.29  1996/08/29 20:34:54  fritz
@@ -154,7 +154,7 @@
 {
         struct sk_buff *skb;
         unsigned long flags;
-        
+
         save_flags(flags);
         cli();
         while ((skb = skb_dequeue(queue)))
@@ -334,7 +334,7 @@
                 while (rbavl) {
                         cnt = readb(&rbuf_l);
                         if ((card->rcvidx[channel] + cnt) > 4000) {
-                                printk(KERN_WARNING 
+                                printk(KERN_WARNING
                                        "icn: (%s) bogus packet on ch%d, dropping.\n",
                                        CID,
                                        channel + 1);
@@ -354,7 +354,7 @@
                                                 printk(KERN_WARNING "ïcn: receive out of memory\n");
                                                 break;
                                         }
-                                        memcpy(skb_put(skb, cnt), card->rcvbuf[channel], cnt); 
+                                        memcpy(skb_put(skb, cnt), card->rcvbuf[channel], cnt);
                                         card->rcvidx[channel] = 0;
                                         card->interface.rcvcallb_skb(card->myid, channel, skb);
                                 }
@@ -403,7 +403,7 @@
 			    writeb (0x0, &sbuf_f);
 			    cnt = skb->len;
 			}
-		        writeb (cnt, &sbuf_l);		    
+		        writeb (cnt, &sbuf_l);
                         memcpy_toio(&sbuf_d, skb->data, cnt);
                         skb_pull(skb, cnt);
                         card->sndcount[channel] -= cnt;
@@ -633,7 +633,7 @@
                                                 vstr[3] = '\0';
                                                 card->fw_rev = (int)simple_strtoul(vstr,NULL,10);
                                                 continue;
-                                                
+
                                         }
                                 }
                         } else {
@@ -758,7 +758,7 @@
 
 /* Load the boot-code into the interface-card's memory and start it.
  * Always called from user-process.
- * 
+ *
  * Parameters:
  *            buffer = pointer to packet
  * Return:
@@ -916,7 +916,7 @@
                         cnt = MIN(256, left);
                         if (copy_from_user(codebuf, p, cnt))
                         	/* FIXME -WRONG */return -EFAULT;
-                        memcpy_toio(&sbuf_l, codebuf, cnt); /* copy data                     */ 
+                        memcpy_toio(&sbuf_l, codebuf, cnt); /* copy data                     */
                         sbnext;                         /* switch to next buffer         */
                         p += cnt;
                         left -= cnt;
@@ -1263,7 +1263,7 @@
                                 char sis[50];
                                 char dcode[4];
                                 int si1, si2;
-                                
+
                                 a = c->arg;
                                 strcpy(sis, c->num);
                                 p = strrchr(sis, ',');
@@ -1589,6 +1589,7 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
 #define icn_init init_module
 #else
 void icn_setup(char *str, int *ints)
@@ -1622,9 +1623,6 @@
         dev.shmem = (icn_shmem *) ((unsigned long)membase & 0x0ffc000);
         dev.channel = -1;
         dev.mcard   = NULL;
-
-        /* No symbols to export, hide all symbols */
-        register_symtab(NULL);
 
         if ((p = strchr(revision, ':'))) {
                 strcpy(rev, p + 1);
diff -u --recursive --new-file v2.1.17/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.1.17/linux/drivers/isdn/isdn_common.c	Fri Nov  1 17:13:16 1996
+++ linux/drivers/isdn/isdn_common.c	Fri Dec 27 12:03:22 1996
@@ -5,7 +5,7 @@
  * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
  * Copyright 1995,96    Thinking Objects Software GmbH Wuerzburg
  * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_common.c,v $
  * Revision 1.23  1996/06/25 18:35:38  fritz
@@ -297,7 +297,7 @@
         int ifmt;
 #endif
 	modem_info *info;
-        
+
         if ((i = isdn_dc2minor(di,channel))==-1) {
                 isdn_trash_skb(skb, FREE_READ);
                 return;
@@ -679,7 +679,7 @@
                                 }
                         for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
                                 modem_info *info = &dev->mdm.info[i];
-                                
+
                                 if (info->isdn_driver == di) {
                                         info->isdn_driver = -1;
                                         info->isdn_channel = -1;
@@ -727,7 +727,7 @@
 /*
  * isdn_readbchan() tries to get data from the read-queue.
  * It MUST be called with interrupts off.
- *  
+ *
  * I hope I got the EFAULT error path right -AK.
  */
 int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user)
@@ -739,7 +739,7 @@
 	int dflag;
         struct sk_buff *skb;
 	u_char *cp;
-	int ret = 0; 
+	int ret = 0;
 
 	if (!dev->drv[di])
 		return 0;
@@ -753,7 +753,7 @@
 	cp = buf;
 	count = 0;
 	while (left) {
-		        ret = 0; 
+		        ret = 0;
                 if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
                         break;
                 if (skb->lock)
@@ -772,8 +772,8 @@
                                 if (dev->drv[di]->DLEflag & DLEmask) {
 									    if (user) {
                                                 ret = put_user(DLE,cp);
-												cp++; 
-												if (ret) break; 
+												cp++;
+												if (ret) break;
                                         } else
                                                 *cp++ = DLE;
                                         dev->drv[di]->DLEflag &= ~DLEmask;
@@ -781,7 +781,7 @@
 									    if (user) {
                                                 ret = put_user(*p,cp);
 												if (ret) break;
-												cp++; 
+												cp++;
                                         } else
                                                 *cp++ = *p;
                                         if (*p == DLE) {
@@ -803,12 +803,12 @@
                                 dflag = 0;
                         }
                         count_put = count_pull;
-						ret = 0; 
+						ret = 0;
                         if (user)
                                 ret = copy_to_user(cp, skb->data, count_put);
                         else
                                 memcpy(cp, skb->data, count_put);
-						count_put -= ret; 
+						count_put -= ret;
                         cp += count_put;
                         left -= count_put;
                 }
@@ -832,7 +832,7 @@
                          * but we pull off the data we got until now.
                          */
 			skb_pull(skb,count_pull);
-                        skb->lock = 0; 
+                        skb->lock = 0;
                 }
 		dev->drv[di]->rcvcount[channel] -= count_put;
 	}
@@ -937,7 +937,7 @@
 			if (copy_to_user(buf, p, len))
 				return -EFAULT;
 			file->f_pos += len;
-			return len; 
+			return len;
 		}
 		return 0;
 	}
@@ -1085,25 +1085,25 @@
 		return ret;
 	save_flags(flags);
 	cli();
-	ret = get_user(i, src); 
-	if (ret) 
-		goto out; 
+	ret = get_user(i, src);
+	if (ret)
+		goto out;
     src += sizeof(int);
 	while (i) {
 		char *c;
 		char *c2;
 
 		if(copy_from_user((char *) &cfg, src, sizeof(cfg)))
-			goto fault; 
+			goto fault;
 		src += sizeof(cfg);
 		if (!isdn_net_new(cfg.name, NULL)) {
 			restore_flags(flags);
 			return -EIO;
 		}
-		if ((ret = isdn_net_setcfg(&cfg))) 
-			goto out; 
+		if ((ret = isdn_net_setcfg(&cfg)))
+			goto out;
 		if(copy_from_user(buf, src, sizeof(buf)))
-			goto fault; 
+			goto fault;
 		src += sizeof(buf);
 		c = buf;
 		while (*c) {
@@ -1112,15 +1112,15 @@
 			strcpy(phone.phone, c);
 			strcpy(phone.name, cfg.name);
 			phone.outgoing = 0;
-			if ((ret = isdn_net_addphone(&phone))) 
-				goto fault; 
+			if ((ret = isdn_net_addphone(&phone)))
+				goto fault;
 			if (c2)
 				c = c2;
 			else
 				c += strlen(c);
 		}
    		if(copy_from_user(buf, src, sizeof(buf)))
-			goto fault; 
+			goto fault;
 		src += sizeof(buf);
 		c = buf;
 		while (*c) {
@@ -1129,8 +1129,8 @@
 			strcpy(phone.phone, c);
 			strcpy(phone.name, cfg.name);
 			phone.outgoing = 1;
-			if ((ret = isdn_net_addphone(&phone))) 
-				goto out; 
+			if ((ret = isdn_net_addphone(&phone)))
+				goto out;
 			if (c2)
 				c = c2;
 			else
@@ -1175,7 +1175,7 @@
 		cfg.callback = (p->local.flags & ISDN_NET_CALLBACK) ? 1 : 0;
 		cfg.chargehup = (p->local.hupflags & 4) ? 1 : 0;
 		cfg.ihup = (p->local.hupflags & 8) ? 1 : 0;
-		ret = 0; 
+		ret = 0;
 		ret += copy_to_user(dest, p->local.name, 10);
 		dest += 10;
 		ret += copy_to_user(dest, (char *) &cfg, sizeof(cfg));
@@ -1183,15 +1183,15 @@
 		strcpy(phone.name, p->local.name);
 		phone.outgoing = 0;
 		if (ret)
-			break; 
-		if ((ret = isdn_net_getphones(&phone, dest)) < 0) 
-			break; 
+			break;
+		if ((ret = isdn_net_getphones(&phone, dest)) < 0)
+			break;
 		else
 			dest += ret;
 		strcpy(phone.name, p->local.name);
 		phone.outgoing = 1;
-		if ((ret = isdn_net_getphones(&phone, dest)) < 0) 
-			break; 
+		if ((ret = isdn_net_getphones(&phone, dest)) < 0)
+			break;
 		else
 			dest += ret;
 		p = p->next;
@@ -1226,11 +1226,11 @@
                                         int i;
                                         for (i = 0;i<ISDN_MAX_CHANNELS;i++) {
                                                 ret = put_user(dev->ibytes[i],p);
-	                                            if (ret) break; 
-												p++; 
+	                                            if (ret) break;
+												p++;
 												ret = put_user(dev->obytes[i],p);
-												p++; 
-												if (ret) break; 
+												p++;
+												if (ret) break;
                                         }
                                         return ret;
                                 } else
@@ -1258,19 +1258,19 @@
                                 /* Add a network-interface */
                                 if (arg) {
                                         if(copy_from_user(name, (char *) arg, sizeof(name)))
-											return -EFAULT; 
+											return -EFAULT;
                                         s = name;
                                 } else
                                         s = NULL;
                                 if ((s = isdn_net_new(s, NULL))) {
-									    return copy_to_user((char *) arg, s, strlen(s) + 1) ? -EFAULT : ret; 
+									    return copy_to_user((char *) arg, s, strlen(s) + 1) ? -EFAULT : ret;
                                 } else
                                         return -ENODEV;
                         case IIOCNETASL:
                                 /* Add a slave to a network-interface */
                                 if (arg) {
                                         if(copy_from_user(bname, (char *) arg, sizeof(bname)))
-											return -EFAULT; 
+											return -EFAULT;
                                 } else
                                         return -EINVAL;
                                 if ((s = isdn_net_newslave(bname))) {
@@ -1293,12 +1293,12 @@
                                         return -EINVAL;
                         case IIOCNETGCF:
                                 /* Get configurable parameters of a network-interface */
-                                if (arg) {				  
+                                if (arg) {
                                         if(copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
-											return -EFAULT; 
+											return -EFAULT;
                                         if (!(ret = isdn_net_getcfg(&cfg))) {
                                                 if(copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))
-													return -EFAULT; 
+													return -EFAULT;
                                         }
                                         return ret;
                                 } else
@@ -1333,13 +1333,13 @@
                                         return -EINVAL;
 #ifdef CONFIG_ISDN_PPP
                         case IIOCNETALN:
-								if (arg) 
+								if (arg)
                                         ret = copy_from_user(name,(char*)arg,sizeof(name));
 								else
-									    return -EINVAL; 
+									    return -EINVAL;
                                 return ret ? -EFAULT : isdn_ppp_dial_slave(name);
                         case IIOCNETDLN:
-							    
+
                                 if(arg) {
 									    ret = copy_from_user(name,(char*)arg,sizeof(name));
                                 } else
@@ -1374,7 +1374,7 @@
                                         char *p;
                                         if(copy_from_user((char *) &iocts, (char *) arg,
                                                       sizeof(isdn_ioctl_struct)))
-											return -EFAULT; 
+											return -EFAULT;
 										if (strlen(iocts.drvid)) {
                                                 if ((p = strchr(iocts.drvid, ',')))
                                                         *p = 0;
@@ -1415,14 +1415,14 @@
                                 if (arg) {
                                         char *p = (char *) arg;
                                         int i;
-                                                                   
+
                                         for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
                                                 if(copy_to_user(p, dev->mdm.info[i].emu.profile,
                                                             ISDN_MODEM_ANZREG))
 													return -EFAULT;
                                                 p += ISDN_MODEM_ANZREG;
                                                 if(copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
-													return -EFAULT; 
+													return -EFAULT;
                                                 p += ISDN_MSNLEN;
                                         }
                                         return (ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS;
@@ -1434,14 +1434,14 @@
                                 if (arg) {
                                         char *p = (char *) arg;
                                         int i;
-                                        
+
                                         for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
                                                 if(copy_from_user(dev->mdm.info[i].emu.profile, p,
                                                               ISDN_MODEM_ANZREG))
-													return -EFAULT; 
+													return -EFAULT;
 												p += ISDN_MODEM_ANZREG;
                                                 if(copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
-													return -EFAULT; 
+													return -EFAULT;
 												p += ISDN_MSNLEN;
                                         }
                                         return 0;
@@ -1455,9 +1455,9 @@
                                         int i;
                                         char *p;
                                         char nstring[255];
-                                        
+
                                         ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
-                      
+
 										if (ret) return -EFAULT;
 										if (strlen(iocts.drvid)) {
                                                 drvidx = -1;
@@ -1472,7 +1472,7 @@
                                                 return -ENODEV;
                                         if (cmd == IIOCSETMAP) {
                                                 ret = copy_from_user(nstring, (char *) iocts.arg, 255);
-												if (ret) return -EFAULT; 
+												if (ret) return -EFAULT;
                                                 memset(dev->drv[drvidx]->msn2eaz, 0,
                                                        sizeof(dev->drv[drvidx]->msn2eaz));
                                                 p = strtok(nstring, ",");
@@ -1489,7 +1489,7 @@
                                                                      dev->drv[drvidx]->msn2eaz[i] : "-",
                                                                      (i < 9) ? "," : "\0");
 												if(copy_to_user((char *) iocts.arg, nstring, strlen(nstring) + 1))
-													return -EFAULT; 
+													return -EFAULT;
 										}
                                         return 0;
                                 } else
@@ -1511,7 +1511,7 @@
 
                                         ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
 										if (ret)
-											    return -EFAULT; 
+											    return -EFAULT;
                                         if (strlen(iocts.drvid)) {
                                                 if ((p = strchr(iocts.drvid, ',')))
                                                         *p = 0;
@@ -1802,7 +1802,7 @@
  * len     = Length of packet-data
  *
  */
-void isdn_receive_callback(int drvidx, int chan, u_char *buf, int len) 
+void isdn_receive_callback(int drvidx, int chan, u_char *buf, int len)
 {
         struct sk_buff *skb;
 
@@ -1819,7 +1819,7 @@
 /*
  *  writebuf replacement for SKB_ABLE drivers
  */
-int isdn_writebuf_stub(int drvidx, int chan, const u_char *buf, int len, 
+int isdn_writebuf_stub(int drvidx, int chan, const u_char *buf, int len,
 		       int user)
 {
 	int ret;
@@ -1841,7 +1841,7 @@
                 if (user) {
 					    if(copy_from_user(skb_put(skb, len), buf, len)) {
 						        kfree_skb(skb,FREE_WRITE);
-						        return -EFAULT; 
+						        return -EFAULT;
 						}
                 } else
                         memcpy(skb_put(skb, len), buf, len);
@@ -1869,7 +1869,7 @@
         int ret;
 	int len = skb->len;	/* skb pointer no longer valid after free */
 
-        if (dev->drv[drvidx]->interface->writebuf_skb) 
+        if (dev->drv[drvidx]->interface->writebuf_skb)
 		ret = dev->drv[drvidx]->interface->
 			writebuf_skb(drvidx, chan, skb);
 	else {
@@ -1970,7 +1970,7 @@
 		if (!dev->drv[drvidx])
 			break;
 	i->channels = drvidx;
- 
+
 	i->rcvcallb_skb = isdn_receive_skb_callback;
 	i->rcvcallb     = isdn_receive_callback;
 	i->statcallb    = isdn_status_callback;
@@ -1980,7 +1980,7 @@
 	cli();
         for (j = 0; j < drvidx; j++)
                 if (!strcmp(i->id,dev->drvid[j]))
-                    sprintf(i->id, "line%d", drvidx);                    
+                    sprintf(i->id, "line%d", drvidx);
 	for (j = 0; j < n; j++)
 		for (k = 0; k < ISDN_MAX_CHANNELS; k++)
 			if (dev->chanmap[k] < 0) {
@@ -2023,15 +2023,10 @@
 	return rev;
 }
 
-static struct symbol_table isdn_syms = {
-#include <linux/symtab_begin.h>
-        X(register_isdn),
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(register_isdn);
 
 static void isdn_export_syms(void)
 {
-        register_symtab(&isdn_syms);
         has_exported = 1;
 }
 
diff -u --recursive --new-file v2.1.17/linux/drivers/isdn/pcbit/module.c linux/drivers/isdn/pcbit/module.c
--- v2.1.17/linux/drivers/isdn/pcbit/module.c	Wed May 15 09:09:00 1996
+++ linux/drivers/isdn/pcbit/module.c	Fri Dec 27 12:03:22 1996
@@ -1,13 +1,13 @@
 /*
  * Copyright (C) 1996 Universidade de Lisboa
- * 
+ *
  * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
  *
- * This software may be used and distributed according to the terms of 
+ * This software may be used and distributed according to the terms of
  * the GNU Public License, incorporated herein by reference.
  */
 
-/*        
+/*
  *        PCBIT-D module support
  */
 
@@ -35,6 +35,7 @@
 extern int pcbit_init_dev(int board, int mem_base, int irq);
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
 #define pcbit_init init_module
 #endif
 
@@ -44,11 +45,11 @@
 
 	num_boards = 0;
 
-	printk(KERN_INFO 
+	printk(KERN_INFO
 	       "PCBIT-D device driver v 0.5 - "
 	       "Copyright (C) 1996 Universidade de Lisboa\n");
 
-	if (mem[0] || irq[0]) 
+	if (mem[0] || irq[0])
 	{
 		for (board=0; board < MAX_PCBIT_CARDS && mem[board] && irq[board]; board++)
 		{
@@ -56,14 +57,14 @@
 				mem[board] = 0xD0000;
 			if (!irq[board])
 				irq[board] = 5;
-			
+
 			if (pcbit_init_dev(board, mem[board], irq[board]) == 0)
 				num_boards++;
-		
-			else 
+
+			else
 			{
-				printk(KERN_WARNING 
-				       "pcbit_init failed for dev %d", 
+				printk(KERN_WARNING
+				       "pcbit_init failed for dev %d",
 				       board + 1);
 				return -EIO;
 			}
@@ -74,7 +75,7 @@
 
 	if (!num_boards)
 	{
-		printk(KERN_INFO 
+		printk(KERN_INFO
 		       "Trying to detect board using default settings\n");
 		if (pcbit_init_dev(0, 0xD0000, 5) == 0)
 			num_boards++;
@@ -82,9 +83,6 @@
 			return -EIO;
 	}
 
-	/* No symbols to export, hide all symbols */
-	register_symtab(NULL);
-
 	return 0;
 }
 
@@ -95,7 +93,7 @@
 
 	for (board = 0; board < num_boards; board++)
 		pcbit_terminate(board);
-	printk(KERN_INFO 
+	printk(KERN_INFO
 	       "PCBIT-D module unloaded\n");
 }
 
@@ -114,7 +112,7 @@
 			mem[i]	= ints[j];
 			j++; argc--;
 		}
-		
+
 		if (argc) {
 			irq[i]	= ints[j];
 			j++; argc--;
@@ -124,6 +122,3 @@
 	}
 }
 #endif
-
-
-
diff -u --recursive --new-file v2.1.17/linux/drivers/isdn/teles/mod.c linux/drivers/isdn/teles/mod.c
--- v2.1.17/linux/drivers/isdn/teles/mod.c	Tue Oct 29 19:58:11 1996
+++ linux/drivers/isdn/teles/mod.c	Fri Dec 27 12:03:22 1996
@@ -53,6 +53,7 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
 #define teles_init init_module
 #else
 void teles_setup(char *str, int *ints)
@@ -114,9 +115,6 @@
                 TeiNew();
                 CallcNew();
                 ll_init();
-
-		/* No symbols to export, hide all symbols */
-		register_symtab(NULL);
 
 #ifdef MODULE
                 printk(KERN_NOTICE "Teles module installed\n");
diff -u --recursive --new-file v2.1.17/linux/drivers/net/bpqether.c linux/drivers/net/bpqether.c
--- v2.1.17/linux/drivers/net/bpqether.c	Wed Dec 18 15:58:47 1996
+++ linux/drivers/net/bpqether.c	Fri Dec 27 12:03:22 1996
@@ -1,9 +1,9 @@
 /*
  *	G8BPQ compatible "AX.25 via ethernet" driver release 003
  *
- *	This is ALPHA test software. This code may break your machine, randomly 
- *	fail to work with new releases, misbehave and/or generally screw up. 
- *	It might even work. 
+ *	This is ALPHA test software. This code may break your machine, randomly
+ *	fail to work with new releases, misbehave and/or generally screw up.
+ *	It might even work.
  *
  *	This code REQUIRES 2.0.0 or higher/ NET3.029
  *
@@ -15,11 +15,11 @@
  *
  *	This is a "pseudo" network driver to allow AX.25 over Ethernet
  *	using G8BPQ encapsulation. It has been extracted from the protocol
- *	implementation because 
+ *	implementation because
  *
  *		- things got unreadable within the protocol stack
  *		- to cure the protocol stack from "feature-ism"
- *		- a protocol implementation shouldn't need to know on 
+ *		- a protocol implementation shouldn't need to know on
  *		  which hardware it is running
  *		- user-level programs like the AX.25 utilities shouldn't
  *		  need to know about the hardware.
@@ -28,7 +28,7 @@
  *		- to have room for extensions
  *		- it just deserves to "live" as an own driver
  *
- *	This driver can use any ethernet destination address, and can be 
+ *	This driver can use any ethernet destination address, and can be
  *	limited to accept frames from one dedicated ethernet card only.
  *
  *	Note that the driver sets up the BPQ devices automagically on
@@ -44,7 +44,7 @@
  *	probably some buffering, and /voila/...
  *
  *	History
- *	BPQ   001	Joerg(DL1BKE)		Extracted BPQ code from AX.25 
+ *	BPQ   001	Joerg(DL1BKE)		Extracted BPQ code from AX.25
  *						protocol stack and added my own
  *						yet existing patches
  *	BPQ   002	Joerg(DL1BKE)		Scan network device list on
@@ -137,7 +137,7 @@
 static __inline__ struct device *bpq_get_ether_dev(struct device *dev)
 {
 	struct bpqdev *bpq;
-	
+
 	bpq = (struct bpqdev *)dev->priv;
 
 	return (bpq != NULL) ? bpq->ethdev : NULL;
@@ -177,7 +177,7 @@
 	struct bpqdev *bpq, *bpq_prev;
 	int result = 0;
 	unsigned long flags;
-	
+
 	save_flags(flags);
 	cli();
 
@@ -189,7 +189,7 @@
 				bpq_prev->next = bpq->next;
 			else
 				bpq_devices = bpq->next;
-				
+
 			if (&bpq->axdev == dev)
 				result = 1;
 
@@ -199,9 +199,9 @@
 
 		bpq_prev = bpq;
 	}
-	
+
 	restore_flags(flags);
-	
+
 	return result;
 }
 
@@ -220,7 +220,7 @@
 	struct bpqdev *bpq;
 
 	skb->sk = NULL;		/* Initially we don't know who it's for */
-	
+
 	dev = bpq_get_ax25_dev(dev);
 
 	if (dev == NULL || dev->start == 0) {
@@ -250,7 +250,7 @@
 
 	ptr = skb_push(skb, 1);
 	*ptr = 0;
-	
+
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_AX25);
 	skb->mac.raw = skb->data;
@@ -269,7 +269,7 @@
 	unsigned char *ptr;
 	struct bpqdev *bpq;
 	int size;
-	
+
 	/*
 	 * Just to be *really* sure not to send anything if the interface
 	 * is down, the ethernet device may have gone.
@@ -282,9 +282,9 @@
 
 	skb_pull(skb, 1);
 	size = skb->len;
-	
-	/* 
-	 * The AX.25 code leaves enough room for the ethernet header, but 
+
+	/*
+	 * The AX.25 code leaves enough room for the ethernet header, but
 	 * sendto() does not.
 	 */
 	if (skb_headroom(skb) < AX25_BPQ_HEADER_LEN) {	/* Ough! */
@@ -305,17 +305,17 @@
 		dev_kfree_skb(skb, FREE_WRITE);
 		skb = newskb;
 	}
-	
+
 	skb->protocol = htons(ETH_P_AX25);
 
 	ptr = skb_push(skb, 2);
 
 	*ptr++ = (size + 5) % 256;
 	*ptr++ = (size + 5) / 256;
-	
+
 	bpq = (struct bpqdev *)dev->priv;
 	bpq->stats.tx_packets++;
-	
+
 	if ((dev = bpq_get_ether_dev(dev)) == NULL) {
 		bpq->stats.tx_dropped++;
 		dev_kfree_skb(skb, FREE_WRITE);
@@ -368,10 +368,10 @@
 
 	if (!suser())
 		return -EPERM;
-	
+
 	if (bpq == NULL)		/* woops! */
 		return -ENODEV;
-	
+
 	switch (cmd) {
 		case SIOCSBPQETHOPT:
 			if ((err = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct bpq_req))) != 0)
@@ -383,9 +383,9 @@
 				default:
 					return -EINVAL;
 			}
-			
+
 			break;
-			
+
 		case SIOCSBPQETHADDR:
 			if ((err = verify_area(VERIFY_READ, ethaddr, sizeof(struct bpq_ethaddr))) != 0)
 				return err;
@@ -407,7 +407,7 @@
 {
 	if (bpq_check_devices(dev))
 		return -ENODEV;		/* oops, it's gone */
-	
+
 	dev->tbusy = 0;
 	dev->start = 1;
 
@@ -444,10 +444,10 @@
 static char * bpq_print_ethaddr(unsigned char *e)
 {
 	static char buf[18];
-	
-	sprintf(buf, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", 
+
+	sprintf(buf, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
 		e[0], e[1], e[2], e[3], e[4], e[5]);
-		
+
 	return buf;
 }
 
@@ -457,7 +457,7 @@
 	int len     = 0;
 	off_t pos   = 0;
 	off_t begin = 0;
-  
+
 	cli();
 
 	len += sprintf(buffer, "dev   ether      destination        accept from\n");
@@ -476,7 +476,7 @@
 			len   = 0;
 			begin = pos;
 		}
-		
+
 		if (pos > offset + length)
 			break;
 	}
@@ -489,7 +489,7 @@
 	if (len > length) len = length;
 
 	return len;
-} 
+}
 
 
 /* ------------------------------------------------------------------------ */
@@ -503,12 +503,12 @@
 	int k;
 	unsigned char *buf;
 	struct bpqdev *bpq, *bpq2;
-	
+
 	if ((bpq = (struct bpqdev *)kmalloc(sizeof(struct bpqdev), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
-		
+
 	memset(bpq, 0, sizeof(struct bpqdev));
-	
+
 	bpq->ethdev = dev;
 
 	bpq->ethname[sizeof(bpq->ethname)-1] = '\0';
@@ -533,7 +533,7 @@
 		kfree(bpq);
 		return -ENODEV;
 	}
-	
+
 	dev->priv = (void *)bpq;	/* pointer back */
 	dev->name = buf;
 	dev->init = bpq_dev_init;
@@ -576,7 +576,7 @@
 	dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
 	dev->mtu             = AX25_DEF_PACLEN;
 	dev->addr_len        = AX25_ADDR_LEN;
-	
+
 	cli();
 
 	if (bpq_devices == NULL) {
@@ -585,7 +585,7 @@
 		for (bpq2 = bpq_devices; bpq2->next != NULL; bpq2 = bpq2->next);
 		bpq2->next = bpq;
 	}
-	
+
 	sti();
 
 	return 0;
@@ -598,7 +598,7 @@
 static int bpq_device_event(struct notifier_block *this,unsigned long event, void *ptr)
 {
 	struct device *dev = (struct device *)ptr;
-	
+
 	if (!dev_is_ethdev(dev))
 		return NOTIFY_DONE;
 
@@ -658,10 +658,10 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-	register_symtab(NULL);
-
 	return bpq_init();
 }
 
@@ -675,7 +675,7 @@
 
 #ifdef CONFIG_PROC_FS
 	proc_net_unregister(PROC_NET_AX25_BPQETHER);
-#endif	
+#endif
 
 	for (bpq = bpq_devices; bpq != NULL; bpq = bpq->next)
 		unregister_netdev(&bpq->axdev);
diff -u --recursive --new-file v2.1.17/linux/drivers/net/de620.c linux/drivers/net/de620.c
--- v2.1.17/linux/drivers/net/de620.c	Fri Mar  1 07:50:43 1996
+++ linux/drivers/net/de620.c	Fri Dec 27 12:03:22 1996
@@ -713,7 +713,7 @@
 		else { /* Yep! Go get it! */
 			skb_reserve(skb,2);	/* Align */
 			skb->dev = dev;
-			skb->free = 1;
+			skb->used = 0;
 			/* skb->data points to the start of sk_buff data area */
 			buffer = skb_put(skb,size);
 			/* copy the packet into the buffer */
diff -u --recursive --new-file v2.1.17/linux/drivers/net/hdlcdrv.c linux/drivers/net/hdlcdrv.c
--- v2.1.17/linux/drivers/net/hdlcdrv.c	Sun Dec 22 16:37:33 1996
+++ linux/drivers/net/hdlcdrv.c	Fri Dec 27 12:03:22 1996
@@ -888,15 +888,11 @@
 
 /* --------------------------------------------------------------------- */
 
-static struct symbol_table hdlcdrv_syms = {
-#include <linux/symtab_begin.h>
-        X(hdlcdrv_receiver),
-        X(hdlcdrv_transmitter),
-        X(hdlcdrv_arbitrate),
-        X(hdlcdrv_register_hdlcdrv),
-        X(hdlcdrv_unregister_hdlcdrv),
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(hdlcdrv_receiver);
+EXPORT_SYMBOL(hdlcdrv_transmitter);
+EXPORT_SYMBOL(hdlcdrv_arbitrate);
+EXPORT_SYMBOL(hdlcdrv_register_hdlcdrv);
+EXPORT_SYMBOL(hdlcdrv_unregister_hdlcdrv);
 
 /* --------------------------------------------------------------------- */
 
@@ -907,7 +903,6 @@
 	printk(KERN_INFO "hdlcdrv: (C) 1996 Thomas Sailer HB9JNX/AE4WA\n");
 	printk(KERN_INFO "hdlcdrv: version 0.2 compiled %s %s\n", 
 	       __TIME__, __DATE__);
-        register_symtab(&hdlcdrv_syms);
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.17/linux/drivers/net/mkiss.c linux/drivers/net/mkiss.c
--- v2.1.17/linux/drivers/net/mkiss.c	Wed Dec 18 15:58:47 1996
+++ linux/drivers/net/mkiss.c	Fri Dec 27 12:03:22 1996
@@ -101,11 +101,11 @@
 
 	for (i = 0; i < ax25_maxdev; i++) {
 		axp = ax25_ctrls[i];
-		
+
 		/* Not allocated ? */
 		if (axp == NULL)
 			break;
-			
+
 		/* Not in use ? */
 		if (!set_bit(AXF_INUSE, &axp->ctrl.flags))
 			break;
@@ -261,9 +261,9 @@
 	struct sk_buff *skb;
 	struct mkiss_channel *mkiss;
 	int count;
-	
+
         tmp_ax = ax;
-                
+
 	if (ax->rbuff[0] > 0x0f) {
 		if (ax->mkiss != NULL) {
 			mkiss= ax->mkiss->tty->driver_data;
@@ -271,7 +271,7 @@
 				tmp_ax = ax->mkiss;
 		}
  	}
- 	
+
 	count = ax->rcount;
 
 	if ((skb = dev_alloc_skb(count)) == NULL) {
@@ -282,7 +282,7 @@
 
 	skb->dev      = tmp_ax->dev;
 	memcpy(skb_put(skb,count), ax->rbuff, count);
-	skb->mac.raw  = skb->data; 
+	skb->mac.raw  = skb->data;
 	skb->protocol = htons(ETH_P_AX25);
 	netif_rx(skb);
 	tmp_ax->rx_packets++;
@@ -307,7 +307,7 @@
 	}
 
 	p = icp;
-	
+
 	if (mkiss->magic  != MKISS_DRIVER_MAGIC) {
 		count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
 		ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
@@ -320,7 +320,7 @@
 		count = kiss_esc(p, (unsigned char *) ax->mkiss->xbuff, len);
 		ax->mkiss->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 		actual = ax->mkiss->tty->driver.write(ax->mkiss->tty, 0, ax->mkiss->xbuff, count);
-		ax->tx_packets++; 
+		ax->tx_packets++;
 		ax->mkiss->dev->trans_start = jiffies;
 		ax->mkiss->xleft = count - actual;
 		ax->mkiss->xhead = ax->mkiss->xbuff + actual;
@@ -336,7 +336,7 @@
 	int actual;
 	struct ax_disp *ax = (struct ax_disp *)tty->disc_data;
 	struct mkiss_channel *mkiss;
-	
+
 	/* First make sure we're connected. */
 	if (ax == NULL || ax->magic != AX25_MAGIC || !ax->dev->start)
 		return;
@@ -368,14 +368,14 @@
 	struct ax_disp *ax = (struct ax_disp*)dev->priv;
 	struct mkiss_channel *mkiss = ax->tty->driver_data;
 	struct ax_disp *tmp_ax;
-	
+
 	tmp_ax = NULL;
-	
+
 	if (mkiss->magic  == MKISS_DRIVER_MAGIC) {
 		if (skb->data[0] < 0x10)
 			skb->data[0] = skb->data[0] + 0x10;
 		tmp_ax = ax->mkiss;
-	}                
+	}
 
 	if (!dev->start)  {
 		printk(KERN_ERR "%s: xmit call when iface is down\n", dev->name);
@@ -385,13 +385,13 @@
 	if (tmp_ax != NULL)
 		if (tmp_ax->dev->tbusy)
 			return 1;
-	     
-	if (tmp_ax != NULL)     
+
+	if (tmp_ax != NULL)
 		if (dev->tbusy) {
 			printk(KERN_ERR "mkiss: dev busy while serial dev is free\n");
 			ax_unlock(ax);
 	        }
-	        
+
 	if (dev->tbusy) {
 		/*
 		 * May be we must check transmitter timeout here ?
@@ -410,7 +410,7 @@
 		ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 		ax_unlock(ax);
 	}
-	
+
 	/* We were not busy, so we are now... :-) */
 	if (skb != NULL) {
 		ax_lock(ax);
@@ -585,7 +585,7 @@
 	if (tty->ldisc.flush_buffer)
 		tty->ldisc.flush_buffer(tty);
 
-	/* Restore default settings */	
+	/* Restore default settings */
 	ax->dev->type = ARPHRD_AX25;
 
 	/* Perform the low-level AX25 initialization. */
@@ -612,7 +612,7 @@
 		ax->mkiss     = tmp_ax;
 		tmp_ax->mkiss = ax;
 	}
-	
+
 	MOD_INC_USE_COUNT;
 
 	/* Done.  We have linked the TTY line to a channel. */
@@ -630,7 +630,7 @@
 
 	mkiss = ax->mode;
 	dev_close(ax->dev);
-	
+
 	tty->disc_data = 0;
 	ax->tty        = NULL;
 
@@ -783,7 +783,7 @@
 		case SIOCGIFENCAP:
 			if ((err = verify_area(VERIFY_WRITE, arg, sizeof(int))) != 0)
 				return err;
-			put_user(4, (int *)arg); 
+			put_user(4, (int *)arg);
 			return 0;
 
 		case SIOCSIFENCAP:
@@ -820,12 +820,12 @@
 	int status;
 
 	if (ax25_maxdev < 4) ax25_maxdev = 4; /* Sanity */
-	
+
 	if ((ax25_ctrls = (ax25_ctrl_t **)kmalloc(sizeof(void*) * ax25_maxdev, GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "mkiss: Can't allocate ax25_ctrls[] array !  No mkiss available\n");
 		return -ENOMEM;
 	}
-	
+
 	/* Clear the pointer array, we allocate devices when we need them */
 	memset(ax25_ctrls, 0, sizeof(void*) * ax25_maxdev); /* Pointers */
 
@@ -879,7 +879,7 @@
 	memset(ax, 0, sizeof (struct ax_disp));
 	ax->magic  = AX25_MAGIC;
 	ax->dev	   = dev;
-	
+
 	/* Finish setting up the DEVICE info. */
 	dev->mtu             = AX_MTU;
 	dev->hard_start_xmit = ax_xmit;
@@ -919,7 +919,7 @@
 static int mkiss_open(struct tty_struct *tty, struct file *filp)
 {
 	struct mkiss_channel *mkiss;
-	int chan;	 	 
+	int chan;
 
 	chan = MINOR(tty->device) - tty->driver.minor_start;
 
@@ -966,11 +966,11 @@
 		case TIOCMGET:
 		case TIOCMBIS:
 		case TIOCMBIC:
-		case TIOCMSET:		
+		case TIOCMSET:
 		case TCSETS:
 		case TCSETSF:		/* should flush first, but... */
 		case TCSETSW:		/* should wait until flush, but... */
-			return 0;		
+			return 0;
 		default:
 			return -ENOIOCTLCMD;
 	}
@@ -980,7 +980,7 @@
 static void mkiss_dummy(struct tty_struct *tty)
 {
 	struct mkiss_channel *mkiss = tty->driver_data;
-	
+
 	if (tty == NULL)
 		return;
 
@@ -991,7 +991,7 @@
 static void mkiss_dummy2(struct tty_struct *tty, unsigned char ch)
 {
 	struct mkiss_channel *mkiss = tty->driver_data;
-	
+
 	if (tty == NULL)
 		return;
 
@@ -1043,7 +1043,7 @@
 
 	mkiss_driver.magic       = MKISS_DRIVER_MAGIC;
 	mkiss_driver.name        = "mkiss";
-	mkiss_driver.major       = MKISS_MAJOR;		
+	mkiss_driver.major       = MKISS_MAJOR;
 	mkiss_driver.minor_start = 0;
 	mkiss_driver.num         = NR_MKISS;
 	mkiss_driver.type        = TTY_DRIVER_TYPE_SERIAL;
@@ -1074,25 +1074,24 @@
 	mkiss_driver.stop         = mkiss_dummy;
 	mkiss_driver.start        = mkiss_dummy;
 	mkiss_driver.hangup       = mkiss_dummy;
-	mkiss_driver.flush_chars  = mkiss_dummy;        
-	mkiss_driver.put_char     = mkiss_dummy2;        
-       
+	mkiss_driver.flush_chars  = mkiss_dummy;
+	mkiss_driver.put_char     = mkiss_dummy2;
+
 	if (tty_register_driver(&mkiss_driver)) {
 		printk(KERN_ERR "Couldn't register Mkiss device\n");
-		return -EIO;		           
-	}                                
+		return -EIO;
+	}
 
 	printk(KERN_INFO "AX.25 Multikiss device enabled\n");
 
-	return 0;		
+	return 0;
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
 
 int init_module(void)
 {
-	register_symtab(NULL);
-
 	return mkiss_init_ctrl_dev();
 }
 
@@ -1106,7 +1105,7 @@
 				/*
 				 * VSV = if dev->start==0, then device
 				 * unregistred while close proc.
-				 */ 
+				 */
 				if (ax25_ctrls[i]->dev.start)
 					unregister_netdev(&(ax25_ctrls[i]->dev));
 
@@ -1119,11 +1118,11 @@
 		ax25_ctrls = NULL;
 	}
 
-	if ((i = tty_register_ldisc(N_AX25, NULL)))  
+	if ((i = tty_register_ldisc(N_AX25, NULL)))
 		printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i);
 
 	if (tty_unregister_driver(&mkiss_driver))	/* remove devive */
 		printk(KERN_ERR "mkiss: can't unregister MKISS device\n");
 }
- 
+
 #endif /* MODULE */
diff -u --recursive --new-file v2.1.17/linux/drivers/net/ni52.c linux/drivers/net/ni52.c
--- v2.1.17/linux/drivers/net/ni52.c	Thu Oct 10 19:10:55 1996
+++ linux/drivers/net/ni52.c	Fri Dec 27 12:03:22 1996
@@ -1163,7 +1163,7 @@
     return 0;
   if(skb->len > XMIT_BUFF_SIZE)
   {
-    printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %ld bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len);
+    printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len);
     return 0;
   }
 
diff -u --recursive --new-file v2.1.17/linux/drivers/net/pi2.c linux/drivers/net/pi2.c
--- v2.1.17/linux/drivers/net/pi2.c	Wed Dec 18 15:58:47 1996
+++ linux/drivers/net/pi2.c	Fri Dec 27 12:03:22 1996
@@ -39,7 +39,7 @@
    		       init() so it doesn't migrate module based ethernet cards up
    		       to eth2 Took out the old module ideas as they are no longer
    		       relevant to the PI driver.
-   July 16, 1994 (dp)  Fixed the B channel rx overrun problem ac referred to 
+   July 16, 1994 (dp)  Fixed the B channel rx overrun problem ac referred to
    		       above. Also added a bit of a hack to improve the maximum
    	               baud rate on the B channel (Search for STUFF2). Included
    		       ioctl stuff from John Paul Morrison. version 0.6 ALPHA
@@ -51,7 +51,7 @@
                        version 0.8 ALPHA
    July 17, 1995 (ac)  Finally polishing of AX25.030+ support
    Oct  29, 1995 (ac)  A couple of minor fixes before this, and this release changes
-   		       to the proper set_mac_address semantics which will break 
+   		       to the proper set_mac_address semantics which will break
    		       a few programs I suspect.
    Aug  18, 1996 (jsn) Converted to be used as a module.
    Dec  13, 1996 (jsn) Fixed to match Linux networking changes.
@@ -124,16 +124,16 @@
 /*
  *	The actual devices we will use
  */
- 
+
 /*
  *	PI device declarations.
  */
- 
+
 static int pi0_preprobe(struct device *dev){return 0;}	/* Dummy probe function */
 static struct device pi0a = { "pi0a", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pi0_preprobe };
 static struct device pi0b = { "pi0b", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, pi0_preprobe };
 
- 
+
 /* The number of low I/O ports used by the card. */
 #define PI_TOTAL_SIZE	8
 
@@ -688,7 +688,7 @@
              * Tx OFF now - flag should have gone
              */
 	    rts(lp, OFF);
-	 
+
 	    restore_flags(flags);
 	    return;
 	}
@@ -831,7 +831,7 @@
 	    c = *lp->txptr++;
 	    /* Wait for tx buffer empty */
 	    while((rdscc(lp->cardbase, cmd, R0) & 0x04) == 0)
-		;   
+		;
 	    wrtscc(lp->cardbase, cmd, R8, c);
 	}
 #endif
@@ -896,7 +896,7 @@
 	    c = *lp->txptr++;
 	    /* Wait for tx buffer empty */
 	    while((rdscc(lp->cardbase, cmd, R0) & 0x04) == 0)
-		;   
+		;
 	    wrtscc(lp->cardbase, cmd, R8, c);
 	}
 #endif
@@ -1225,9 +1225,9 @@
        be rejected by get_dma_buffer().
     */
     register_netdev(&pi0a);
-    
+
     pi0a.priv = kmalloc(sizeof(struct pi_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA);
-			
+
     pi0a.dma = PI_DMA;
     pi0a.base_addr = ioaddr + 2;
     pi0a.irq = 0;
@@ -1244,7 +1244,7 @@
     pi_probe(&pi0b, card_type);
 
     pi0b.irq = pi0a.irq;	/* IRQ is shared */
-    
+
     return 0;
 }
 
@@ -1510,7 +1510,7 @@
 	printk(KERN_ERR "PI: pi_interrupt(): irq %d for unknown device.\n", irq);
 	return;
     }
-#endif    
+#endif
     /* Read interrupt status register (only valid from channel A)
      * Process all pending interrupts in while loop
      */
@@ -1591,7 +1591,7 @@
     int ret = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct pi_req));
     if (ret)
 	return ret;
-	
+
     if(cmd!=SIOCDEVPRIVATE)
     	return -EINVAL;
 
@@ -1628,7 +1628,7 @@
 	   pi_close(dev);
 	   free_dma(lp->dmachan);
 	   dev->dma = lp->dmachan = rq.dmachan;
-	   if (request_dma(lp->dmachan,"pi2")) 
+	   if (request_dma(lp->dmachan,"pi2"))
 		ret = -EAGAIN;
 	   pi_open(dev);
 	   restore_flags(flags);
@@ -1672,9 +1672,10 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-    register_symtab(NULL);
     return pi_init();
 }
 
diff -u --recursive --new-file v2.1.17/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.1.17/linux/drivers/net/ppp.c	Thu Dec 12 19:37:06 1996
+++ linux/drivers/net/ppp.c	Fri Dec 27 12:03:23 1996
@@ -246,7 +246,7 @@
 static char ppp_warning[] = KERN_WARNING "PPP: ALERT! not INUSE! %d\n";
 
 static char szVersion[]		= PPP_VERSION;
- 
+
 /*
  * Information for the protocol decoder
  */
@@ -347,13 +347,13 @@
 		"TCP compression code copyright 1989 Regents of the "
 		"University of California\n");
 #endif
-	
+
 	printk (KERN_INFO
 		"PPP Dynamic channel allocation code copyright 1995 "
 		"Caldera, Inc.\n");
 /*
  * Register the tty discipline
- */	
+ */
 	(void) memset (&ppp_ldisc, 0, sizeof (ppp_ldisc));
 	ppp_ldisc.magic		= TTY_LDISC_MAGIC;
 	ppp_ldisc.open		= ppp_tty_open;
@@ -365,7 +365,7 @@
 	ppp_ldisc.receive_room	= ppp_tty_room;
 	ppp_ldisc.receive_buf	= ppp_tty_receive;
 	ppp_ldisc.write_wakeup	= ppp_tty_wakeup;
-	
+
 	status = tty_register_ldisc (N_PPP, &ppp_ldisc);
 	if (status == 0)
 		printk (KERN_INFO "PPP line discipline registered.\n");
@@ -454,13 +454,9 @@
 	ppp->sc_rc_state = NULL;
 }
 
-static struct symbol_table ppp_syms = {
-#include <linux/symtab_begin.h>
-	X(ppp_register_compressor),
-	X(ppp_unregister_compressor),
-	X(ppp_crc16_table),
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(ppp_register_compressor);
+EXPORT_SYMBOL(ppp_unregister_compressor);
+EXPORT_SYMBOL(ppp_crc16_table);
 
 /* called at boot/load time for each ppp device defined in the kernel */
 
@@ -474,8 +470,6 @@
 	if (first_time) {
 		first_time = 0;
 		answer	   = ppp_first_time();
-		if (answer == 0)
-			(void) register_symtab (&ppp_syms);
 	}
 	if (answer == 0)
 		answer = -ENODEV;
@@ -576,7 +570,7 @@
 		mru = PPP_MRU;
 
 	mru += 10;
-	
+
 	if (ppp->flags & SC_DEBUG)
 		printk (KERN_INFO "ppp: channel %s mtu = %d, mru = %d\n",
 			dev->name, new_mtu, new_mru);
@@ -2168,7 +2162,7 @@
 		ptr = data.ptr;
 		if ((__u32) nb >= (__u32)CCP_MAX_OPTION_LENGTH)
 			nb = CCP_MAX_OPTION_LENGTH;
-	
+
 		error = verify_area (VERIFY_READ, ptr, nb);
 	}
 
@@ -3179,7 +3173,7 @@
 	/* try to find the exact same free device which we had before */
 	ctl	 = ppp_list;
 	if_num	 = 0;
-  
+
 	while (ctl) {
 		ppp = ctl2ppp (ctl);
 		if (!set_bit(0, &ppp->inuse)) {
@@ -3209,7 +3203,7 @@
 	/* try to find an free device */
 	ctl	 = ppp_list;
 	if_num	 = 0;
-  
+
 	while (ctl) {
 		ppp = ctl2ppp (ctl);
 		if (!set_bit(0, &ppp->inuse))
@@ -3233,7 +3227,7 @@
 		ppp->line      = if_num;
 		ppp->tty       = NULL;
 		ppp->dev       = dev;
-    
+
 		dev->next      = NULL;
 		dev->init      = ppp_init_dev;
 		dev->name      = ctl->name;
@@ -3241,7 +3235,7 @@
 		dev->priv      = (void *) ppp;
 
 		sprintf (dev->name, "ppp%d", if_num);
-    
+
 		/* link in the new channel */
 		ctl->next      = ppp_list;
 		ppp_list       = ctl;
@@ -3424,8 +3418,7 @@
 	if (status != 0)
 		printk (KERN_INFO
 		       "PPP: ppp_init() failure %d\n", status);
-	else
-		(void) register_symtab (&ppp_syms);
+
 	return (status);
 }
 
@@ -3480,7 +3473,7 @@
 		       "PPP: ppp line discipline successfully unregistered\n");
 /*
  * De-register the devices so that there is no problem with them
- */	
+ */
 	next_ctl = ppp_list;
 	while (next_ctl) {
 		ctl	 = next_ctl;
diff -u --recursive --new-file v2.1.17/linux/drivers/net/pt.c linux/drivers/net/pt.c
--- v2.1.17/linux/drivers/net/pt.c	Wed Dec 18 15:58:47 1996
+++ linux/drivers/net/pt.c	Fri Dec 27 12:03:23 1996
@@ -36,8 +36,8 @@
  *		pt_loopback functions - they were unused.
  * 13/12/96 jsn Fixed to match Linux networking changes.
  */
- 
-/* 
+
+/*
  * default configuration of the PackeTwin,
  * ie What Craig uses his PT for.
  */
@@ -172,7 +172,7 @@
     else
 	lp->rcvbuf = lp->rxdmabuf1;
 }
-		
+
 static void hardware_send_packet(struct pt_local *lp, struct sk_buff *skb)
 {
     char kickflag;
@@ -214,7 +214,7 @@
 		} /*switch */
 		return;
 	}
-	
+
     lp->stats.tx_packets++;
 
     save_flags(flags);
@@ -224,18 +224,18 @@
 
 #ifdef PT_DEBUG
 	printk(KERN_DEBUG "PT: hardware_send_packet(): kickflag = %d (%d).\n", kickflag, lp->base & CHANA);
-#endif	
+#endif
     skb_queue_tail(&lp->sndq, skb);
     if (kickflag) {
         /* Simulate interrupt to transmit */
             if (lp->dmachan)
-            {	
+            {
             	pt_txisr(lp);
             } else {
             	save_flags(flags);
 	           	cli();
             	if (lp->tstate == IDLE)
-                	pt_txisr(lp); 
+                	pt_txisr(lp);
             	restore_flags(flags);
             }
     }
@@ -331,7 +331,7 @@
 
 #ifdef PT_DEBUG
 	printk(KERN_DEBUG "PT: scc_init(): (%d).\n", lp->base & CHANA);
-#endif	
+#endif
     save_flags(flags);
     cli();
 
@@ -344,26 +344,26 @@
     } else {
     	wrtscc(lp->cardbase, cmd, R9, CHRB);		/* Reset channel B */
     }
-    
+
     /* Deselect all Rx and Tx interrupts */
     wrtscc(lp->cardbase, cmd, R1, 0);
-    
+
     /* Turn off external interrupts (like CTS/CD) */
     wrtscc(lp->cardbase, cmd, R15, 0);
-           
+
     /* X1 clock, SDLC mode */
     wrtscc(lp->cardbase, cmd, R4, SDLC | X1CLK);
-	
+
 	/* Preset CRC and set mode */
 	if (lp->nrzi)
 	{
     	/* Preset Tx CRC, put into NRZI mode */
-       wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);		
+       wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
     } else {
     	/* Preset Tx CRC, put into NRZ mode */
-       wrtscc(lp->cardbase, cmd, R10, CRCPS);    
+       wrtscc(lp->cardbase, cmd, R10, CRCPS);
     }
-    
+
     /* Tx/Rx parameters */
     if (lp->speed)		/* Use internal clocking */
     {
@@ -375,7 +375,7 @@
            wrtscc(lp->cardbase, cmd, R11, TCTRxCP | RCRTxCP | TRxCBR);
            wrtscc(lp->cardbase,cmd, R14, 0);	/* wiz1 */
     }
-       
+
     /* Null out SDLC start address */
     wrtscc(lp->cardbase, cmd, R6, 0);
 
@@ -397,12 +397,12 @@
 		br = lp->speed;
 		tc = ((lp->xtal / 32) / (br * 2)) - 2;
 	    wrtscc(lp->cardbase, cmd, R12, tc & 0xff);		/* lower byte */
-   		wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);	/* upper byte */			
+   		wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);	/* upper byte */
 	}
 
 	/* Turn transmitter off, to setup stuff */
    	pt_rts(lp, OFF);
-   	
+
 	/* External clocking */
 	if (lp->speed)
 	{
@@ -415,7 +415,7 @@
         if (lp->base & CHANA)
             outb_p( (pt_sercfg &= ~PT_EXTCLKA), (lp->cardbase + SERIAL_CFG) );
         else
-            outb_p( (pt_sercfg &= ~PT_EXTCLKB), (lp->cardbase + SERIAL_CFG) );        	    
+            outb_p( (pt_sercfg &= ~PT_EXTCLKB), (lp->cardbase + SERIAL_CFG) );
     } else {
 		/* DPLL frm rtxc,BRG src PCLK */
 /*		wrtscc(lp->cardbase, cmd, R14, BRSRC | SSRTxC);*/
@@ -423,14 +423,14 @@
         if (lp->base & CHANA)
             outb_p( (pt_sercfg |= PT_EXTCLKA), (lp->cardbase + SERIAL_CFG) );
         else
-            outb_p( (pt_sercfg |= PT_EXTCLKB), (lp->cardbase + SERIAL_CFG) );     
+            outb_p( (pt_sercfg |= PT_EXTCLKB), (lp->cardbase + SERIAL_CFG) );
     }
 
-    if (!lp->dmachan)	
+    if (!lp->dmachan)
 		wrtscc(lp->cardbase, cmd, R1, (INT_ALL_Rx | EXT_INT_ENAB));
 
     wrtscc(lp->cardbase, cmd, R15, BRKIE);	/* ABORT int */
-	
+
 	/* Turn on the DTR to tell modem we're alive */
 	if (lp->base & CHANA)
 	    outb_p( (pt_sercfg |= PT_DTRA_ON), (lp->cardbase + SERIAL_CFG) );
@@ -439,7 +439,7 @@
 
     /* Now, turn on the receiver and hunt for a flag */
     wrtscc(lp->cardbase, cmd, R3, RxENABLE | RxCRC_ENAB | AUTO_ENAB | Rx8 );
-	
+
 	restore_flags(flags);
 
 } /* scc_init() */
@@ -451,11 +451,11 @@
 	struct pt_local *lp = (struct pt_local*) dev->priv;
 #ifdef PT_DEBUG
 	printk(KERN_DEBUG "PT: chipset_init(): pt0a tstate = %d.\n", ((struct pt_local*)pt0a.priv)->tstate);
-	printk(KERN_DEBUG "PT: chipset_init(): pt0b tstate = %d.\n", ((struct pt_local*)pt0b.priv)->tstate);	
+	printk(KERN_DEBUG "PT: chipset_init(): pt0b tstate = %d.\n", ((struct pt_local*)pt0b.priv)->tstate);
 #endif
 	/* Reset SCC if both channels are to be canned */
 	if ( ((lp->base & CHANA) && !(pt_sercfg & PT_DTRB_ON)) ||
-			(!(lp->base & CHANA) && !(pt_sercfg & PT_DTRA_ON)) ) 
+			(!(lp->base & CHANA) && !(pt_sercfg & PT_DTRA_ON)) )
 	{
 		wrtscc(lp->cardbase, lp->base + CTL, R9, FHWRES);
         	/* Reset int and dma registers */
@@ -463,7 +463,7 @@
 	        outb_p((pt_dmacfg = 0), lp->cardbase + DMA_CFG);
 #ifdef PT_DEBUG
 		printk(KERN_DEBUG "PT: chipset_init() Resetting SCC, called by ch (%d).\n", lp->base & CHANA);
-#endif			        
+#endif
 	}
 	/* Reset individual channel */
     	if (lp->base & CHANA) {
@@ -471,11 +471,11 @@
         	outb_p( (pt_sercfg &= ~PT_DTRA_ON), lp->cardbase + SERIAL_CFG);
     	} else {
         	wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | DLC | NV | CHRB);
-			outb_p( (pt_sercfg &= ~PT_DTRB_ON), lp->cardbase + SERIAL_CFG);			 
-	}	
-} /* chipset_init() */	
-	
-	
+			outb_p( (pt_sercfg &= ~PT_DTRB_ON), lp->cardbase + SERIAL_CFG);
+	}
+} /* chipset_init() */
+
+
 
 int pt_init(void)
 {
@@ -532,7 +532,7 @@
     pt_probe(&pt0b);
 
     pt0b.irq = pt0a.irq;	/* IRQ is shared */
-    
+
     return 0;
 } /* pt_init() */
 
@@ -545,7 +545,7 @@
     int a = 1;
     int b = 1;
     unsigned long start_time, end_time;
-    
+
     inb_p(ioaddr + TMR1CLR);
     inb_p(ioaddr + TMR2CLR);
 
@@ -558,7 +558,7 @@
     outb_p(SC1 | LSB_MSB | MODE0, ioaddr + TMRCMD);
     outb_p((time << 1) & 0xff, ioaddr + TMR1);
     outb_p((time >> 7) & 0xff, ioaddr + TMR1);
-    
+
     /* wait until counter reg is loaded */
     do {
         /* Latch count for reading */
@@ -581,20 +581,20 @@
             return 0;
         }
     }
-    
+
     /* Now fix the timers up for general operation */
-    
+
     /* Clear the timers */
     inb_p(ioaddr + TMR1CLR);
     inb_p(ioaddr + TMR2CLR);
-    
+
     outb_p(SC1 | LSB_MSB | MODE0, ioaddr + TMRCMD);
     inb_p(ioaddr + TMR1CLR);
-    
+
     outb_p(SC2 | LSB_MSB | MODE0, ioaddr + TMRCMD);
     /* Should this be tmr1 or tmr2? wiz3*/
     inb_p(ioaddr + TMR1CLR);
-    
+
     return 1;
 } /* hw_probe() */
 
@@ -606,13 +606,13 @@
 	int cmd = lp->base + CTL;
 #ifdef PT_DEBUG
 	printk(KERN_DEBUG "PT: pt_rts(): Transmitter status will be %d (%d).\n", x, lp->base & CHANA);
-#endif			
+#endif
 	if (x == ON) {
 	    /* Ex ints off to avoid int */
 	    wrtscc(lp->cardbase, cmd, R15, 0);
 	    wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8);	/* Rx off */
 	    lp->rstate = IDLE;
-	    
+
 	    if(lp->dmachan)
 	    {
 	        /* Setup for Tx DMA */
@@ -621,7 +621,7 @@
 	        /* No interrupts */
 	        wrtscc(lp->cardbase, cmd, R1, 0);
 	    }
-	
+
             if (!lp->clockmode)
             {
                 if (lp->speed)
@@ -637,7 +637,7 @@
             /* Transmitter on now */
         } else {		/* turning off Tx */
             lp->tstate = IDLE;
-            
+
             /* Turn off Tx by dropping RTS */
             wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR);
             if (!lp->clockmode)
@@ -651,7 +651,7 @@
                     tc = ((lp->xtal / 32) / (br * 2)) - 2;
                     wrtscc(lp->cardbase, cmd, R12, tc & 0xff);
                     wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);
-                    
+
                     /* SEARCH mode, BRG source */
                     wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH);
                     /* Enable the BRG */
@@ -661,23 +661,23 @@
             /* Flush Rx fifo */
             /* Turn Rx off */
             wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8);
-            
+
             /* Reset error latch */
             wrtscc(lp->cardbase, cmd, R0, ERR_RES);
-            
+
             /* get status byte from R1 */
             (void) rdscc(lp->cardbase, cmd, R1);
-            
+
             /* Read and dump data in queue */
             (void) rdscc(lp->cardbase, cmd, R8);
             (void) rdscc(lp->cardbase, cmd, R8);
             (void) rdscc(lp->cardbase, cmd, R8);
-            
+
             /* Now, turn on Rx and hunt for a flag */
               wrtscc(lp->cardbase, cmd, R3, RxENABLE | AUTO_ENAB | Rx8 );
-              
+
             lp->rstate = ACTIVE;
-            
+
             if (lp->dmachan)
             {
                 setup_rx_dma(lp);
@@ -691,9 +691,9 @@
 	}
 	wrtscc(lp->cardbase, cmd, R15, BRKIE );
     }
-} /* pt_rts() */	
-		
-				
+} /* pt_rts() */
+
+
 static int valid_dma_page(unsigned long addr, unsigned long dev_bufsize)
 {
     if (((addr & 0xffff) + dev_bufsize) <= 0x10000)
@@ -708,7 +708,7 @@
 	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);		/* addr is an AX.25 shifted ASCII */
 	return 0;		/* mac address */
 }
-	
+
 
 /* Allocate a buffer which does not cross a DMA page boundary */
 static char * get_dma_buffer(unsigned long *mem_ptr)
@@ -765,11 +765,11 @@
 
     lp->base = dev->base_addr;
     lp->cardbase = dev->base_addr & 0x3f0;
-	
+
     /* These need to be initialised before scc_init() is called.
      */
     lp->xtal = XTAL;
-    
+
     if (dev->base_addr & CHANA) {
         lp->speed = DEF_A_SPEED;
         lp->txdelay = DEF_A_TXDELAY;
@@ -801,10 +801,10 @@
 	 * properly first!!
 	 */
 	lp->dmachan = 0;
-	
+
         if (dev->irq < 2) {
             autoirq_setup(0);
-            
+
             /* Turn on PT interrupts */
             save_flags(flags);
             cli();
@@ -818,7 +818,7 @@
 	    /* Turn off PT interrupts */
 	    save_flags(flags);
 	    cli();
-            outb_p( (pt_sercfg  &= ~ PT_EI), lp->cardbase + INT_CFG);            
+            outb_p( (pt_sercfg  &= ~ PT_EI), lp->cardbase + INT_CFG);
             restore_flags(flags);
 
             if (!dev->irq) {
@@ -893,7 +893,7 @@
     unsigned long flags;
     struct pt_local *lp = dev->priv;
     static first_time = 1;
-    
+
     if (dev->base_addr & CHANA)
     {
         if (first_time)
@@ -905,12 +905,12 @@
             }
         }
  	irq2dev_map[dev->irq] = dev;
- 
-         /* Reset hardware */	
+
+         /* Reset hardware */
          chipset_init(dev);
      }
      lp->tstate = IDLE;
-    
+
      if (dev->base_addr & CHANA)
      {
          scc_init(dev);
@@ -919,12 +919,12 @@
      /* Save a copy of register RR0 for comparing with later on */
      /* We always put 0 in zero count */
      lp->saved_RR0 = rdscc(lp->cardbase, lp->base + CTL, R0) & ~ZCOUNT;
-    
+
     /* master interrupt enable */
     save_flags(flags);
     cli();
     wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | NV);
-    outb_p( pt_sercfg |= PT_EI, lp->cardbase + INT_CFG);    
+    outb_p( pt_sercfg |= PT_EI, lp->cardbase + INT_CFG);
     restore_flags(flags);
 
     lp->open_time = jiffies;
@@ -935,7 +935,7 @@
     first_time = 0;
 
     MOD_INC_USE_COUNT;
-	
+
     return 0;
 } /* pt_open() */
 
@@ -945,7 +945,7 @@
 
 #ifdef PT_DEBUG
 	printk(KERN_DEBUG "PT: pt_send_packet(): (%d)\n", lp->base & CHANA);
-#endif			
+#endif
 	/* If some higher layer thinks we've missed an tx-done interrupt
 	   we are passed NULL. Caution: dev_tint() handles the cli()/sti()
 	   itself.*/
@@ -955,11 +955,11 @@
 	}
 	hardware_send_packet(lp, skb);
 	dev->trans_start = jiffies;
-	
+
 	return 0;
 }
-				   
-	   
+
+
 
 /* The inverse routine to pt_open() */
 static int pt_close(struct device *dev)
@@ -970,12 +970,12 @@
 	int cmd;
 
 	cmd = lp->base + CTL;
-		
+
 	save_flags(flags);
 	cli();
-	
+
 	/* Reset SCC or channel */
-	chipset_init(dev);	
+	chipset_init(dev);
 	disable_dma(lp->dmachan);
 
 	lp->open_time = 0;
@@ -985,15 +985,15 @@
 	/* Free any buffers left in the hardware transmit queue */
 	while ((ptr = skb_dequeue(&lp->sndq)) != NULL)
 		free_p(ptr);
-		
+
 	restore_flags(flags);
-	
+
 #ifdef PT_DEBUG
-	printk(KERN_DEBUG "PT: pt_close(): Closing down channel (%d).\n", lp->base & CHANA);	
-#endif	
+	printk(KERN_DEBUG "PT: pt_close(): Closing down channel (%d).\n", lp->base & CHANA);
+#endif
 
 	MOD_DEC_USE_COUNT;
-	
+
 	return 0;
 } /* pt_close() */
 
@@ -1010,7 +1010,7 @@
 
     if (cmd != SIOCDEVPRIVATE)
         return -EINVAL;
-        
+
     copy_from_user(&rq, ifr->ifr_data, sizeof(struct pt_req));
 
     switch (rq.cmd) {
@@ -1044,7 +1044,7 @@
 	   pt_close(dev);
 	   free_dma(lp->dmachan);
 	   dev->dma = lp->dmachan = rq.dmachan;
-	   if (request_dma(lp->dmachan,"pt")) 
+	   if (request_dma(lp->dmachan,"pt"))
 		ret = -EAGAIN;
 	   pt_open(dev);
 	   restore_flags(flags);
@@ -1103,7 +1103,7 @@
 	/* For some reason, we turn off the Tx interrupts here! */
 	if (!lp->dmachan)
 		wrtscc(lp->cardbase, lp->base + CTL, R1, INT_ALL_Rx | EXT_INT_ENAB);
-	
+
     if (lp->base & CHANA) {
         outb_p(time & 0xff, lp->cardbase + TMR1);
         outb_p((time >> 8)&0xff, lp->cardbase + TMR1);
@@ -1119,23 +1119,23 @@
 	unsigned long flags;
 	int cmd;
 	unsigned char c;
-	
+
 	save_flags(flags);
 	cli();
 	cmd = lp->base + CTL;
 
 #ifdef PT_DEBUG
 	printk(KERN_DEBUG "PT: pt_txisr(): tstate = %d (%d).\n", lp->tstate, lp->base & CHANA);
-#endif	
-	
-	switch (lp->tstate) 
+#endif
+
+	switch (lp->tstate)
 	{
 	case CRCOUT:
 	    lp->tstate = FLAGOUT;
 	    tdelay(lp, lp->squeldelay);
 	    restore_flags(flags);
 	    return;
-	    
+
 	case IDLE:
 	    /* Transmitter idle. Find a frame for transmission */
 	    if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL)
@@ -1144,7 +1144,7 @@
 	         * Tx off now - flag should have gone
 	         */
 	        pt_rts(lp, OFF);
-	        
+
 	        restore_flags(flags);
 	        return;
 	    }
@@ -1155,7 +1155,7 @@
 		    lp->txcnt = (int) lp->sndbuf->len - 1;
 		}
 	    /* If a buffer to send, drop though here */
-	
+
 	case DEFER:
 	    /* Check DCD - debounce it */
 	    /* See Intel Microcommunications Handbook p2-308 */
@@ -1184,12 +1184,12 @@
 	    tdelay(lp, lp->txdelay);
 	    restore_flags(flags);
 	    return;
-	
+
 	case ACTIVE:
 	    /* Here we are actively sending a frame */
 	    if (lp->txcnt--)
 	    {
-	        /* XLZ - checkout Gracilis PT code to see if the while 
+	        /* XLZ - checkout Gracilis PT code to see if the while
 	         * loop is better or not.
 	         */
 	        c = *lp->txptr++;
@@ -1228,7 +1228,7 @@
 		printk(KERN_ERR "PT: pt_txisr(): Invalid tstate (%d) for chan %s.\n", lp->tstate, (cmd & CHANA? "A": "B") );
 		pt_rts(lp, OFF);
 		lp->tstate = IDLE;
-		break;		
+		break;
     } 				/*switch */
     restore_flags(flags);
 }
@@ -1250,15 +1250,15 @@
 
     /* Get status byte from R1 */
     rse = rdscc(lp->cardbase, cmd, R1);
-    
+
 #ifdef PT_DEBUG
     printk(KERN_DEBUG "PT: pt_rxisr(): R1 = %#3x. (%d)\n", rse, lp->base & CHANA);
-#endif        
+#endif
 
 	if (lp->dmachan && (rse & Rx_OVR))
 		lp->rstate = RXERROR;
-		
-    if (rdscc(lp->cardbase, cmd, R0) & Rx_CH_AV && !lp->dmachan) 
+
+    if (rdscc(lp->cardbase, cmd, R0) & Rx_CH_AV && !lp->dmachan)
     {
         /* There is a char to be stored
          * Read special condition bits before reading the data char
@@ -1291,22 +1291,22 @@
              (void) rdscc(lp->cardbase, cmd, R8);
              (void) rdscc(lp->cardbase, cmd, R8);
              (void) rdscc(lp->cardbase, cmd, R8);
-             
+
              /* Reset error latch */
              wrtscc(lp->cardbase, cmd, R0, ERR_RES);
              lp->rstate = ACTIVE;
-             
+
              /* Resync the SCC */
              wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
-             
+
          }
      }
-     
+
      if (rse & END_FR)
      {
 #ifdef PT_DEBUG
 	printk(KERN_DEBUG "PT: pt_rxisr() Got end of a %u byte frame.\n", lp->rcvbuf->cnt);
-#endif	     
+#endif
 		if (lp->dmachan)
 		{
 			clear_dma_ff(lp->dmachan);
@@ -1314,7 +1314,7 @@
 		} else {
 			bytecount = lp->rcvbuf->cnt;
 		}
-			
+
          /* END OF FRAME - Make sure Rx was active */
          if (lp->rcvbuf->cnt > 0 || lp->dmachan)
          {
@@ -1339,12 +1339,12 @@
         	         lp->rcvbuf->cnt = 0;
 
 					/* Re-sync the SCC */
-					wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);			
-        	         
+					wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
+
         	     }
 #ifdef PT_DEBUG
 	printk(KERN_DEBUG "PT: pt_rxisr() %s error.\n", (rse & CRC_ERR)? "CRC" : "state");
-#endif                 
+#endif
              } else {
                  /* We have a valid frame */
                  if (lp->dmachan)
@@ -1353,11 +1353,11 @@
 					/* Get buffer for next frame */
                  	cur_buf = lp->rcvbuf;
                  	switchbuffers(lp);
-                 	setup_rx_dma(lp);                 	
+                 	setup_rx_dma(lp);
                  } else {
 	                 pkt_len = lp->rcvbuf->cnt -= 2;  /* Toss 2 CRC bytes */
     	             pkt_len += 1;	/* make room for KISS control byte */
-        		}         
+        		}
 
                  /* Malloc up new buffer */
                  sksize = pkt_len;
@@ -1370,7 +1370,7 @@
                      return;
                  }
                  skb->dev = dev;
-                 
+
                  /* KISS kludge = prefix with a 0 byte */
                  cfix=skb_put(skb,pkt_len);
                  *cfix++=0;
@@ -1411,13 +1411,13 @@
 
 #ifdef PT_DEBUG
 	printk(KERN_DEBUG "PT: pt_tmrisr(): tstate = %d (%d).\n", lp->tstate, lp->base & CHANA);
-#endif		
-	
+#endif
+
     save_flags(flags);
     cli();
-    
-    
-    switch (lp->tstate) 
+
+
+    switch (lp->tstate)
     {
     /* Most of this stuff is in pt_exisr() */
     case FLAGOUT:
@@ -1426,19 +1426,19 @@
 /*    case ACTIVE:
     case UNDERRUN:*/
         pt_exisr(lp);
-        break; 
-      
+        break;
+
     default:
 	if (lp->base & CHANA)
  	    printk(KERN_ERR "PT: pt_tmrisr(): Invalid tstate %d for Channel A\n", lp->tstate);
 	else
 	    printk(KERN_ERR "PT: pt_tmrisr(): Invalid tstate %d for Channel B\n", lp->tstate);
-	break;		
+	break;
     } /* end switch */
     restore_flags(flags);
 } /* pt_tmrisr() */
 
-	
+
 /*
  * This routine is called by the kernel when there is an interrupt for the
  * PT.
@@ -1452,7 +1452,7 @@
     unsigned char st;
     register int cbase = dev->base_addr & 0x3f0;
     unsigned long flags;
-    
+
     /* Read the PT's interrupt register, this is not the SCC one! */
     intreg = inb_p(cbase + INT_REG);
     while(( intreg & 0x07) != 0x07) {
@@ -1462,11 +1462,11 @@
         	/* Read interrupt vector from R2, channel B */
 #ifdef PT_DEBUG
 		printk(KERN_DEBUG "PT: pt_interrupt(): R3 = %#3x", st);
-#endif		        
+#endif
 /*        	st = rdscc(lp->cardbase, cbase + CHANB + CTL, R2) & 0x0e;*/
 #ifdef PT_DEBUG
 		printk(KERN_DEBUG "PI: R2 = %#3x.\n", st);
-#endif	
+#endif
 			if (st & CHARxIP) {
 			    /* Channel A Rx */
 	            lp = (struct pt_local*)pt0a.priv;
@@ -1498,7 +1498,7 @@
             wrtscc(lp->cardbase, lp->base + CTL, R0, RES_H_IUS);
             restore_flags(flags);
         }  /* end of SCC ints */
-        
+
         if (!(intreg & PT_TMR1_MSK))
         {
             /* Clear timer 1 */
@@ -1528,19 +1528,19 @@
     unsigned char st;
     char c;
     int length;
-    
+
     save_flags(flags);
     cli();
-    
+
     /* Get external status */
     st = rdscc(lp->cardbase, cmd, R0);
 
 #ifdef PT_DEBUG
 	printk(KERN_DEBUG "PT: exisr(): R0 = %#3x tstate = %d (%d).\n", st, lp->tstate, lp->base & CHANA);
-#endif	
+#endif
     /* Reset external status latch */
     wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
-    
+
     if ((lp->rstate >= ACTIVE) && (st & BRK_ABRT) && lp->dmachan)
     {
     	setup_rx_dma(lp);
@@ -1552,7 +1552,7 @@
     case ACTIVE:		/* Unexpected underrun */
 #ifdef PT_DEBUG
 	printk(KERN_DEBUG "PT: exisr(): unexpected underrun detected.\n");
-#endif	    
+#endif
         free_p(lp->sndbuf);
         lp->sndbuf = NULL;
         if (!lp->dmachan)
@@ -1565,7 +1565,7 @@
         tdelay(lp, lp->squeldelay);
         restore_flags(flags);
         return;
-    case UNDERRUN:		
+    case UNDERRUN:
         lp->tstate = CRCOUT;
         restore_flags(flags);
         return;
@@ -1587,47 +1587,47 @@
 	        lp->txcnt = (int) lp->sndbuf->len - 1;
 	    }
         /* Fall through if we have a packet */
-    
+
     case ST_TXDELAY:
     	if (lp->dmachan)
     	{
     		/* Disable DMA chan */
     		disable_dma(lp->dmachan);
-    		
+
     		/* Set up for TX dma */
     		wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);
-    		
+
     		length = lp->sndbuf->len - 1;
     		memcpy(lp->txdmabuf, &lp->sndbuf->data[1], length);
-    		
+
     		/* Setup DMA controller for Tx */
     		setup_tx_dma(lp, length);
-    		
+
     		enable_dma(lp->dmachan);
-    		
+
     		/* Reset CRC, Txint pending */
     		wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC | RES_Tx_P);
-    		
+
     		/* Allow underrun only */
     		wrtscc(lp->cardbase, cmd, R15, TxUIE);
-    		
+
     		/* Enable TX DMA */
     		wrtscc(lp->cardbase, cmd, R1, WT_RDY_ENAB | WT_FN_RDYFN | EXT_INT_ENAB);
-    		
+
     		/* Send CRC on underrun */
     		wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);
-    		
+
     		lp->tstate = ACTIVE;
     		break;
-    	} 
+    	}
         /* Get first char to send */
         lp->txcnt--;
         c = *lp->txptr++;
         /* Reset CRC for next frame */
         wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC);
-        
+
         /* send abort on underrun */
-        if (lp->nrzi)	
+        if (lp->nrzi)
         {
             wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER);
         } else {
@@ -1635,10 +1635,10 @@
         }
         /* send first char */
         wrtscc(lp->cardbase, cmd, R8, c);
-        
+
         /* Reset end of message latch */
         wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);
-        
+
         /* stuff an extra one in */
 /*        while ((rdscc(lp->cardbase, cmd, R0) & Tx_BUF_EMP) && lp->txcnt)
         {
@@ -1646,21 +1646,21 @@
             c = *lp->txptr++;
             wrtscc(lp->cardbase, cmd, R8, c);
         }*/
-        
+
         /* select Tx interrupts to enable */
         /* Allow underrun int only */
         wrtscc(lp->cardbase, cmd, R15, TxUIE);
-        
+
         /* Reset external interrupts */
         wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
-        
+
         /* Tx and Rx ints enabled */
         wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB);
-        
+
         lp->tstate = ACTIVE;
         restore_flags(flags);
         return;
-        
+
         /* slotime has timed out */
     case DEFER:
         /* Check DCD - debounce it
@@ -1691,14 +1691,14 @@
         tdelay(lp, lp->txdelay);
         restore_flags(flags);
         return;
- 
+
  	/* Only for int driven parts */
  	if (lp->dmachan)
  	{
  		restore_flags(flags);
  		return;
  	}
- 	
+
     } /* end switch */
     /*
      * Rx mode only
@@ -1710,24 +1710,24 @@
     {
 #ifdef PT_DEBUG
 	printk(KERN_DEBUG "PT: exisr(): abort detected.\n");
-#endif        
+#endif
   		/* read and dump all of SCC Rx FIFO */
         (void) rdscc(lp->cardbase, cmd, R8);
         (void) rdscc(lp->cardbase, cmd, R8);
-        (void) rdscc(lp->cardbase, cmd, R8);      
-        
+        (void) rdscc(lp->cardbase, cmd, R8);
+
         lp->rcp = lp->rcvbuf->data;
         lp->rcvbuf->cnt = 0;
-        
+
 		/* Re-sync the SCC */
-		wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);			
+		wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
 
     }
-    
+
     /* Check for DCD transitions */
     if ( (st & DCD) != (lp->saved_RR0 & DCD))
     {
-#ifdef PT_DEBUG    
+#ifdef PT_DEBUG
         printk(KERN_DEBUG "PT: pt_exisr(): DCD is now %s.\n", (st & DCD)? "ON" : "OFF" );
 #endif
 		if (st & DCD)
@@ -1737,13 +1737,13 @@
 			{
 #ifdef PT_DEBUG
 				printk(KERN_DEBUG "PT: pt_exisr() dumping %u bytes from buffer.\n", lp->rcvbuf->cnt);
-#endif					
+#endif
 				/* wind back buffers */
 				lp->rcp = lp->rcvbuf->data;
 				lp->rcvbuf->cnt = 0;
 			}
 		} else {  /* DCD off */
-			
+
 			/* read and dump al SCC FIFO */
 			(void)rdscc(lp->cardbase, cmd, R8);
 			(void)rdscc(lp->cardbase, cmd, R8);
@@ -1752,11 +1752,11 @@
 			/* wind back buffers */
 			lp->rcp = lp->rcvbuf->data;
 			lp->rcvbuf->cnt = 0;
-			
+
 			/* Re-sync the SCC */
-			wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);			
-		}		
-			
+			wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);
+		}
+
     }
     /* Update the saved version of register RR) */
     lp->saved_RR0 = st &~ ZCOUNT;
@@ -1765,9 +1765,10 @@
 } /* pt_exisr() */
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-    register_symtab(NULL);
     return pt_init();
 }
 
@@ -1780,7 +1781,7 @@
     kfree(pt0a.priv);
     pt0a.priv = NULL;
     unregister_netdev(&pt0a);
-    
+
     kfree(pt0b.priv);
     pt0b.priv = NULL;
     unregister_netdev(&pt0b);
diff -u --recursive --new-file v2.1.17/linux/drivers/net/slhc.c linux/drivers/net/slhc.c
--- v2.1.17/linux/drivers/net/slhc.c	Tue Oct 29 19:58:12 1996
+++ linux/drivers/net/slhc.c	Fri Dec 27 12:03:23 1996
@@ -87,7 +87,6 @@
 static long decode(unsigned char **cpp);
 static unsigned char * put16(unsigned char *cp, unsigned short x);
 static unsigned short pull16(unsigned char **cpp);
-static void export_slhc_syms(void);
 
 /* Initialize compression data structure
  *	slots must be in range 0 to 255 (zero meaning no compression)
@@ -720,30 +719,20 @@
 	}
 }
 
-static struct symbol_table slhc_syms = {
 /* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
-#include <linux/symtab_begin.h>
-        /* VJ header compression */
-        X(slhc_init),
-        X(slhc_free),
-        X(slhc_remember),
-        X(slhc_compress),
-        X(slhc_uncompress),
-        X(slhc_toss),
-#include <linux/symtab_end.h>
-};
-
-static void export_slhc_syms(void)
-{
-	register_symtab(&slhc_syms);
-}
+/* VJ header compression */
+EXPORT_SYMBOL(slhc_init);
+EXPORT_SYMBOL(slhc_free);
+EXPORT_SYMBOL(slhc_remember);
+EXPORT_SYMBOL(slhc_compress);
+EXPORT_SYMBOL(slhc_uncompress);
+EXPORT_SYMBOL(slhc_toss);
 
 #ifdef MODULE
 
 int init_module(void)
 {
 	printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California\n");
-	export_slhc_syms();
 	return 0;
 }
 
@@ -751,11 +740,12 @@
 {
 	return;
 }
+
 #else /* MODULE */
 
 void slhc_install(void)
 {
-	export_slhc_syms();
 }
-#endif
+
+#endif /* MODULE */
 #endif /* CONFIG_INET */
diff -u --recursive --new-file v2.1.17/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c
--- v2.1.17/linux/drivers/net/sunlance.c	Wed Dec 18 15:58:47 1996
+++ linux/drivers/net/sunlance.c	Mon Dec 23 10:13:53 1996
@@ -42,8 +42,13 @@
 
 	11/17/96: Handle LE_C0_MERR in lance_interrupt(). (ecd@skynet.be)
 
+	12/22/96: Don't loop forever in lance_rx() on incomplete packets.
+		  This was the sun4c killer. Shit, stupid bug.
+		  (ecd@skynet.be)
 */
+
 #undef DEBUG_DRIVER
+
 static char *version =
 	"sunlance.c:v1.9 21/Aug/96 Miguel de Icaza (miguel@nuclecu.unam.mx)\n";
 
@@ -429,7 +434,6 @@
 		if ((bits & LE_R1_POK) != LE_R1_POK) {
 			lp->stats.rx_over_errors++;
 			lp->stats.rx_errors++;
-			continue;
 		} else if (bits & LE_R1_ERR) {
 			/* Count only the end frame as a rx error,
 			 * not the beginning
@@ -624,7 +628,8 @@
 
 	last_dev = dev;
 
-	if (request_irq (dev->irq, &lance_interrupt, SA_SHIRQ, lancestr, (void *) dev)) {
+	if (request_irq (dev->irq, &lance_interrupt, SA_SHIRQ,
+			 lancestr, (void *) dev)) {
 		printk ("Lance: Can't get irq %d\n", dev->irq);
 		return -EAGAIN;
 	}
@@ -635,7 +640,8 @@
 
 	/* On the 4m, setup the ledma to provide the upper bits for buffers */
 	if (lp->ledma)
-		lp->ledma->regs->dma_test = ((unsigned int) lp->init_block) & 0xff000000;
+		lp->ledma->regs->dma_test = ((unsigned int) lp->init_block)
+						& 0xff000000;
 
 	lance_init_ring (dev);
 	load_csrs (lp);
@@ -716,7 +722,8 @@
 		lp->ledma->regs->cond_reg |= DMA_RST_ENET;
 		udelay (200);
 		lp->ledma->regs->cond_reg &= ~DMA_RST_ENET;
-		lp->ledma->regs->dma_test = ((unsigned int) lp->init_block) & 0xff000000;
+		lp->ledma->regs->dma_test = ((unsigned int) lp->init_block)
+						& 0xff000000;
 	}
 	lance_init_ring (dev);
 	load_csrs (lp);
@@ -737,6 +744,7 @@
 	volatile struct lance_regs *ll = lp->ll;
 	volatile struct lance_init_block *ib = lp->init_block;
 	volatile unsigned long flush;
+	unsigned long flags;
 	int entry, skblen, len;
 	int status = 0;
 	static int outs;
@@ -748,7 +756,7 @@
 		if (tickssofar < 100) {
 			status = -1;
 		} else {
-			printk ("%s: transmit timed out, status %04x, resetting\n",
+			printk ("%s: transmit timed out, status %04x, reset\n",
 				dev->name, ll->rdp);
 			lance_reset (dev);
 		}
@@ -762,35 +770,25 @@
 	}
 
 	if (skb->len <= 0) {
-		printk ("skb len is %d\n", skb->len);
+		printk ("skb len is %ld\n", skb->len);
 		return 0;
 	}
+
 	/* Block a timer-based transmit from overlapping. */
-#ifdef OLD_METHOD
-	dev->tbusy = 1;
-#else
 	if (set_bit (0, (void *) &dev->tbusy) != 0) {
 		printk ("Transmitter access conflict.\n");
 		return -1;
 	}
-#endif
+
 	skblen = skb->len;
 
-	if (!TX_BUFFS_AVAIL)
-		return -1;
+	save_and_cli(flags);
 
-#ifdef DEBUG_DRIVER
-	/* dump the packet */
-	{
-		int i;
-	
-		for (i = 0; i < 64; i++) {
-			if ((i % 16) == 0)
-				printk ("\n");
-			printk ("%2.2x ", skb->data [i]);
-		}
+	if (!TX_BUFFS_AVAIL) {
+		restore_flags(flags);
+		return -1;
 	}
-#endif
+
 	len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
 	entry = lp->tx_new & TX_RING_MOD_MASK;
 	ib->btx_ring [entry].length = (-len) | 0xf000;
@@ -820,6 +818,7 @@
 	if (lp->ledma)
 		flush = ll->rdp;
 
+	restore_flags(flags);
 	return status;
 }
 
@@ -862,15 +861,13 @@
 		
 		crc = 0xffffffff;
 		for (byte = 0; byte < 6; byte++)
-			for (bit = *addrs++, j = 0; j < 8; j++, bit>>=1)
-			{
+			for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
 				int test;
 
 				test = ((bit ^ crc) & 0x01);
 				crc >>= 1;
 
-				if (test)
-				{
+				if (test) {
 					crc = crc ^ poly;
 				}
 			}
@@ -933,16 +930,17 @@
 	dev->base_addr = (long) sdev;
 
 	/* Copy the IDPROM ethernet address to the device structure, later we
-	 * will copy the address in the device structure to the lance initialization
-	 * block
+	 * will copy the address in the device structure to the lance
+	 * initialization block.
 	 */
 	for (i = 0; i < 6; i++)
-		printk ("%2.2x%c",
-			dev->dev_addr[i] = idprom->id_ethaddr[i], i == 5 ? ' ': ':');
+		printk ("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i],
+			i == 5 ? ' ': ':');
 	printk("\n");
 
 	/* Get the IO region */
-	prom_apply_sbus_ranges (sdev->my_bus, &sdev->reg_addrs [0], sdev->num_registers);
+	prom_apply_sbus_ranges (sdev->my_bus, &sdev->reg_addrs [0],
+				sdev->num_registers);
 	ll = sparc_alloc_io (sdev->reg_addrs [0].phys_addr, 0,
 			     sizeof (struct lance_regs), lancestr,
 			     sdev->reg_addrs[0].which_io, 0x0);
@@ -953,7 +951,8 @@
 	memset ((char *)dev->priv, 0, sizeof (struct lance_private));
 
 	if (lebuffer){
-		prom_apply_sbus_ranges (lebuffer->my_bus, &lebuffer->reg_addrs [0],
+		prom_apply_sbus_ranges (lebuffer->my_bus,
+					&lebuffer->reg_addrs [0],
 					lebuffer->num_registers);
 		lp->init_block = (void *)
 			sparc_alloc_io (lebuffer->reg_addrs [0].phys_addr, 0,
@@ -966,8 +965,10 @@
 				   lancedma);
 		lp->pio_buffer = 0;
 	}
-	lp->busmaster_regval = prom_getintdefault(sdev->prom_node, "busmaster-regval",
-						  (LE_C3_BSWP|LE_C3_ACON|LE_C3_BCON));
+	lp->busmaster_regval = prom_getintdefault(sdev->prom_node,
+						  "busmaster-regval",
+						  (LE_C3_BSWP | LE_C3_ACON |
+						   LE_C3_BCON));
     
 	lp->ll = ll;
 	lp->name = lancestr;
@@ -1014,10 +1015,10 @@
 				       sizeof(prop));
 
 			if (strcmp(prop, "true")) {
-				printk("%s: warning: overriding option 'tpe-link-test?'\n",
-				       dev->name);
-				printk("%s: warning: mail any problems to ecd@skynet.be\n",
-				       dev->name);
+				printk("%s: warning: overriding option "
+				       "'tpe-link-test?'\n", dev->name);
+				printk("%s: warning: mail any problems "
+				       "to ecd@skynet.be\n", dev->name);
 				set_auxio(AUXIO_LINK_TEST, 0);
 			}
 no_link_test:
@@ -1039,7 +1040,8 @@
 
 	/* This should never happen. */
 	if ((int)(lp->init_block->brx_ring) & 0x07) {
-		printk(" **ERROR** LANCE Rx and Tx rings not on even boundary.\n");
+		printk("%s: ERROR: Rx and Tx rings not on even boundary.\n",
+		       dev->name);
 		return ENODEV;
 	}
 
@@ -1092,13 +1094,15 @@
 			if (strcmp (sdev->prom_name, "ledma") == 0) {
 				cards++;
 				ledma = find_ledma (sdev);
-				if ((v = sparc_lance_init(dev, sdev->child, ledma, 0)))
+				if ((v = sparc_lance_init(dev, sdev->child,
+							  ledma, 0)))
 					return v;
 				continue;
 			}
 			if (strcmp (sdev->prom_name, "lebuffer") == 0){
 				cards++;
-				if ((v = sparc_lance_init(dev, sdev->child, 0, sdev)))
+				if ((v = sparc_lance_init(dev, sdev->child,
+							  0, sdev)))
 					return v;
 				continue;
 			}
diff -u --recursive --new-file v2.1.17/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.1.17/linux/drivers/pci/pci.c	Wed Dec 18 15:58:48 1996
+++ linux/drivers/pci/pci.c	Mon Dec 23 19:22:12 1996
@@ -194,7 +194,7 @@
 	DEVICE( ALLIANCE,	ALLIANCE_PROMOTIO, "Promotion-6410"),
 	DEVICE( ALLIANCE,	ALLIANCE_PROVIDEO, "Provideo"),
 	DEVICE( VMIC,		VMIC_VME,	"VMIVME-7587"),
- 	DEVICE( DIGI,		DIGI_RIGHTSWITCH, "Digi RightSwitch SE-6"),
+ 	DEVICE( DIGI,		DIGI_RIGHTSWITCH, "RightSwitch SE-6"),
 	DEVICE( MUTECH,		MUTECH_MV1000,	"MV-1000"),
 	DEVICE( ZEITNET,	ZEITNET_1221,	"1221"),
 	DEVICE( ZEITNET,	ZEITNET_1225,	"1225"),
@@ -522,6 +522,7 @@
 	      case PCI_VENDOR_ID_PLX:		return "PLX";
 	      case PCI_VENDOR_ID_ALLIANCE:	return "Alliance";
 	      case PCI_VENDOR_ID_VMIC:		return "VMIC";
+	      case PCI_VENDOR_ID_DIGI:		return "Digi Intl.";
 	      case PCI_VENDOR_ID_MUTECH:	return "Mutech";
 	      case PCI_VENDOR_ID_TOSHIBA:	return "Toshiba";
 	      case PCI_VENDOR_ID_ZEITNET:	return "ZeitNet";
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/NCR53c406a.c linux/drivers/scsi/NCR53c406a.c
--- v2.1.17/linux/drivers/scsi/NCR53c406a.c	Fri Apr 12 09:49:40 1996
+++ linux/drivers/scsi/NCR53c406a.c	Fri Dec 27 12:03:23 1996
@@ -729,7 +729,7 @@
 }
 
 int 
-NCR53c406a_reset(Scsi_Cmnd *SCpnt){
+NCR53c406a_reset(Scsi_Cmnd *SCpnt, unsigned int ignored){
     DEB(printk("NCR53c406a_reset called\n"));
     outb(C4_IMG, CONFIG4);      /* Select reg set 0 */
     outb(CHIP_RESET, CMD_REG);
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/NCR53c406a.h linux/drivers/scsi/NCR53c406a.h
--- v2.1.17/linux/drivers/scsi/NCR53c406a.h	Wed Feb 14 09:26:25 1996
+++ linux/drivers/scsi/NCR53c406a.h	Fri Dec 27 12:03:23 1996
@@ -57,7 +57,7 @@
 int NCR53c406a_command(Scsi_Cmnd *);
 int NCR53c406a_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int NCR53c406a_abort(Scsi_Cmnd *);
-int NCR53c406a_reset(Scsi_Cmnd *);
+int NCR53c406a_reset(Scsi_Cmnd *, unsigned int);
 int NCR53c406a_biosparm(Disk *, kdev_t, int []);
 
 #endif /* _NCR53C406A_H */
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c
--- v2.1.17/linux/drivers/scsi/aha1740.c	Fri Nov  1 17:13:18 1996
+++ linux/drivers/scsi/aha1740.c	Fri Dec 27 12:03:23 1996
@@ -499,7 +499,7 @@
    that it will get some kind of response for the command in SCpnt.  We must
    oblige, or the command will hang the scsi system */
 
-int aha1740_reset(Scsi_Cmnd * SCpnt)
+int aha1740_reset(Scsi_Cmnd * SCpnt, unsigned int ignored)
 {
     DEB(printk("aha1740_reset called\n"));
     return SCSI_RESET_PUNT;
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/aha1740.h linux/drivers/scsi/aha1740.h
--- v2.1.17/linux/drivers/scsi/aha1740.h	Thu Sep 21 09:01:48 1995
+++ linux/drivers/scsi/aha1740.h	Fri Dec 27 12:03:23 1996
@@ -157,7 +157,7 @@
 int aha1740_command(Scsi_Cmnd *);
 int aha1740_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int aha1740_abort(Scsi_Cmnd *);
-int aha1740_reset(Scsi_Cmnd *);
+int aha1740_reset(Scsi_Cmnd *, unsigned int);
 int aha1740_biosparam(Disk *, kdev_t, int*);
 
 #define AHA1740_ECBS 32
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- v2.1.17/linux/drivers/scsi/fdomain.c	Sun Nov 10 20:12:12 1996
+++ linux/drivers/scsi/fdomain.c	Fri Dec 27 12:03:23 1996
@@ -1007,7 +1007,7 @@
    Write_FIFO_port       = port_base + Write_FIFO;
    Write_SCSI_Data_port  = port_base + Write_SCSI_Data;
 
-   fdomain_16x0_reset( NULL );
+   fdomain_16x0_reset( NULL, 0 );
 
    if (fdomain_test_loopback()) {
 #if DEBUG_DETECT
@@ -1892,7 +1892,7 @@
    return SCSI_ABORT_SUCCESS;
 }
 
-int fdomain_16x0_reset( Scsi_Cmnd *SCpnt )
+int fdomain_16x0_reset( Scsi_Cmnd *SCpnt, unsigned int ignored )
 {
 #if DEBUG_RESET
    static int called_once = 0;
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/fdomain.h linux/drivers/scsi/fdomain.h
--- v2.1.17/linux/drivers/scsi/fdomain.h	Fri Oct 13 07:38:18 1995
+++ linux/drivers/scsi/fdomain.h	Fri Dec 27 12:03:23 1996
@@ -29,7 +29,7 @@
 int        fdomain_16x0_command( Scsi_Cmnd * );
 int        fdomain_16x0_abort( Scsi_Cmnd * );
 const char *fdomain_16x0_info( struct Scsi_Host * );
-int        fdomain_16x0_reset( Scsi_Cmnd * ); 
+int        fdomain_16x0_reset( Scsi_Cmnd *, unsigned int ); 
 int        fdomain_16x0_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) );
 int        fdomain_16x0_biosparam( Disk *, kdev_t, int * );
 int        fdomain_16x0_proc_info( char *buffer, char **start, off_t offset,
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
--- v2.1.17/linux/drivers/scsi/ide-scsi.c	Thu Dec 12 19:37:07 1996
+++ linux/drivers/scsi/ide-scsi.c	Fri Dec 27 12:03:23 1996
@@ -467,7 +467,7 @@
 int init_module (void)
 {
 	idescsi_init ();
-	idescsi_template.usage_count = &mod_use_count_;
+	idescsi_template.usage_count = &__this_module.usecount;
 	scsi_register_module (MODULE_SCSI_HA, &idescsi_template);
 	return 0;
 }
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c
--- v2.1.17/linux/drivers/scsi/ppa.c	Tue Nov 19 15:53:56 1996
+++ linux/drivers/scsi/ppa.c	Fri Dec 27 12:03:23 1996
@@ -463,7 +463,7 @@
         return SCSI_ABORT_SNOOZE;
 }
 
-int     ppa_reset( Scsi_Cmnd * cmd )
+int     ppa_reset( Scsi_Cmnd * cmd, unsigned int ignored )
 
 {       ppa_abort_flag = 2;
         return SCSI_RESET_PUNT;
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/ppa.h linux/drivers/scsi/ppa.h
--- v2.1.17/linux/drivers/scsi/ppa.h	Thu Mar 14 12:57:46 1996
+++ linux/drivers/scsi/ppa.h	Fri Dec 27 12:03:23 1996
@@ -14,7 +14,7 @@
 int ppa_command(Scsi_Cmnd *);
 int ppa_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
 int ppa_abort(Scsi_Cmnd *);
-int ppa_reset(Scsi_Cmnd *);
+int ppa_reset(Scsi_Cmnd *, unsigned int);
 int ppa_biosparam(Disk *, kdev_t, int[]);
 
 #define PPA {			\
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/qlogicfas.c linux/drivers/scsi/qlogicfas.c
--- v2.1.17/linux/drivers/scsi/qlogicfas.c	Thu Jul 11 07:41:25 1996
+++ linux/drivers/scsi/qlogicfas.c	Fri Dec 27 12:03:23 1996
@@ -656,7 +656,7 @@
 
 /*----------------------------------------------------------------*/
 /* reset SCSI bus */
-int	qlogicfas_reset(Scsi_Cmnd * cmd)
+int	qlogicfas_reset(Scsi_Cmnd * cmd, unsigned int ignored)
 {
 	qabort = 2;
 	ql_zap();
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/qlogicfas.h linux/drivers/scsi/qlogicfas.h
--- v2.1.17/linux/drivers/scsi/qlogicfas.h	Thu Jul 11 07:41:25 1996
+++ linux/drivers/scsi/qlogicfas.h	Fri Dec 27 12:03:24 1996
@@ -6,7 +6,7 @@
 int qlogicfas_command(Scsi_Cmnd *);
 int qlogicfas_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
 int qlogicfas_abort(Scsi_Cmnd *);
-int qlogicfas_reset(Scsi_Cmnd *);
+int qlogicfas_reset(Scsi_Cmnd *, unsigned int);
 int qlogicfas_biosparam(Disk *, kdev_t, int[]);
 
 #ifndef NULL
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.1.17/linux/drivers/scsi/scsi.c	Sun Dec 22 16:37:37 1996
+++ linux/drivers/scsi/scsi.c	Fri Dec 27 12:03:24 1996
@@ -97,10 +97,6 @@
                  struct Scsi_Host *shpnt, char * scsi_result);
 void scsi_build_commandblocks(Scsi_Device * SDpnt);
 
-#ifdef CONFIG_MODULES
-extern struct symbol_table scsi_symbol_table;
-#endif
-
 static FreeSectorBitmap * dma_malloc_freelist = NULL;
 static int scsi_need_isa_bounce_buffers;
 static unsigned int dma_sectors = 0;
@@ -2558,10 +2554,6 @@
     timer_table[SCSI_TIMER].fn = scsi_main_timeout;
     timer_table[SCSI_TIMER].expires = 0;
 
-#ifdef CONFIG_MODULES
-    register_symtab(&scsi_symbol_table);
-#endif    
-
     /* Register the /proc/scsi/scsi entry */
 #if CONFIG_PROC_FS 
     proc_scsi_register(0, &proc_scsi_scsi);    
@@ -3479,7 +3471,6 @@
 
     timer_table[SCSI_TIMER].fn = scsi_main_timeout;
     timer_table[SCSI_TIMER].expires = 0;
-    register_symtab(&scsi_symbol_table);
     scsi_loadable_module_flag = 1;
 
     /* Register the /proc/scsi/scsi entry */
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/scsi_module.c linux/drivers/scsi/scsi_module.c
--- v2.1.17/linux/drivers/scsi/scsi_module.c	Thu Nov  9 08:24:08 1995
+++ linux/drivers/scsi/scsi_module.c	Fri Dec 27 12:03:24 1996
@@ -32,7 +32,7 @@
 #include <linux/module.h>
 
 int init_module(void) {
-    driver_template.usage_count = &mod_use_count_;
+    driver_template.usage_count = &__this_module.usecount;
     scsi_register_module(MODULE_SCSI_HA, &driver_template);
     return (driver_template.present == 0);
 }
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- v2.1.17/linux/drivers/scsi/scsi_syms.c	Thu May  2 07:48:54 1996
+++ linux/drivers/scsi/scsi_syms.c	Fri Dec 27 12:03:24 1996
@@ -5,6 +5,7 @@
 #define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/config.h>
+
 #ifdef CONFIG_MODULES
 
 #include <linux/sched.h>
@@ -37,47 +38,39 @@
 extern void print_command (unsigned char *command);
 extern void print_sense(const char * devclass, Scsi_Cmnd * SCpnt);
 
-struct symbol_table scsi_symbol_table = {
-#include <linux/symtab_begin.h>
-    X(scsi_register_module),
-    X(scsi_unregister_module),
-    X(scsi_free),
-    X(scsi_malloc),
-    X(scsi_register),
-    X(scsi_unregister),
-    X(scsicam_bios_param),
-    X(allocate_device),
-    X(scsi_do_cmd),
-    X(scsi_command_size),
-    X(scsi_init_malloc),
-    X(scsi_init_free),
-    X(scsi_ioctl),
-    X(print_command),
-    X(print_sense),
-    X(print_msg),
-    X(print_status),
-    X(dma_free_sectors),
-    X(kernel_scsi_ioctl),
-    X(need_isa_buffer),
-    X(request_queueable),
-    X(print_Scsi_Cmnd),
-    X(scsi_mark_host_reset),
-    X(scsi_mark_bus_reset),
+EXPORT_SYMBOL(scsi_register_module);
+EXPORT_SYMBOL(scsi_unregister_module);
+EXPORT_SYMBOL(scsi_free);
+EXPORT_SYMBOL(scsi_malloc);
+EXPORT_SYMBOL(scsi_register);
+EXPORT_SYMBOL(scsi_unregister);
+EXPORT_SYMBOL(scsicam_bios_param);
+EXPORT_SYMBOL(allocate_device);
+EXPORT_SYMBOL(scsi_do_cmd);
+EXPORT_SYMBOL(scsi_command_size);
+EXPORT_SYMBOL(scsi_init_malloc);
+EXPORT_SYMBOL(scsi_init_free);
+EXPORT_SYMBOL(scsi_ioctl);
+EXPORT_SYMBOL(print_command);
+EXPORT_SYMBOL(print_sense);
+EXPORT_SYMBOL(print_msg);
+EXPORT_SYMBOL(print_status);
+EXPORT_SYMBOL(dma_free_sectors);
+EXPORT_SYMBOL(kernel_scsi_ioctl);
+EXPORT_SYMBOL(need_isa_buffer);
+EXPORT_SYMBOL(request_queueable);
+EXPORT_SYMBOL(print_Scsi_Cmnd);
+EXPORT_SYMBOL(scsi_mark_host_reset);
+EXPORT_SYMBOL(scsi_mark_bus_reset);
 #if defined(CONFIG_PROC_FS)
-    X(proc_print_scsidevice),
+EXPORT_SYMBOL(proc_print_scsidevice);
 #endif
 /*
  * These are here only while I debug the rest of the scsi stuff.
  */
-    X(scsi_hostlist),
-    X(scsi_hosts),
-    X(scsi_devicelist),
-    X(scsi_devices),
-
-    /********************************************************
-     * Do not add anything below this line,
-     * as the stacked modules depend on this!
-     */
-#include <linux/symtab_end.h>
-};
-#endif
+EXPORT_SYMBOL(scsi_hostlist);
+EXPORT_SYMBOL(scsi_hosts);
+EXPORT_SYMBOL(scsi_devicelist);
+EXPORT_SYMBOL(scsi_devices);
+
+#endif /* CONFIG_MODULES */
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.1.17/linux/drivers/scsi/sd.c	Fri Nov 15 23:49:09 1996
+++ linux/drivers/scsi/sd.c	Fri Dec 27 12:03:24 1996
@@ -1534,7 +1534,7 @@
 #ifdef MODULE
 
 int init_module(void) {
-    sd_template.usage_count = &mod_use_count_;
+    sd_template.usage_count = &__this_module.usecount;
     return scsi_register_module(MODULE_SCSI_DEV, &sd_template);
 }
 
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v2.1.17/linux/drivers/scsi/sg.c	Tue Oct 29 19:58:13 1996
+++ linux/drivers/scsi/sg.c	Fri Dec 27 12:03:24 1996
@@ -632,7 +632,7 @@
 #ifdef MODULE
 
 int init_module(void) {
-    sg_template.usage_count = &mod_use_count_;
+    sg_template.usage_count = &__this_module.usecount;
     return scsi_register_module(MODULE_SCSI_DEV, &sg_template);
 }
 
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v2.1.17/linux/drivers/scsi/sr.c	Thu Dec 12 19:37:17 1996
+++ linux/drivers/scsi/sr.c	Fri Dec 27 12:03:24 1996
@@ -1006,7 +1006,7 @@
 #ifdef MODULE
 
 int init_module(void) {
-        sr_template.usage_count = &mod_use_count_;
+        sr_template.usage_count = &__this_module.usecount;
         return scsi_register_module(MODULE_SCSI_DEV, &sr_template);
 }
 
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v2.1.17/linux/drivers/scsi/st.c	Tue Oct 29 19:58:13 1996
+++ linux/drivers/scsi/st.c	Fri Dec 27 12:03:24 1996
@@ -3068,7 +3068,7 @@
 #ifdef MODULE
 
 int init_module(void) {
-  st_template.usage_count = &mod_use_count_;
+  st_template.usage_count = &__this_module.usecount;
   return scsi_register_module(MODULE_SCSI_DEV, &st_template);
 }
 
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c
--- v2.1.17/linux/drivers/scsi/wd7000.c	Mon Sep 16 13:05:18 1996
+++ linux/drivers/scsi/wd7000.c	Fri Dec 27 12:03:24 1996
@@ -1462,7 +1462,7 @@
 /*
  *  I also have no idea how to do a reset...
  */
-int wd7000_reset(Scsi_Cmnd * SCpnt)
+int wd7000_reset(Scsi_Cmnd * SCpnt, unsigned int ignored)
 {
     return SCSI_RESET_PUNT;
 }
diff -u --recursive --new-file v2.1.17/linux/drivers/scsi/wd7000.h linux/drivers/scsi/wd7000.h
--- v2.1.17/linux/drivers/scsi/wd7000.h	Thu Sep 21 09:01:48 1995
+++ linux/drivers/scsi/wd7000.h	Fri Dec 27 12:03:24 1996
@@ -17,7 +17,7 @@
 int wd7000_command(Scsi_Cmnd *);
 int wd7000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int wd7000_abort(Scsi_Cmnd *);
-int wd7000_reset(Scsi_Cmnd *);
+int wd7000_reset(Scsi_Cmnd *, unsigned int);
 int wd7000_biosparam(Disk *, kdev_t, int *);
 
 #ifndef NULL
diff -u --recursive --new-file v2.1.17/linux/fs/affs/inode.c linux/fs/affs/inode.c
--- v2.1.17/linux/fs/affs/inode.c	Tue Nov 12 15:56:11 1996
+++ linux/fs/affs/inode.c	Fri Dec 27 12:03:24 1996
@@ -4,7 +4,7 @@
  *  (c) 1996  Hans-Joachim Widmaier - Rewritten
  *
  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
- * 
+ *
  *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
  *
  *  (C) 1991  Linus Torvalds - minix filesystem
@@ -98,11 +98,11 @@
 	pr_debug("AFFS: write_super() at %d, clean=%d\n",CURRENT_TIME,clean);
 }
 
-static struct super_operations affs_sops = { 
+static struct super_operations affs_sops = {
 	affs_read_inode,
 	affs_notify_change,
 	affs_write_inode,
-	affs_put_inode,	
+	affs_put_inode,
 	affs_put_super,
 	affs_write_super,
 	affs_statfs,
@@ -467,7 +467,7 @@
 	size   = s->u.affs_sb.s_partition_size - reserved;
 	num_bm = (size + s->s_blocksize * 8 - 32 - 1) / (s->s_blocksize * 8 - 32);
 	az_no  = (size + AFFS_ZONE_SIZE - 1) / (AFFS_ZONE_SIZE - 32);
-	ptype  = num_bm * sizeof(struct affs_bm_info) + 
+	ptype  = num_bm * sizeof(struct affs_bm_info) +
 		 az_no * sizeof(struct affs_alloc_zone) +
 		 MAX_ZONES * sizeof(struct affs_zone);
 	pr_debug("num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype);
@@ -666,7 +666,7 @@
 
 	inode->u.affs_i.i_protect      = prot;
 	inode->u.affs_i.i_parent       = htonl(file_end->parent);
-	inode->u.affs_i.i_original     = 0;	
+	inode->u.affs_i.i_original     = 0;
 	inode->u.affs_i.i_zone         = 0;
 	inode->u.affs_i.i_hlink        = 0;
 	inode->u.affs_i.i_pa_cnt       = 0;
@@ -682,7 +682,7 @@
 		inode->i_mode = inode->i_sb->u.affs_sb.s_mode;
 	else
 		inode->i_mode = prot_to_mode(prot);
-	
+
 	if (inode->i_sb->u.affs_sb.s_flags & SF_SETUID)
 		inode->i_uid = inode->i_sb->u.affs_sb.s_uid;
 	else {
@@ -761,7 +761,7 @@
 			 sys_tz.tz_minuteswest * 60;
 	affs_brelse(bh);
 	affs_brelse(lbh);
-	
+
 	inode->i_op = NULL;
 	if (S_ISREG(inode->i_mode)) {
 		if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) {
@@ -829,16 +829,16 @@
 	error = inode_change_ok(inode,attr);
 	if (error)
 		return error;
-	
+
 	if (((attr->ia_valid & ATTR_UID) && (inode->i_sb->u.affs_sb.s_flags & SF_SETUID)) ||
 	    ((attr->ia_valid & ATTR_GID) && (inode->i_sb->u.affs_sb.s_flags & SF_SETGID)) ||
 	    ((attr->ia_valid & ATTR_MODE) &&
 	     (inode->i_sb->u.affs_sb.s_flags & (SF_SETMODE | SF_IMMUTABLE))))
 		error = -EPERM;
-	
+
 	if (error)
 		return (inode->i_sb->u.affs_sb.s_flags & SF_QUIET) ? 0 : error;
-	
+
 	if (attr->ia_valid & ATTR_MODE)
 		inode->u.affs_i.i_protect = mode_to_prot(attr->ia_mode);
 
@@ -870,7 +870,7 @@
 
 	if (!dir || !(inode = get_empty_inode()))
 		return NULL;
-	
+
 	sb = dir->i_sb;
 	inode->i_sb    = sb;
 	inode->i_flags = sb->s_flags;
@@ -950,12 +950,12 @@
 	hash = affs_hash_name(name,len,AFFS_I2FSTYPE(dir),AFFS_I2HSIZE(dir));
 
 	lock_super(inode->i_sb);
-	DIR_END(inode_bh->b_data,inode)->hash_chain = 
+	DIR_END(inode_bh->b_data,inode)->hash_chain =
 				((struct dir_front *)dir_bh->b_data)->hashtable[hash];
 	((struct dir_front *)dir_bh->b_data)->hashtable[hash] = ntohl(inode->i_ino);
 	if (link_bh) {
 		LINK_END(inode_bh->b_data,inode)->original   = ntohl(link->i_ino);
-		LINK_END(inode_bh->b_data,inode)->link_chain = 
+		LINK_END(inode_bh->b_data,inode)->link_chain =
 						FILE_END(link_bh->b_data,link)->link_chain;
 		FILE_END(link_bh->b_data,link)->link_chain   = ntohl(inode->i_ino);
 		affs_fix_checksum(AFFS_I2BSIZE(link),link_bh->b_data,5);
@@ -994,14 +994,12 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
 
 int
 init_module(void)
 {
-	int	 status;
-	if ((status = init_affs_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_affs_fs();
 }
 
 void
diff -u --recursive --new-file v2.1.17/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- v2.1.17/linux/fs/binfmt_aout.c	Tue Oct 29 19:58:19 1996
+++ linux/fs/binfmt_aout.c	Fri Dec 27 12:03:24 1996
@@ -37,7 +37,7 @@
 #ifndef MODULE
 	NULL, NULL, load_aout_binary, load_aout_library, aout_core_dump
 #else
-	NULL, &mod_use_count_, load_aout_binary, load_aout_library, aout_core_dump
+	NULL, &__this_module.usecount, load_aout_binary, load_aout_library, aout_core_dump
 #endif
 };
 
diff -u --recursive --new-file v2.1.17/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.1.17/linux/fs/binfmt_elf.c	Sun Dec 22 16:37:38 1996
+++ linux/fs/binfmt_elf.c	Fri Dec 27 12:03:24 1996
@@ -59,7 +59,7 @@
 #ifndef MODULE
 	NULL, NULL, load_elf_binary, load_elf_library, elf_core_dump
 #else
-	NULL, &mod_use_count_, load_elf_binary, load_elf_library, elf_core_dump
+	NULL, &__this_module.usecount, load_elf_binary, load_elf_library, elf_core_dump
 #endif
 };
 
diff -u --recursive --new-file v2.1.17/linux/fs/binfmt_java.c linux/fs/binfmt_java.c
--- v2.1.17/linux/fs/binfmt_java.c	Fri Nov 22 18:28:19 1996
+++ linux/fs/binfmt_java.c	Fri Dec 27 12:03:24 1996
@@ -144,7 +144,7 @@
 #ifndef MODULE
 	NULL, 0, load_java, NULL, NULL
 #else
-	NULL, &mod_use_count_, load_java, NULL, NULL
+	NULL, &__this_module.usecount, load_java, NULL, NULL
 #endif
 };
 
@@ -161,7 +161,7 @@
 #ifndef MODULE
 	NULL, 0, load_applet, NULL, NULL
 #else
-	NULL, &mod_use_count_, load_applet, NULL, NULL
+	NULL, &__this_module.usecount, load_applet, NULL, NULL
 #endif
 };
 
diff -u --recursive --new-file v2.1.17/linux/fs/binfmt_script.c linux/fs/binfmt_script.c
--- v2.1.17/linux/fs/binfmt_script.c	Thu Dec 12 17:02:45 1996
+++ linux/fs/binfmt_script.c	Fri Dec 27 12:03:24 1996
@@ -100,7 +100,7 @@
 #ifndef MODULE
 	NULL, 0, load_script, NULL, NULL
 #else
-	NULL, &mod_use_count_, load_script, NULL, NULL
+	NULL, &__this_module.usecount, load_script, NULL, NULL
 #endif
 };
 
diff -u --recursive --new-file v2.1.17/linux/fs/block_dev.c linux/fs/block_dev.c
--- v2.1.17/linux/fs/block_dev.c	Tue Oct 29 19:58:19 1996
+++ linux/fs/block_dev.c	Sun Dec 29 10:10:46 1996
@@ -23,19 +23,16 @@
 long block_write(struct inode * inode, struct file * filp,
 	const char * buf, unsigned long count)
 {
-	int blocksize, blocksize_bits, i, j, buffercount,write_error;
+	int blocksize, blocksize_bits, i, buffercount,write_error;
 	int block, blocks;
 	loff_t offset;
 	int chars;
 	int written = 0;
-	int cluster_list[MAX_BUF_PER_PAGE];
 	struct buffer_head * bhlist[NBUF];
-	int blocks_per_cluster;
 	unsigned int size;
 	kdev_t dev;
 	struct buffer_head * bh, *bufferlist[NBUF];
 	register char * p;
-	int excess;
 
 	write_error = buffercount = 0;
 	dev = inode->i_rdev;
@@ -52,8 +49,6 @@
 		i >>= 1;
 	}
 
-	blocks_per_cluster = PAGE_SIZE / blocksize;
-
 	block = filp->f_pos >> blocksize_bits;
 	offset = filp->f_pos & (blocksize-1);
 
@@ -69,15 +64,14 @@
 			chars=count;
 
 #if 0
-		if (chars == blocksize)
-			bh = getblk(dev, block, blocksize);
-		else
-			bh = breada(dev,block,block+1,block+2,-1);
-
+		/* get the buffer head */
+		{
+			struct buffer_head * (*fn)(kdev_t, int, int) = getblk;
+			if (chars != blocksize)
+				fn = bread;
+			bh = fn(dev, block, blocksize);
+		}
 #else
-		for(i=0; i<blocks_per_cluster; i++) cluster_list[i] = block+i;
-		if((block % blocks_per_cluster) == 0)
-		  generate_cluster(dev, cluster_list, blocksize);
 		bh = getblk(dev, block, blocksize);
 
 		if (chars != blocksize && !buffer_uptodate(bh)) {
@@ -91,15 +85,8 @@
 		    blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9) / 2;
 		    if (block + blocks > size) blocks = size - block;
 		    if (blocks > NBUF) blocks=NBUF;
-		    excess = (block + blocks) % blocks_per_cluster;
-		    if ( blocks > excess )
-			blocks -= excess;
 		    bhlist[0] = bh;
 		    for(i=1; i<blocks; i++){
-		      if(((i+block) % blocks_per_cluster) == 0) {
-			for(j=0; j<blocks_per_cluster; j++) cluster_list[j] = block+i+j;
-			generate_cluster(dev, cluster_list, blocksize);
-		      };
 		      bhlist[i] = getblk (dev, block+i, blocksize);
 		      if(!bhlist[i]){
 			while(i >= 0) brelse(bhlist[i--]);
@@ -167,8 +154,6 @@
 	int blocksize_bits, i;
 	unsigned int blocks, rblocks, left;
 	int bhrequest, uptodate;
-	int cluster_list[MAX_BUF_PER_PAGE];
-	int blocks_per_cluster;
 	struct buffer_head ** bhb, ** bhe;
 	struct buffer_head * buflist[NBUF];
 	struct buffer_head * bhreq[NBUF];
@@ -176,7 +161,6 @@
 	loff_t size;
 	kdev_t dev;
 	int read;
-	int excess;
 
 	dev = inode->i_rdev;
 	blocksize = BLOCK_SIZE;
@@ -195,8 +179,6 @@
 	else
 		size = INT_MAX;
 
-	blocks_per_cluster = PAGE_SIZE / blocksize;
-
 	if (offset > size)
 		left = 0;
 	/* size - offset might not fit into left, so check explicitly. */
@@ -217,9 +199,6 @@
 	if (filp->f_reada) {
 	        if (blocks < read_ahead[MAJOR(dev)] / (blocksize >> 9))
 			blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9);
-		excess = (block + blocks) % blocks_per_cluster;
-		if ( blocks > excess )
-			blocks -= excess;		
 		if (rblocks > blocks)
 			blocks = rblocks;
 		
@@ -242,12 +221,6 @@
 		uptodate = 1;
 		while (blocks) {
 			--blocks;
-#if 1
-			if((block % blocks_per_cluster) == 0) {
-			  for(i=0; i<blocks_per_cluster; i++) cluster_list[i] = block+i;
-			  generate_cluster(dev, cluster_list, blocksize);
-			}
-#endif
 			*bhb = getblk(dev, block++, blocksize);
 			if (*bhb && !buffer_uptodate(*bhb)) {
 				uptodate = 0;
@@ -268,7 +241,6 @@
 		/* Now request them all */
 		if (bhrequest) {
 			ll_rw_block(READ, bhrequest, bhreq);
-			refill_freelist(blocksize);
 		}
 
 		do { /* Finish off all I/O that has actually completed */
diff -u --recursive --new-file v2.1.17/linux/fs/buffer.c linux/fs/buffer.c
--- v2.1.17/linux/fs/buffer.c	Sun Dec 22 16:37:38 1996
+++ linux/fs/buffer.c	Sun Dec 29 11:18:33 1996
@@ -10,15 +10,12 @@
  * data, of course), but instead letting the caller do it.
  */
 
-/*
- * NOTE! There is one discordant note here: checking floppies for
- * disk change. This is where it fits best, I think, as it should
- * invalidate changed floppy-disk-caches.
- */
- 
 /* Some bdflush() changes for the dynamic ramdisk - Paul Gortmaker, 12/94 */
 /* Start bdflush() with kernel_thread not syscall - Paul Gortmaker, 12/95 */
 
+/* Removed a lot of unnecessary code and simplified things now that
+   the buffer cache isn't our primary cache - Andrew Tridgell 12/96 */
+
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
@@ -41,39 +38,34 @@
 #define NR_SIZES 5
 static char buffersize_index[17] =
 {-1,  0,  1, -1,  2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4};
-static short int bufferindex_size[NR_SIZES] = {512, 1024, 2048, 4096, 8192};
 
 #define BUFSIZE_INDEX(X) ((int) buffersize_index[(X)>>9])
 #define MAX_BUF_PER_PAGE (PAGE_SIZE / 512)
+#define MAX_UNUSED_BUFFERS 30 /* don't ever have more than this number of 
+				 unused buffer heads */
+#define HASH_PAGES         4  /* number of pages to use for the hash table */
+#define NR_HASH (HASH_PAGES*PAGE_SIZE/sizeof(struct buffer_head *))
+#define HASH_MASK (NR_HASH-1)
 
 static int grow_buffers(int pri, int size);
-static int shrink_specific_buffers(unsigned int priority, int size);
-static int maybe_shrink_lav_buffers(int);
 
-static int nr_hash = 0;  /* Size of hash table */
 static struct buffer_head ** hash_table;
 static struct buffer_head * lru_list[NR_LIST] = {NULL, };
-/* next_to_age is an array of pointers into the lru lists, used to
-   cycle through the buffers aging their contents when deciding which
-   buffers to discard when more memory is needed */
-static struct buffer_head * next_to_age[NR_LIST] = {NULL, };
 static struct buffer_head * free_list[NR_SIZES] = {NULL, };
 
 static struct buffer_head * unused_list = NULL;
-struct buffer_head * reuse_list = NULL;
+static struct buffer_head * reuse_list = NULL;
 static struct wait_queue * buffer_wait = NULL;
 
-int nr_buffers = 0;
-int nr_buffers_type[NR_LIST] = {0,};
-int nr_buffers_size[NR_SIZES] = {0,};
-int nr_buffers_st[NR_SIZES][NR_LIST] = {{0,},};
-int buffer_usage[NR_SIZES] = {0,};  /* Usage counts used to determine load average */
-int buffers_lav[NR_SIZES] = {0,};  /* Load average of buffer usage */
-int nr_free[NR_SIZES] = {0,};
+static int nr_buffers = 0;
+static int nr_buffers_type[NR_LIST] = {0,};
+static int nr_buffer_heads = 0;
+static int nr_unused_buffer_heads = 0;
+static int refilled = 0;       /* Set NZ when a buffer freelist is refilled 
+				  this is used by the loop device */
+
+/* this is used by some architectures to estimate available memory */
 int buffermem = 0;
-int nr_buffer_heads = 0;
-int refilled = 0;       /* Set NZ when a buffer freelist is refilled */
-extern int *blksize_size[];
 
 /* Here is the parameter block for the bdflush process. If you add or
  * remove any of the parameters, make sure to update kernel/sysctl.c.
@@ -82,8 +74,9 @@
 static void wakeup_bdflush(int);
 
 #define N_PARAM 9
-#define LAV
 
+/* the dummy values in this structure are left in there for compatibility
+   with old programs that play with the /proc entries */
 union bdflush_param{
 	struct {
 		int nfract;  /* Percentage of buffer cache dirty to 
@@ -94,26 +87,17 @@
 				each time we call refill */
 		int nref_dirt; /* Dirty buffer threshold for activating bdflush
 				  when trying to refill buffers. */
-		int clu_nfract;  /* Percentage of buffer cache to scan to 
-				    search for free clusters */
+		int dummy1;    /* unused */
 		int age_buffer;  /* Time for normal buffer to age before 
 				    we flush it */
 		int age_super;  /* Time for superblock to age before we 
 				   flush it */
-		int lav_const;  /* Constant used for load average (time
-				   constant */
-		int lav_ratio;  /* Used to determine how low a lav for a
-				   particular size can go before we start to
-				   trim back the buffers */
+		int dummy2;    /* unused */
+		int dummy3;    /* unused */
 	} b_un;
 	unsigned int data[N_PARAM];
 } bdf_prm = {{60, 500, 64, 256, 15, 30*HZ, 5*HZ, 1884, 2}};
 
-/* The lav constant is set for 1 minute, as long as the update process runs
-   every 5 seconds.  If you change the frequency of update, the time
-   constant will also change. */
-
-
 /* These are the min and max parameter values that we will allow to be assigned */
 int bdflush_min[N_PARAM] = {  0,  10,    5,   25,  0,   100,   100, 1, 1};
 int bdflush_max[N_PARAM] = {100,5000, 2000, 2000,100, 60000, 60000, 2047, 5};
@@ -328,7 +312,7 @@
 	}
 }
 
-#define _hashfn(dev,block) (((unsigned)(HASHDEV(dev)^block))%nr_hash)
+#define _hashfn(dev,block) (((unsigned)(HASHDEV(dev)^block))&HASH_MASK)
 #define hash(dev,block) hash_table[_hashfn(dev,block)]
 
 static inline void remove_from_hash_queue(struct buffer_head * bh)
@@ -355,11 +339,6 @@
 		 lru_list[bh->b_list] = bh->b_next_free;
 	if (lru_list[bh->b_list] == bh)
 		 lru_list[bh->b_list] = NULL;
-	if (next_to_age[bh->b_list] == bh)
-		next_to_age[bh->b_list] = bh->b_next_free;
-	if (next_to_age[bh->b_list] == bh)
-		next_to_age[bh->b_list] = NULL;
-
 	bh->b_next_free = bh->b_prev_free = NULL;
 }
 
@@ -372,7 +351,6 @@
 		panic("Free list corrupted");
 	if(!free_list[isize])
 		panic("Free list empty");
-	nr_free[isize]--;
 	if(bh->b_next_free == bh)
 		 free_list[isize] = NULL;
 	else {
@@ -392,7 +370,6 @@
 		return;
 	}
 	nr_buffers_type[bh->b_list]--;
-	nr_buffers_st[BUFSIZE_INDEX(bh->b_size)][bh->b_list]--;
 	remove_from_hash_queue(bh);
 	remove_from_lru_list(bh);
 }
@@ -403,8 +380,6 @@
 		return;
 	if (bh == lru_list[bh->b_list]) {
 		lru_list[bh->b_list] = bh->b_next_free;
-		if (next_to_age[bh->b_list] == bh)
-			next_to_age[bh->b_list] = bh->b_next_free;
 		return;
 	}
 	if(bh->b_dev == B_FREE)
@@ -416,8 +391,6 @@
 		lru_list[bh->b_list] = bh;
 		lru_list[bh->b_list]->b_prev_free = bh;
 	}
-	if (!next_to_age[bh->b_list])
-		next_to_age[bh->b_list] = bh;
 
 	bh->b_next_free = lru_list[bh->b_list];
 	bh->b_prev_free = lru_list[bh->b_list]->b_prev_free;
@@ -439,7 +412,6 @@
 		bh->b_prev_free = bh;
 	}
 
-	nr_free[isize]++;
 	bh->b_next_free = free_list[isize];
 	bh->b_prev_free = free_list[isize]->b_prev_free;
 	free_list[isize]->b_prev_free->b_next_free = bh;
@@ -457,15 +429,13 @@
 		lru_list[bh->b_list] = bh;
 		bh->b_prev_free = bh;
 	}
-	if (!next_to_age[bh->b_list])
-		next_to_age[bh->b_list] = bh;
+
 	if (bh->b_next_free) panic("VFS: buffer LRU pointers corrupted");
 	bh->b_next_free = lru_list[bh->b_list];
 	bh->b_prev_free = lru_list[bh->b_list]->b_prev_free;
 	lru_list[bh->b_list]->b_prev_free->b_next_free = bh;
 	lru_list[bh->b_list]->b_prev_free = bh;
 	nr_buffers_type[bh->b_list]++;
-	nr_buffers_st[BUFSIZE_INDEX(bh->b_size)][bh->b_list]++;
 /* put the buffer in new hash-queue if it has a device */
 	bh->b_prev = NULL;
 	bh->b_next = NULL;
@@ -518,6 +488,7 @@
 
 void set_blocksize(kdev_t dev, int size)
 {
+	extern int *blksize_size[];
 	int i, nlist;
 	struct buffer_head * bh, *bhnext;
 
@@ -566,26 +537,69 @@
 	}
 }
 
-#define BADNESS(bh) (buffer_dirty(bh) || buffer_locked(bh))
 
-void refill_freelist(int size)
+/* check if a buffer is OK to be reclaimed */
+static inline int can_reclaim(struct buffer_head *bh, int size)
+{
+	if (bh->b_count || 
+	    buffer_protected(bh) || buffer_locked(bh))
+		return 0;
+			 
+	if (mem_map[MAP_NR((unsigned long) bh->b_data)].count != 1 ||
+	    buffer_dirty(bh)) {
+		refile_buffer(bh);
+		return 0;
+	}
+
+	if (bh->b_size != size)
+		return 0;
+
+	return 1;
+}
+
+/* find a candidate buffer to be reclaimed */
+static struct buffer_head *find_candidate(struct buffer_head *list,int *list_len,int size)
+{
+	struct buffer_head *bh;
+	
+	for (bh = list; 
+	     bh && (*list_len) > 0; 
+	     bh = bh->b_next_free, (*list_len)--) {
+		if (size != bh->b_size) {
+			/* this provides a mechanism for freeing blocks
+			   of other sizes, this is necessary now that we
+			   no longer have the lav code. */
+			try_to_free_buffer(bh,&bh,1);
+			continue;
+		}
+
+		if (buffer_locked(bh) && 
+		    (bh->b_list == BUF_LOCKED || bh->b_list == BUF_LOCKED1)) {
+			/* Buffers are written in the order they are placed 
+			   on the locked list. If we encounter a locked
+			   buffer here, this means that the rest of them
+			   are also locked */
+			(*list_len) = 0;
+			return NULL;
+		}
+
+		if (can_reclaim(bh,size))
+		    return bh;
+	}
+
+	return NULL;
+}
+
+static void refill_freelist(int size)
 {
-	struct buffer_head * bh, * tmp;
-	struct buffer_head * candidate[NR_LIST];
+	struct buffer_head * bh;
+	struct buffer_head * candidate[BUF_DIRTY];
 	unsigned int best_time, winner;
-	int isize = BUFSIZE_INDEX(size);
-	int buffers[NR_LIST];
+	int buffers[BUF_DIRTY];
 	int i;
 	int needed;
 
-	/* First see if we even need this.  Sometimes it is advantageous
-	 to request some blocks in a filesystem that we know that we will
-	 be needing ahead of time. */
-
-	if (nr_free[isize] > 100)
-		return;
-
-	++refilled;
+	refilled = 1;
 	/* If there are too many dirty buffers, we wake up the update process
 	   now so as to ensure that there are still clean buffers available
 	   for user processes to use (and dirty) */
@@ -598,72 +612,24 @@
 		needed -= PAGE_SIZE;
 	}
 
-	if(needed <= 0) return;
-
-	/* See if there are too many buffers of a different size.
-	   If so, victimize them */
-
-	while(maybe_shrink_lav_buffers(size))
-	 {
-		 if(!grow_buffers(GFP_BUFFER, size)) break;
-		 needed -= PAGE_SIZE;
-		 if(needed <= 0) return;
-	 };
-
+repeat:
 	/* OK, we cannot grow the buffer cache, now try to get some
 	   from the lru list */
 
 	/* First set the candidate pointers to usable buffers.  This
 	   should be quick nearly all of the time. */
 
-repeat0:
-	for(i=0; i<NR_LIST; i++){
-		if(i == BUF_DIRTY || i == BUF_SHARED || 
-		   nr_buffers_type[i] == 0) {
-			candidate[i] = NULL;
-			buffers[i] = 0;
-			continue;
-		}
+	if(needed <= 0) return;
+
+	for(i=0; i<BUF_DIRTY; i++){
 		buffers[i] = nr_buffers_type[i];
-		for (bh = lru_list[i]; buffers[i] > 0; bh = tmp, buffers[i]--)
-		 {
-			 if(buffers[i] < 0) panic("Here is the problem");
-			 tmp = bh->b_next_free;
-			 if (!bh) break;
-			 
-			 if (mem_map[MAP_NR((unsigned long) bh->b_data)].count != 1 ||
-			     buffer_dirty(bh)) {
-				 refile_buffer(bh);
-				 continue;
-			 }
-			 
-			 if (bh->b_count || buffer_protected(bh) || bh->b_size != size)
-				  continue;
-			 
-			 /* Buffers are written in the order they are placed 
-			    on the locked list. If we encounter a locked
-			    buffer here, this means that the rest of them
-			    are also locked */
-			 if (buffer_locked(bh) && (i == BUF_LOCKED || i == BUF_LOCKED1)) {
-				 buffers[i] = 0;
-				 break;
-			 }
-			 
-			 if (BADNESS(bh)) continue;
-			 break;
-		 };
-		if(!buffers[i]) candidate[i] = NULL; /* Nothing on this list */
-		else candidate[i] = bh;
-		if(candidate[i] && candidate[i]->b_count) panic("Here is the problem");
+		candidate[i] = find_candidate(lru_list[i], &buffers[i], size);
 	}
 	
- repeat:
-	if(needed <= 0) return;
-	
 	/* Now see which candidate wins the election */
 	
 	winner = best_time = UINT_MAX;	
-	for(i=0; i<NR_LIST; i++){
+	for(i=0; i<BUF_DIRTY; i++){
 		if(!candidate[i]) continue;
 		if(candidate[i]->b_lru_time < best_time){
 			best_time = candidate[i]->b_lru_time;
@@ -674,65 +640,21 @@
 	/* If we have a winner, use it, and then get a new candidate from that list */
 	if(winner != UINT_MAX) {
 		i = winner;
-		bh = candidate[i];
-		candidate[i] = bh->b_next_free;
-		if(candidate[i] == bh) candidate[i] = NULL;  /* Got last one */
-		if (bh->b_count || bh->b_size != size)
-			 panic("Busy buffer in candidate list\n");
-		if (mem_map[MAP_NR((unsigned long) bh->b_data)].count != 1)
-			 panic("Shared buffer in candidate list\n");
-		if (buffer_protected(bh))
-			panic("Protected buffer in candidate list\n");
-		if (BADNESS(bh)) panic("Buffer in candidate list with BADNESS != 0\n");
-		
-		if(bh->b_dev == B_FREE)
-			panic("Wrong list");
-		remove_from_queues(bh);
-		bh->b_dev = B_FREE;
-		put_last_free(bh);
-		needed -= bh->b_size;
-		buffers[i]--;
-		if(buffers[i] < 0) panic("Here is the problem");
+		while (needed>0 && (bh=candidate[i])) {
+			candidate[i] = bh->b_next_free;
+			if(candidate[i] == bh) candidate[i] = NULL;  /* Got last one */		
+			remove_from_queues(bh);
+			bh->b_dev = B_FREE;
+			put_last_free(bh);
+			needed -= bh->b_size;
+			buffers[i]--;
+			if(buffers[i] == 0) candidate[i] = NULL;
 		
-		if(buffers[i] == 0) candidate[i] = NULL;
-		
-		/* Now all we need to do is advance the candidate pointer
-		   from the winner list to the next usable buffer */
-		if(candidate[i] && buffers[i] > 0){
-			if(buffers[i] <= 0) panic("Here is another problem");
-			for (bh = candidate[i]; buffers[i] > 0; bh = tmp, buffers[i]--) {
-				if(buffers[i] < 0) panic("Here is the problem");
-				tmp = bh->b_next_free;
-				if (!bh) break;
-				
-				if (mem_map[MAP_NR((unsigned long) bh->b_data)].count != 1 ||
-				    buffer_dirty(bh)) {
-					refile_buffer(bh);
-					continue;
-				};
-				
-				if (bh->b_count || buffer_protected(bh) || bh->b_size != size)
-					 continue;
-				
-				/* Buffers are written in the order they are
-				   placed on the locked list.  If we encounter
-				   a locked buffer here, this means that the
-				   rest of them are also locked */
-				if (buffer_locked(bh) && (i == BUF_LOCKED || i == BUF_LOCKED1)) {
-					buffers[i] = 0;
-					break;
-				}
-	      
-				if (BADNESS(bh)) continue;
-				break;
-			};
-			if(!buffers[i]) candidate[i] = NULL; /* Nothing here */
-			else candidate[i] = bh;
-			if(candidate[i] && candidate[i]->b_count) 
-				 panic("Here is the problem");
+			if (candidate[i] && !can_reclaim(candidate[i],size))
+				candidate[i] = find_candidate(candidate[i],&buffers[i], size);
 		}
-		
-		goto repeat;
+		if (needed >= 0)
+			goto repeat;
 	}
 	
 	if(needed <= 0) return;
@@ -742,7 +664,7 @@
 	if (nr_free_pages > min_free_pages + 5) {
 		if (grow_buffers(GFP_BUFFER, size)) {
 			needed -= PAGE_SIZE;
-			goto repeat0;
+			goto repeat;
 		};
 	}
 	
@@ -750,7 +672,7 @@
 	if (!grow_buffers(GFP_ATOMIC, size))
 		wakeup_bdflush(1);
 	needed -= PAGE_SIZE;
-	goto repeat0;
+	goto repeat;
 }
 
 /*
@@ -768,9 +690,6 @@
 	struct buffer_head * bh;
 	int isize = BUFSIZE_INDEX(size);
 
-	/* Update this for the buffer size lav. */
-	buffer_usage[isize]++;
-
 	/* If there are too many dirty buffers, we wake up the update process
 	   now so as to ensure that there are still clean buffers available
 	   for user processes to use (and dirty) */
@@ -828,7 +747,6 @@
 void refile_buffer(struct buffer_head * buf)
 {
 	int dispose;
-	int isize;
 
 	if(buf->b_dev == B_FREE) {
 		printk("Attempt to refile free buffer\n");
@@ -836,17 +754,13 @@
 	}
 	if (buffer_dirty(buf))
 		dispose = BUF_DIRTY;
-	else if ((mem_map[MAP_NR((unsigned long) buf->b_data)].count > 1) || buffer_protected(buf))
-		dispose = BUF_SHARED;
 	else if (buffer_locked(buf))
 		dispose = BUF_LOCKED;
-	else if (buf->b_list == BUF_SHARED)
-		dispose = BUF_UNSHARED;
 	else
 		dispose = BUF_CLEAN;
 	if(dispose == BUF_CLEAN) buf->b_lru_time = jiffies;
 	if(dispose != buf->b_list)  {
-		if(dispose == BUF_DIRTY || dispose == BUF_UNSHARED)
+		if(dispose == BUF_DIRTY)
 			 buf->b_lru_time = jiffies;
 		if(dispose == BUF_LOCKED && 
 		   (buf->b_flushtime - buf->b_lru_time) <= bdf_prm.b_un.age_super)
@@ -857,16 +771,13 @@
 		if (dispose == BUF_DIRTY) {
 		/* 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] > 
-		   (nr_buffers - nr_buffers_type[BUF_SHARED]) *
-		   bdf_prm.b_un.nfract/100)
+		if (nr_buffers_type[BUF_DIRTY] > nr_buffers * bdf_prm.b_un.nfract/100)
 			 wakeup_bdflush(0);
 		/* If this is a loop device, and
-		 * more than half of the buffers of this size are dirty... */ 
+		 * more than half of the buffers are dirty... */ 
 		/* (Prevents no-free-buffers deadlock with loop device.) */
-		isize = BUFSIZE_INDEX(buf->b_size);
 		if (MAJOR(buf->b_dev) == LOOP_MAJOR &&
-		    nr_buffers_st[isize][BUF_DIRTY]*2>nr_buffers_size[isize])
+		    nr_buffers_type[BUF_DIRTY]*2>nr_buffers)
 			wakeup_bdflush(1);
 		}
 	}
@@ -993,11 +904,15 @@
 	return NULL;
 }
 
-/*
- * See fs/inode.c for the weird use of volatile..
- */
 static void put_unused_buffer_head(struct buffer_head * bh)
 {
+	if (nr_unused_buffer_heads >= MAX_UNUSED_BUFFERS) {
+		nr_buffer_heads--;
+		kfree(bh);
+		return;
+	}
+	memset(bh,0,sizeof(*bh));
+	nr_unused_buffer_heads++;
 	bh->b_next_free = unused_list;
 	unused_list = bh;
 	wake_up(&buffer_wait);
@@ -1005,21 +920,23 @@
 
 static void get_more_buffer_heads(void)
 {
-	int i;
 	struct buffer_head * bh;
 
-	for (;;) {
-		if (unused_list)
-			return;
-
+	while (!unused_list) {
 		/*
 		 * This is critical.  We can't swap out pages to get
 		 * more buffer heads, because the swap-out may need
 		 * more buffer-heads itself.  Thus GFP_ATOMIC.
 		 */
-		bh = (struct buffer_head *) get_free_page(GFP_ATOMIC);
-		if (bh)
-			break;
+		/* we now use kmalloc() here instead of gfp as we want
+                   to be able to easily release buffer heads - they
+                   took up quite a bit of memory (tridge) */
+		bh = (struct buffer_head *) kmalloc(sizeof(*bh),GFP_ATOMIC);
+		if (bh) {
+			put_unused_buffer_head(bh);
+			nr_buffer_heads++;
+			return;
+		}
 
 		/*
 		 * Uhhuh. We're _really_ low on memory. Now we just
@@ -1030,10 +947,6 @@
 		sleep_on(&buffer_wait);
 	}
 
-	for (nr_buffer_heads+=i=PAGE_SIZE/sizeof*bh ; i>0; i--) {
-		bh->b_next_free = unused_list;	/* only make link */
-		unused_list = bh++;
-	}
 }
 
 /* 
@@ -1076,6 +989,7 @@
 		return NULL;
 	bh = unused_list;
 	unused_list = bh->b_next_free;
+	nr_unused_buffer_heads--;
 	return bh;
 }
 
@@ -1401,7 +1315,6 @@
 
 	tmp = bh;
 	while (1) {
-		nr_free[isize]++;
 		if (insert_point) {
 			tmp->b_next_free = insert_point->b_next_free;
 			tmp->b_prev_free = insert_point;
@@ -1413,7 +1326,6 @@
 		}
 		insert_point = tmp;
 		++nr_buffers;
-		++nr_buffers_size[isize];
 		if (tmp->b_this_page)
 			tmp = tmp->b_this_page;
 		else
@@ -1443,7 +1355,6 @@
 {
 	unsigned long page;
 	struct buffer_head * tmp, * p;
-	int isize = BUFSIZE_INDEX(bh->b_size);
 
 	*bhp = bh;
 	page = (unsigned long) bh->b_data;
@@ -1465,7 +1376,6 @@
 		p = tmp;
 		tmp = tmp->b_this_page;
 		nr_buffers--;
-		nr_buffers_size[isize]--;
 		if (p == *bhp)
 		  {
 		    *bhp = p->b_prev_free;
@@ -1481,177 +1391,6 @@
 	return !mem_map[MAP_NR(page)].count;
 }
 
-/* Age buffers on a given page, according to whether they have been
-   visited recently or not. */
-static inline void age_buffer(struct buffer_head *bh)
-{
-	struct buffer_head *tmp = bh;
-	int touched = 0;
-
-	/*
-	 * When we age a page, we mark all other buffers in the page
-	 * with the "has_aged" flag.  Then, when these aliased buffers
-	 * come up for aging, we skip them until next pass.  This
-	 * ensures that a page full of multiple buffers only gets aged
-	 * once per pass through the lru lists. 
-	 */
-	if (clear_bit(BH_Has_aged, &bh->b_state))
-		return;
-	
-	do {
-		touched |= clear_bit(BH_Touched, &tmp->b_state);
-		tmp = tmp->b_this_page;
-		set_bit(BH_Has_aged, &tmp->b_state);
-	} while (tmp != bh);
-	clear_bit(BH_Has_aged, &bh->b_state);
-
-	if (touched) 
-		touch_page(mem_map + MAP_NR((unsigned long) bh->b_data));
-	else
-		age_page(mem_map + MAP_NR((unsigned long) bh->b_data));
-}
-
-/*
- * Consult the load average for buffers and decide whether or not
- * we should shrink the buffers of one size or not.  If we decide yes,
- * do it and return 1.  Else return 0.  Do not attempt to shrink size
- * that is specified.
- *
- * I would prefer not to use a load average, but the way things are now it
- * seems unavoidable.  The way to get rid of it would be to force clustering
- * universally, so that when we reclaim buffers we always reclaim an entire
- * page.  Doing this would mean that we all need to move towards QMAGIC.
- */
-
-static int maybe_shrink_lav_buffers(int size)
-{	   
-	int nlist;
-	int isize;
-	int total_lav, total_n_buffers, n_sizes;
-	
-	/* Do not consider the shared buffers since they would not tend
-	   to have getblk called very often, and this would throw off
-	   the lav.  They are not easily reclaimable anyway (let the swapper
-	   make the first move). */
-  
-	total_lav = total_n_buffers = n_sizes = 0;
-	for(nlist = 0; nlist < NR_SIZES; nlist++)
-	 {
-		 total_lav += buffers_lav[nlist];
-		 if(nr_buffers_size[nlist]) n_sizes++;
-		 total_n_buffers += nr_buffers_size[nlist];
-		 total_n_buffers -= nr_buffers_st[nlist][BUF_SHARED]; 
-	 }
-	
-	/* See if we have an excessive number of buffers of a particular
-	   size - if so, victimize that bunch. */
-  
-	isize = (size ? BUFSIZE_INDEX(size) : -1);
-	
-	if (n_sizes > 1)
-		 for(nlist = 0; nlist < NR_SIZES; nlist++)
-		  {
-			  if(nlist == isize) continue;
-			  if(nr_buffers_size[nlist] &&
-			     bdf_prm.b_un.lav_const * buffers_lav[nlist]*total_n_buffers < 
-			     total_lav * (nr_buffers_size[nlist] - nr_buffers_st[nlist][BUF_SHARED]))
-				   if(shrink_specific_buffers(6, bufferindex_size[nlist])) 
-					    return 1;
-		  }
-	return 0;
-}
-
-/*
- * Try to free up some pages by shrinking the buffer-cache
- *
- * Priority tells the routine how hard to try to shrink the
- * buffers: 6 means "don't bother too much", while a value
- * of 0 means "we'd better get some free pages now".
- *
- * "limit" is meant to limit the shrink-action only to pages
- * that are in the 0 - limit address range, for DMA re-allocations.
- * We ignore that right now.
- */
-
-static int shrink_specific_buffers(unsigned int priority, int size)
-{
-	struct buffer_head *bh;
-	int nlist;
-	int i, isize, isize1;
-
-#ifdef DEBUG
-	if(size) printk("Shrinking buffers of size %d\n", size);
-#endif
-	/* First try the free lists, and see if we can get a complete page
-	   from here */
-	isize1 = (size ? BUFSIZE_INDEX(size) : -1);
-
-	for(isize = 0; isize<NR_SIZES; isize++){
-		if(isize1 != -1 && isize1 != isize) continue;
-		bh = free_list[isize];
-		if(!bh) continue;
-		for (i=0 ; !i || bh != free_list[isize]; bh = bh->b_next_free, i++) {
-			if (bh->b_count || buffer_protected(bh) ||
-			    !bh->b_this_page)
-				 continue;
-			if (!age_of((unsigned long) bh->b_data) &&
-			    try_to_free_buffer(bh, &bh, 6))
-				 return 1;
-			if(!bh) break;
-			/* Some interrupt must have used it after we
-			   freed the page.  No big deal - keep looking */
-		}
-	}
-	
-	/* Not enough in the free lists, now try the lru list */
-	
-	for(nlist = 0; nlist < NR_LIST; nlist++) {
-	repeat1:
-		if(priority > 2 && nlist == BUF_SHARED) continue;
-		i = nr_buffers_type[nlist];
-		i = ((BUFFEROUT_WEIGHT * i) >> 10) >> priority;
-		for ( ; i > 0; i-- ) {
-			bh = next_to_age[nlist];
-			if (!bh)
-				break;
-			next_to_age[nlist] = bh->b_next_free;
-
-			/* First, age the buffer. */
-			age_buffer(bh);
-			/* We may have stalled while waiting for I/O
-			   to complete. */
-			if(bh->b_list != nlist) goto repeat1;
-			if (bh->b_count || buffer_protected(bh) ||
-			    !bh->b_this_page)
-				 continue;
-			if(size && bh->b_size != size) continue;
-			if (buffer_locked(bh))
-				 if (priority)
-					  continue;
-				 else
-					  wait_on_buffer(bh);
-			if (buffer_dirty(bh)) {
-				bh->b_count++;
-				bh->b_flushtime = 0;
-				ll_rw_block(WRITEA, 1, &bh);
-				bh->b_count--;
-				continue;
-			}
-			/* At priority 6, only consider really old
-			   (age==0) buffers for reclaiming.  At
-			   priority 0, consider any buffers. */
-			if ((age_of((unsigned long) bh->b_data) >>
-			     (6-priority)) > 0)
-				continue;				
-			if (try_to_free_buffer(bh, &bh, 0))
-				 return 1;
-			if(!bh) break;
-		}
-	}
-	return 0;
-}
-
-
 /* ================== Debugging =================== */
 
 void show_buffers(void)
@@ -1659,17 +1398,18 @@
 	struct buffer_head * bh;
 	int found = 0, locked = 0, dirty = 0, used = 0, lastused = 0;
 	int protected = 0;
-	int shared;
-	int nlist, isize;
+	int nlist;
+	static char *buf_types[NR_LIST] = {"CLEAN","LOCKED","LOCKED1","DIRTY"};
 
 	printk("Buffer memory:   %6dkB\n",buffermem>>10);
 	printk("Buffer heads:    %6d\n",nr_buffer_heads);
 	printk("Buffer blocks:   %6d\n",nr_buffers);
 
 	for(nlist = 0; nlist < NR_LIST; nlist++) {
-	  shared = found = locked = dirty = used = lastused = protected = 0;
+	  found = locked = dirty = used = lastused = protected = 0;
 	  bh = lru_list[nlist];
 	  if(!bh) continue;
+
 	  do {
 		found++;
 		if (buffer_locked(bh))
@@ -1678,260 +1418,32 @@
 			protected++;
 		if (buffer_dirty(bh))
 			dirty++;
-		if (mem_map[MAP_NR(((unsigned long) bh->b_data))].count != 1)
-			shared++;
 		if (bh->b_count)
 			used++, lastused = found;
 		bh = bh->b_next_free;
 	  } while (bh != lru_list[nlist]);
-	  printk("Buffer[%d] mem: %d buffers, %d used (last=%d), "
-		 "%d locked, %d protected, %d dirty %d shrd\n",
-		 nlist, found, used, lastused,
-		 locked, protected, dirty, shared);
+	  printk("%8s: %d buffers, %d used (last=%d), "
+		 "%d locked, %d protected, %d dirty\n",
+		 buf_types[nlist], found, used, lastused,
+		 locked, protected, dirty);
 	};
-	printk("Size    [LAV]     Free  Clean  Unshar     Lck    Lck1   Dirty  Shared \n");
-	for(isize = 0; isize<NR_SIZES; isize++){
-		printk("%5d [%5d]: %7d ", bufferindex_size[isize],
-		       buffers_lav[isize], nr_free[isize]);
-		for(nlist = 0; nlist < NR_LIST; nlist++)
-			 printk("%7d ", nr_buffers_st[isize][nlist]);
-		printk("\n");
-	}
 }
 
 
-/* ====================== Cluster patches for ext2 ==================== */
-
-/*
- * try_to_reassign() checks if all the buffers on this particular page
- * are unused, and reassign to a new cluster them if this is true.
- */
-static inline int try_to_reassign(struct buffer_head * bh, struct buffer_head ** bhp,
-			   kdev_t dev, unsigned int starting_block)
-{
-	unsigned long page;
-	struct buffer_head * tmp, * p;
-
-	*bhp = bh;
-	page = (unsigned long) bh->b_data;
-	page &= PAGE_MASK;
-	if(mem_map[MAP_NR(page)].count != 1) return 0;
-	tmp = bh;
-	do {
-		if (!tmp)
-			 return 0;
-		
-		if (tmp->b_count || buffer_protected(tmp) ||
-		    buffer_dirty(tmp) || buffer_locked(tmp))
-			 return 0;
-		tmp = tmp->b_this_page;
-	} while (tmp != bh);
-	tmp = bh;
-	
-	while((unsigned long) tmp->b_data & (PAGE_SIZE - 1)) 
-		 tmp = tmp->b_this_page;
-	
-	/* This is the buffer at the head of the page */
-	bh = tmp;
-	do {
-		p = tmp;
-		tmp = tmp->b_this_page;
-		remove_from_queues(p);
-		p->b_dev = dev;
-		mark_buffer_uptodate(p, 0);
-		clear_bit(BH_Req, &p->b_state);
-		p->b_blocknr = starting_block++;
-		insert_into_queues(p);
-	} while (tmp != bh);
-	return 1;
-}
-
-/*
- * Try to find a free cluster by locating a page where
- * all of the buffers are unused.  We would like this function
- * to be atomic, so we do not call anything that might cause
- * the process to sleep.  The priority is somewhat similar to
- * the priority used in shrink_buffers.
- * 
- * My thinking is that the kernel should end up using whole
- * pages for the buffer cache as much of the time as possible.
- * This way the other buffers on a particular page are likely
- * to be very near each other on the free list, and we will not
- * be expiring data prematurely.  For now we only cannibalize buffers
- * of the same size to keep the code simpler.
- */
-static int reassign_cluster(kdev_t dev, 
-		     unsigned int starting_block, int size)
-{
-	struct buffer_head *bh;
-	int isize = BUFSIZE_INDEX(size);
-	int i;
-
-	/* We want to give ourselves a really good shot at generating
-	   a cluster, and since we only take buffers from the free
-	   list, we "overfill" it a little. */
-
-	while(nr_free[isize] < 32) refill_freelist(size);
-
-	bh = free_list[isize];
-	if(bh)
-		 for (i=0 ; !i || bh != free_list[isize] ; bh = bh->b_next_free, i++) {
-			 if (!bh->b_this_page)	continue;
-			 if (try_to_reassign(bh, &bh, dev, starting_block))
-				 return 4;
-		 }
-	return 0;
-}
-
-/* This function tries to generate a new cluster of buffers
- * from a new page in memory.  We should only do this if we have
- * not expanded the buffer cache to the maximum size that we allow.
- */
-static unsigned long try_to_generate_cluster(kdev_t dev, int block, int size)
-{
-	struct buffer_head * bh, * tmp, * arr[MAX_BUF_PER_PAGE];
-	int isize = BUFSIZE_INDEX(size);
-	unsigned long offset;
-	unsigned long page;
-	int nblock;
-
-	page = get_free_page(GFP_NOBUFFER);
-	if(!page) return 0;
-
-	bh = create_buffers(page, size);
-	if (!bh) {
-		free_page(page);
-		return 0;
-	};
-	nblock = block;
-	for (offset = 0 ; offset < PAGE_SIZE ; offset += size) {
-		if (find_buffer(dev, nblock++, size))
-			 goto not_aligned;
-	}
-	tmp = bh;
-	nblock = 0;
-	while (1) {
-		arr[nblock++] = bh;
-		bh->b_count = 1;
-		bh->b_flushtime = 0;
-		bh->b_state = 0;
-		bh->b_dev = dev;
-		bh->b_list = BUF_CLEAN;
-		bh->b_blocknr = block++;
-		nr_buffers++;
-		nr_buffers_size[isize]++;
-		insert_into_queues(bh);
-		if (bh->b_this_page)
-			bh = bh->b_this_page;
-		else
-			break;
-	}
-	buffermem += PAGE_SIZE;
-	mem_map[MAP_NR(page)].buffers = bh;
-	bh->b_this_page = tmp;
-	while (nblock-- > 0)
-		brelse(arr[nblock]);
-	return 4; /* ?? */
-not_aligned:
-	while ((tmp = bh) != NULL) {
-		bh = bh->b_this_page;
-		put_unused_buffer_head(tmp);
-	}
-	free_page(page);
-	return 0;
-}
-
-unsigned long generate_cluster(kdev_t dev, int b[], int size)
-{
-	int i, offset;
-	
-	for (i = 0, offset = 0 ; offset < PAGE_SIZE ; i++, offset += size) {
-		if(i && b[i]-1 != b[i-1]) return 0;  /* No need to cluster */
-		if(find_buffer(dev, b[i], size)) return 0;
-	};
-
-	/* OK, we have a candidate for a new cluster */
-	
-	/* See if one size of buffer is over-represented in the buffer cache,
-	   if so reduce the numbers of buffers */
-	if(maybe_shrink_lav_buffers(size))
-	 {
-		 int retval;
-		 retval = try_to_generate_cluster(dev, b[0], size);
-		 if(retval) return retval;
-	 };
-	
-	if (nr_free_pages > min_free_pages*2) 
-		 return try_to_generate_cluster(dev, b[0], size);
-	else
-		 return reassign_cluster(dev, b[0], size);
-}
-
-unsigned long generate_cluster_swab32(kdev_t dev, int b[], int size)
-{
-	int i, offset;
-	
-	for (i = 0, offset = 0 ; offset < PAGE_SIZE ; i++, offset += size) {
-		if(i && le32_to_cpu(b[i])-1 !=
-		   le32_to_cpu(b[i-1])) return 0;  /* No need to cluster */
-		if(find_buffer(dev, le32_to_cpu(b[i]), size)) return 0;
-	};
-
-	/* OK, we have a candidate for a new cluster */
-	
-	/* See if one size of buffer is over-represented in the buffer cache,
-	   if so reduce the numbers of buffers */
-	if(maybe_shrink_lav_buffers(size))
-	 {
-		 int retval;
-		 retval = try_to_generate_cluster(dev, le32_to_cpu(b[0]), size);
-		 if(retval) return retval;
-	 };
-	
-	if (nr_free_pages > min_free_pages*2) 
-		 return try_to_generate_cluster(dev, le32_to_cpu(b[0]), size);
-	else
-		 return reassign_cluster(dev, le32_to_cpu(b[0]), size);
-}
-
 /* ===================== Init ======================= */
 
 /*
- * This initializes the initial buffer free list.  nr_buffers_type is set
- * to one less the actual number of buffers, as a sop to backwards
- * compatibility --- the old code did this (I think unintentionally,
- * but I'm not sure), and programs in the ps package expect it.
- * 					- TYT 8/30/92
+ * allocate the hash table and init the free list
  */
 void buffer_init(void)
 {
-	int i;
-	int isize = BUFSIZE_INDEX(BLOCK_SIZE);
-	long memsize = num_physpages << PAGE_SHIFT;
-
-	if (memsize >= 64*1024*1024)
-		nr_hash = 65521;
-	else if (memsize >= 32*1024*1024)
-		nr_hash = 32749;
-	else if (memsize >= 16*1024*1024)
-		nr_hash = 16381;
-	else if (memsize >= 8*1024*1024)
-		nr_hash = 8191;
-	else if (memsize >= 4*1024*1024)
-		nr_hash = 4093;
-	else nr_hash = 997;
-	
-	hash_table = (struct buffer_head **) vmalloc(nr_hash * 
-						     sizeof(struct buffer_head *));
-
+	hash_table = (struct buffer_head **)vmalloc(NR_HASH*sizeof(struct buffer_head *));
+	if (!hash_table)
+		panic("Failed to allocate buffer hash table\n");
+	memset(hash_table,0,NR_HASH*sizeof(struct buffer_head *));
 
-	for (i = 0 ; i < nr_hash ; i++)
-		hash_table[i] = NULL;
 	lru_list[BUF_CLEAN] = 0;
 	grow_buffers(GFP_KERNEL, BLOCK_SIZE);
-	if (!free_list[isize])
-		panic("VFS: Unable to initialize buffer free list!");
-	return;
 }
 
 
@@ -1967,7 +1479,7 @@
 
 asmlinkage int sync_old_buffers(void)
 {
-	int i, isize;
+	int i;
 	int ndirty, nwritten;
 	int nlist;
 	int ncount;
@@ -2023,13 +1535,6 @@
 	printk("Wrote %d/%d buffers\n", nwritten, ndirty);
 #endif
 	
-	/* We assume that we only come through here on a regular
-	   schedule, like every 5 seconds.  Now update load averages.  
-	   Shift usage counts to prevent overflow. */
-	for(isize = 0; isize<NR_SIZES; isize++){
-		CALC_LOAD(buffers_lav[isize], bdf_prm.b_un.lav_const, buffer_usage[isize]);
-		buffer_usage[isize] = 0;
-	}
 	return 0;
 }
 
@@ -2194,8 +1699,7 @@
 		/* If there are still a lot of dirty buffers around, skip the sleep
 		   and flush some more */
 		
-		if(nr_buffers_type[BUF_DIRTY] <= (nr_buffers - nr_buffers_type[BUF_SHARED]) * 
-		   bdf_prm.b_un.nfract/100) {
+		if(nr_buffers_type[BUF_DIRTY] <= nr_buffers * bdf_prm.b_un.nfract/100) {
 			current->signal = 0;
 			interruptible_sleep_on(&bdflush_wait);
 		}
diff -u --recursive --new-file v2.1.17/linux/fs/dcache.c linux/fs/dcache.c
--- v2.1.17/linux/fs/dcache.c	Sun Mar 24 12:09:36 1996
+++ linux/fs/dcache.c	Mon Dec 23 10:08:12 1996
@@ -27,7 +27,7 @@
  * to be short.
  */
 #define DCACHE_NAME_LEN	15
-#define DCACHE_SIZE 128
+#define DCACHE_SIZE 1024
 
 struct hash_list {
 	struct dir_cache_entry * next;
diff -u --recursive --new-file v2.1.17/linux/fs/ext/inode.c linux/fs/ext/inode.c
--- v2.1.17/linux/fs/ext/inode.c	Tue Oct 29 19:58:20 1996
+++ linux/fs/ext/inode.c	Fri Dec 27 12:03:25 1996
@@ -46,7 +46,7 @@
 	return;
 }
 
-static struct super_operations ext_sops = { 
+static struct super_operations ext_sops = {
 	ext_read_inode,
 	NULL,
 	ext_write_inode,
@@ -57,7 +57,7 @@
 	NULL
 };
 
-struct super_block *ext_read_super(struct super_block *s,void *data, 
+struct super_block *ext_read_super(struct super_block *s,void *data,
 				   int silent)
 {
 	struct buffer_head *bh;
@@ -346,7 +346,7 @@
 	struct buffer_head * bh;
 
 	bh = ext_getblk(inode,block,create);
-	if (!bh || buffer_uptodate(bh)) 
+	if (!bh || buffer_uptodate(bh))
 		return bh;
 	ll_rw_block(READ, 1, &bh);
 	wait_on_buffer(bh);
@@ -462,13 +462,11 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-	int status;
-
-	if ((status = init_ext_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_ext_fs();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.1.17/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v2.1.17/linux/fs/ext2/inode.c	Fri Nov 15 23:49:09 1996
+++ linux/fs/ext2/inode.c	Sun Dec 22 16:16:53 1996
@@ -329,42 +329,6 @@
 	return result;
 }
 
-static int block_getcluster (struct inode * inode, struct buffer_head * bh,
-					  int nr,
-					  int blocksize)
-{
-	u32 * p;
-	int firstblock = 0;
-	int result = 0;
-	int i;
-
-	/* Check to see if clustering possible here. */
-
-	if(!bh) return 0;
-
-	if((nr & ((PAGE_SIZE >> EXT2_BLOCK_SIZE_BITS(inode->i_sb)) - 1)) != 0)
-		goto out;
-	if(nr + 3 > EXT2_ADDR_PER_BLOCK(inode->i_sb)) goto out;
-
-	for(i=0; i< (PAGE_SIZE >> EXT2_BLOCK_SIZE_BITS(inode->i_sb)); i++) {
-	  p = (u32 *) bh->b_data + nr + i;
-	  
-	  /* All blocks in cluster must already be allocated */
-	  if(le32_to_cpu(*p) == 0) goto out;
-	  
-	  /* See if aligned correctly */
-	  if(i==0) firstblock = le32_to_cpu(*p);
-	  else if(le32_to_cpu(*p) != firstblock + i) goto out;
-	}
-	
-	p = (u32 *) bh->b_data + nr;
-	result = generate_cluster_swab32(bh->b_dev, (int *) p, blocksize);
-
-      out:
-	brelse(bh);
-	return result;
-}
-
 struct buffer_head * ext2_getblk (struct inode * inode, long block,
 				  int create, int * err)
 {
@@ -425,56 +389,6 @@
 			   create, inode->i_sb->s_blocksize, b, err);
 	return block_getblk (inode, bh, block & (addr_per_block - 1), create,
 			     inode->i_sb->s_blocksize, b, err);
-}
-
-int ext2_getcluster (struct inode * inode, long block)
-{
-	struct buffer_head * bh;
-	int err, create;
-	unsigned long b;
-	unsigned long addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
-	int addr_per_block_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb);
-
-	create = 0;
-	err = -EIO;
-	if (block < 0) {
-		ext2_warning (inode->i_sb, "ext2_getblk", "block < 0");
-		return 0;
-	}
-	if (block > EXT2_NDIR_BLOCKS + addr_per_block +
-		(1 << (addr_per_block_bits * 2)) +
-		((1 << (addr_per_block_bits * 2)) << addr_per_block_bits)) {
-		ext2_warning (inode->i_sb, "ext2_getblk", "block > big");
-		return 0;
-	}
-
-	err = -ENOSPC;
-	b = block;
-	if (block < EXT2_NDIR_BLOCKS) return 0;
-
-	block -= EXT2_NDIR_BLOCKS;
-
-	if (block < addr_per_block) {
-		bh = inode_getblk (inode, EXT2_IND_BLOCK, create, b, &err);
-		return block_getcluster (inode, bh, block, 
-					 inode->i_sb->s_blocksize);
-	}
-	block -= addr_per_block;
-	if (block < (1 << (addr_per_block_bits * 2))) {
-		bh = inode_getblk (inode, EXT2_DIND_BLOCK, create, b, &err);
-		bh = block_getblk (inode, bh, block >> addr_per_block_bits,
-				   create, inode->i_sb->s_blocksize, b, &err);
-		return block_getcluster (inode, bh, block & (addr_per_block - 1),
-				     inode->i_sb->s_blocksize);
-	}
-	block -= (1 << (addr_per_block_bits * 2));
-	bh = inode_getblk (inode, EXT2_TIND_BLOCK, create, b, &err);
-	bh = block_getblk (inode, bh, block >> (addr_per_block_bits * 2),
-			   create, inode->i_sb->s_blocksize, b, &err);
-	bh = block_getblk (inode, bh, (block >> addr_per_block_bits) & (addr_per_block - 1),
-			   create, inode->i_sb->s_blocksize, b, &err);
-	return block_getcluster (inode, bh, block & (addr_per_block - 1),
-				 inode->i_sb->s_blocksize);
 }
 
 struct buffer_head * ext2_bread (struct inode * inode, int block, 
diff -u --recursive --new-file v2.1.17/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.1.17/linux/fs/ext2/super.c	Fri Nov 15 23:49:10 1996
+++ linux/fs/ext2/super.c	Fri Dec 27 12:03:25 1996
@@ -129,7 +129,7 @@
 	return;
 }
 
-static struct super_operations ext2_sops = { 
+static struct super_operations ext2_sops = {
 	ext2_read_inode,
 	NULL,
 	ext2_write_inode,
@@ -421,22 +421,22 @@
 	if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV) {
 		if (le32_to_cpu(es->s_feature_incompat) & ~EXT2_FEATURE_INCOMPAT_SUPP) {
 			printk("EXT2-fs: %s: couldn't mount because of "
-			       "unsupported optional features.\n", 
+			       "unsupported optional features.\n",
 			       kdevname(dev));
 			goto failed_mount;
 		}
 		if (!(sb->s_flags & MS_RDONLY) &&
 		    (le32_to_cpu(es->s_feature_ro_compat) & ~EXT2_FEATURE_RO_COMPAT_SUPP)) {
 			printk("EXT2-fs: %s: couldn't mount RDWR because of "
-			       "unsupported optional features.\n", 
+			       "unsupported optional features.\n",
 			       kdevname(dev));
 			goto failed_mount;
 		}
 	}
 	sb->s_blocksize_bits = le32_to_cpu(sb->u.ext2_sb.s_es->s_log_block_size) + 10;
 	sb->s_blocksize = 1 << sb->s_blocksize_bits;
-	if (sb->s_blocksize != BLOCK_SIZE && 
-	    (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||  
+	if (sb->s_blocksize != BLOCK_SIZE &&
+	    (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||
 	     sb->s_blocksize == 4096)) {
 		unsigned long offset;
 
@@ -675,7 +675,7 @@
 	else {
 		/*
 		 * Mounting a RDONLY partition read-write, so reread and
-		 * store the current valid flag.  (It may have been changed 
+		 * store the current valid flag.  (It may have been changed
 		 * by e2fsck since we originally mounted the partition.)
 		 */
 		sb->u.ext2_sb.s_mount_state = le16_to_cpu(es->s_state);
@@ -695,13 +695,11 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-	int status;
-
-	if ((status = init_ext2_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_ext2_fs();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.1.17/linux/fs/fat/fatfs_syms.c linux/fs/fat/fatfs_syms.c
--- v2.1.17/linux/fs/fat/fatfs_syms.c	Tue Mar  5 13:03:26 1996
+++ linux/fs/fat/fatfs_syms.c	Fri Dec 27 12:03:25 1996
@@ -14,45 +14,40 @@
 
 extern struct file_operations fat_dir_operations;
 
-static struct symbol_table fat_syms = {
-#include <linux/symtab_begin.h>
-	X(fat_a2alias),
-	X(fat_a2uni),
-	X(fat_add_cluster),
-	X(fat_bmap),
-	X(fat_brelse),
-	X(fat_cache_inval_inode),
-	X(fat_code2uni),
-	X(fat_date_unix2dos),
-	X(fat_dir_operations),
-	X(fat_file_read),
-	X(fat_file_write),
-	X(fat_fs_panic),
-	X(fat_get_entry),
-	X(fat_lock_creation),
-	X(fat_mark_buffer_dirty),
-	X(fat_mmap),
-	X(fat_notify_change),
-	X(fat_parent_ino),
-	X(fat_put_inode),
-	X(fat_put_super),
-	X(fat_read_inode),
-	X(fat_read_super),
-	X(fat_readdirx),
-	X(fat_readdir),
-	X(fat_scan),
-	X(fat_smap),
-	X(fat_statfs),
-	X(fat_truncate),
-	X(fat_uni2asc_pg),
-	X(fat_uni2code),
-	X(fat_unlock_creation),
-	X(fat_write_inode),
-#include <linux/symtab_end.h>
-};                                           
+EXPORT_SYMBOL(fat_a2alias);
+EXPORT_SYMBOL(fat_a2uni);
+EXPORT_SYMBOL(fat_add_cluster);
+EXPORT_SYMBOL(fat_bmap);
+EXPORT_SYMBOL(fat_brelse);
+EXPORT_SYMBOL(fat_cache_inval_inode);
+EXPORT_SYMBOL(fat_code2uni);
+EXPORT_SYMBOL(fat_date_unix2dos);
+EXPORT_SYMBOL(fat_dir_operations);
+EXPORT_SYMBOL(fat_file_read);
+EXPORT_SYMBOL(fat_file_write);
+EXPORT_SYMBOL(fat_fs_panic);
+EXPORT_SYMBOL(fat_get_entry);
+EXPORT_SYMBOL(fat_lock_creation);
+EXPORT_SYMBOL(fat_mark_buffer_dirty);
+EXPORT_SYMBOL(fat_mmap);
+EXPORT_SYMBOL(fat_notify_change);
+EXPORT_SYMBOL(fat_parent_ino);
+EXPORT_SYMBOL(fat_put_inode);
+EXPORT_SYMBOL(fat_put_super);
+EXPORT_SYMBOL(fat_read_inode);
+EXPORT_SYMBOL(fat_read_super);
+EXPORT_SYMBOL(fat_readdirx);
+EXPORT_SYMBOL(fat_readdir);
+EXPORT_SYMBOL(fat_scan);
+EXPORT_SYMBOL(fat_smap);
+EXPORT_SYMBOL(fat_statfs);
+EXPORT_SYMBOL(fat_truncate);
+EXPORT_SYMBOL(fat_uni2asc_pg);
+EXPORT_SYMBOL(fat_uni2code);
+EXPORT_SYMBOL(fat_unlock_creation);
+EXPORT_SYMBOL(fat_write_inode);
 
 int init_fat_fs(void)
 {
-	return register_symtab(&fat_syms);
+	return 0;
 }
-
diff -u --recursive --new-file v2.1.17/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c
--- v2.1.17/linux/fs/hpfs/hpfs_fs.c	Tue Oct 29 19:58:42 1996
+++ linux/fs/hpfs/hpfs_fs.c	Fri Dec 27 12:03:25 1996
@@ -29,7 +29,7 @@
 #include "hpfs.h"
 #include "hpfs_caps.h"
 
-/* 
+/*
  * HPFS is a mixture of 512-byte blocks and 2048-byte blocks.  The 2k blocks
  * are used for directories and bitmaps.  For bmap to work, we must run the
  * file system with 512-byte blocks.  The 2k blocks are assembled in buffers
@@ -115,7 +115,7 @@
  * seen -- in fact noncontiguous files are seldom seen.  I think this is
  * partly the open() call that lets programs specify the length of an
  * output file when they know it, and partly because HPFS.IFS really is
- * very good at resisting fragmentation. 
+ * very good at resisting fragmentation.
  */
 
 /* notation */
@@ -298,7 +298,7 @@
 }
 
 /*
- * test for directory's inode number 
+ * test for directory's inode number
  */
 
 static inline int ino_is_dir(ino_t ino)
@@ -606,7 +606,7 @@
 			else
 				return 0;
 		}
-		else if (!strcmp(p,"nocheck")) 
+		else if (!strcmp(p,"nocheck"))
 			*nocheck=1;
 		else
 			return 1;
@@ -1043,7 +1043,7 @@
  * Search allocation tree *b for the given file sector number and return
  * the disk sector number.  Buffer *bhp has the tree in it, and can be
  * reused for subtrees when access to *b is no longer needed.
- * *bhp is busy on entry and exit. 
+ * *bhp is busy on entry and exit.
  */
 
 static secno bplus_lookup(struct inode *inode, struct bplus_header *b,
@@ -1342,7 +1342,7 @@
  *     0 => .   -1 => ..   1 1.1 ... 8.9 9 => files  -2 => eof
  *
  * The directory inode caches one position-to-dnode correspondence so
- * we won't have to repeatedly scan the top levels of the tree. 
+ * we won't have to repeatedly scan the top levels of the tree.
  */
 
 /*
@@ -1427,7 +1427,7 @@
 
 /*
  * Map the dir entry at subtree coordinates given by *posp, and
- * increment *posp to point to the following dir entry. 
+ * increment *posp to point to the following dir entry.
  */
 
 static struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp,
@@ -1754,13 +1754,11 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-	int status;
-
-	if ((status = init_hpfs_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_hpfs_fs();
 }
 
 void cleanup_module(void)
@@ -1769,4 +1767,3 @@
 }
 
 #endif
-
diff -u --recursive --new-file v2.1.17/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.1.17/linux/fs/isofs/inode.c	Tue Oct 29 19:58:43 1996
+++ linux/fs/isofs/inode.c	Fri Dec 27 12:03:25 1996
@@ -1,6 +1,6 @@
 /*
  *  linux/fs/isofs/inode.c
- * 
+ *
  *  (C) 1991  Linus Torvalds - minix filesystem
  *      1992, 1993, 1994  Eric Youngdale Modified for ISO9660 filesystem.
  *      1994  Eberhard Moenkeberg - multi session handling.
@@ -41,7 +41,7 @@
 	lock_super(sb);
 
 #ifdef LEAK_CHECK
-	printk("Outstanding mallocs:%d, outstanding buffers: %d\n", 
+	printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
 	       check_malloc, check_bread);
 #endif
 	sb->s_dev = 0;
@@ -50,7 +50,7 @@
 	return;
 }
 
-static struct super_operations isofs_sops = { 
+static struct super_operations isofs_sops = {
 	isofs_read_inode,
 	NULL,			/* notify_change */
 	NULL,			/* write_inode */
@@ -127,7 +127,7 @@
 			else if (!strcmp(value,"auto")) popt->conversion = 'a';
 			else return 0;
 		}
-		else if (value && 
+		else if (value &&
 			 (!strcmp(this_char,"block") ||
 			  !strcmp(this_char,"mode") ||
 			  !strcmp(this_char,"uid") ||
@@ -143,8 +143,8 @@
 		  if (*vpnt) return 0;
 		  switch(*this_char) {
 		  case 'b':
-		    if (   ivalue != 512 
-			&& ivalue != 1024 
+		    if (   ivalue != 512
+			&& ivalue != 1024
 			&& ivalue != 2048) return 0;
 		    popt->blocksize = ivalue;
 		    break;
@@ -177,7 +177,7 @@
  *
  * A broken CDwriter software or drive firmware does not set new standards,
  * at least not if conflicting with the existing ones.
- * 
+ *
  * emoenke@gwdg.de
  */
 #define WE_OBEY_THE_WRITTEN_STANDARDS 1
@@ -201,7 +201,7 @@
 				       CDROMMULTISESSION,
 				       (unsigned long) &ms_info);
       set_fs(USER_DS);
-#if 0 
+#if 0
       printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
       if (i==0)
 	{
@@ -258,7 +258,7 @@
 	printk("gid = %d\n", opt.gid);
 	printk("uid = %d\n", opt.uid);
 #endif
-	
+
 	blocksize_bits = 0;
 	{
 	  int i = opt.blocksize;
@@ -274,7 +274,7 @@
 	s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
 
 	vol_desc_start = isofs_get_last_session(dev);
-	
+
 	for (iso_blknum = vol_desc_start+16;
              iso_blknum < vol_desc_start+100; iso_blknum++) {
                 int b = iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits);
@@ -292,26 +292,26 @@
 		vdp = (struct iso_volume_descriptor *)bh->b_data;
 		hdp = (struct hs_volume_descriptor *)bh->b_data;
 
-		
+
 		if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
 		  if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
 			goto out;
 		  if (isonum_711 (hdp->type) == ISO_VD_END)
 		        goto out;
-		
+
 		        s->u.isofs_sb.s_high_sierra = 1;
 			high_sierra = 1;
 		        opt.rock = 'n';
 		        h_pri = (struct hs_primary_descriptor *)vdp;
 			break;
 		}
-		
+
 		if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
 		  if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
 			goto out;
 		  if (isonum_711 (vdp->type) == ISO_VD_END)
 			goto out;
-		
+
 		        pri = (struct iso_primary_descriptor *)vdp;
 			break;
 	        }
@@ -326,7 +326,7 @@
 		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
-	
+
 	if(high_sierra){
 	  rootp = (struct iso_directory_record *) h_pri->root_directory_record;
 #ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
@@ -350,9 +350,9 @@
 	  s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
 	  s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
 	}
-	
+
 	s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */
-	
+
 	/* RDE: convert log zone size to bit shift */
 
 	orig_zonesize = s -> u.isofs_sb.s_log_zone_size;
@@ -368,22 +368,22 @@
 
 	/* RDE: data zone now byte offset! */
 
-	s->u.isofs_sb.s_firstdatazone = ((isonum_733 (rootp->extent) + 
+	s->u.isofs_sb.s_firstdatazone = ((isonum_733 (rootp->extent) +
 					   isonum_711 (rootp->ext_attr_length))
 					 << s -> u.isofs_sb.s_log_zone_size);
 	s->s_magic = ISOFS_SUPER_MAGIC;
-	
+
 	/* The CDROM is read-only, has no nodes (devices) on it, and since
 	   all of the files appear to be owned by root, we really do not want
 	   to allow suid.  (suid or devices will not show up unless we have
 	   Rock Ridge extensions) */
-	
+
 	s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
-	
+
 	brelse(bh);
-	
+
 	printk(KERN_DEBUG "Max size:%ld   Log zone size:%ld\n",
-	       s->u.isofs_sb.s_max_size, 
+	       s->u.isofs_sb.s_max_size,
 	       1UL << s->u.isofs_sb.s_log_zone_size);
 	printk(KERN_DEBUG "First datazone:%ld   Root inode number %d\n",
 	       s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size,
@@ -392,7 +392,7 @@
 	if(high_sierra) printk(KERN_DEBUG "Disc in High Sierra format.\n");
 	unlock_super(s);
 	/* set up enough so that it can read an inode */
-	
+
 	/*
 	 * Force the blocksize to 512 for 512 byte sectors.  The file
 	 * read primitives really get it wrong in a bad way if we don't
@@ -430,7 +430,7 @@
 	s->u.isofs_sb.s_mode = opt.mode & 0777;
 	s->s_blocksize = opt.blocksize;
 	s->s_blocksize_bits = blocksize_bits;
-	s->s_mounted = iget(s, (isonum_733(rootp->extent) + 
+	s->s_mounted = iget(s, (isonum_733(rootp->extent) +
 			    isonum_711(rootp->ext_attr_length))
 				<< s -> u.isofs_sb.s_log_zone_size);
 	unlock_super(s);
@@ -507,7 +507,7 @@
 	  printk("unable to read i-node block");
 	  goto fail;
 	}
-	
+
 	pnt = ((unsigned char *) bh->b_data
 	       + (inode->i_ino & (bufsize - 1)));
 	raw_inode = ((struct iso_directory_record *) pnt);
@@ -552,7 +552,7 @@
 		for(i=0; i< raw_inode->name_len[0]; i++)
 			if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
 				break;
-		if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';') 
+		if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
 			inode->i_mode |= S_IXUGO; /* execute permission */
 	}
 	inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
@@ -571,12 +571,12 @@
    byte of the file length.  Catch this and holler.  WARNING: this will make
    it impossible for a file to be > 16Mb on the CDROM!!!*/
 
-	if(inode->i_sb->u.isofs_sb.s_cruft == 'y' && 
+	if(inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
 	   inode->i_size & 0xff000000){
 /*	  printk("Illegal format on cdrom.  Pester manufacturer.\n"); */
 	  inode->i_size &= 0x00ffffff;
 	}
-	
+
 	if (raw_inode->interleave[0]) {
 		printk("Interleaved files not (yet) supported.\n");
 		inode->i_size = 0;
@@ -598,17 +598,17 @@
 #endif
 
 #ifdef DEBUG
-	printk("Get inode %d: %d %d: %d\n",inode->i_ino, block, 
+	printk("Get inode %d: %d %d: %d\n",inode->i_ino, block,
 	       ((int)pnt) & 0x3ff, inode->i_size);
 #endif
-	
-	inode->i_mtime = inode->i_atime = inode->i_ctime = 
+
+	inode->i_mtime = inode->i_atime = inode->i_ctime =
 	  iso_date(raw_inode->date, high_sierra);
 
-	inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) + 
+	inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) +
 					   isonum_711 (raw_inode->ext_attr_length))
 	  << inode -> i_sb -> u.isofs_sb.s_log_zone_size;
-	
+
 	inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */
 	switch (inode->i_sb->u.isofs_sb.s_conversion){
 	case 'a':
@@ -633,31 +633,31 @@
 	  /* hmm..if we want uid or gid set, override the rock ridge setting */
 	 test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid);
 	}
-	
+
 #ifdef DEBUG
 	printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
 #endif
 	brelse(bh);
-	
+
 	inode->i_op = NULL;
 
 	/* get the volume sequence number */
 	volume_seq_no = isonum_723 (raw_inode->volume_sequence_number) ;
 
-	/* 
+	/*
 	 * Disable checking if we see any volume number other than 0 or 1.
 	 * We could use the cruft option, but that has multiple purposes, one
 	 * of which is limiting the file size to 16Mb.  Thus we silently allow
 	 * volume numbers of 0 to go through without complaining.
 	 */
-	if (inode->i_sb->u.isofs_sb.s_cruft == 'n' && 
+	if (inode->i_sb->u.isofs_sb.s_cruft == 'n' &&
 	    (volume_seq_no != 0) && (volume_seq_no != 1)) {
 	  printk("Warning: defective cdrom (volume sequence number). Enabling \"cruft\" mount option.\n");
 	  inode->i_sb->u.isofs_sb.s_cruft = 'y';
 	}
 
 #ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
-	if (inode->i_sb->u.isofs_sb.s_cruft != 'y' && 
+	if (inode->i_sb->u.isofs_sb.s_cruft != 'y' &&
 	    (volume_seq_no != 0) && (volume_seq_no != 1)) {
 		printk("Multi volume CD somehow got mounted.\n");
 	} else
@@ -725,31 +725,31 @@
 	int directory_size;
 	struct buffer_head * bh;
 	struct iso_directory_record * de;
-	
+
 	offset = 0;
 	block = extent << (ISOFS_ZONE_BITS(parent) - bufbits);
 	if (!(bh = bread(parent->i_dev, block, bufsize)))  return -1;
-	
+
 	while (1 == 1) {
 		de = (struct iso_directory_record *) (bh->b_data + offset);
-		if (*((unsigned char *) de) == 0) 
+		if (*((unsigned char *) de) == 0)
 		{
 			brelse(bh);
 			printk("Directory .. not found\n");
 			return -1;
 		}
-		
+
 		offset += *((unsigned char *) de);
 
-		if (offset >= bufsize) 
+		if (offset >= bufsize)
 		{
 			printk(".. Directory not in first block"
 			       " of directory.\n");
 			brelse(bh);
 			return -1;
 		}
-		
-		if (de->name_len[0] == 1 && de->name[0] == 1) 
+
+		if (de->name_len[0] == 1 && de->name[0] == 1)
 		{
 			parent_dir = find_rock_ridge_relocation(de, parent);
 			directory_size = isonum_733 (de->size);
@@ -761,7 +761,7 @@
 	printk("Parent dir:%x\n",parent_dir);
 #endif
 	/* Now we know the extent where the parent dir starts on. */
-	
+
 	result = -1;
 
 	offset = 0;
@@ -770,17 +770,17 @@
 	{
 		return -1;
 	}
-	
+
 	for(;;)
 	{
 		de = (struct iso_directory_record *) (bh->b_data + offset);
 		inode_number = (block << bufbits)+(offset & (bufsize - 1));
-		
+
 		/* If the length byte is zero, we should move on to the next
 		   CDROM sector.  If we are at the end of the directory, we
 		   kick out of the while loop. */
-		
-		if (*((unsigned char *) de) == 0) 
+
+		if (*((unsigned char *) de) == 0)
 		{
 			brelse(bh);
 			offset = 0;
@@ -802,7 +802,7 @@
 			}
 			continue;
 		}
-		
+
 		/* Make sure that the entire directory record is in the current
 		   bh block.  If not, we malloc a buffer, and put the two
 		   halves together, so that we can cleanly read the block.  */
@@ -821,7 +821,7 @@
 			brelse(bh);
 			offset -= bufsize;
  			directory_size -= bufsize;
-			if(directory_size < 0) 
+			if(directory_size < 0)
 			{
 				printk("Directory size < 0\n");
 				return -1;
@@ -833,12 +833,12 @@
 			}
  			memcpy((char *)cpnt+frag1, bh->b_data, offset);
 		}
-		
+
 		if (find_rock_ridge_relocation(de, parent) == extent){
 			result = inode_number;
 			goto out;
 		}
-		
+
 		if (cpnt) {
 			kfree(cpnt);
 			cpnt = NULL;
@@ -859,7 +859,7 @@
 #endif
 	return result;
 }
-    
+
 #ifdef LEAK_CHECK
 #undef malloc
 #undef free_s
@@ -900,13 +900,11 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-	int status;
-
-	if ((status = init_iso9660_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_iso9660_fs();
 }
 
 void cleanup_module(void)
@@ -915,4 +913,3 @@
 }
 
 #endif
-
diff -u --recursive --new-file v2.1.17/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.1.17/linux/fs/minix/inode.c	Sun Dec 22 16:37:38 1996
+++ linux/fs/minix/inode.c	Fri Dec 27 12:03:25 1996
@@ -74,7 +74,7 @@
 	return;
 }
 
-static struct super_operations minix_sops = { 
+static struct super_operations minix_sops = {
 	minix_read_inode,
 	NULL,
 	minix_write_inode,
@@ -163,7 +163,7 @@
 	return errmsg;
 }
 
-struct super_block *minix_read_super(struct super_block *s,void *data, 
+struct super_block *minix_read_super(struct super_block *s,void *data,
 				     int silent)
 {
 	struct buffer_head *bh;
@@ -441,7 +441,7 @@
 /*
  * The minix V1 fs getblk functions.
  */
-static struct buffer_head * V1_inode_getblk(struct inode * inode, int nr, 
+static struct buffer_head * V1_inode_getblk(struct inode * inode, int nr,
 					    int create)
 {
 	int tmp;
@@ -475,7 +475,7 @@
 	return result;
 }
 
-static struct buffer_head * V1_block_getblk(struct inode * inode, 
+static struct buffer_head * V1_block_getblk(struct inode * inode,
 	struct buffer_head * bh, int nr, int create)
 {
 	int tmp;
@@ -525,7 +525,7 @@
 	return result;
 }
 
-static struct buffer_head * V1_minix_getblk(struct inode * inode, int block, 
+static struct buffer_head * V1_minix_getblk(struct inode * inode, int block,
 					    int create)
 {
 	struct buffer_head * bh;
@@ -554,7 +554,7 @@
 /*
  * The minix V2 fs getblk functions.
  */
-static struct buffer_head * V2_inode_getblk(struct inode * inode, int nr, 
+static struct buffer_head * V2_inode_getblk(struct inode * inode, int nr,
 					    int create)
 {
 	int tmp;
@@ -588,7 +588,7 @@
 	return result;
 }
 
-static struct buffer_head * V2_block_getblk(struct inode * inode, 
+static struct buffer_head * V2_block_getblk(struct inode * inode,
 	struct buffer_head * bh, int nr, int create)
 {
 	int tmp;
@@ -638,7 +638,7 @@
 	return result;
 }
 
-static struct buffer_head * V2_minix_getblk(struct inode * inode, int block, 
+static struct buffer_head * V2_minix_getblk(struct inode * inode, int block,
 					    int create)
 {
 	struct buffer_head * bh;
@@ -952,13 +952,11 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-	int status;
-
-	if ((status = init_minix_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_minix_fs();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.1.17/linux/fs/msdos/msdosfs_syms.c linux/fs/msdos/msdosfs_syms.c
--- v2.1.17/linux/fs/msdos/msdosfs_syms.c	Thu Feb 15 09:21:30 1996
+++ linux/fs/msdos/msdosfs_syms.c	Fri Dec 27 12:03:25 1996
@@ -10,38 +10,29 @@
 #include <linux/mm.h>
 #include <linux/msdos_fs.h>
 
-static struct symbol_table msdos_syms = {
-#include <linux/symtab_begin.h>
-	/*
-	 * Support for umsdos fs
-	 *
-	 * These symbols are _always_ exported, in case someone
-	 * wants to install the umsdos module later.
-	 */
-  	X(msdos_create),
-  	X(msdos_lookup),
-  	X(msdos_mkdir),
-  	X(msdos_read_inode),
-  	X(msdos_rename),
-  	X(msdos_rmdir),
-  	X(msdos_unlink),
-  	X(msdos_unlink_umsdos),
-  	X(msdos_read_super),
-  	X(msdos_put_super), 
-#include <linux/symtab_end.h>
-};                                           
+/*
+ * Support for umsdos fs
+ *
+ * These symbols are _always_ exported, in case someone
+ * wants to install the umsdos module later.
+ */
+EXPORT_SYMBOL(msdos_create);
+EXPORT_SYMBOL(msdos_lookup);
+EXPORT_SYMBOL(msdos_mkdir);
+EXPORT_SYMBOL(msdos_read_inode);
+EXPORT_SYMBOL(msdos_rename);
+EXPORT_SYMBOL(msdos_rmdir);
+EXPORT_SYMBOL(msdos_unlink);
+EXPORT_SYMBOL(msdos_unlink_umsdos);
+EXPORT_SYMBOL(msdos_read_super);
+EXPORT_SYMBOL(msdos_put_super);
+
 
 struct file_system_type msdos_fs_type = {
 	msdos_read_super, "msdos", 1, NULL
 };
 
-
 int init_msdos_fs(void)
 {
-	int status;
-
-	if ((status = register_filesystem(&msdos_fs_type)) == 0)
-		status = register_symtab(&msdos_syms);
-	return status;
+	return register_filesystem(&msdos_fs_type);
 }
-
diff -u --recursive --new-file v2.1.17/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.1.17/linux/fs/ncpfs/inode.c	Wed Dec 18 15:58:51 1996
+++ linux/fs/ncpfs/inode.c	Fri Dec 27 12:03:25 1996
@@ -151,7 +151,7 @@
                 DDPRINTK("ncp_put_inode: put directory %ld\n",
 			 inode->i_ino);
                 ncp_invalid_dir_cache(inode);
-        }                
+        }
 
 	clear_inode(inode);
 	unlock_super(sb);
@@ -228,7 +228,7 @@
 	lock_super(sb);
 
         NCP_SBP(sb) = server;
-        
+
 	sb->s_blocksize = 1024; /* Eh...  Is this correct? */
 	sb->s_blocksize_bits = 10;
 	sb->s_magic = NCP_SUPER_MAGIC;
@@ -269,7 +269,7 @@
 		unlock_super(sb);
 		goto fail;
 	}
-   
+
         /*
          * Make the connection to the server
          */
@@ -402,11 +402,11 @@
 #endif
 }
 
-static void 
+static void
 ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
 {
 	struct statfs tmp;
-	
+
 	/* We cannot say how much disk space is left on a mounted
            NetWare Server, because free space is distributed over
            volumes, and the current user might have disk quotas. So
@@ -439,11 +439,11 @@
 	if ((result = inode_change_ok(inode, attr)) < 0)
 		return result;
 
-	if (((attr->ia_valid & ATTR_UID) && 
+	if (((attr->ia_valid & ATTR_UID) &&
 	     (attr->ia_uid != NCP_SERVER(inode)->m.uid)))
 		return -EPERM;
 
-	if (((attr->ia_valid & ATTR_GID) && 
+	if (((attr->ia_valid & ATTR_GID) &&
 	     (attr->ia_uid != NCP_SERVER(inode)->m.gid)))
                 return -EPERM;
 
@@ -461,14 +461,14 @@
 		ncp_date_unix2dos(attr->ia_ctime,
 				  &(info.creationTime), &(info.creationDate));
 	}
-	
+
 	if ((attr->ia_valid & ATTR_MTIME) != 0)
 	{
 		info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
 		ncp_date_unix2dos(attr->ia_mtime,
 				  &(info.modifyTime), &(info.modifyDate));
 	}
-	
+
 	if ((attr->ia_valid & ATTR_ATIME) != 0)
 	{
 		__u16 dummy;
@@ -527,7 +527,7 @@
 
 	return result;
 }
-		
+
 #ifdef DEBUG_NCP_MALLOC
 int ncp_malloced;
 int ncp_current_malloced;
@@ -543,6 +543,8 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int
 init_module( void)
 {
@@ -556,9 +558,7 @@
 #endif
         ncp_init_dir_cache();
 
-	if ((status = init_ncp_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_ncp_fs();
 }
 
 void
diff -u --recursive --new-file v2.1.17/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.1.17/linux/fs/nfs/inode.c	Tue Oct 29 19:58:44 1996
+++ linux/fs/nfs/inode.c	Fri Dec 27 12:03:25 1996
@@ -42,7 +42,7 @@
 static void nfs_read_inode(struct inode *);
 static void nfs_statfs(struct super_block *, struct statfs *, int bufsiz);
 
-static struct super_operations nfs_sops = { 
+static struct super_operations nfs_sops = {
 	nfs_read_inode,		/* read inode */
 	nfs_notify_change,	/* notify change */
 	NULL,			/* write inode */
@@ -280,7 +280,7 @@
 	int error;
 
 	sattr.mode = (unsigned) -1;
-	if (attr->ia_valid & ATTR_MODE) 
+	if (attr->ia_valid & ATTR_MODE)
 		sattr.mode = attr->ia_mode;
 
 	sattr.uid = (unsigned) -1;
@@ -360,13 +360,11 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-	int status;
-
-	if ((status = init_nfs_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_nfs_fs();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.1.17/linux/fs/proc/procfs_syms.c linux/fs/proc/procfs_syms.c
--- v2.1.17/linux/fs/proc/procfs_syms.c	Sun Dec 22 16:37:38 1996
+++ linux/fs/proc/procfs_syms.c	Fri Dec 27 12:13:54 1996
@@ -9,36 +9,30 @@
  * in the procfs.
  */
 extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
-				off_t offset, int length, int inout);
+				       off_t offset, int length, int inout);
 extern struct inode_operations proc_scsi_inode_operations;
 
-static struct symbol_table procfs_syms = {
-/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
-#include <linux/symtab_begin.h>
-	X(proc_register),
-	X(proc_register_dynamic),
-	X(proc_unregister),
-	X(proc_root),
-	X(proc_get_inode),
-	X(in_group_p),
-	X(generate_cluster),
-	X(proc_net_inode_operations),
-	X(proc_net),
+EXPORT_SYMBOL(proc_register);
+EXPORT_SYMBOL(proc_register_dynamic);
+EXPORT_SYMBOL(proc_unregister);
+EXPORT_SYMBOL(proc_root);
+EXPORT_SYMBOL(proc_get_inode);
+EXPORT_SYMBOL(in_group_p);
+EXPORT_SYMBOL(proc_net_inode_operations);
+EXPORT_SYMBOL(proc_net);
+
+/*
+ * This is required so that if we load scsi later, that the
+ * scsi code can attach to /proc/scsi in the correct manner.
+ */
+EXPORT_SYMBOL(proc_scsi);
+EXPORT_SYMBOL(proc_scsi_inode_operations);
+EXPORT_SYMBOL(dispatch_scsi_info_ptr);
 
-	/*
-	 * This is required so that if we load scsi later, that the
-	 * scsi code can attach to /proc/scsi in the correct manner.
-	 */
-	X(proc_scsi),
-	X(proc_scsi_inode_operations),
-	X(dispatch_scsi_info_ptr),
-	
 #if defined(CONFIG_SUN_OPENPROMFS_MODULE)
-	X(proc_openprom_register),
-	X(proc_openprom_deregister),
-#endif	
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(proc_openprom_register);
+EXPORT_SYMBOL(proc_openprom_deregister);
+#endif
 
 static struct file_system_type proc_fs_type = {
 	proc_read_super, "proc", 0, NULL
@@ -46,10 +40,5 @@
 
 int init_proc_fs(void)
 {
-	int status;
-
-        if ((status = register_filesystem(&proc_fs_type)) == 0)
-		status = register_symtab(&procfs_syms);
-	return status;
+	return register_filesystem(&proc_fs_type) == 0;
 }
-
diff -u --recursive --new-file v2.1.17/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.1.17/linux/fs/smbfs/inode.c	Thu Dec 12 17:02:45 1996
+++ linux/fs/smbfs/inode.c	Fri Dec 27 12:03:25 1996
@@ -438,6 +438,8 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int
 init_module(void)
 {
@@ -453,9 +455,7 @@
 
 	smb_init_dir_cache();
 
-	if ((status = init_smb_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_smb_fs();
 }
 
 void
diff -u --recursive --new-file v2.1.17/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v2.1.17/linux/fs/sysv/inode.c	Tue Oct 29 19:58:45 1996
+++ linux/fs/sysv/inode.c	Fri Dec 27 12:03:25 1996
@@ -42,7 +42,7 @@
 }
 
 
-static struct super_operations sysv_sops = { 
+static struct super_operations sysv_sops = {
 	sysv_read_inode,
 	sysv_notify_change,
 	sysv_write_inode,
@@ -72,7 +72,7 @@
 	sb->sv_inodes_per_block = 512/64;
 	sb->sv_inodes_per_block_1 = 512/64-1;
 	sb->sv_inodes_per_block_bits = 9-6;
-	sb->sv_toobig_block = 10 + 
+	sb->sv_toobig_block = 10 +
 	  (sb->sv_ind_per_block = 512/4) +
 	  (sb->sv_ind_per_block_2 = (512/4)*(512/4)) +
 	  (sb->sv_ind_per_block_3 = (512/4)*(512/4)*(512/4));
@@ -99,7 +99,7 @@
 	sb->sv_inodes_per_block = 1024/64;
 	sb->sv_inodes_per_block_1 = 1024/64-1;
 	sb->sv_inodes_per_block_bits = 10-6;
-	sb->sv_toobig_block = 10 + 
+	sb->sv_toobig_block = 10 +
 	  (sb->sv_ind_per_block = 1024/4) +
 	  (sb->sv_ind_per_block_2 = (1024/4)*(1024/4)) +
 	  (sb->sv_ind_per_block_3 = (1024/4)*(1024/4)*(1024/4));
@@ -336,7 +336,7 @@
 	return sb;
 }
 
-struct super_block *sysv_read_super(struct super_block *sb,void *data, 
+struct super_block *sysv_read_super(struct super_block *sb,void *data,
 				     int silent)
 {
 	struct buffer_head *bh;
@@ -669,7 +669,7 @@
 	return result;
 }
 
-static struct buffer_head * block_getblk(struct inode * inode, 
+static struct buffer_head * block_getblk(struct inode * inode,
 	struct buffer_head * bh, int nr, int create)
 {
 	struct super_block *sb;
@@ -985,19 +985,17 @@
 
 	for (i = 0; i < 3; i++) {
 		if ((ouch = register_filesystem(&sysv_fs_type[i])) != 0)
-			return ouch;
+			break;
 	}
         return ouch;
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-	int status;
-
-	if ((status = init_sysv_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_sysv_fs();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.1.17/linux/fs/ufs/ufs_super.c linux/fs/ufs/ufs_super.c
--- v2.1.17/linux/fs/ufs/ufs_super.c	Wed Dec 18 15:58:52 1996
+++ linux/fs/ufs/ufs_super.c	Fri Dec 27 12:03:26 1996
@@ -57,13 +57,11 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-	int status;
-
-	if ((status = init_ufs_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_ufs_fs();
 }
 
 void cleanup_module(void)
@@ -138,7 +136,7 @@
 		goto ufs_read_super_lose;
 	}
 	/* XXX - redo this so we can free it later... */
-	usb = (struct ufs_superblock *)__get_free_page(GFP_KERNEL); 
+	usb = (struct ufs_superblock *)__get_free_page(GFP_KERNEL);
 	if (usb == NULL) {
 		brelse(bh1);
 		brelse(bh2);
@@ -325,4 +323,3 @@
 	copy_to_user(buf, sp, bufsiz);
 	return;
 }
-
diff -u --recursive --new-file v2.1.17/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- v2.1.17/linux/fs/umsdos/inode.c	Tue Oct 29 19:58:46 1996
+++ linux/fs/umsdos/inode.c	Fri Dec 27 12:03:26 1996
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/umsdos/inode.c
  *
- *	Written 1993 by Jacques Gelinas 
+ *	Written 1993 by Jacques Gelinas
  *	Inspired from linux/fs/msdos/... by Werner Almesberger
  *
  */
@@ -275,7 +275,7 @@
 {
 	int ret = 0;
 
-	if ((ret = inode_change_ok(inode, attr)) != 0) 
+	if ((ret = inode_change_ok(inode, attr)) != 0)
 		return ret;
 
 	if (inode->i_nlink > 0){
@@ -321,17 +321,17 @@
 				ret = umsdos_emd_dir_read (emd_owner,&filp,(char*)&entry
 					,UMSDOS_REC_SIZE);
 				if (ret == 0){
-					if (attr->ia_valid & ATTR_UID) 
+					if (attr->ia_valid & ATTR_UID)
 						entry.uid = attr->ia_uid;
-					if (attr->ia_valid & ATTR_GID) 
+					if (attr->ia_valid & ATTR_GID)
 						entry.gid = attr->ia_gid;
-					if (attr->ia_valid & ATTR_MODE) 
+					if (attr->ia_valid & ATTR_MODE)
 						entry.mode = attr->ia_mode;
-					if (attr->ia_valid & ATTR_ATIME) 
+					if (attr->ia_valid & ATTR_ATIME)
 						entry.atime = attr->ia_atime;
-					if (attr->ia_valid & ATTR_MTIME) 
+					if (attr->ia_valid & ATTR_MTIME)
 						entry.mtime = attr->ia_mtime;
-					if (attr->ia_valid & ATTR_CTIME) 
+					if (attr->ia_valid & ATTR_CTIME)
 						entry.ctime = attr->ia_ctime;
 
 					entry.nlink = inode->i_nlink;
@@ -352,7 +352,7 @@
 			PRINTK (("\n"));
 		}
 	}
-	if (ret == 0) 
+	if (ret == 0)
 		inode_setattr(inode, attr);
 	return ret;
 }
@@ -366,7 +366,7 @@
 	so it's easier to tell them apart.
 */
 
-static struct super_operations umsdos_sops = { 
+static struct super_operations umsdos_sops = {
 	UMSDOS_read_inode,
 	UMSDOS_notify_change,
 	UMSDOS_write_inode,
@@ -431,7 +431,7 @@
 
 				This feature allows the installation
 				of a linux system within a DOS system in a subdirectory.
-	
+
 				A user may install its linux stuff in c:\linux
 				avoiding any clash with existing DOS file and subdirectory.
 				When linux boots, it hides this fact, showing a normal
@@ -505,13 +505,11 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-	int status;
-
-	if ((status = init_umsdos_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_umsdos_fs();
 }
 
 void cleanup_module(void)
@@ -520,4 +518,3 @@
 }
 
 #endif
-
diff -u --recursive --new-file v2.1.17/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.1.17/linux/fs/vfat/namei.c	Tue Oct 29 19:58:46 1996
+++ linux/fs/vfat/namei.c	Fri Dec 27 12:04:47 1996
@@ -1572,34 +1572,23 @@
 	fat_read_inode(inode, &vfat_dir_inode_operations);
 }
 
-
-
-
 static struct file_system_type vfat_fs_type = {
 	vfat_read_super, "vfat", 1, NULL
 };
 
-static struct symbol_table vfat_syms = {
-#include <linux/symtab_begin.h>
-	X(vfat_create),
-	X(vfat_unlink),
-	X(vfat_mkdir),
-	X(vfat_rmdir),
-	X(vfat_rename),
-	X(vfat_put_super),
-	X(vfat_read_super),
-	X(vfat_read_inode),
-	X(vfat_lookup),
-#include <linux/symtab_end.h>
-};                                           
+EXPORT_SYMBOL(vfat_create);
+EXPORT_SYMBOL(vfat_unlink);
+EXPORT_SYMBOL(vfat_mkdir);
+EXPORT_SYMBOL(vfat_rmdir);
+EXPORT_SYMBOL(vfat_rename);
+EXPORT_SYMBOL(vfat_put_super);
+EXPORT_SYMBOL(vfat_read_super);
+EXPORT_SYMBOL(vfat_read_inode);
+EXPORT_SYMBOL(vfat_lookup);
 
 int init_vfat_fs(void)
 {
-	int status;
-
-	if ((status = register_filesystem(&vfat_fs_type)) == 0)
-		status = register_symtab(&vfat_syms);
-	return status;
+	return register_filesystem(&vfat_fs_type);
 }
 
 #ifdef MODULE
@@ -1607,7 +1596,6 @@
 {
 	return init_vfat_fs();
 }
-
 
 void cleanup_module(void)
 {
diff -u --recursive --new-file v2.1.17/linux/fs/xiafs/inode.c linux/fs/xiafs/inode.c
--- v2.1.17/linux/fs/xiafs/inode.c	Tue Oct 29 19:58:47 1996
+++ linux/fs/xiafs/inode.c	Fri Dec 27 12:04:47 1996
@@ -2,7 +2,7 @@
  *  linux/fs/xiafs/inode.c
  *
  *  Copyright (C) Q. Frank Xia, 1993.
- *  
+ *
  *  Based on Linus' minix/inode.c
  *  Copyright (C) Linus Torvalds, 1991, 1992.
  *
@@ -24,7 +24,7 @@
 #include "xiafs_mac.h"
 
 static u_long random_nr;
-  
+
 void xiafs_put_inode(struct inode *inode)
 {
     if (inode->i_nlink)
@@ -48,7 +48,7 @@
     MOD_DEC_USE_COUNT;
 }
 
-static struct super_operations xiafs_sops = { 
+static struct super_operations xiafs_sops = {
     xiafs_read_inode,
     NULL,
     xiafs_write_inode,
@@ -94,8 +94,8 @@
     }
     s->s_blocksize = sp->s_zone_size;
     s->s_blocksize_bits = 10 + sp->s_zone_shift;
-    if (s->s_blocksize != BLOCK_SIZE && 
-	(s->s_blocksize == 1024 || s->s_blocksize == 2048 ||  
+    if (s->s_blocksize != BLOCK_SIZE &&
+	(s->s_blocksize == 1024 || s->s_blocksize == 2048 ||
 	 s->s_blocksize == 4096)) {
       brelse(bh);
       set_blocksize(dev, s->s_blocksize);
@@ -148,7 +148,7 @@
     s->s_dev = dev;
     s->s_op = &xiafs_sops;
     s->s_mounted = iget(s, _XIAFS_ROOT_INO);
-    if (!s->s_mounted) 
+    if (!s->s_mounted)
         goto xiafs_read_super_fail;
     unlock_super(s);
     random_nr=CURRENT_TIME;
@@ -220,7 +220,7 @@
     zone -= XIAFS_ADDRS_PER_Z(inode->i_sb);
     i = inode->u.xiafs_i.i_dind_zone;
     if (i)
-      i = zone_bmap(bread(inode->i_dev, i, XIAFS_ZSIZE(inode->i_sb)), 
+      i = zone_bmap(bread(inode->i_dev, i, XIAFS_ZSIZE(inode->i_sb)),
 		    zone >> XIAFS_ADDRS_PER_Z_BITS(inode->i_sb));
     if (i)
       i= zone_bmap(bread(inode->i_dev,i, XIAFS_ZSIZE(inode->i_sb)),
@@ -240,7 +240,7 @@
     return random_nr + inode->i_sb->u.xiafs_sb.s_firstdatazone;
 }
 
-static struct buffer_head * 
+static struct buffer_head *
 dt_getblk(struct inode * inode, u_long *lp, int create, u_long prev_addr)
 {
     int tmp;
@@ -270,8 +270,8 @@
     return result;
 }
 
-static struct buffer_head * 
-indt_getblk(struct inode * inode, struct buffer_head * bh, 
+static struct buffer_head *
+indt_getblk(struct inode * inode, struct buffer_head * bh,
 	    int nr, int create, u_long prev_addr)
 {
     int tmp;
@@ -347,9 +347,9 @@
     }
     zone -= XIAFS_ADDRS_PER_Z(inode->i_sb);
     bh = dt_getblk(inode, &(inode->u.xiafs_i.i_dind_zone), create, prev_addr);
-    bh = indt_getblk(inode, bh, zone>>XIAFS_ADDRS_PER_Z_BITS(inode->i_sb), 
+    bh = indt_getblk(inode, bh, zone>>XIAFS_ADDRS_PER_Z_BITS(inode->i_sb),
 		     create, prev_addr);
-    bh = indt_getblk(inode, bh, zone&(XIAFS_ADDRS_PER_Z(inode->i_sb)-1), 
+    bh = indt_getblk(inode, bh, zone&(XIAFS_ADDRS_PER_Z(inode->i_sb)-1),
 		     create, prev_addr);
     return bh;
 }
@@ -390,7 +390,7 @@
     	printk("XIA-FS: read i-node zone failed (%s %d)\n", WHERE_ERR);
     	return;
     }
-    raw_inode = ((struct xiafs_inode *) bh->b_data) + 
+    raw_inode = ((struct xiafs_inode *) bh->b_data) +
                  ((ino-1) & (XIAFS_INODES_PER_Z(inode->i_sb) - 1));
     inode->i_mode = raw_inode->i_mode;
     inode->i_uid = raw_inode->i_uid;
@@ -445,7 +445,7 @@
     	inode->i_dirt=0;
     	return 0;
     }
-    zone = 1 + inode->i_sb->u.xiafs_sb.s_imap_zones + 
+    zone = 1 + inode->i_sb->u.xiafs_sb.s_imap_zones +
                 inode->i_sb->u.xiafs_sb.s_zmap_zones +
 		(ino-1) / XIAFS_INODES_PER_Z(inode->i_sb);
     if (!(bh=bread(inode->i_dev, zone, XIAFS_ZSIZE(inode->i_sb)))) {
@@ -468,7 +468,7 @@
     else {
         XIAFS_PUT_BLOCKS(raw_inode, inode->i_blocks);
         for (zone = 0; zone < 8; zone++)
-	    raw_inode->i_zone[zone] = (raw_inode->i_zone[zone] & 0xff000000) 
+	    raw_inode->i_zone[zone] = (raw_inode->i_zone[zone] & 0xff000000)
 	                             | (inode->u.xiafs_i.i_zone[zone] & 0xffffff);
 	raw_inode->i_ind_zone = (raw_inode->i_ind_zone & 0xff000000)
 	                             | (inode->u.xiafs_i.i_ind_zone   & 0xffffff);
@@ -523,13 +523,11 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
-	int status;
-
-	if ((status = init_xiafs_fs()) == 0)
-		register_symtab(0);
-	return status;
+	return init_xiafs_fs();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.1.17/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- v2.1.17/linux/include/asm-alpha/unistd.h	Tue Nov 19 15:53:56 1996
+++ linux/include/asm-alpha/unistd.h	Fri Dec 27 12:04:48 1996
@@ -170,6 +170,7 @@
 #define __NR_getresuid			344
 #define __NR_pciconfig_read		345
 #define __NR_pciconfig_write		346
+#define __NR_query_module		347
 
 #if defined(__LIBRARY__) && defined(__GNUC__)
 
@@ -214,7 +215,7 @@
 type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5)	 \
 {									 \
 	extern long syscall (int, ...);					 \
-	return syscall(__NR_##name, arg1, arg2, arg3, arg4);		 \
+	return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5);	 \
 }
 
 #endif /* __LIBRARY__ && __GNUC__ */
diff -u --recursive --new-file v2.1.17/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- v2.1.17/linux/include/asm-i386/unistd.h	Wed Oct 16 10:48:29 1996
+++ linux/include/asm-i386/unistd.h	Fri Dec 27 12:04:48 1996
@@ -171,6 +171,7 @@
 #define __NR_mremap		163
 #define __NR_setresuid		164
 #define __NR_getresuid		165
+#define __NR_query_module	166
 
 /* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
 
diff -u --recursive --new-file v2.1.17/linux/include/asm-sparc/bitops.h linux/include/asm-sparc/bitops.h
--- v2.1.17/linux/include/asm-sparc/bitops.h	Wed Dec 18 15:59:01 1996
+++ linux/include/asm-sparc/bitops.h	Mon Dec 23 10:13:53 1996
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.39 1996/12/10 06:06:35 davem Exp $
+/* $Id: bitops.h,v 1.40 1996/12/23 05:28:49 davem Exp $
  * bitops.h: Bit string operations on the Sparc.
  *
  * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -473,6 +473,12 @@
 
 #define ext2_find_first_zero_bit     find_first_zero_le_bit
 #define ext2_find_next_zero_bit      find_next_zero_le_bit
+
+/* Bitmap functions for the minix filesystem.  */
+#define minix_set_bit(nr,addr) set_bit(nr,addr)
+#define minix_clear_bit(nr,addr) clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.1.17/linux/include/asm-sparc/pgtable.h linux/include/asm-sparc/pgtable.h
--- v2.1.17/linux/include/asm-sparc/pgtable.h	Sun Dec 22 16:37:40 1996
+++ linux/include/asm-sparc/pgtable.h	Mon Dec 23 10:13:53 1996
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.54 1996/12/03 02:38:31 davem Exp $ */
+/* $Id: pgtable.h,v 1.56 1996/12/23 05:28:50 davem Exp $ */
 #ifndef _SPARC_PGTABLE_H
 #define _SPARC_PGTABLE_H
 
@@ -105,6 +105,9 @@
  * holds the same as on the i386.
  */
 extern pte_t pg0[1024];
+extern pte_t pg1[1024];
+extern pte_t pg2[1024];
+extern pte_t pg3[1024];
 
 extern unsigned long ptr_in_current_pgd;
 
diff -u --recursive --new-file v2.1.17/linux/include/asm-sparc/pgtsun4c.h linux/include/asm-sparc/pgtsun4c.h
--- v2.1.17/linux/include/asm-sparc/pgtsun4c.h	Wed Dec 18 15:59:01 1996
+++ linux/include/asm-sparc/pgtsun4c.h	Mon Dec 23 10:13:53 1996
@@ -1,4 +1,4 @@
-/* $Id: pgtsun4c.h,v 1.32 1996/12/08 08:39:04 davem Exp $
+/* $Id: pgtsun4c.h,v 1.33 1996/12/20 07:55:04 davem Exp $
  * pgtsun4c.h:  Sun4c specific pgtable.h defines and code.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -109,7 +109,7 @@
 extern __inline__ void sun4c_put_segmap(unsigned long addr, unsigned long entry)
 {
 
-  __asm__ __volatile__("\n\tstba %1, [%0] %2\n\t" : :
+  __asm__ __volatile__("\n\tstba %1, [%0] %2; nop; nop; nop;\n\t" : :
 		       "r" (addr), "r" (entry),
 		       "i" (ASI_SEGMAP));
 
@@ -128,7 +128,7 @@
 
 extern __inline__ void sun4c_put_pte(unsigned long addr, unsigned long entry)
 {
-  __asm__ __volatile__("\n\tsta %1, [%0] %2\n\t" : :
+  __asm__ __volatile__("\n\tsta %1, [%0] %2; nop; nop; nop;\n\t" : :
 		       "r" (addr), 
 		       "r" ((entry & ~(_SUN4C_PAGE_PRESENT))), "i" (ASI_PTE));
 
@@ -148,7 +148,7 @@
 
 extern __inline__ int sun4c_set_context(int ctx)
 {
-  __asm__ __volatile__("\n\tstba %0, [%1] %2\n\t" : :
+  __asm__ __volatile__("\n\tstba %0, [%1] %2; nop; nop; nop;\n\t" : :
 		       "r" (ctx), "r" (AC_CONTEXT), "i" (ASI_CONTROL));
 
   return ctx;
diff -u --recursive --new-file v2.1.17/linux/include/asm-sparc64/bitops.h linux/include/asm-sparc64/bitops.h
--- v2.1.17/linux/include/asm-sparc64/bitops.h	Wed Dec 18 15:59:02 1996
+++ linux/include/asm-sparc64/bitops.h	Mon Dec 23 10:13:53 1996
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.4 1996/12/12 15:50:14 davem Exp $
+/* $Id: bitops.h,v 1.5 1996/12/21 06:09:28 davem Exp $
  * bitops.h: Bit string operations on the V9.
  *
  * Copyright 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -204,10 +204,6 @@
 #define find_first_zero_le_bit(addr, size) \
         find_next_zero_le_bit((addr), (size), 0)
 
----------------------------------------------------------
-| byte | byte | byte | byte | byte | byte | byte | byte |
----------------------------------------------------------
- 63  56 55  48 47  40 39  32 31  24 23  16 15   8 7    0
 extern __inline__ unsigned long __swab64(unsigned long value)
 {
 	return (((value>>56) & 0x00000000000000ff) |
diff -u --recursive --new-file v2.1.17/linux/include/linux/cdrom.h linux/include/linux/cdrom.h
--- v2.1.17/linux/include/linux/cdrom.h	Tue Nov 12 15:56:14 1996
+++ linux/include/linux/cdrom.h	Sun Dec 29 11:18:04 1996
@@ -61,7 +61,36 @@
  *
  * - XA data (green, mode2 form2): | sync - head - sub - data - EDC |
  *                                 |  12  -   4  -  8  - 2324 -  4  |
+ *
+ * Sector types (format) - Forces the CD-ROM to read the specified sector type,
+ *                         attempt to read any other format ends with an error
+ *
+ * format       sector type             user data size (bytes)
+ * -----------------------------------------------------------------------------
+ *   1     CD DA (Red Book)             2352    (CD_FRAMESIZE_RAW)
+ *   2     Mode1 Form1 (Yellow Book)    2048    (CD_FRAMESIZE)
+ *   3     Mode1 Form2 (Yellow Book)    2336    (CD_FRAMESIZE_RAW0)
+ *   4     Mode2 Form1 (Green Book)     2048    (CD_FRAMESIZE)
+ *   5     Mode2 Form2 (Green Book)     2328    (2324+4 spare bytes)
+ *
+ *
+ * Data Selection Field (pc.c[9]) - This value controls the actual number
+ *                                  of bytes transferred from the CD-ROM
+ *
+ * bit      7       6        5        4        3       2        1        0
+ * ----------------------------------------------------------------------------
+ *     |  Sync  |   Sub  | Header |  User  | EDC & | Error |  Block  | reserved
+ *     |        | Header |        |  Data  |  ECC  | Flags |  Error  |
+ *     \-------------------------------------------/\---------------/
+ *                           |                              |
+ *                           V                              V
+ *                   stored on CD (2532)    generated during error correction
+ *
+ * The maximal number of bytes returned by CD-ROM is 2646 (CD_FRAMESIZE_RAWER),
+ * when pc.c[9] = 0xfa.
+ *
  */
+ 
 
 /*
  * CDROM IOCTL structures
diff -u --recursive --new-file v2.1.17/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.1.17/linux/include/linux/fs.h	Wed Dec 18 15:59:03 1996
+++ linux/include/linux/fs.h	Sun Dec 29 11:34:13 1996
@@ -573,20 +573,17 @@
 
 extern void refile_buffer(struct buffer_head * buf);
 extern void set_writetime(struct buffer_head * buf, int flag);
-extern void refill_freelist(int size);
 extern int try_to_free_buffer(struct buffer_head*, struct buffer_head**, int);
 
 extern int nr_buffers;
 extern int buffermem;
 extern int nr_buffer_heads;
 
-#define BUF_CLEAN 0
-#define BUF_UNSHARED 1 /* Buffers that were shared but are not any more */
-#define BUF_LOCKED 2   /* Buffers scheduled for write */
-#define BUF_LOCKED1 3  /* Supers, inodes */
-#define BUF_DIRTY 4    /* Dirty buffers, not yet scheduled for write */
-#define BUF_SHARED 5   /* Buffers shared */
-#define NR_LIST 6
+#define BUF_CLEAN	0
+#define BUF_LOCKED	1	/* Buffers scheduled for write */
+#define BUF_LOCKED1	2	/* Supers, inodes */
+#define BUF_DIRTY	3	/* Dirty buffers, not yet scheduled for write */
+#define NR_LIST		4
 
 void mark_buffer_uptodate(struct buffer_head * bh, int on);
 
diff -u --recursive --new-file v2.1.17/linux/include/linux/if.h linux/include/linux/if.h
--- v2.1.17/linux/include/linux/if.h	Thu Dec 12 19:37:18 1996
+++ linux/include/linux/if.h	Sun Dec 22 21:10:06 1996
@@ -19,7 +19,7 @@
 #ifndef _LINUX_IF_H
 #define _LINUX_IF_H
 
-#include <linux/types.h>		/* for "caddr_t" et al		*/
+#include <linux/types.h>		/* for "__kernel_caddr_t" et al	*/
 #include <linux/socket.h>		/* for "struct sockaddr" et al	*/
 
 /* Standard interface flags. */
@@ -109,7 +109,7 @@
 		int	ifru_mtu;
 		struct  ifmap ifru_map;
 		char	ifru_slave[IFNAMSIZ];	/* Just fits the size */
-		caddr_t	ifru_data;
+		__kernel_caddr_t	ifru_data;
 	} ifr_ifru;
 };
 
@@ -139,8 +139,8 @@
 	int	ifc_len;			/* size of buffer	*/
 	union 
 	{
-		caddr_t	ifcu_buf;
-		struct	ifreq *ifcu_req;
+		__kernel_caddr_t	ifcu_buf;
+		struct	ifreq 		*ifcu_req;
 	} ifc_ifcu;
 };
 #define	ifc_buf	ifc_ifcu.ifcu_buf		/* buffer address	*/
diff -u --recursive --new-file v2.1.17/linux/include/linux/module.h linux/include/linux/module.h
--- v2.1.17/linux/include/linux/module.h	Sun Nov 10 20:12:14 1996
+++ linux/include/linux/module.h	Sun Dec 29 11:34:23 1996
@@ -1,138 +1,212 @@
 /*
  * Dynamic loading of modules into the kernel.
  *
- * Modified by Bjorn Ekwall <bj0rn@blox.se>
+ * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
  */
 
 #ifndef _LINUX_MODULE_H
 #define _LINUX_MODULE_H
 
 #ifdef __GENKSYMS__
-#  define _set_ver(sym,vers) sym
-#  undef  MODVERSIONS
-#  define MODVERSIONS
+# undef MODVERSIONS
+# define MODVERSIONS
 #else /* ! __GENKSYMS__ */
 # if defined(MODVERSIONS) && !defined(MODULE) && defined(EXPORT_SYMTAB)
-#   define _set_ver(sym,vers) sym
 #   include <linux/modversions.h>
 # endif
 #endif /* __GENKSYMS__ */
 
-/* values of module.state */
-#define MOD_UNINITIALIZED 0
-#define MOD_RUNNING 1
-#define MOD_DELETED 2
-
-/* maximum length of module name */
-#define MOD_MAX_NAME 64
-
-/* magic marker for modules inserted from kerneld, to be auto-reaped */
-#define MOD_AUTOCLEAN 0x40000000 /* big enough, but no sign problems... */
-#define MOD_VISITED   0x20000000 /* Thanks Jacques! */
-
-/* maximum length of symbol name */
-#define SYM_MAX_NAME 60
-
-struct kernel_sym { /* sent to "insmod" */
-	unsigned long value;		/* value of symbol */
-	char name[SYM_MAX_NAME];	/* name of symbol */
-};
+/* Don't need to bring in all of uaccess.h just for this decl.  */
+struct exception_table_entry;
 
-struct module_ref {
-	struct module *module;
-	struct module_ref *next;
+/* Used by get_kernel_syms, which is depreciated.  */
+struct kernel_sym
+{
+	unsigned long value;
+	char name[60];		/* should have been 64-sizeof(long); oh well */
 };
 
-struct internal_symbol {
-	void *addr;
+struct module_symbol
+{
+	unsigned long value;
 	const char *name;
-	};
-
-struct symbol_table { /* received from "insmod" */
-	int size; /* total, including string table!!! */
-	int n_symbols;
-	int n_refs;
-	struct internal_symbol symbol[0]; /* actual size defined by n_symbols */
-	struct module_ref ref[0]; /* actual size defined by n_refs */
 };
-/*
- * Note: The string table follows immediately after the symbol table in memory!
- */
-struct _exceptinfo{
-	struct exception_table_entry *start;
-	struct exception_table_entry *stop;
+
+struct module_ref
+{
+	struct module *dep;	/* "parent" pointer */
+	struct module *ref;	/* "child" pointer */
+	struct module_ref *next_ref;
 };
 
-struct module {
+struct module
+{
+	unsigned long size_of_struct;	/* == sizeof(module) */
 	struct module *next;
-	struct module_ref *ref;	/* the list of modules that refer to me */
-	struct symbol_table *symtab;
 	const char *name;
-	int size;			/* size of module in pages */
-	void* addr;			/* address of module */
-	int state;
-	void (*cleanup)(void);		/* cleanup routine */
-	struct _exceptinfo exceptinfo;
-};
+	unsigned long size;
 
-/*
-	prior to modules-2.1 there were no real way to identify
-	which insmod is talking to us Now a special signature must
-	be written here.
-
-	The new module utilities knows about older kernel and write
-	the init in the signature and the cleanup in the init.
-	This is to make sure newer utilities work with older kernel
-	so it is simple for people to upgrade.
-*/
-#define MODULE_2_1_7_SIG	((void*)0x00000217)
+	long usecount;
+	unsigned long flags;		/* AUTOCLEAN et al */
 
-struct mod_routines {
-	void *signature;
-	int (*init)(void);		/* initialization routine */
-	void (*cleanup)(void);		/* cleanup routine */
-	struct _exceptinfo exceptinfo;
+	unsigned nsyms;
+	unsigned ndeps;
+
+	struct module_symbol *syms;
+	struct module_ref *deps;
+	struct module_ref *refs;
+	int (*init)(void);
+	void (*cleanup)(void);
+	const struct exception_table_entry *ex_table_start;
+	const struct exception_table_entry *ex_table_end;
+#ifdef __alpha__
+	unsigned long gp;
+#endif
 };
 
-/*
- * The first word of the module contains the use count.
- */
-#define GET_USE_COUNT(module)	(* (long *) (module)->addr)
-/*
- * define the count variable, and usage macros.
- */
+struct module_info
+{
+  unsigned long addr;
+  unsigned long size;
+  unsigned long flags;
+};
+
+/* Bits of module.flags.  */
+
+#define MOD_UNINITIALIZED	0
+#define MOD_RUNNING		1
+#define MOD_DELETED		2
+#define MOD_AUTOCLEAN		4
+#define MOD_VISITED  		8
+
+/* Values for query_module's which.  */
+
+#define QM_MODULES	1
+#define QM_DEPS		2
+#define QM_REFS		3
+#define QM_SYMBOLS	4
+#define QM_INFO		5
+
+/* Backwards compatibility definition.  */
+
+#define GET_USE_COUNT(module)	((module)->usecount)
+
+/* Indirect stringification.  */
+
+#define __MODULE_STRING_1(x)	#x
+#define __MODULE_STRING(x)	__MODULE_STRING_1(x)
 
 #ifdef MODULE
 
-extern long mod_use_count_;
-#define MOD_INC_USE_COUNT      (mod_use_count_++, mod_use_count_ |= MOD_VISITED)
-#define MOD_DEC_USE_COUNT      (mod_use_count_--, mod_use_count_ |= MOD_VISITED)
-#define MOD_IN_USE	       ((mod_use_count_ & ~(MOD_AUTOCLEAN | MOD_VISITED)) != 0)
+/* Embedded module documentation macros.  */
+
+/* For documentation purposes only.  */
+
+#define MODULE_AUTHOR(name)						   \
+const char __module_author[] __attribute__((section(".modinfo"))) = 	   \
+"author=" name
+
+/* Could potentially be used by kerneld...  */
+
+#define MODULE_SUPPORTED_DEVICE(dev)					   \
+const char __module_device[] __attribute__((section(".modinfo"))) = 	   \
+"device=" dev
+
+/* Used to verify parameters given to the module.  The TYPE arg should
+   be a string in the following format:
+   	[min[-max]]{b,h,i,l,s}
+   The MIN and MAX specifiers delimit the length of the array.  If MAX
+   is omitted, it defaults to MIN; if both are omitted, the default is 1.
+   The final character is a type specifier:
+	b	byte
+	h	short
+	i	int
+	l	long
+	s	string
+*/
+
+#define MODULE_PARM(var,type)			\
+const char __module_parm_##var[]		\
+__attribute__((section(".modinfo"))) =		\
+"parm_" __MODULE_STRING(var) "=" type
+
+/* The attributes of a section are set the first time the section is
+   seen; we want .modinfo to not be allocated.  This header should be
+   included before any functions or variables are defined.  */
+
+__asm__(".section .modinfo\n\t.text");
+
+/* Define the module variable, and usage macros.  */
+extern struct module __this_module;
+
+#define MOD_INC_USE_COUNT \
+	(__this_module.usecount++, __this_module.flags |= MOD_VISITED)
+#define MOD_DEC_USE_COUNT \
+	(__this_module.usecount--, __this_module.flags |= MOD_VISITED)
+#define MOD_IN_USE \
+	(__this_module.usecount != 0)
 
 #ifndef __NO_VERSION__
 #include <linux/version.h>
-char kernel_version[]=UTS_RELEASE;
-#endif
-
+const char __module_kernel_version[] __attribute__((section(".modinfo"))) =
+"kernel_version=" UTS_RELEASE;
 #if defined(MODVERSIONS) && !defined(__GENKSYMS__)
-int Using_Versions; /* gcc will handle this global (used as a flag) correctly */
+const char __module_using_checksums[] __attribute__((section(".modinfo"))) =
+"using_checksums=1";
+#endif
 #endif
 
-#else
+#else /* MODULE */
+
+#define MODULE_AUTHOR(name)
+#define MODULE_SUPPORTED_DEVICE(name)
+#define MODULE_PARM(var,type)
 
 #define MOD_INC_USE_COUNT	do { } while (0)
 #define MOD_DEC_USE_COUNT	do { } while (0)
 #define MOD_IN_USE		1
+
 extern struct module *module_list;
 
-#endif
+#endif /* MODULE */
+
+/* Export a symbol either from the kernel or a module.
+
+   In the kernel, the symbol is added to the kernel's global symbol table.
+
+   In a module, it controls which variables are exported.  If no
+   variables are explicitly exported, the action is controled by the
+   insmod -[xX] flags.  Otherwise, only the variables listed are exported.
+   This obviates the need for the old register_symtab() function.  */
+
+#if defined(__GENKSYMS__)
+
+/* We want the EXPORT_SYMBOL tag left intact for recognition.  */
+
+#elif !defined(CONFIG_MODULES)
+
+#define EXPORT_SYMBOL(var)
+#define EXPORT_SYMBOL_NOVERS(var)
+#define EXPORT_NO_SYMBOLS
+
+#else
+
+#define EXPORT_SYMBOL(var)				\
+const struct module_symbol __export_##var 		\
+__attribute__((section("__ksymtab"))) = {		\
+	(unsigned long)&var, __MODULE_STRING(var)	\
+}							\
+
+#define EXPORT_SYMBOL_NOVERS(var) EXPORT_SYMBOL(var)
 
-/* insert new symbol table */
-extern int register_symtab_from(struct symbol_table *, long *);
 #ifdef MODULE
-#define register_symtab(symtab) register_symtab_from(symtab, &mod_use_count_)
+/* Force a module to export no symbols.  */
+#define EXPORT_NO_SYMBOLS				\
+__asm__(".section __ksymtab\n.text")
 #else
-#define register_symtab(symtab) register_symtab_from(symtab, 0)
-#endif
+#define EXPORT_NO_SYMBOLS
+#endif /* MODULE */
 
 #endif
+
+#endif /* _LINUX_MODULE_H */
diff -u --recursive --new-file v2.1.17/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v2.1.17/linux/include/linux/netdevice.h	Sun Dec 22 16:37:41 1996
+++ linux/include/linux/netdevice.h	Sun Dec 29 10:40:42 1996
@@ -83,7 +83,8 @@
 	int		hh_refcnt;	/* number of users */
 	unsigned short  hh_type;	/* protocol identifier, f.e ETH_P_IP */
 	char		hh_uptodate;	/* hh_data is valid */
-	char		hh_data[16];    /* cached hardware header */
+	/* cached hardware header; allow for machine alignment needs.  */
+	unsigned long	hh_data[16/sizeof(unsigned long)];
 };
 
 /*
diff -u --recursive --new-file v2.1.17/linux/include/linux/socket.h linux/include/linux/socket.h
--- v2.1.17/linux/include/linux/socket.h	Sun Dec 22 16:37:41 1996
+++ linux/include/linux/socket.h	Sun Dec 22 20:57:49 1996
@@ -34,9 +34,9 @@
 	void	*	msg_name;	/* Socket name			*/
 	int		msg_namelen;	/* Length of name		*/
 	struct iovec *	msg_iov;	/* Data blocks			*/
-	size_t		msg_iovlen;	/* Number of blocks		*/
+	__kernel_size_t	msg_iovlen;	/* Number of blocks		*/
 	void 	*	msg_control;	/* Per protocol magic (eg BSD file descriptor passing) */
-	size_t		msg_controllen;	/* Length of cmsg list */
+	__kernel_size_t	msg_controllen;	/* Length of cmsg list */
 	unsigned	msg_flags;
 };
 
@@ -47,7 +47,7 @@
  */
 
 struct cmsghdr {
-	size_t		cmsg_len;	/* data byte count, including hdr */
+	__kernel_size_t	cmsg_len;	/* data byte count, including hdr */
         int		cmsg_level;	/* originating protocol */
         int		cmsg_type;	/* protocol-specific type */
 	unsigned char	cmsg_data[0];
@@ -105,7 +105,6 @@
 
 struct ucred
 {
-	/* Should we be using __kernel_*_t here ?? */
 	__kernel_pid_t	pid;
 	__kernel_uid_t	uid;
 	__kernel_gid_t	gid;
diff -u --recursive --new-file v2.1.17/linux/include/linux/symtab_begin.h linux/include/linux/symtab_begin.h
--- v2.1.17/linux/include/linux/symtab_begin.h	Sun Mar 17 16:15:05 1996
+++ linux/include/linux/symtab_begin.h	Thu Jan  1 02:00:00 1970
@@ -1,45 +0,0 @@
-#include <linux/linkage.h>
-
-#ifdef MODVERSIONS
-# undef _set_ver
-# undef X
-/*
- * These two macros _will_ get enough arguments from the X* macros
- * since "sym" expands to "symaddr, symstr" from the #define in *.ver
- */
-# define _basic_version(symaddr,symstr)  symaddr, symstr
-# define _alias_version(really,symaddr,symstr)  (void *) & really , symstr
-
-# ifndef __GENKSYMS__
-#  ifdef MODULE
-#    define _set_ver(sym,ver) \
-	(void *) & sym ## _R ## ver, SYMBOL_NAME_STR(sym) "_R" #ver
-#  else /* !MODULE */
-#    define _set_ver(sym,ver) \
-	(void *) & sym, SYMBOL_NAME_STR(sym) "_R" #ver
-#  endif /* !MODULE */
-#  define X(sym) { _basic_version(sym) }
-/*
- * For _really_ stacked modules:
- *
- * Use "Xalias(local_symbol, symbol_from_other_module)"
- * to make subsequent modules really use "local_symbol"
- * when they think that they are using "symbol_from_other_module"
- *
- * The "aliasing" module can still use "symbol_from_other_module",
- * but can now replace and/or modify the behaviour of that symbol.
- */
-#  define Xalias(really,sym) { _alias_version(really,sym) }
-# endif /* !__GENKSYMS__ */
-#else /* !MODVERSIONS */
-# define X(sym) { (void *) & sym, SYMBOL_NAME_STR(sym)}
-# define Xalias(really,sym) { (void *) & really, SYMBOL_NAME_STR(sym)}
-#endif /* MODVERSIONS */
-/*
- * Some symbols always need to be unversioned.  This includes
- * compiler generated calls to functions.
- */
-#define XNOVERS(sym) { (void *) & sym, SYMBOL_NAME_STR(sym)}
-
-#define EMPTY {0,0}
-	0, 0, 0, {
diff -u --recursive --new-file v2.1.17/linux/include/linux/symtab_end.h linux/include/linux/symtab_end.h
--- v2.1.17/linux/include/linux/symtab_end.h	Thu Nov  9 08:24:09 1995
+++ linux/include/linux/symtab_end.h	Thu Jan  1 02:00:00 1970
@@ -1,15 +0,0 @@
-#ifdef MODVERSIONS
-#undef _set_ver
-#if defined(MODULE) && !defined(__GENKSYMS__)
-#define _set_ver(sym,vers) sym ## _R ## vers
-#else
-#define _set_ver(a,b) a
-#endif
-#endif /* MODVERSIONS */
-#undef X
-#undef EMPTY
-	 /* mark end of table, last entry above ended with a comma! */
-	 { (void *)0, (char *)0 }
-	},
-	/* no module refs, insmod will take care of that instead! */
-	{ { (struct module *)0, (struct module_ref *)0 } }
diff -u --recursive --new-file v2.1.17/linux/include/linux/time.h linux/include/linux/time.h
--- v2.1.17/linux/include/linux/time.h	Tue Nov 12 15:56:14 1996
+++ linux/include/linux/time.h	Fri Dec 27 12:04:48 1996
@@ -22,10 +22,10 @@
 #define NFDBITS			__NFDBITS
 
 #ifdef __KERNEL__
-void do_gettimeofday(struct timeval *tv);
-void do_settimeofday(struct timeval *tv);
-void get_fast_time(struct timeval *tv);
-void (*do_get_fast_time)(struct timeval *);
+extern void do_gettimeofday(struct timeval *tv);
+extern void do_settimeofday(struct timeval *tv);
+extern void get_fast_time(struct timeval *tv);
+extern void (*do_get_fast_time)(struct timeval *);
 #endif
 
 #define FD_SETSIZE		__FD_SETSIZE
diff -u --recursive --new-file v2.1.17/linux/include/linux/uio.h linux/include/linux/uio.h
--- v2.1.17/linux/include/linux/uio.h	Thu Dec 12 19:37:20 1996
+++ linux/include/linux/uio.h	Sun Dec 22 20:56:28 1996
@@ -17,7 +17,7 @@
 struct iovec
 {
 	void *iov_base;		/* BSD uses caddr_t (1003.1g requires void *) */
-	size_t iov_len;		/* Must be size_t (1003.1g) */
+	__kernel_size_t iov_len; /* Must be size_t (1003.1g) */
 };
 
 /*
diff -u --recursive --new-file v2.1.17/linux/init/main.c linux/init/main.c
--- v2.1.17/linux/init/main.c	Sun Dec 22 16:37:42 1996
+++ linux/init/main.c	Fri Dec 27 12:04:48 1996
@@ -713,7 +713,6 @@
 
 
 extern void setup_arch(char **, unsigned long *, unsigned long *);
-extern void arch_syms_export(void);
 
 #ifndef __SMP__
 
@@ -882,7 +881,6 @@
 	ipc_init();
 #endif
 	dquot_init();
-	arch_syms_export();
 	sti();
 	check_bugs();
 
diff -u --recursive --new-file v2.1.17/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.1.17/linux/kernel/ksyms.c	Sun Dec 22 16:37:42 1996
+++ linux/kernel/ksyms.c	Fri Dec 27 12:04:48 1996
@@ -1,4 +1,4 @@
-/* 
+/*
  * Herein lies all the functions/variables that are "exported" for linkage
  * with dynamically loaded kernel modules.
  *			Jon.
@@ -6,7 +6,7 @@
  * - Stacked module support and unified symbol table added (June 1994)
  * - External symbol table support added (December 1994)
  * - Versions on symbols added (December 1994)
- * by Bjorn Ekwall <bj0rn@blox.se>
+ *   by Bjorn Ekwall <bj0rn@blox.se>
  */
 
 #include <linux/module.h>
@@ -52,7 +52,7 @@
 
 extern unsigned char aux_device_present, kbd_read_mask;
 #ifdef __i386__
-	extern struct drive_info_struct drive_info;
+extern struct drive_info_struct drive_info;
 #endif
 
 #ifdef CONFIG_PCI
@@ -83,294 +83,278 @@
 
 extern void hard_reset_now(void);
 
-struct symbol_table symbol_table = {
-#include <linux/symtab_begin.h>
 #ifdef MODVERSIONS
-	{ (void *)1 /* Version version :-) */,
-		SYMBOL_NAME_STR (Using_Versions) },
+const struct module_symbol __export_Using_Versions
+__attribute__((section("__ksymtab"))) = {
+	1 /* Version version */, "Using_Versions"
+};
 #endif
 
-	/* stackable module support */
-	X(register_symtab_from),
 #ifdef CONFIG_KERNELD
-	X(kerneld_send),
+EXPORT_SYMBOL(kerneld_send);
 #endif
-	X(get_options),
+EXPORT_SYMBOL(get_options);
 
 #ifdef CONFIG_PCI
-	/* PCI BIOS support */
-	X(pcibios_present),
-	X(pcibios_find_class),
-	X(pcibios_find_device),
-	X(pcibios_read_config_byte),
-	X(pcibios_read_config_word),
-	X(pcibios_read_config_dword),
-	X(pcibios_write_config_byte),
-	X(pcibios_write_config_word),
-	X(pcibios_write_config_dword),
-    	X(pcibios_strerror),
-	X(pci_strvendor),
-	X(pci_strdev),
-#endif
-
-	/* process memory management */
-	X(do_mmap),
-	X(do_munmap),
-	X(exit_mm),
-
-	/* internal kernel memory management */
-	X(__get_free_pages),
-	X(free_pages),
-	X(kmalloc),
-	X(kfree),
-	X(vmalloc),
-	X(vfree),
- 	X(mem_map),
- 	X(remap_page_range),
-	X(max_mapnr),
-	X(num_physpages),
-	X(high_memory),
-	X(update_vm_cache),
-
-	/* filesystem internal functions */
-	X(getname),
-	X(putname),
-	X(__iget),
-	X(iput),
-	X(namei),
-	X(lnamei),
-	X(open_namei),
-	X(sys_close),
-	X(close_fp),
-	X(check_disk_change),
-	X(invalidate_buffers),
-	X(invalidate_inodes),
-	X(invalidate_inode_pages),
-	X(fsync_dev),
-	X(permission),
-	X(inode_setattr),
-	X(inode_change_ok),
-	X(set_blocksize),
-	X(getblk),
-	X(bread),
-	X(breada),
-	X(__brelse),
-	X(__bforget),
-	X(ll_rw_block),
-	X(__wait_on_buffer),
-	X(mark_buffer_uptodate),
-	X(unlock_buffer),
-	X(dcache_lookup),
-	X(dcache_add),
-	X(add_blkdev_randomness),
-	X(generic_file_read),
-	X(generic_file_mmap),
-	X(generic_readpage),
-
-	/* device registration */
-	X(register_chrdev),
-	X(unregister_chrdev),
-	X(register_blkdev),
-	X(unregister_blkdev),
-	X(tty_register_driver),
-	X(tty_unregister_driver),
-	X(tty_std_termios),
+/* PCI BIOS support */
+EXPORT_SYMBOL(pcibios_present);
+EXPORT_SYMBOL(pcibios_find_class);
+EXPORT_SYMBOL(pcibios_find_device);
+EXPORT_SYMBOL(pcibios_read_config_byte);
+EXPORT_SYMBOL(pcibios_read_config_word);
+EXPORT_SYMBOL(pcibios_read_config_dword);
+EXPORT_SYMBOL(pcibios_write_config_byte);
+EXPORT_SYMBOL(pcibios_write_config_word);
+EXPORT_SYMBOL(pcibios_write_config_dword);
+EXPORT_SYMBOL(pcibios_strerror);
+EXPORT_SYMBOL(pci_strvendor);
+EXPORT_SYMBOL(pci_strdev);
+#endif
+
+/* process memory management */
+EXPORT_SYMBOL(do_mmap);
+EXPORT_SYMBOL(do_munmap);
+EXPORT_SYMBOL(exit_mm);
+
+/* internal kernel memory management */
+EXPORT_SYMBOL(__get_free_pages);
+EXPORT_SYMBOL(free_pages);
+EXPORT_SYMBOL(kmalloc);
+EXPORT_SYMBOL(kfree);
+EXPORT_SYMBOL(vmalloc);
+EXPORT_SYMBOL(vfree);
+EXPORT_SYMBOL(mem_map);
+EXPORT_SYMBOL(remap_page_range);
+EXPORT_SYMBOL(max_mapnr);
+EXPORT_SYMBOL(num_physpages);
+EXPORT_SYMBOL(high_memory);
+EXPORT_SYMBOL(update_vm_cache);
+
+/* filesystem internal functions */
+EXPORT_SYMBOL(getname);
+EXPORT_SYMBOL(putname);
+EXPORT_SYMBOL(__iget);
+EXPORT_SYMBOL(iput);
+EXPORT_SYMBOL(namei);
+EXPORT_SYMBOL(lnamei);
+EXPORT_SYMBOL(open_namei);
+EXPORT_SYMBOL(sys_close);
+EXPORT_SYMBOL(close_fp);
+EXPORT_SYMBOL(check_disk_change);
+EXPORT_SYMBOL(invalidate_buffers);
+EXPORT_SYMBOL(invalidate_inodes);
+EXPORT_SYMBOL(invalidate_inode_pages);
+EXPORT_SYMBOL(fsync_dev);
+EXPORT_SYMBOL(permission);
+EXPORT_SYMBOL(inode_setattr);
+EXPORT_SYMBOL(inode_change_ok);
+EXPORT_SYMBOL(set_blocksize);
+EXPORT_SYMBOL(getblk);
+EXPORT_SYMBOL(bread);
+EXPORT_SYMBOL(breada);
+EXPORT_SYMBOL(__brelse);
+EXPORT_SYMBOL(__bforget);
+EXPORT_SYMBOL(ll_rw_block);
+EXPORT_SYMBOL(__wait_on_buffer);
+EXPORT_SYMBOL(mark_buffer_uptodate);
+EXPORT_SYMBOL(unlock_buffer);
+EXPORT_SYMBOL(dcache_lookup);
+EXPORT_SYMBOL(dcache_add);
+EXPORT_SYMBOL(add_blkdev_randomness);
+EXPORT_SYMBOL(generic_file_read);
+EXPORT_SYMBOL(generic_file_mmap);
+EXPORT_SYMBOL(generic_readpage);
+
+/* device registration */
+EXPORT_SYMBOL(register_chrdev);
+EXPORT_SYMBOL(unregister_chrdev);
+EXPORT_SYMBOL(register_blkdev);
+EXPORT_SYMBOL(unregister_blkdev);
+EXPORT_SYMBOL(tty_register_driver);
+EXPORT_SYMBOL(tty_unregister_driver);
+EXPORT_SYMBOL(tty_std_termios);
 
 #if defined(CONFIG_BLK_DEV_IDECD) || \
     defined(CONFIG_BLK_DEV_SR) || \
     defined(CONFIG_CM206)
-       X(register_cdrom),
-       X(unregister_cdrom),
-       X(cdrom_fops),
+EXPORT_SYMBOL(register_cdrom);
+EXPORT_SYMBOL(unregister_cdrom);
+EXPORT_SYMBOL(cdrom_fops);
 #endif
  
-	/* block device driver support */
-	X(block_read),
-	X(block_write),
-	X(block_fsync),
-	X(wait_for_request),
-	X(blksize_size),
-	X(hardsect_size),
-	X(blk_size),
-	X(blk_dev),
-	X(is_read_only),
-	X(set_device_ro),
-	X(bmap),
-	X(sync_dev),
-	X(get_blkfops),
-	X(blkdev_open),
-	X(blkdev_release),
-	X(gendisk_head),
-	X(resetup_one_dev),
-	X(unplug_device),
+/* block device driver support */
+EXPORT_SYMBOL(block_read);
+EXPORT_SYMBOL(block_write);
+EXPORT_SYMBOL(block_fsync);
+EXPORT_SYMBOL(wait_for_request);
+EXPORT_SYMBOL(blksize_size);
+EXPORT_SYMBOL(hardsect_size);
+EXPORT_SYMBOL(blk_size);
+EXPORT_SYMBOL(blk_dev);
+EXPORT_SYMBOL(is_read_only);
+EXPORT_SYMBOL(set_device_ro);
+EXPORT_SYMBOL(bmap);
+EXPORT_SYMBOL(sync_dev);
+EXPORT_SYMBOL(get_blkfops);
+EXPORT_SYMBOL(blkdev_open);
+EXPORT_SYMBOL(blkdev_release);
+EXPORT_SYMBOL(gendisk_head);
+EXPORT_SYMBOL(resetup_one_dev);
+EXPORT_SYMBOL(unplug_device);
 #ifdef __i386__
-	X(drive_info),
+EXPORT_SYMBOL(drive_info);
 #endif
 
-#ifdef CONFIG_SERIAL	
-	/* Module creation of serial units */
-	X(register_serial),
-	X(unregister_serial),
-#endif
-	/* tty routines */
-	X(tty_hangup),
-	X(tty_wait_until_sent),
-	X(tty_check_change),
-	X(tty_hung_up_p),
-	X(do_SAK),
-	X(console_print),
-
-	/* filesystem registration */
-	X(register_filesystem),
-	X(unregister_filesystem),
-
-	/* executable format registration */
-	X(register_binfmt),
-	X(unregister_binfmt),
-	X(search_binary_handler),
-	X(prepare_binprm),
-	X(remove_arg_zero),
-
-	/* execution environment registration */
-	X(lookup_exec_domain),
-	X(register_exec_domain),
-	X(unregister_exec_domain),
-
-	/* sysctl table registration */
-	X(register_sysctl_table),
-	X(unregister_sysctl_table),
-	X(sysctl_string),
-	X(sysctl_intvec),
-	X(proc_dostring),
-	X(proc_dointvec),
-	X(proc_dointvec_minmax),
-
-	/* interrupt handling */
-	X(request_irq),
-	X(free_irq),
-	X(enable_irq),
-	X(disable_irq),
-	X(probe_irq_on),
-	X(probe_irq_off),
-	X(bh_active),
-	X(bh_mask),
-	X(bh_mask_count),
-	X(bh_base),
-	X(add_timer),
-	X(del_timer),
-	X(tq_timer),
-	X(tq_immediate),
-	X(tq_scheduler),
-	X(timer_active),
-	X(timer_table),
- 	X(intr_count),
-
-	/* autoirq from  drivers/net/auto_irq.c */
-	X(autoirq_setup),
-	X(autoirq_report),
-
-	/* dma handling */
-	X(request_dma),
-	X(free_dma),
+/* tty routines */
+EXPORT_SYMBOL(tty_hangup);
+EXPORT_SYMBOL(tty_wait_until_sent);
+EXPORT_SYMBOL(tty_check_change);
+EXPORT_SYMBOL(tty_hung_up_p);
+EXPORT_SYMBOL(do_SAK);
+EXPORT_SYMBOL(console_print);
+
+/* filesystem registration */
+EXPORT_SYMBOL(register_filesystem);
+EXPORT_SYMBOL(unregister_filesystem);
+
+/* executable format registration */
+EXPORT_SYMBOL(register_binfmt);
+EXPORT_SYMBOL(unregister_binfmt);
+EXPORT_SYMBOL(search_binary_handler);
+EXPORT_SYMBOL(prepare_binprm);
+EXPORT_SYMBOL(remove_arg_zero);
+
+/* execution environment registration */
+EXPORT_SYMBOL(lookup_exec_domain);
+EXPORT_SYMBOL(register_exec_domain);
+EXPORT_SYMBOL(unregister_exec_domain);
+
+/* sysctl table registration */
+EXPORT_SYMBOL(register_sysctl_table);
+EXPORT_SYMBOL(unregister_sysctl_table);
+EXPORT_SYMBOL(sysctl_string);
+EXPORT_SYMBOL(sysctl_intvec);
+EXPORT_SYMBOL(proc_dostring);
+EXPORT_SYMBOL(proc_dointvec);
+EXPORT_SYMBOL(proc_dointvec_minmax);
+
+/* interrupt handling */
+EXPORT_SYMBOL(request_irq);
+EXPORT_SYMBOL(free_irq);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(probe_irq_on);
+EXPORT_SYMBOL(probe_irq_off);
+EXPORT_SYMBOL(bh_active);
+EXPORT_SYMBOL(bh_mask);
+EXPORT_SYMBOL(bh_mask_count);
+EXPORT_SYMBOL(bh_base);
+EXPORT_SYMBOL(add_timer);
+EXPORT_SYMBOL(del_timer);
+EXPORT_SYMBOL(tq_timer);
+EXPORT_SYMBOL(tq_immediate);
+EXPORT_SYMBOL(tq_scheduler);
+EXPORT_SYMBOL(timer_active);
+EXPORT_SYMBOL(timer_table);
+EXPORT_SYMBOL(intr_count);
+
+/* autoirq from  drivers/net/auto_irq.c */
+EXPORT_SYMBOL(autoirq_setup);
+EXPORT_SYMBOL(autoirq_report);
+
+/* dma handling */
+EXPORT_SYMBOL(request_dma);
+EXPORT_SYMBOL(free_dma);
 #ifdef HAVE_DISABLE_HLT
-	X(disable_hlt),
-	X(enable_hlt),
+EXPORT_SYMBOL(disable_hlt);
+EXPORT_SYMBOL(enable_hlt);
 #endif
 
-	/* IO port handling */
-	X(check_region),
-	X(request_region),
-	X(release_region),
-
-	/* process management */
-	X(wake_up),
-	X(wake_up_interruptible),
-	X(sleep_on),
-	X(interruptible_sleep_on),
-	X(schedule),
-	X(current_set),
-	X(jiffies),
-	X(xtime),
-	X(do_gettimeofday),
-	X(loops_per_sec),
-	X(need_resched),
-	X(kstat),
-	X(kill_proc),
-	X(kill_pg),
-	X(kill_sl),
-
-	/* misc */
-	X(panic),
-	X(printk),
-	X(sprintf),
-	X(vsprintf),
-	X(kdevname),
-	X(simple_strtoul),
-	X(system_utsname),
-	X(sys_call_table),
-	X(hard_reset_now),
-	X(_ctype),
-	X(secure_tcp_sequence_number),
-
-	/* Signal interfaces */
-	X(send_sig),
-
-	/* Program loader interfaces */
-	X(setup_arg_pages),
-	X(copy_strings),
-	X(do_execve),
-	X(flush_old_exec),
-	X(open_inode),
-	X(read_exec),
-
-	/* Miscellaneous access points */
-	X(si_meminfo),
-
-	/* Added to make file system as module */
-	X(set_writetime),
-	X(sys_tz),
-	X(__wait_on_super),
-	X(file_fsync),
-	X(clear_inode),
-	X(refile_buffer),
-	X(nr_async_pages),
-	X(___strtok),
-	X(init_fifo),
-	X(super_blocks),
-	X(reuse_list),
-	X(fifo_inode_operations),
-	X(chrdev_inode_operations),
-	X(blkdev_inode_operations),
-	X(read_ahead),
-	X(get_hash_table),
-	X(get_empty_inode),
-	X(insert_inode_hash),
-	X(event),
-	X(__down),
-	X(__up),
-	X(securelevel),
+/* IO port handling */
+EXPORT_SYMBOL(check_region);
+EXPORT_SYMBOL(request_region);
+EXPORT_SYMBOL(release_region);
+
+/* process management */
+EXPORT_SYMBOL(wake_up);
+EXPORT_SYMBOL(wake_up_interruptible);
+EXPORT_SYMBOL(sleep_on);
+EXPORT_SYMBOL(interruptible_sleep_on);
+EXPORT_SYMBOL(schedule);
+EXPORT_SYMBOL(current_set);
+EXPORT_SYMBOL(jiffies);
+EXPORT_SYMBOL(xtime);
+EXPORT_SYMBOL(do_gettimeofday);
+EXPORT_SYMBOL(loops_per_sec);
+EXPORT_SYMBOL(need_resched);
+EXPORT_SYMBOL(kstat);
+EXPORT_SYMBOL(kill_proc);
+EXPORT_SYMBOL(kill_pg);
+EXPORT_SYMBOL(kill_sl);
+
+/* misc */
+EXPORT_SYMBOL(panic);
+EXPORT_SYMBOL(printk);
+EXPORT_SYMBOL(sprintf);
+EXPORT_SYMBOL(vsprintf);
+EXPORT_SYMBOL(kdevname);
+EXPORT_SYMBOL(simple_strtoul);
+EXPORT_SYMBOL(system_utsname);
+EXPORT_SYMBOL(sys_call_table);
+EXPORT_SYMBOL(hard_reset_now);
+EXPORT_SYMBOL(_ctype);
+EXPORT_SYMBOL(secure_tcp_sequence_number);
+
+/* Signal interfaces */
+EXPORT_SYMBOL(send_sig);
+
+/* Program loader interfaces */
+EXPORT_SYMBOL(setup_arg_pages);
+EXPORT_SYMBOL(copy_strings);
+EXPORT_SYMBOL(do_execve);
+EXPORT_SYMBOL(flush_old_exec);
+EXPORT_SYMBOL(open_inode);
+EXPORT_SYMBOL(read_exec);
+
+/* Miscellaneous access points */
+EXPORT_SYMBOL(si_meminfo);
+
+/* Added to make file system as module */
+EXPORT_SYMBOL(set_writetime);
+EXPORT_SYMBOL(sys_tz);
+EXPORT_SYMBOL(__wait_on_super);
+EXPORT_SYMBOL(file_fsync);
+EXPORT_SYMBOL(clear_inode);
+EXPORT_SYMBOL(refile_buffer);
+EXPORT_SYMBOL(nr_async_pages);
+EXPORT_SYMBOL(___strtok);
+EXPORT_SYMBOL(init_fifo);
+EXPORT_SYMBOL(super_blocks);
+EXPORT_SYMBOL(reuse_list);
+EXPORT_SYMBOL(fifo_inode_operations);
+EXPORT_SYMBOL(chrdev_inode_operations);
+EXPORT_SYMBOL(blkdev_inode_operations);
+EXPORT_SYMBOL(read_ahead);
+EXPORT_SYMBOL(get_hash_table);
+EXPORT_SYMBOL(get_empty_inode);
+EXPORT_SYMBOL(insert_inode_hash);
+EXPORT_SYMBOL(event);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(securelevel);
+
 /* all busmice */
-	X(add_mouse_randomness),
-	X(fasync_helper),
+EXPORT_SYMBOL(add_mouse_randomness);
+EXPORT_SYMBOL(fasync_helper);
+
 /* psaux mouse */
-	X(aux_device_present),
-	X(kbd_read_mask),
+EXPORT_SYMBOL(aux_device_present);
+EXPORT_SYMBOL(kbd_read_mask);
 
 #ifdef CONFIG_BLK_DEV_MD
-	X(disk_name),	/* for md.c */
+EXPORT_SYMBOL(disk_name);	/* for md.c */
 #endif
  	
-	/* binfmt_aout */
-	X(get_write_access),
-	X(put_write_access),
-
-	/********************************************************
-	 * Do not add anything below this line,
-	 * as the stacked modules depend on this!
-	 */
-#include <linux/symtab_end.h>
-};
-
-/*
-int symbol_table_size = sizeof (symbol_table) / sizeof (symbol_table[0]);
-*/
+/* binfmt_aout */
+EXPORT_SYMBOL(get_write_access);
+EXPORT_SYMBOL(put_write_access);
diff -u --recursive --new-file v2.1.17/linux/kernel/module.c linux/kernel/module.c
--- v2.1.17/linux/kernel/module.c	Fri Nov 22 18:28:21 1996
+++ linux/kernel/module.c	Fri Dec 27 12:33:40 1996
@@ -4,789 +4,925 @@
 #include <linux/string.h>
 #include <linux/module.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
 #include <linux/config.h>
-
 #include <asm/uaccess.h>
+#include <linux/vmalloc.h>
+
 /*
  * Originally by Anonymous (as far as I know...)
  * Linux version by Bas Laarhoven <bas@vimec.nl>
  * 0.99.14 version by Jon Tombs <jon@gtex02.us.es>,
- *
  * Heavily modified by Bjorn Ekwall <bj0rn@blox.se> May 1994 (C)
- * This source is covered by the GNU GPL, the same as all kernel sources.
- *
- * Features:
- *	- Supports stacked modules (removable only of there are no dependents).
- *	- Supports table of symbols defined by the modules.
- *	- Supports /proc/ksyms, showing value, name and owner of all
- *	  the symbols defined by all modules (in stack order).
- *	- Added module dependencies information into /proc/modules
- *	- Supports redefines of all symbols, for streams-like behaviour.
- *	- Compatible with older versions of insmod.
- *
- * New addition in December 1994: (Bjorn Ekwall, idea from Jacques Gelinas)
- *	- Externally callable function:
- *
- *		"int register_symtab(struct symbol_table *)"
+ * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
  *
- *	  This function can be called from within the kernel,
- *	  and ALSO from loadable modules.
- *	  The goal is to assist in modularizing the kernel even more,
- *	  and finally: reducing the number of entries in ksyms.c
- *	  since every subsystem should now be able to decide and
- *	  control exactly what symbols it wants to export, locally!
- *
- * On 1-Aug-95:  <Matti.Aarnio@utu.fi>  altered code to use same style as
- *		 do  /proc/net/XXX  "files".  Namely allow more than 4kB
- *		 (or what the block size is) output.
- *
- *	- Use dummy syscall functions for users who disable all
- *	  module support. Similar to kernel/sys.c (Paul Gortmaker)
+ * This source is covered by the GNU GPL, the same as all kernel sources.
  */
 
 #ifdef CONFIG_MODULES		/* a *big* #ifdef block... */
 
-static struct module kernel_module;
-struct module *module_list = &kernel_module;
+extern struct module_symbol __start___ksymtab[];
+extern struct module_symbol __stop___ksymtab[];
+
+extern const struct exception_table_entry __start___ex_table[];
+extern const struct exception_table_entry __stop___ex_table[];
 
-static int freeing_modules; /* true if some modules are marked for deletion */
+static struct module kernel_module =
+{
+	sizeof(struct module),	/* size_of_struct */
+	NULL,			/* next */
+	"",			/* name */
+	0,			/* size */
+	1,			/* usecount */
+	MOD_RUNNING,		/* flags */
+	0,			/* nsyms -- to filled in in init_modules */
+	0,			/* ndeps */
+	__start___ksymtab,	/* syms */
+	NULL,			/* deps */
+	NULL,			/* refs */
+	NULL,			/* init */
+	NULL,			/* cleanup */
+	__start___ex_table,	/* ex_table_start */
+	__stop___ex_table,	/* ex_table_end */
+#ifdef __alpha__
+	NULL,			/* gp */
+#endif
+};
+
+struct module *module_list = &kernel_module;
 
-static struct module *find_module( const char *name);
-static int free_modules( void);
+static long get_mod_name(const char *user_name, char **buf);
+static void put_mod_name(char *buf);
+static struct module *find_module(const char *name);
+static void free_module(struct module *);
 
-extern struct symbol_table symbol_table; /* in kernel/ksyms.c */
 
 /*
  * Called at boot time
  */
-void init_modules(void) {
-	struct internal_symbol *sym;
-	int i;
 
-	for (i = 0, sym = symbol_table.symbol; sym->name; ++sym, ++i)
-		;
-	symbol_table.n_symbols = i;
-
-	kernel_module.symtab = &symbol_table;
-	kernel_module.state = MOD_RUNNING; /* Hah! */
-	kernel_module.name = "";
-}
+void init_modules(void)
+{
+	kernel_module.nsyms = __stop___ksymtab - __start___ksymtab;
 
+#ifdef __alpha__
+	{
+		register unsigned long gp __asm__("$29");
+		kernel_module.gp = gp;
+	}
+#endif
+}
 
 /*
  * Copy the name of a module from user space.
  */
-inline int
-get_mod_name(char *user_name, char *buf)
+
+static inline long
+get_mod_name(const char *user_name, char **buf)
 {
-	/* Should return -EBIG instead of -EFAULT when the name
-       is too long, but that we couldn't detect real faults then.
-       Maybe strncpy_from_user() should return -EBIG, when
-       the source string is too long. */
-	return strncpy_from_user(buf, user_name, MOD_MAX_NAME); 
+	unsigned long page;
+	long retval;
+
+	if ((unsigned long)user_name >= TASK_SIZE)
+		return -EFAULT;
+
+	page = __get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
+	if (retval > 0) {
+		if (retval < PAGE_SIZE) {
+			*buf = (char *)page;
+			return retval;
+		}
+		retval = -ENAMETOOLONG;
+	} else if (!retval)
+		retval = -EINVAL;
+
+	free_page(page);
+	return retval;
 }
 
+static inline void
+put_mod_name(char *buf)
+{
+	free_page((unsigned long)buf);
+}
 
 /*
  * Allocate space for a module.
  */
+
 asmlinkage unsigned long
-sys_create_module(char *module_name, unsigned long size)
+sys_create_module(const char *name_user, size_t size)
 {
-	struct module *mp;
-	void* addr;
-	int error;
-	int npages;
-	int sspace = sizeof(struct module) + MOD_MAX_NAME;
-	char name[MOD_MAX_NAME];
-
-	if (!suser())
-		return -EPERM;
-	if (module_name == NULL || size == 0)
-		return -EINVAL;
-	if ((error = get_mod_name(module_name, name)) < 0)
-		return error;
+	char *name;
+	long namelen, error;
+	struct module *mod;
+
+	if (!suser()) {
+		error = -EPERM;
+		goto err0;
+	}
+	if ((namelen = get_mod_name(name_user, &name)) < 0) {
+		error = namelen;
+		goto err0;
+	}
+	if (size < sizeof(struct module)+namelen) {
+		error = -EINVAL;
+		goto err1;
+	}
 	if (find_module(name) != NULL) {
-		return -EEXIST;
+		error = -EEXIST;
+		goto err1;
 	}
-
-	if ((mp = (struct module*) kmalloc(sspace, GFP_KERNEL)) == NULL) {
-		return -ENOMEM;
+	if ((mod = (struct module *)vmalloc(size)) == NULL) {
+		error = -ENOMEM;
+		goto err1;
 	}
-	strcpy((char *)(mp + 1), name); /* why not? */
 
-	npages = (size + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE;
-	if ((addr = vmalloc(npages * PAGE_SIZE)) == 0) {
-		kfree_s(mp, sspace);
-		return -ENOMEM;
-	}
+	memset(mod, 0, sizeof(*mod));
+	mod->size_of_struct = sizeof(*mod);
+	mod->next = module_list;
+	mod->name = (char *)(mod + 1);
+	mod->size = size;
+	memcpy((char*)(mod+1), name, namelen+1);
 
-	mp->next = module_list;
-	mp->ref = NULL;
-	mp->symtab = NULL;
-	mp->name = (char *)(mp + 1);
-	mp->size = npages;
-	mp->addr = addr;
-	mp->state = MOD_UNINITIALIZED;
-	mp->cleanup = NULL;
-	mp->exceptinfo.start = NULL;
-	mp->exceptinfo.stop = NULL;
-
-	* (long *) addr = 0;	/* set use count to zero */
-	module_list = mp;	/* link it in */
-
-	pr_debug("module `%s' (%lu pages @ 0x%08lx) created\n",
-		mp->name, (unsigned long) mp->size, (unsigned long) mp->addr);
-	return (unsigned long) addr;
-}
+	put_mod_name(name);
 
+	module_list = mod;	/* link it in */
+
+	return (unsigned long) mod;
+
+err1:
+	put_mod_name(name);
+err0:
+	return error;
+}
 
 /*
  * Initialize a module.
  */
-asmlinkage int
-sys_init_module(char *module_name, char *code, unsigned codesize,
-		struct mod_routines *routines,
-		struct symbol_table *symtab)
-{
-	struct module *mp;
-	struct symbol_table *newtab;
-	char name[MOD_MAX_NAME];
-	int error;
-	struct mod_routines rt;
 
-	if (!suser())
-		return -EPERM;
-
-#ifdef __i386__
-	/* A little bit of protection... we "know" where the user stack is... */
-
-	if (symtab && ((unsigned long)symtab > 0xb0000000)) {
-		printk(KERN_WARNING "warning: you are using an old insmod, no symbols will be inserted!\n");
-		symtab = NULL;
+asmlinkage int
+sys_init_module(const char *name_user, struct module *mod_user)
+{
+	struct module mod_tmp, *mod;
+	char *name, *n_name;
+	long namelen, n_namelen, i, error;
+	unsigned long mod_user_size;
+	struct module_ref *dep;
+
+	if (!suser()) {
+		error = -EPERM;
+		goto err0;
+	}
+	if ((namelen = get_mod_name(name_user, &name)) < 0) {
+		error = namelen;
+		goto err0;
+	}
+	if ((mod = find_module(name)) == NULL) {
+		error = -ENOENT;
+		goto err1;
+	}
+
+	/* In the future we can check for various known sizes, but for
+	   now there is only one.  */
+	if ((error = get_user(mod_user_size, &mod_user->size_of_struct)) != 0)
+		goto err1;
+	if (mod_user_size != sizeof(struct module)) {
+		printk(KERN_ERR "init_module: Invalid module header size.\n"
+		       KERN_ERR "A new version of the modutils is likely "
+				"needed.\n");
+		error = -EINVAL;
+		goto err1;
+	}
+
+	/* Hold the current contents while we play with the user's idea
+	   of righteousness.  */
+	mod_tmp = *mod;
+
+	error = copy_from_user(mod, mod_user, sizeof(struct module));
+	if (error) {
+		error = -EFAULT;
+		goto err2;
+	}
+
+	/* Sanity check the size of the module.  */
+	error = -EINVAL;
+
+	if (mod->size > mod_tmp.size) {
+		printk(KERN_ERR "init_module: Size of initialized module "
+				"exceeds size of created module.\n");
+		goto err2;
+	}
+
+	/* Make sure all interesting pointers are sane.  */
+
+#define bound(p, n, m)  ((unsigned long)(p) >= (unsigned long)(m+1) &&  \
+	         (unsigned long)((p)+(n)) <= (unsigned long)(m) + (m)->size)
+
+	if (!bound(mod->name, namelen, mod)) {
+		printk(KERN_ERR "init_module: mod->name out of bounds.\n");
+		goto err2;
+	}
+	if (mod->nsyms && !bound(mod->syms, mod->nsyms, mod)) {
+		printk(KERN_ERR "init_module: mod->syms out of bounds.\n");
+		goto err2;
+	}
+	if (mod->ndeps && !bound(mod->deps, mod->ndeps, mod)) {
+		printk(KERN_ERR "init_module: mod->deps out of bounds.\n");
+		goto err2;
+	}
+	if (mod->init && !bound(mod->init, 0, mod)) {
+		printk(KERN_ERR "init_module: mod->init out of bounds.\n");
+		goto err2;
+	}
+	if (mod->cleanup && !bound(mod->cleanup, 0, mod)) {
+		printk(KERN_ERR "init_module: mod->cleanup out of bounds.\n");
+		goto err2;
+	}
+	if (mod->ex_table_start > mod->ex_table_end
+	    || (mod->ex_table_start &&
+		!((unsigned long)mod->ex_table_start >= (unsigned long)(mod+1)
+		  && ((unsigned long)mod->ex_table_end
+		      < (unsigned long)mod + mod->size)))
+	    || (((unsigned long)mod->ex_table_start
+		 - (unsigned long)mod->ex_table_end)
+		% sizeof(struct exception_table_entry))) {
+		printk(KERN_ERR "init_module: mod->ex_table_* invalid.\n");
+		goto err2;
+	}
+	if (mod->flags & ~MOD_AUTOCLEAN) {
+		printk(KERN_ERR "init_module: mod->flags invalid.\n");
+		goto err2;
+	}
+#ifdef __alpha__
+	if (!bound(mod->gp - 0x8000, 0, mod)) {
+		printk(KERN_ERR "init_module: mod->gp out of bounds.\n");
+		goto err2;
 	}
 #endif
-	if ((error = get_mod_name(module_name, name)) < 0)
-		return error;
-	pr_debug("initializing module `%s', %d (0x%x) bytes\n",
-		name, codesize, codesize);
-	if (copy_from_user(&rt, routines, sizeof rt))
-			return -EFAULT;
-	if ((mp = find_module(name)) == NULL)
-		return -ENOENT;
-	if (codesize & MOD_AUTOCLEAN) {
-		/*
-		 * set autoclean marker from codesize...
-		 * set usage count to "zero"
-		 */
-		codesize &= ~MOD_AUTOCLEAN;
-		GET_USE_COUNT(mp) = MOD_AUTOCLEAN;
-	}
-	if ((codesize + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE > mp->size)
-		return -EINVAL;
-	if (copy_from_user((char *)mp->addr + sizeof (long), code, codesize))
-			return -EFAULT;
-	memset((char *)mp->addr + sizeof (long) + codesize, 0,
-		mp->size * PAGE_SIZE - (codesize + sizeof (long)));
-	pr_debug("module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
-		(unsigned long) rt.init, (unsigned long) rt.cleanup);
-	if (rt.signature != MODULE_2_1_7_SIG){
-		printk ("Older insmod used with kernel 2.1.7 +\n");
-		return -EINVAL;
-	}
-	mp->cleanup = rt.cleanup;
-	mp->exceptinfo = rt.exceptinfo;
 
-	/* update kernel symbol table */
-	if (symtab) { /* symtab == NULL means no new entries to handle */
-		struct internal_symbol *sym;
-		struct module_ref *ref;
-		int size;
-		int i;
-		int legal_start;
-
-		error = get_user(size, &symtab->size);
-		if (error)
-				return error;
-		if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
-			return -ENOMEM;
-		}
-
-		if (copy_from_user((char *)(newtab), symtab, size)) {
-				kfree_s(newtab, size);
-				return -EFAULT;
-		}
-
-		/* sanity check */
-		legal_start = sizeof(struct symbol_table) +
-			newtab->n_symbols * sizeof(struct internal_symbol) +
-			newtab->n_refs * sizeof(struct module_ref);
-
-		if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) || (legal_start > size)) {
-			printk(KERN_WARNING "Rejecting illegal symbol table (n_symbols=%d,n_refs=%d)\n",
-			       newtab->n_symbols, newtab->n_refs);
-			kfree_s(newtab, size);
-			return -EINVAL;
-		}
+#undef bound
 
-		/* relocate name pointers, index referred from start of table */
-		for (sym = &(newtab->symbol[0]), i = 0; i < newtab->n_symbols; ++sym, ++i) {
-			if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
-				printk(KERN_WARNING "Rejecting illegal symbol table\n");
-				kfree_s(newtab, size);
-				return -EINVAL;
-			}
-			/* else */
-			sym->name += (long)newtab;
-		}
-		mp->symtab = newtab;
-
-		/* Update module references.
-		 * On entry, from "insmod", ref->module points to
-		 * the referenced module!
-		 * Now it will point to the current module instead!
-		 * The ref structure becomes the first link in the linked
-		 * list of references to the referenced module.
-		 * Also, "sym" from above, points to the first ref entry!!!
-		 */
-		for (ref = (struct module_ref *)sym, i = 0;
-			i < newtab->n_refs; ++ref, ++i) {
-
-			/* Check for valid reference */
-			struct module *link = module_list;
-			while (link && (ref->module != link))
-				link = link->next;
-
-			if (link == (struct module *)0) {
-				printk(KERN_WARNING "Non-module reference! Rejected!\n");
-				return -EINVAL;
-			}
+	/* Check that the user isn't doing something silly with the name.  */
 
-			ref->next = ref->module->ref;
-			ref->module->ref = ref;
-			ref->module = mp;
-		}
-	}
-
-	GET_USE_COUNT(mp) += 1;
-	if ((*rt.init)() != 0) {
-		GET_USE_COUNT(mp) = 0;
+	if ((n_namelen = get_mod_name(mod->name - (unsigned long)mod
+				      + (unsigned long)mod_user,
+				      &n_name)) < 0) {
+		error = n_namelen;
+		goto err2;
+	}
+	if (namelen != n_namelen || strcmp(n_name, mod_tmp.name) != 0) {
+		printk(KERN_ERR "init_module: changed module name to "
+				"`%s' from `%s'\n",
+		       n_name, mod_tmp.name);
+		error = -EINVAL;
+		goto err3;
+	}
+
+	/* Ok, that's about all the sanity we can stomach; copy the rest.  */
+
+	error = copy_from_user(mod+1, mod_user+1, mod->size-sizeof(*mod));
+	if (error) {
+		error = -EFAULT;
+		goto err3;
+	}
+
+	/* Update module references.  */
+	mod->next = mod_tmp.next;
+	mod->refs = NULL;
+	for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
+		struct module *o, *d = dep->dep;
+
+		/* Make sure the indicated dependancies are really modules.  */
+		if (d == mod) {
+			printk(KERN_ERR "init_module: self-referential "
+					"dependancy in mod->deps.\n");
+			error = -EINVAL;
+			goto err3;
+		}
+
+		for (o = module_list; o != &kernel_module; o = o->next)
+			if (o == d) goto found_dep;
+
+		printk(KERN_ERR "init_module: found dependancy that is "
+				"(no longer?) a module.\n");
+		error = -EINVAL;
+		goto err3;
+		
+	found_dep:
+		dep->ref = mod;
+		dep->next_ref = d->refs;
+		d->refs = dep;
+	}
+
+	/* Free our temporary memory.  */
+	put_mod_name(n_name);
+	put_mod_name(name);
+
+	/* Initialize the module.  */
+	mod->usecount = 1;
+	if (mod->init && mod->init() != 0) {
+		mod->usecount = 0;
 		return -EBUSY;
 	}
-	GET_USE_COUNT(mp) -= 1;
-	mp->state = MOD_RUNNING;
+	mod->usecount--;
 
+	/* And set it running.  */
+	mod->flags |= MOD_RUNNING;
 	return 0;
+
+err3:
+	put_mod_name(n_name);
+err2:
+	*mod = mod_tmp;
+err1:
+	put_mod_name(name);
+err0:
+	return error;
 }
 
 asmlinkage int
-sys_delete_module(char *module_name)
+sys_delete_module(const char *name_user)
 {
-	struct module *mp;
-	char name[MOD_MAX_NAME];
-	int error;
+	struct module *mod, *next;
+	char *name;
+	long error;
 
 	if (!suser())
 		return -EPERM;
-	/* else */
-	if (module_name != NULL) {
-		if ((error = get_mod_name(module_name, name)) < 0)
+
+	if (name_user) {
+		if ((error = get_mod_name(name_user, &name)) < 0)
 			return error;
-		if ((mp = find_module(name)) == NULL)
+		if (error == 0) {
+			put_mod_name(name);
+			return -EINVAL;
+		}
+		if ((mod = find_module(name)) == NULL) {
+			put_mod_name(name);
 			return -ENOENT;
-		if ((mp->ref != NULL) ||
-		    ((GET_USE_COUNT(mp) & ~(MOD_AUTOCLEAN | MOD_VISITED)) != 0))
+		}
+		put_mod_name(name);
+		if (mod->refs != NULL || mod->usecount != 0)
 			return -EBUSY;
-		GET_USE_COUNT(mp) &= ~(MOD_AUTOCLEAN | MOD_VISITED);
-		if (mp->state == MOD_RUNNING)
-			(*mp->cleanup)();
-		mp->state = MOD_DELETED;
-		free_modules();
+
+		free_module(mod);
+		return 0;
 	}
-	/* for automatic reaping */
-	else {
-		struct module *mp_next;
-		for (mp = module_list; mp != &kernel_module; mp = mp_next) {
-			mp_next = mp->next;
-			if ((mp->ref == NULL) && (mp->state == MOD_RUNNING) &&
-			    ((GET_USE_COUNT(mp) & ~MOD_VISITED) == MOD_AUTOCLEAN)) {
-			    	if ((GET_USE_COUNT(mp) & MOD_VISITED)) {
-					/* Don't reap until one "cycle" after last _use_ */
-			   		GET_USE_COUNT(mp) &= ~MOD_VISITED;
-				}
-				else {
-					GET_USE_COUNT(mp) &= ~(MOD_AUTOCLEAN | MOD_VISITED);
-					(*mp->cleanup)();
-					mp->state = MOD_DELETED;
-					free_modules();
-				}
-			}
+
+	/* Do automatic reaping */
+	for (mod = module_list; mod != &kernel_module; mod = next) {
+		next = mod->next;
+		if (mod->refs == NULL &&
+		    mod->usecount == 0 &&
+		    ((mod->flags & (MOD_AUTOCLEAN|MOD_RUNNING|MOD_DELETED))
+		     == (MOD_AUTOCLEAN|MOD_RUNNING))) {
+			if (mod->flags & MOD_VISITED)
+				mod->flags &= ~MOD_VISITED;
+			else
+				free_module(mod);
 		}
 	}
 	return 0;
 }
 
+/* Query various bits about modules.  */
 
-/*
- * Copy the kernel symbol table to user space.  If the argument is null,
- * just return the size of the table.
- *
- * Note that the transient module symbols are copied _first_,
- * in lifo order!!!
- *
- * The symbols to "insmod" are according to the "old" format: struct kernel_sym,
- * which is actually quite handy for this purpose.
- * Note that insmod inserts a struct symbol_table later on...
- * (as that format is quite handy for the kernel...)
- *
- * For every module, the first (pseudo)symbol copied is the module name
- * and the address of the module struct.
- * This lets "insmod" keep track of references, and build the array of
- * struct module_refs in the symbol table.
- * The format of the module name is "#module", so that "insmod" can easily
- * notice when a module name comes along. Also, this will make it possible
- * to use old versions of "insmod", albeit with reduced functionality...
- * The "kernel" module has an empty name.
- */
-asmlinkage int
-sys_get_kernel_syms(struct kernel_sym *table)
+static int
+qm_modules(char *buf, size_t bufsize, size_t *ret)
 {
-	struct internal_symbol *from;
-	struct kernel_sym isym;
-	struct kernel_sym *to;
-	struct module *mp = module_list;
-	int i;
-	int nmodsyms = 0;
-	int err;
+	struct module *mod;
+	size_t nmod, space, len;
 
-	for (mp = module_list; mp; mp = mp->next) {
-		if (mp->symtab && mp->symtab->n_symbols) {
-			/* include the count for the module name! */
-			nmodsyms += mp->symtab->n_symbols + 1;
-		}
-		else
-			/* include the count for the module name! */
-			nmodsyms += 1; /* return modules without symbols too */
+	nmod = space = 0;
+
+	for (mod=module_list; mod != &kernel_module; mod=mod->next, ++nmod) {
+		len = strlen(mod->name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, mod->name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
 	}
 
-	if (table != NULL) {
-		to = table;
+	if (put_user(nmod, ret))
+		return -EFAULT;
+	else
+		return 0;
 
-		/* copy all module symbols first (always LIFO order) */
-		for (mp = module_list; mp; mp = mp->next) {
-			if (mp->state == MOD_RUNNING) {
-				/* magic: write module info as a pseudo symbol */
-				isym.value = (unsigned long)mp;
-				sprintf(isym.name, "#%s", mp->name);
-				err = copy_to_user(to, &isym, sizeof isym);
-				if (err)
-						return -EFAULT;
-				++to;
-
-				if (mp->symtab != NULL) {
-					for (i = mp->symtab->n_symbols,
-						from = mp->symtab->symbol;
-						i > 0; --i, ++from, ++to) {
-
-						isym.value = (unsigned long)from->addr;
-						strncpy(isym.name, from->name, sizeof isym.name);
-						err = copy_to_user(to, &isym, sizeof isym);
-						if (err)
-								return -EFAULT;
-					}
-				}
-			}
-		}
-	}
+calc_space_needed:
+	for (space += len; mod; mod = mod->next)
+		space += strlen(mod->name)+1;
 
-	return nmodsyms;
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
 }
 
-/*
- * Look for a module by name, ignoring modules marked for deletion.
- */
-struct module *
-find_module( const char *name)
+static int
+qm_deps(struct module *mod, char *buf, size_t bufsize, size_t *ret)
 {
-	struct module *mp;
+	size_t i, space, len;
 
-	for (mp = module_list ; mp ; mp = mp->next) {
-		if (mp->state == MOD_DELETED)
-			continue;
-		if (!strcmp(mp->name, name))
-			break;
+	if (mod == &kernel_module)
+		return -EINVAL;
+	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = 0;
+	for (i = 0; i < mod->ndeps; ++i) {
+		const char *dep_name = mod->deps[i].dep->name;
+
+		len = strlen(dep_name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, dep_name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
 	}
-	return mp;
+
+	if (put_user(i, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	for (space += len; i < mod->ndeps; ++i)
+		space += strlen(mod->deps[i].dep->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
 }
 
-static void
-drop_refs(struct module *mp)
+static int
+qm_refs(struct module *mod, char *buf, size_t bufsize, size_t *ret)
 {
-	struct module *step;
-	struct module_ref *prev;
+	size_t nrefs, space, len;
 	struct module_ref *ref;
 
-	for (step = module_list; step; step = step->next) {
-		for (prev = ref = step->ref; ref; ref = prev->next) {
-			if (ref->module == mp) {
-				if (ref == step->ref)
-					step->ref = ref->next;
-				else
-					prev->next = ref->next;
-				break; /* every module only references once! */
-			}
-			else
-				prev = ref;
-		}
+	if (mod == &kernel_module)
+		return -EINVAL;
+	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = 0;
+	for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
+		const char *ref_name = ref->ref->name;
+
+		len = strlen(ref_name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, ref_name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
 	}
+
+	if (put_user(nrefs, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	for (space += len; ref; ref = ref->next_ref)
+		space += strlen(ref->ref->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static int
+qm_symbols(struct module *mod, char *buf, size_t bufsize, size_t *ret)
+{
+	size_t i, space, len;
+	struct module_symbol *s;
+	char *strings;
+	unsigned long *vals;
+
+	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = mod->nsyms * 2*sizeof(void *);
+
+	if (!access_ok(VERIFY_WRITE, buf, space))
+		return -EFAULT;
+
+	i = len = 0;
+	s = mod->syms;
+
+	if (space > bufsize)
+		goto calc_space_needed;
+
+	bufsize -= space;
+	vals = (unsigned long *)buf;
+	strings = buf+space;
+
+	for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
+		len = strlen(s->name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+
+		if (copy_to_user(strings, s->name, len)
+		    || __put_user(s->value, vals+0)
+		    || __put_user(space, vals+1))
+			return -EFAULT;
+
+		strings += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(i, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	for (space += len; i < mod->nsyms; ++i, ++s)
+		space += strlen(s->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
 }
 
-/*
- * Try to free modules which have been marked for deletion.  Returns nonzero
- * if a module was actually freed.
- */
-int
-free_modules( void)
+static int
+qm_info(struct module *mod, char *buf, size_t bufsize, size_t *ret)
 {
-	struct module *mp;
-	struct module **mpp;
-	int did_deletion;
-
-	did_deletion = 0;
-	freeing_modules = 0;
-	mpp = &module_list;
-	while ((mp = *mpp) != NULL) {
-		if (mp->state != MOD_DELETED) {
-			mpp = &mp->next;
-		} else {
-			if ((GET_USE_COUNT(mp) != 0) || (mp->ref != NULL)) {
-				freeing_modules = 1;
-				mpp = &mp->next;
-			} else {	/* delete it */
-				*mpp = mp->next;
-				if (mp->symtab) {
-					if (mp->symtab->n_refs)
-						drop_refs(mp);
-					if (mp->symtab->size)
-						kfree_s(mp->symtab, mp->symtab->size);
-				}
-				vfree(mp->addr);
-				kfree_s(mp, sizeof(struct module) + MOD_MAX_NAME);
-				did_deletion = 1;
-			}
+	int error = 0;
+
+	if (mod == &kernel_module)
+		return -EINVAL;
+
+	if (sizeof(struct module_info) <= bufsize) {
+		struct module_info info;
+		info.addr = (unsigned long)mod;
+		info.size = mod->size;
+		info.flags = mod->flags;
+
+		if (copy_to_user(buf, &info, sizeof(struct module_info)))
+			return -EFAULT;
+	} else
+		error = -ENOSPC;
+
+	if (put_user(sizeof(struct module_info), ret))
+		return -EFAULT;
+
+	return error;
+}
+
+asmlinkage int
+sys_query_module(const char *name_user, int which, char *buf, size_t bufsize,
+		 size_t *ret)
+{
+	struct module *mod;
+
+	if (name_user == NULL)
+		mod = &kernel_module;
+	else {
+		long namelen;
+		char *name;
+
+		if ((namelen = get_mod_name(name_user, &name)) < 0)
+			return namelen;
+		if (namelen == 0)
+			mod = &kernel_module;
+		else if ((mod = find_module(name)) == NULL) {
+			put_mod_name(name);
+			return -ENOENT;
 		}
+		put_mod_name(name);
 	}
-	return did_deletion;
-}
 
+	switch (which)
+	{
+	case 0:
+		return 0;
+	case QM_MODULES:
+		return qm_modules(buf, bufsize, ret);
+	case QM_DEPS:
+		return qm_deps(mod, buf, bufsize, ret);
+	case QM_REFS:
+		return qm_refs(mod, buf, bufsize, ret);
+	case QM_SYMBOLS:
+		return qm_symbols(mod, buf, bufsize, ret);
+	case QM_INFO:
+		return qm_info(mod, buf, bufsize, ret);
+	}
+
+	return -EINVAL;
+}
 
 /*
- * Called by the /proc file system to return a current list of modules.
+ * Copy the kernel symbol table to user space.  If the argument is
+ * NULL, just return the size of the table.
+ *
+ * This call is depreciated in favour of query_module+QM_SYMBOLS which
+ * does not arbitrarily limit the length of the symbol.
  */
-int get_module_list(char *buf)
+
+asmlinkage int
+sys_get_kernel_syms(struct kernel_sym *table)
 {
-	char *p;
-	const char *q;
+	struct module *mod;
 	int i;
-	struct module *mp;
-	struct module_ref *ref;
-	char size[32];
 
-	p = buf;
-	/* Do not show the kernel pseudo module */
-	for (mp = module_list ; mp && mp->next; mp = mp->next) {
-		if (p - buf > 4096 - 100)
-			break;			/* avoid overflowing buffer */
-		q = mp->name;
-		if (*q == '\0' && mp->size == 0 && mp->ref == NULL)
-			continue; /* don't list modules for kernel syms */
-		i = 20;
-		while (*q) {
-			*p++ = *q++;
-			i--;
-		}
-		sprintf(size, "%d", mp->size);
-		i -= strlen(size);
-		if (i <= 0)
-			i = 1;
-		while (--i >= 0)
-			*p++ = ' ';
-		q = size;
-		while (*q)
-			*p++ = *q++;
-		if (mp->state == MOD_UNINITIALIZED)
-			q = "  (uninitialized)";
-		else if (mp->state == MOD_RUNNING)
-			q = "";
-		else if (mp->state == MOD_DELETED)
-			q = "  (deleted)";
-		else
-			q = "  (bad state)";
-		while (*q)
-			*p++ = *q++;
-
-		*p++ = '\t';
-		if ((ref = mp->ref) != NULL) {
-			*p++ = '[';
-			for (; ref; ref = ref->next) {
-				q = ref->module->name;
-				while (*q)
-					*p++ = *q++;
-				if (ref->next)
-					*p++ = ' ';
-			}
-			*p++ = ']';
-		}
-		if (mp->state == MOD_RUNNING) {
-			sprintf(size,"\t%ld%s",
-				GET_USE_COUNT(mp) & ~(MOD_AUTOCLEAN | MOD_VISITED),
-				((GET_USE_COUNT(mp) & MOD_AUTOCLEAN)?
-					" (autoclean)":""));
-			q = size;
-			while (*q)
-				*p++ = *q++;
+	for (mod = module_list, i = 0; mod; mod = mod->next) {
+		/* include the count for the module name! */
+		i += mod->nsyms + 1;
+	}
+
+	if (table == NULL)
+		return i;
+
+	for (mod = module_list, i = 0; mod; mod = mod->next) {
+		struct kernel_sym ksym;
+		struct module_symbol *msym;
+		unsigned int j;
+
+		if ((mod->flags & (MOD_RUNNING|MOD_DELETED)) != MOD_RUNNING)
+			continue;
+
+		/* magic: write module info as a pseudo symbol */
+		ksym.value = (unsigned long)mod;
+		ksym.name[0] = '#';
+		strncpy(ksym.name+1, mod->name, sizeof(ksym.name)-1);
+		ksym.name[sizeof(ksym.name)-1] = '\0';
+
+		if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)
+			return i;
+		++i, ++table;
+
+		if (mod->nsyms == 0)
+			continue;
+
+		for (j = 0, msym = mod->syms; j < mod->nsyms; ++j, ++msym) {
+			ksym.value = msym->value;
+			strncpy(ksym.name, msym->name, sizeof(ksym.name));
+			ksym.name[sizeof(ksym.name)-1] = '\0';
+
+			if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)
+				return i;
+			++i, ++table;
 		}
-		*p++ = '\n';
 	}
-	return p - buf;
+	return i;
 }
 
-
 /*
- * Called by the /proc file system to return a current list of ksyms.
+ * Look for a module by name, ignoring modules marked for deletion.
  */
-int get_ksyms_list(char *buf, char **start, off_t offset, int length)
+
+static struct module *
+find_module(const char *name)
 {
-	struct module *mp;
-	struct internal_symbol *sym;
-	int i;
-	char *p = buf;
-	int len     = 0;	/* code from  net/ipv4/proc.c */
-	off_t pos   = 0;
-	off_t begin = 0;
+	struct module *mod;
 
-	for (mp = module_list; mp; mp = mp->next) {
-		if ((mp->state == MOD_RUNNING) &&
-		    (mp->symtab != NULL) &&
-		    (mp->symtab->n_symbols > 0)) {
-			for (i = mp->symtab->n_symbols,
-				sym = mp->symtab->symbol;
-				i > 0; --i, ++sym) {
-
-				p = buf + len;
-				if (mp->name[0]) {
-					len += sprintf(p, "%08lx %s\t[%s]\n",
-						       (long)sym->addr,
-						       sym->name, mp->name);
-				} else {
-					len += sprintf(p, "%08lx %s\n",
-						       (long)sym->addr,
-						       sym->name);
-				}
-				pos = begin + len;
-				if (pos < offset) {
-					len   = 0;
-					begin = pos;
-				}
-				pos = begin + len;
-				if (pos > offset+length)
-					goto leave_the_loop;
-			}
-		}
+	for (mod = module_list; mod ; mod = mod->next) {
+		if (mod->flags & MOD_DELETED)
+			continue;
+		if (!strcmp(mod->name, name))
+			break;
 	}
-    leave_the_loop:
-	*start = buf + (offset - begin);
-	len -= (offset - begin);
-	if (len > length)
-		len = length;
-	return len;
+
+	return mod;
 }
 
 /*
- * Rules:
- * - The new symbol table should be statically allocated, or else you _have_
- *   to set the "size" field of the struct to the number of bytes allocated.
- *
- * - The strings that name the symbols will not be copied, maybe the pointers
- *
- * - For a loadable module, the function should only be called in the
- *   context of init_module
- *
- * Those are the only restrictions! (apart from not being reentrant...)
- *
- * If you want to remove a symbol table for a loadable module,
- * the call looks like: "register_symtab(0)".
- *
- * The look of the code is mostly dictated by the format of
- * the frozen struct symbol_table, due to compatibility demands.
+ * Free the given module.
  */
-#define INTSIZ sizeof(struct internal_symbol)
-#define REFSIZ sizeof(struct module_ref)
-#define SYMSIZ sizeof(struct symbol_table)
-#define MODSIZ sizeof(struct module)
-static struct symbol_table nulltab;
 
-int
-register_symtab_from(struct symbol_table *intab, long *from)
+static void
+free_module(struct module *mod)
 {
-	struct module *mp;
-	struct module *link;
-	struct symbol_table *oldtab;
-	struct symbol_table *newtab;
-	struct module_ref *newref;
-	int size;
-
-	if (intab && (intab->n_symbols == 0)) {
-		struct internal_symbol *sym;
-		/* How many symbols, really? */
-
-		for (sym = intab->symbol; sym->name; ++sym)
-			intab->n_symbols +=1;
-	}
-
-	for (mp = module_list; mp != &kernel_module; mp = mp->next) {
-		/*
-		 * "from" points to "mod_use_count_" (== start of module)
-		 * or is == 0 if called from a non-module
-		 */
-		if ((unsigned long)(mp->addr) == (unsigned long)from)
-			break;
+	struct module_ref *dep;
+	unsigned i;
+
+	/* Let the module clean up.  */
+
+	mod->flags |= MOD_DELETED;
+	if (mod->flags & MOD_RUNNING) {
+		mod->cleanup();
+		mod->flags &= ~MOD_RUNNING;
 	}
 
-	if (mp == &kernel_module) {
-		/* Aha! Called from an "internal" module */
-		if (!intab)
-			return 0; /* or -ESILLY_PROGRAMMER :-) */
-
-		/* create a pseudo module! */
-		if (!(mp = (struct module*) kmalloc(MODSIZ, GFP_KERNEL))) {
-			/* panic time! */
-			printk(KERN_ERR "Out of memory for new symbol table!\n");
-			return -ENOMEM;
-		}
-		/* else  OK */
-		memset(mp, 0, MODSIZ);
-		mp->state = MOD_RUNNING; /* Since it is resident... */
-		mp->name = ""; /* This is still the "kernel" symbol table! */
-		mp->symtab = intab;
-
-		/* link it in _after_ the resident symbol table */
-		mp->next = kernel_module.next;
-		kernel_module.next = mp;
+	/* Remove the module from the dependancy lists.  */
 
-		return 0;
+	for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
+		struct module_ref **pp;
+		for (pp = &dep->dep->refs; *pp != dep; pp = &(*pp)->next_ref)
+			continue;
+		*pp = dep->next_ref;
 	}
 
-	/* else ******** Called from a loadable module **********/
+	/* And from the main module list.  */
 
-	/*
-	 * This call should _only_ be done in the context of the
-	 * call to  init_module  i.e. when loading the module!!
-	 * Or else...
-	 */
-
-	/* Any table there before? */
-	if ((oldtab = mp->symtab) == (struct symbol_table*)0) {
-		/* No, just insert it! */
-		mp->symtab = intab;
-		return 0;
+	if (mod == module_list) {
+		module_list = mod->next;
+	} else {
+		struct module *p;
+		for (p = module_list; p->next != mod; p = p->next)
+			continue;
+		p->next = mod->next;
 	}
 
-	/* else  ****** we have to replace the module symbol table ******/
+	/* And free the memory.  */
 
-	if (oldtab->n_refs == 0) { /* no problems! */
-		mp->symtab = intab;
-		/* if the old table was kmalloc-ed, drop it */
-		if (oldtab->size > 0)
-			kfree_s(oldtab, oldtab->size);
+	vfree(mod);
+}
 
-		return 0;
-	}
+/*
+ * Called by the /proc file system to return a current list of modules.
+ */
 
-	/* else */
-	/***** The module references other modules... insmod said so! *****/
-	/* We have to allocate a new symbol table, or we lose them! */
-	if (intab == (struct symbol_table*)0)
-		intab = &nulltab; /* easier code with zeroes in place */
-
-	/* the input symbol table space does not include the string table */
-	/* (it does for symbol tables that insmod creates) */
-
-	if (!(newtab = (struct symbol_table*)kmalloc(
-		size = SYMSIZ + intab->n_symbols * INTSIZ +
-			oldtab->n_refs * REFSIZ,
-		GFP_KERNEL))) {
-		/* panic time! */
-		printk(KERN_ERR "Out of memory for new symbol table!\n");
-		return -ENOMEM;
-	}
+int get_module_list(char *p)
+{
+	size_t left = PAGE_SIZE;
+	struct module *mod;
+	char tmpstr[64];
+	struct module_ref *ref;
+
+	for (mod = module_list; mod != &kernel_module; mod = mod->next) {
+		long len;
+		const char *q;
 
-	/* copy up to, and including, the new symbols */
-	memcpy(newtab, intab, SYMSIZ + intab->n_symbols * INTSIZ);
+#define safe_copystr(str, len)						\
+		do {							\
+			if (left < len)					\
+				goto fini;				\
+			memcpy(p, str, len); p += len, left -= len;	\
+		} while (0)
 
-	newtab->size = size;
-	newtab->n_refs = oldtab->n_refs;
+        	len = strlen(mod->name);
+		safe_copystr(mod->name, len);
 
-	/* copy references */
-	memcpy( ((char *)newtab) + SYMSIZ + intab->n_symbols * INTSIZ,
-		((char *)oldtab) + SYMSIZ + oldtab->n_symbols * INTSIZ,
-		oldtab->n_refs * REFSIZ);
+		if ((len = 20 - len) > 0) {
+			if (left < len)
+				goto fini;
+			memset(p, ' ', len);
+			p += len;
+			left -= len;
+		}
 
-	/* relink references from the old table to the new one */
+		len = sprintf(tmpstr, "%8lu", mod->size);
+		safe_copystr(tmpstr, len);
+
+		if (mod->flags & MOD_RUNNING) {
+			len = sprintf(tmpstr, "%4lu", mod->usecount);
+			safe_copystr(tmpstr, len);
+		}
 
-	/* pointer to the first reference entry in newtab! Really! */
-	newref = (struct module_ref*) &(newtab->symbol[newtab->n_symbols]);
+		if (mod->flags & MOD_DELETED)
+			q = "  (deleted)";
+		else if (mod->flags & MOD_RUNNING)
+			q = "";
+		else
+			q = "  (uninitialized)";
+		len = strlen(q);
+		safe_copystr(q, len);
+
+		safe_copystr("\t", 1);
+
+		if ((ref = mod->refs) != NULL) {
+			safe_copystr("[", 1);
+			while (1) {
+				q = ref->ref->name;
+				len = strlen(q);
+				safe_copystr(q, len);
+
+				if ((ref = ref->next_ref) != NULL)
+					safe_copystr(" ", 1);
+				else
+					break;
+			}
+			safe_copystr("]", 1);
+		}
+
+		if ((mod->flags & (MOD_RUNNING | MOD_AUTOCLEAN))
+		    == (MOD_RUNNING | MOD_AUTOCLEAN)) {
+			safe_copystr(" (autoclean)", 12);
+		}
 
-	/* check for reference links from previous modules */
-	for (	link = module_list;
-		link && (link != &kernel_module);
-		link = link->next) {
+		safe_copystr("\n", 1);
 
-		if (link->ref && (link->ref->module == mp))
-			link->ref = newref++;
+#undef safe_copystr
 	}
 
-	mp->symtab = newtab;
+fini:
+	return PAGE_SIZE - left;
+}
 
-	/* all references (if any) have been handled */
+/*
+ * Called by the /proc file system to return a current list of ksyms.
+ */
 
-	/* if the old table was kmalloc-ed, drop it */
-	if (oldtab->size > 0)
-		kfree_s(oldtab, oldtab->size);
+int
+get_ksyms_list(char *buf, char **start, off_t offset, int length)
+{
+	struct module *mod;
+	char *p = buf;
+	int len     = 0;	/* code from  net/ipv4/proc.c */
+	off_t pos   = 0;
+	off_t begin = 0;
 
-	return 0;
+	for (mod = module_list; mod; mod = mod->next) {
+		unsigned i;
+		struct module_symbol *sym;
+
+		if (!(mod->flags & MOD_RUNNING) || (mod->flags & MOD_DELETED))
+			continue;
+
+		for (i = mod->nsyms, sym = mod->syms; i > 0; --i, ++sym) {
+			p = buf + len;
+			if (*mod->name) {
+				len += sprintf(p, "%0*lx %s\t[%s]\n",
+					       (int)(2*sizeof(void*)),
+					       sym->value, sym->name,
+					       mod->name);
+			} else {
+				len += sprintf(p, "%0*lx %s\n",
+					       (int)(2*sizeof(void*)),
+					       sym->value, sym->name);
+			}
+			pos = begin + len;
+			if (pos < offset) {
+				len = 0;
+				begin = pos;
+			}
+			pos = begin + len;
+			if (pos > offset+length)
+				goto leave_the_loop;
+		}
+	}
+leave_the_loop:
+	*start = buf + (offset - begin);
+	len -= (offset - begin);
+	if (len > length)
+		len = length;
+	return len;
 }
 
 #else		/* CONFIG_MODULES */
 
 /* Dummy syscalls for people who don't want modules */
 
-asmlinkage unsigned long sys_create_module(void)
+asmlinkage unsigned long
+sys_create_module(const char *name_user, size_t size)
 {
 	return -ENOSYS;
 }
 
-asmlinkage int sys_init_module(void)
+asmlinkage int
+sys_init_module(const char *name_user, struct module *mod_user)
 {
 	return -ENOSYS;
 }
 
-asmlinkage int sys_delete_module(void)
+asmlinkage int
+sys_delete_module(const char *name_user)
 {
 	return -ENOSYS;
 }
 
-asmlinkage int sys_get_kernel_syms(void)
+asmlinkage int
+sys_query_module(const char *name_user, int which, char *buf, size_t bufsize,
+		 size_t *ret)
 {
+	/* Let the program know about the new interface.  Not that
+	   it'll do them much good.  */
+	if (which == 0)
+		return 0;
+
 	return -ENOSYS;
 }
 
-int register_symtab_from(struct symbol_table *intab, long *from)
+asmlinkage int
+sys_get_kernel_syms(struct kernel_sym *table)
 {
-	return 0;
+	return -ENOSYS;
 }
 
 #endif	/* CONFIG_MODULES */
-
diff -u --recursive --new-file v2.1.17/linux/net/802/llc_macinit.c linux/net/802/llc_macinit.c
--- v2.1.17/linux/net/802/llc_macinit.c	Wed Dec 18 15:59:14 1996
+++ linux/net/802/llc_macinit.c	Fri Dec 27 12:04:48 1996
@@ -1,9 +1,9 @@
 /*
  * NET		An implementation of the IEEE 802.2 LLC protocol for the
- *		LINUX operating system.  LLC is implemented as a set of 
+ *		LINUX operating system.  LLC is implemented as a set of
  *		state machines and callbacks for higher networking layers.
  *
- *		Code for initialization, termination, registration and 
+ *		Code for initialization, termination, registration and
  *		MAC layer glue.
  *
  *		Written by Tim Alpaerts, Tim_Alpaerts@toyota-motor-europe.com
@@ -16,7 +16,7 @@
  *	Changes
  *		Alan Cox	:	Chainsawed to Linux format
  *					Added llc_ to names
- *					Started restructuring handlers 
+ *					Started restructuring handlers
  */
 
 #include <linux/module.h>
@@ -35,11 +35,11 @@
 /*
  *	All incoming frames pass thru mac_data_indicate().
  *	Here an llc structure is associated with an skb depending on the source
- *	MAC address in the pdu. 
+ *	MAC address in the pdu.
  *	The received sk_buffs with pdus other than I_CMD and I_RSP
  *	are freed by mac_data_indicate() after processing,
  *	the I pdu buffers are freed by the cl2llc client when it no longer needs
- *	the skb. 
+ *	the skb.
 */
 
 int llc_mac_data_indicate(llcptr lp, struct sk_buff *skb, struct device *dev, struct packet_type *pt)
@@ -49,12 +49,12 @@
 	unsigned char type;
 	frameptr fr;
 	int free=1;
-	
+
 	/*
-	 *	Truncate buffer to true 802.3 length  
+	 *	Truncate buffer to true 802.3 length
 	 *	[FIXME: move to 802.2 demux]
 	 */
-	  
+
 	ll = *(skb->data -2) * 256 + *(skb->data -1);
 	skb_trim( skb, ll );
 
@@ -64,23 +64,23 @@
 
 	if (type <= FRMR_RSP)
 	{
-		/* 
-		 *	PDU is of the type 2 set 
+		/*
+		 *	PDU is of the type 2 set
 		 */
-		if ((lp->llc_mode == MODE_ABM)||(type == SABME_CMD)) 
+		if ((lp->llc_mode == MODE_ABM)||(type == SABME_CMD))
 			llc_process_otype2_frame(lp, skb, type);
-              
+
 	}
-	else 
+	else
 	{
 		/*
-		 *	PDU belongs to type 1 set 
+		 *	PDU belongs to type 1 set
 		 */
 	        p_flag = fr->u_hdr.u_pflag;
         	switch(type)
         	{
 		        case TEST_CMD:
-				llc_sendpdu(lp, TEST_RSP, 0,ll -3, 
+				llc_sendpdu(lp, TEST_RSP, 0,ll -3,
 					fr->u_hdr.u_info);
 				break;
 			case TEST_RSP:
@@ -88,12 +88,12 @@
 				{
 					lp->ops->test_indication_ep(lp,
 						ll -3, fr->u_hdr.u_info);
-				}   
+				}
 				break;
-			case XID_CMD: 	
+			case XID_CMD:
 				/*
-				 *	Basic format XID is handled by LLC itself 
-				 *	Doc 5.4.1.1.2 p 48/49 
+				 *	Basic format XID is handled by LLC itself
+				 *	Doc 5.4.1.1.2 p 48/49
 				 */
 
 				if ((ll == 6)&&(fr->u_hdr.u_info[0] == 0x81))
@@ -105,10 +105,10 @@
 				}
 				break;
 
-			case XID_RSP:	        
+			case XID_RSP:
 				if( ll == 6 && fr->u_hdr.u_info[0] == 0x81 )
 				{
-					lp->k = fr->u_hdr.u_info[2]; 
+					lp->k = fr->u_hdr.u_info[2];
 				}
 				if (lp->ops->xid_indication_ep != NULL)
 				{
@@ -118,24 +118,24 @@
 				break;
 
 			case UI_CMD:
-				if(lp->ops->unit_data_indication_ep != NULL) 
+				if(lp->ops->unit_data_indication_ep != NULL)
 				{
 					free=lp->ops->unit_data_indication_ep(lp,
 						ll-3, fr->u_hdr.u_info);
 				}
 				break;
-	               
-			default: 
+
+			default:
 				/*
-				 *	All other type 1 pdus ignored for now 
+				 *	All other type 1 pdus ignored for now
 				 */
-		}         
+		}
 	}
-	
+
 	if (free&&(!(IS_IFRAME(fr))))
 	{
 		/*
-		 *	No auto free for I pdus 
+		 *	No auto free for I pdus
 		 */
 		skb->sk = NULL;
 		kfree_skb(skb, FREE_READ);
@@ -148,9 +148,9 @@
  *	Create an LLC client. As it is the job of the caller to clean up
  *	LLC's on device down, the device list must be locked before this call.
  */
- 
+
 int register_cl2llc_client(llcptr lp, const char *device, llc_ops *ops, u8 *rmac, u8 ssap, u8 dsap)
-{       
+{
 	char eye_init[] = "LLC\0";
 
 	memset(lp, 0, sizeof(*lp));
@@ -163,12 +163,12 @@
 	lp->n1 = 1490;
 	lp->n2 = 10;
 	lp->timer_interval[P_TIMER] = HZ;    /* 1 sec */
-	lp->timer_interval[REJ_TIMER] = HZ/8; 
+	lp->timer_interval[REJ_TIMER] = HZ/8;
 	lp->timer_interval[ACK_TIMER] = HZ/8;
 	lp->timer_interval[BUSY_TIMER] = HZ*2;
 	lp->local_sap = ssap;
 	lp->ops = ops;
-	lp->remote_mac_len = lp->dev->addr_len; 
+	lp->remote_mac_len = lp->dev->addr_len;
 	memcpy(lp->remote_mac, rmac, lp->remote_mac_len);
 	lp->state = 0;
 	lp->llc_mode = MODE_ADM;
@@ -188,26 +188,20 @@
 }
 
 
-static struct symbol_table cl2llc_proto_syms = 
-{
-#include <linux/symtab_begin.h>
-	X(register_cl2llc_client),
-	X(unregister_cl2llc_client),
-	X(llc_data_request),
-	X(llc_unit_data_request),
-	X(llc_test_request),
-	X(llc_xid_request),
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(register_cl2llc_client);
+EXPORT_SYMBOL(unregister_cl2llc_client);
+EXPORT_SYMBOL(llc_data_request);
+EXPORT_SYMBOL(llc_unit_data_request);
+EXPORT_SYMBOL(llc_test_request);
+EXPORT_SYMBOL(llc_xid_request);
 
 
 #define ALL_TYPES_8022 0
 
 void llc_init(struct net_proto *proto)
 {
-	register_symtab( &cl2llc_proto_syms ); 
 	printk(KERN_NOTICE "IEEE 802.2 LLC for Linux 2.1 (c) 1996 Tim Alpaerts\n");
-	return;        
+	return;
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.1.17/linux/net/802/p8022.c linux/net/802/p8022.c
--- v2.1.17/linux/net/802/p8022.c	Mon Mar 25 08:58:23 1996
+++ linux/net/802/p8022.c	Fri Dec 27 12:04:48 1996
@@ -14,7 +14,7 @@
  *	frames. We have the absolute minimum needed for IPX,
  *	IP and Appletalk phase 2.
  */
- 
+
 static struct datalink_proto *
 find_8022_client(unsigned char type)
 {
@@ -46,7 +46,7 @@
 }
 
 static void
-p8022_datalink_header(struct datalink_proto *dl, 
+p8022_datalink_header(struct datalink_proto *dl,
 		struct sk_buff *skb, unsigned char *dest_node)
 {
 	struct device	*dev = skb->dev;
@@ -59,7 +59,7 @@
 	dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len);
 }
 
-static struct packet_type p8022_packet_type = 
+static struct packet_type p8022_packet_type =
 {
 	0,	/* MUTTER ntohs(ETH_P_8022),*/
 	NULL,		/* All devices */
@@ -68,21 +68,15 @@
 	NULL,
 };
 
-static struct symbol_table p8022_proto_syms = {
-#include <linux/symtab_begin.h>
-	X(register_8022_client),
-	X(unregister_8022_client),
-#include <linux/symtab_end.h>
-};
- 
+EXPORT_SYMBOL(register_8022_client);
+EXPORT_SYMBOL(unregister_8022_client);
 
 void p8022_proto_init(struct net_proto *pro)
 {
 	p8022_packet_type.type=htons(ETH_P_802_2);
 	dev_add_pack(&p8022_packet_type);
-	register_symtab(&p8022_proto_syms);
 }
-	
+
 struct datalink_proto *
 register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *))
 {
diff -u --recursive --new-file v2.1.17/linux/net/802/p8022tr.c linux/net/802/p8022tr.c
--- v2.1.17/linux/net/802/p8022tr.c	Sat Mar 30 13:20:33 1996
+++ linux/net/802/p8022tr.c	Fri Dec 27 12:04:48 1996
@@ -16,7 +16,7 @@
  *	frames. We have the absolute minimum needed for IPX,
  *	IP and Appletalk phase 2.
  */
- 
+
 static struct datalink_proto *
 find_8022tr_client(unsigned char type)
 {
@@ -48,7 +48,7 @@
 }
 
 static void
-p8022tr_datalink_header(struct datalink_proto *dl, 
+p8022tr_datalink_header(struct datalink_proto *dl,
 		struct sk_buff *skb, unsigned char *dest_node)
 {
 	struct device	*dev = skb->dev;
@@ -66,30 +66,25 @@
 	memmove(newdata, olddata, dev->hard_header_len - SNAP_HEADER_LEN);
 }
 
-static struct packet_type p8022tr_packet_type = 
+static struct packet_type p8022tr_packet_type =
 {
-	0,	
+	0,
 	NULL,		/* All devices */
 	p8022tr_rcv,
 	NULL,
 	NULL,
 };
- 
 
-static struct symbol_table p8022tr_proto_syms = {
-#include <linux/symtab_begin.h>
-	X(register_8022tr_client),
-	X(unregister_8022tr_client),
-#include <linux/symtab_end.h>
-};
+
+EXPORT_SYMBOL(register_8022tr_client);
+EXPORT_SYMBOL(unregister_8022tr_client);
 
 void p8022tr_proto_init(struct net_proto *pro)
 {
 	p8022tr_packet_type.type=htons(ETH_P_TR_802_2);
 	dev_add_pack(&p8022tr_packet_type);
-	register_symtab(&p8022tr_proto_syms);
 }
-	
+
 struct datalink_proto *
 register_8022tr_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *))
 {
@@ -134,4 +129,3 @@
 
 	restore_flags(flags);
 }
-
diff -u --recursive --new-file v2.1.17/linux/net/802/psnap.c linux/net/802/psnap.c
--- v2.1.17/linux/net/802/psnap.c	Mon Mar 25 08:58:23 1996
+++ linux/net/802/psnap.c	Fri Dec 27 12:04:48 1996
@@ -9,7 +9,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  */
- 
+
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
@@ -25,7 +25,7 @@
 /*
  *	Find a snap client by matching the 5 bytes.
  */
- 
+
 static struct datalink_proto *find_snap_client(unsigned char *desc)
 {
 	struct datalink_proto	*proto;
@@ -37,27 +37,27 @@
 /*
  *	A SNAP packet has arrived
  */
- 
+
 int snap_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 {
-	static struct packet_type psnap_packet_type = 
+	static struct packet_type psnap_packet_type =
 	{
-		0,	
+		0,
 		NULL,		/* All Devices */
 		snap_rcv,
 		NULL,
 		NULL,
 	};
-	
+
 	struct datalink_proto	*proto;
 
 	proto = find_snap_client(skb->h.raw);
-	if (proto != NULL) 
+	if (proto != NULL)
 	{
 		/*
 		 *	Pass the frame on.
 		 */
-		 
+
 		skb->h.raw += 5;
 		skb_pull(skb,5);
 		if (psnap_packet_type.type == 0)
@@ -72,7 +72,7 @@
 /*
  *	Put a SNAP header on a frame and pass to 802.2
  */
- 
+
 static void snap_datalink_header(struct datalink_proto *dl, struct sk_buff *skb, unsigned char *dest_node)
 {
 	memcpy(skb_push(skb,5),dl->type,5);
@@ -83,25 +83,20 @@
  *	Set up the SNAP layer
  */
 
-static struct symbol_table snap_proto_syms = {
-#include <linux/symtab_begin.h>
-	X(register_snap_client),
-	X(unregister_snap_client),
-#include <linux/symtab_end.h>
-};
- 
+EXPORT_SYMBOL(register_snap_client);
+EXPORT_SYMBOL(unregister_snap_client);
+
 void snap_proto_init(struct net_proto *pro)
 {
 	snap_dl=register_8022_client(0xAA, snap_rcv);
 	if(snap_dl==NULL)
 		printk("SNAP - unable to register with 802.2\n");
-	register_symtab(&snap_proto_syms);
 }
-	
+
 /*
  *	Register SNAP clients. We don't yet use this for IP or IPX.
  */
- 
+
 struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *))
 {
 	struct datalink_proto	*proto;
@@ -110,7 +105,7 @@
 		return NULL;
 
 	proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
-	if (proto != NULL) 
+	if (proto != NULL)
 	{
 		memcpy(proto->type, desc,5);
 		proto->type_len = 5;
@@ -152,4 +147,3 @@
 
 	restore_flags(flags);
 }
-
diff -u --recursive --new-file v2.1.17/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v2.1.17/linux/net/appletalk/ddp.c	Sun Dec 22 16:37:42 1996
+++ linux/net/appletalk/ddp.c	Fri Dec 27 12:04:49 1996
@@ -5,8 +5,8 @@
  *		Alan Cox  <Alan.Cox@linux.org>
  *			  <iialan@www.linux.org.uk>
  *
- *		With more than a little assistance from 
- *	
+ *		With more than a little assistance from
+ *
  *		Wesley Craig <netatalk@umich.edu>
  *
  *	Fixes:
@@ -33,7 +33,7 @@
  *	TODO
  *		ASYNC I/O
  */
- 
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <asm/uaccess.h>
@@ -95,15 +95,15 @@
  *	handler using this technique. They can be added although we do not
  *	use this facility.
  */
- 
+
 static void atalk_remove_socket(struct sock *sk)
 {
 	unsigned long flags;
 	struct sock *s;
-	
+
 	save_flags(flags);
 	cli();
-	
+
 	s=atalk_socket_list;
 	if(s==sk)
 	{
@@ -138,22 +138,22 @@
 {
 	struct sock *s;
 
-	for( s = atalk_socket_list; s != NULL; s = s->next ) 
+	for( s = atalk_socket_list; s != NULL; s = s->next )
 	{
-		if ( to->sat_port != s->protinfo.af_at.src_port ) 
+		if ( to->sat_port != s->protinfo.af_at.src_port )
 		{
 			continue;
 	   	}
 
 	    	if ( to->sat_addr.s_net == 0 &&
 		    to->sat_addr.s_node == ATADDR_BCAST &&
-		    s->protinfo.af_at.src_net == atif->address.s_net ) 
+		    s->protinfo.af_at.src_net == atif->address.s_net )
 		{
 			break;
 	    	}
 
 	    	if ( to->sat_addr.s_net == s->protinfo.af_at.src_net &&
-		    (to->sat_addr.s_node == s->protinfo.af_at.src_node 
+		    (to->sat_addr.s_node == s->protinfo.af_at.src_node
 		     ||to->sat_addr.s_node == ATADDR_BCAST ))
 		{
 			break;
@@ -167,22 +167,22 @@
 /*
  *	Find a socket in the list.
  */
- 
+
 static struct sock *atalk_find_socket(struct sockaddr_at *sat)
 {
 	struct sock *s;
 
-	for ( s = atalk_socket_list; s != NULL; s = s->next ) 
+	for ( s = atalk_socket_list; s != NULL; s = s->next )
 	{
-		if ( s->protinfo.af_at.src_net != sat->sat_addr.s_net ) 
+		if ( s->protinfo.af_at.src_net != sat->sat_addr.s_net )
 		{
 			continue;
 		}
-		if ( s->protinfo.af_at.src_node != sat->sat_addr.s_node ) 
+		if ( s->protinfo.af_at.src_node != sat->sat_addr.s_node )
 		{
 			continue;
 		}
-		if ( s->protinfo.af_at.src_port != sat->sat_port ) 
+		if ( s->protinfo.af_at.src_port != sat->sat_port )
 		{
 			continue;
 		}
@@ -203,7 +203,7 @@
 /*
  *	Handler for deferred kills.
  */
- 
+
 static void atalk_destroy_timer(unsigned long data)
 {
 	atalk_destroy_socket((struct sock *)data);
@@ -213,12 +213,12 @@
 {
 	struct sk_buff *skb;
 	atalk_remove_socket(sk);
-	
+
 	while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
 	{
 		kfree_skb(skb,FREE_READ);
 	}
-	
+
 	if(sk->wmem_alloc == 0 && sk->rmem_alloc == 0 && sk->dead)
 	{
 		sk_free(sk);
@@ -239,9 +239,9 @@
 
 
 /*
- *	Called from proc fs 
+ *	Called from proc fs
  */
- 
+
 int atalk_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	struct sock *s;
@@ -267,10 +267,10 @@
 			s->protinfo.af_at.dest_port);
 		len += sprintf (buffer+len,"%08X:%08X ", s->wmem_alloc, s->rmem_alloc);
 		len += sprintf (buffer+len,"%02X %d\n", s->state, SOCK_INODE(s->socket)->i_uid);
-		
+
 		/* Are we still dumping unwanted data then discard the record */
 		pos=begin+len;
-		
+
 		if(pos<offset)
 		{
 			len=0;			/* Keep dumping into the buffer start */
@@ -279,13 +279,13 @@
 		if(pos>offset+length)		/* We have dumped enough */
 			break;
 	}
-	
+
 	/* The data in question runs from begin to begin+len */
 	*start=buffer+(offset-begin);	/* Start of wanted data */
 	len-=(offset-begin);		/* Remove unwanted header data from length */
 	if(len>length)
 		len=length;		/* Remove unwanted tail data from length */
-	
+
 	return len;
 }
 
@@ -303,21 +303,21 @@
 /*
  *	Appletalk interface control
  */
- 
+
 /*
- *	Drop a device. Doesn't drop any of its routes - that is the 
- *	the callers problem. Called when we down the interface or 
+ *	Drop a device. Doesn't drop any of its routes - that is the
+ *	the callers problem. Called when we down the interface or
  *	delete the address.
  */
- 
+
 static void atif_drop_device(struct device *dev)
 {
 	struct atalk_iface **iface = &atalk_iface_list;
 	struct atalk_iface *tmp;
 
-	while ((tmp = *iface) != NULL) 
+	while ((tmp = *iface) != NULL)
 	{
-		if (tmp->dev == dev) 
+		if (tmp->dev == dev)
 		{
 			*iface = tmp->next;
 			kfree_s(tmp, sizeof(struct atalk_iface));
@@ -331,7 +331,7 @@
 {
 	struct atalk_iface *iface=(struct atalk_iface *)
 					kmalloc(sizeof(*iface), GFP_KERNEL);
-	unsigned long flags;					
+	unsigned long flags;
 	if(iface==NULL)
 		return NULL;
 	iface->dev=dev;
@@ -348,7 +348,7 @@
 /*
  *	Perform phase 2 AARP probing on our tentative address.
  */
- 
+
 static int atif_probe_device(struct atalk_iface *atif)
 {
 	int ct;
@@ -357,19 +357,19 @@
 	int probe_node=atif->address.s_node;
 	int netct;
 	int nodect;
-	
+
 	struct ifreq atreq;
 	struct sockaddr_at *sa;
 	int err;
 
 /*
  *	THIS IS A HACK: Farallon cards want to do their own picking of
- *	addresses. This needs tidying up post 1.4, but we need it in 
+ *	addresses. This needs tidying up post 1.4, but we need it in
  *	now for the 1.4 release as is.
  *
  */
 	if((atif->dev->type == ARPHRD_LOCALTLK || atif->dev->type == ARPHRD_PPP)
-		&& atif->dev->do_ioctl) 
+		&& atif->dev->do_ioctl)
 	{
 		/* fake up the request and pass it down */
 		sa = (struct sockaddr_at*)&atreq.ifr_addr;
@@ -389,11 +389,11 @@
 		 *	properly. We can then also dump the localtalk test.
 		 */
 		return err;
-	}	
+	}
 	/*
 	 *	Offset the network we start probing with.
 	 */
-	 
+
 	if(probe_net==ATADDR_ANYNET)
 	{
 		if(!netrange)
@@ -401,15 +401,15 @@
 		else
 			probe_net=ntohs(atif->nets.nr_firstnet) + (jiffies%netrange);
 	}
-	
+
 	if(probe_node == ATADDR_ANYNODE)
 		probe_node = jiffies&0xFF;
-	
-	
+
+
 	/*
 	 *	Scan the networks.
 	 */
-	 
+
 	for(netct=0;netct<=netrange;netct++)
 	{
 		/*
@@ -474,7 +474,7 @@
 /*
  *	Give a device find its atif control structure
  */
- 
+
 struct atalk_iface *atalk_find_dev(struct device *dev)
 {
 	struct atalk_iface *iface;
@@ -488,15 +488,15 @@
  *	Find a match for 'any network' - ie any of our interfaces with that
  *	node number will do just nicely.
  */
- 
+
 static struct atalk_iface *atalk_find_anynet(int node, struct device *dev)
 {
 	struct atalk_iface *iface;
-	for(iface=atalk_iface_list;iface!=NULL;iface=iface->next) 
+	for(iface=atalk_iface_list;iface!=NULL;iface=iface->next)
 	{
 		if ( iface->dev != dev || ( iface->status & ATIF_PROBE ))
 			continue;
-		if ( node == ATADDR_BCAST || iface->address.s_node == node ) 
+		if ( node == ATADDR_BCAST || iface->address.s_node == node )
 			return iface;
 	}
 	return NULL;
@@ -505,13 +505,13 @@
 /*
  *	Find a match for a specific network:node pair
  */
- 
+
 static struct atalk_iface *atalk_find_interface(int net, int node)
 {
 	struct atalk_iface *iface;
 	for(iface=atalk_iface_list;iface!=NULL;iface=iface->next)
 	{
-		if((node==ATADDR_BCAST || iface->address.s_node==node) 
+		if((node==ATADDR_BCAST || iface->address.s_node==node)
 			&& iface->address.s_net==net && !(iface->status&ATIF_PROBE))
 			return iface;
 	}
@@ -524,7 +524,7 @@
  *	the socket (later on...). We know about host routes and the fact
  *	that a route must be direct to broadcast.
  */
- 
+
 static struct atalk_route *atrtr_find(struct at_addr *target)
 {
 	struct atalk_route *r;
@@ -543,12 +543,12 @@
 	return NULL;
 }
 
-			
+
 /*
  *	Given an appletalk network find the device to use. This can be
  *	a simple lookup. Funny stuff like routers can wait 8)
  */
- 
+
 static struct device *atrtr_get_dev(struct at_addr *sa)
 {
 	struct atalk_route *atr=atrtr_find(sa);
@@ -561,7 +561,7 @@
 /*
  *	Set up a default router.
  */
- 
+
 static void atrtr_set_default(struct device *dev)
 {
 	atrtr_default.dev=dev;
@@ -575,7 +575,7 @@
  *	entry in the list. While it uses netranges we always set them to one
  *	entry to work like netatalk.
  */
- 
+
 static int atrtr_create(struct rtentry *r, struct device *devhint)
 {
 	struct sockaddr_at *ta=(struct sockaddr_at *)&r->rt_dst;
@@ -583,22 +583,22 @@
 	struct atalk_route *rt;
 	struct atalk_iface *iface, *riface;
 	unsigned long flags;
-	
+
 	save_flags(flags);
-	
+
 	/*
 	 *	Fixme: Raise/Lower a routing change semaphore for these
 	 *	operations.
 	 */
-	 
+
 	/*
 	 *	Validate the request
-	 */	
+	 */
 	if(ta->sat_family!=AF_APPLETALK)
 		return -EINVAL;
 	if(devhint == NULL && ga->sat_family != AF_APPLETALK)
 		return -EINVAL;
-	
+
 	/*
 	 *	Now walk the routing table and make our decisions
 	 */
@@ -608,7 +608,7 @@
 		if(r->rt_flags != rt->flags)
 			continue;
 
-		if(ta->sat_addr.s_net == rt->target.s_net) 
+		if(ta->sat_addr.s_net == rt->target.s_net)
 		{
 			if(!(rt->flags&RTF_HOST))
 				break;
@@ -617,9 +617,9 @@
 		}
 	}
 
-	if ( devhint == NULL ) 
+	if ( devhint == NULL )
 	{
-		for ( riface = NULL, iface = atalk_iface_list; iface; iface = iface->next ) 
+		for ( riface = NULL, iface = atalk_iface_list; iface; iface = iface->next )
 		{
 			if ( riface == NULL && ntohs( ga->sat_addr.s_net ) >= ntohs( iface->nets.nr_firstnet ) &&
 				ntohs( ga->sat_addr.s_net ) <=	ntohs( iface->nets.nr_lastnet ))
@@ -647,11 +647,11 @@
 	/*
 	 *	Fill in the entry.
 	 */
-	rt->target=ta->sat_addr;			
+	rt->target=ta->sat_addr;
 	rt->dev=devhint;
 	rt->flags=r->rt_flags;
 	rt->gateway=ga->sat_addr;
-	
+
 	restore_flags(flags);
 	return 0;
 }
@@ -660,17 +660,17 @@
 /*
  *	Delete a route. Find it and discard it.
  */
- 
+
 static int atrtr_delete( struct at_addr *addr )
 {
 	struct atalk_route **r = &atalk_router_list;
 	struct atalk_route *tmp;
 
-	while ((tmp = *r) != NULL) 
+	while ((tmp = *r) != NULL)
 	{
 		if (tmp->target.s_net == addr->s_net &&
 			    (!(tmp->flags&RTF_GATEWAY) ||
-			    tmp->target.s_node == addr->s_node )) 
+			    tmp->target.s_node == addr->s_node ))
 		{
 			*r = tmp->next;
 			kfree_s(tmp, sizeof(struct atalk_route));
@@ -685,15 +685,15 @@
  *	Called when a device is downed. Just throw away any routes
  *	via it.
  */
- 
+
 void atrtr_device_down(struct device *dev)
 {
 	struct atalk_route **r = &atalk_router_list;
 	struct atalk_route *tmp;
 
-	while ((tmp = *r) != NULL) 
+	while ((tmp = *r) != NULL)
 	{
-		if (tmp->dev == dev) 
+		if (tmp->dev == dev)
 		{
 			*r = tmp->next;
 			kfree_s(tmp, sizeof(struct atalk_route));
@@ -728,7 +728,7 @@
 /*
  *	Device configuration ioctl calls.
  */
- 
+
 int atif_ioctl(int cmd, void *arg)
 {
 	struct ifreq atreq;
@@ -741,17 +741,17 @@
 	int ct;
 	int limit;
 	struct rtentry rtdef;
-	
+
 	err = copy_from_user(&atreq,arg,sizeof(atreq));
 	if (err)
-		return -EFAULT; 
+		return -EFAULT;
 
 	if((dev=dev_get(atreq.ifr_name))==NULL)
 		return -ENODEV;
-		
+
 	sa=(struct sockaddr_at*)&atreq.ifr_addr;
 	atif=atalk_find_dev(dev);
-	
+
 	switch(cmd)
 	{
 		case SIOCSIFADDR:
@@ -779,7 +779,7 @@
 				 */
 				if(atif->status&ATIF_PROBE)
 					return -EBUSY;
-					
+
 				atif->address.s_net=sa->sat_addr.s_net;
 				atif->address.s_node=sa->sat_addr.s_node;
 				atrtr_device_down(dev);	/* Flush old routes */
@@ -791,10 +791,10 @@
 			atif->nets= *nr;
 
 			/*
-			 *	Check if the chosen address is used. If so we 
-			 *	error and atalkd will try another. 
+			 *	Check if the chosen address is used. If so we
+			 *	error and atalkd will try another.
 			 */
-			 
+
 			if(!(dev->flags&IFF_LOOPBACK) && atif_probe_device(atif)<0)
 			{
 				atif_drop_device(dev);
@@ -805,7 +805,7 @@
 			 *	Hey it worked - add the direct
 			 *	routes.
 			 */
-				
+
 			sa=(struct sockaddr_at *)&rtdef.rt_gateway;
 			sa->sat_family=AF_APPLETALK;
 			sa->sat_addr.s_net=atif->address.s_net;
@@ -819,13 +819,13 @@
 			/*
 			 *	Routerless initial state.
 			 */
-			if(nr->nr_firstnet==htons(0) && nr->nr_lastnet==htons(0xFFFE)) 
+			if(nr->nr_firstnet==htons(0) && nr->nr_lastnet==htons(0xFFFE))
 			{
 				sa->sat_addr.s_net=atif->address.s_net;
 				atrtr_create(&rtdef, dev);
 				atrtr_set_default(dev);
-			} 
-			else 
+			}
+			else
 			{
 				limit=ntohs(nr->nr_lastnet);
 				if(limit-ntohs(nr->nr_firstnet) > 256)
@@ -867,15 +867,15 @@
 /*
  *	Routing ioctl() calls
  */
-  
+
 static int atrtr_ioctl(unsigned int cmd, void *arg)
 {
 	int err;
 	struct rtentry rt;
-	
+
 	err = copy_from_user(&rt,arg,sizeof(rt));
 	if (err)
-		return -EFAULT; 
+		return -EFAULT;
 
 	switch(cmd)
 	{
@@ -972,15 +972,15 @@
  *	Checksum: This is 'optional'. It's quite likely also a good
  *	candidate for assembler hackery 8)
  */
- 
+
 unsigned short atalk_checksum(struct ddpehdr *ddp, int len)
 {
 	unsigned long sum=0;	/* Assume unsigned long is >16 bits */
 	unsigned char *data=(unsigned char *)ddp;
-	
+
 	len-=4;		/* skip header 4 bytes */
-	data+=4;	
-	
+	data+=4;
+
 	/* This ought to be unwrapped neatly. I'll trust gcc for now */
 	while(len--)
 	{
@@ -997,12 +997,12 @@
 		return htons((unsigned short)sum);
 	return 0xFFFF;		/* Use 0xFFFF for 0. 0 itself means none */
 }
-	
+
 /*
  *	Generic fcntl calls are already dealt with. If we don't need funny ones
  *	this is the all you need. Async I/O is also separate.
  */
-  
+
 static int atalk_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 /*	struct sock *sk=sock->sk;*/
@@ -1014,24 +1014,24 @@
 }
 
 /*
- *	Set 'magic' options for appletalk. If we don't have any this is fine 
+ *	Set 'magic' options for appletalk. If we don't have any this is fine
  *	as it is.
  */
- 
+
 static int atalk_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
 {
 	struct sock *sk;
 	int err,opt;
-	
+
 	sk=sock->sk;
-	
+
 	if(optval==NULL)
 		return(-EINVAL);
 
 	err = get_user(opt, (int *)optval);
 	if (err)
 		return err;
-	
+
 	switch(level)
 	{
 		case SOL_ATALK:
@@ -1041,7 +1041,7 @@
 					return -EOPNOTSUPP;
 			}
 			break;
-			
+
 		default:
 			return -EOPNOTSUPP;
 	}
@@ -1051,14 +1051,14 @@
 /*
  *	Get any magic options. Comment above applies.
  */
- 
+
 static int atalk_getsockopt(struct socket *sock, int level, int optname,
 	char *optval, int *optlen)
 {
 	struct sock *sk;
 	int val=0;
 	int err;
-	
+
 	sk=sock->sk;
 
 	switch(level)
@@ -1084,7 +1084,7 @@
 /*
  *	Only for connection oriented sockets - ignore
  */
- 
+
 static int atalk_listen(struct socket *sock, int backlog)
 {
 	return -EOPNOTSUPP;
@@ -1093,7 +1093,7 @@
 /*
  *	These are standard.
  */
- 
+
 static void def_callback1(struct sock *sk)
 {
 	if(!sk->dead)
@@ -1113,7 +1113,7 @@
  *	Create a socket. Initialise the socket, blank the addresses
  *	set the state.
  */
- 
+
 static int atalk_create(struct socket *sock, int protocol)
 {
 	struct sock *sk;
@@ -1148,15 +1148,15 @@
 	sk->state=TCP_CLOSE;
 	sk->socket=sock;
 	sk->type=sock->type;
-	
+
 	sk->mtu=DDP_MAXSZ;
-	
+
 	if(sock!=NULL)
 	{
 		sk->sleep=&sock->wait;
 		sock->sk=sk;
 	}
-	
+
 	sk->state_change=def_callback1;
 	sk->data_ready=def_callback2;
 	sk->write_space=def_callback1;
@@ -1169,7 +1169,7 @@
 /*
  *	Copy a socket. No work needed.
  */
- 
+
 static int atalk_dup(struct socket *newsock,struct socket *oldsock)
 {
 	return(atalk_create(newsock,SOCK_DGRAM));
@@ -1178,7 +1178,7 @@
 /*
  *	Free a socket. No work needed
  */
- 
+
 static int atalk_release(struct socket *sock, struct socket *peer)
 {
 	struct sock *sk=sock->sk;
@@ -1191,12 +1191,12 @@
 	atalk_destroy_socket(sk);
 	return(0);
 }
-		
+
 /*
  *	Pick a source address if one is not given. Just return
  *	an error if not supportable.
  */
- 
+
 static int atalk_pick_port(struct sockaddr_at *sat)
 {
 	for ( sat->sat_port = ATPORT_RESERVED; sat->sat_port < ATPORT_LAST; sat->sat_port++ )
@@ -1206,7 +1206,7 @@
 	}
 	return -EBUSY;
 }
- 		
+
 static int atalk_autobind(struct sock *sk)
 {
 	struct at_addr *ap = atalk_find_primary();
@@ -1229,17 +1229,17 @@
 /*
  *	Set the address 'our end' of the connection.
  */
- 
+
 static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
 	struct sock *sk;
 	struct sockaddr_at *addr=(struct sockaddr_at *)uaddr;
-	
+
 	sk=sock->sk;
-	
+
 	if(sk->zapped==0)
 		return(-EINVAL);
-		
+
 	if(addr_len!=sizeof(struct sockaddr_at))
 		return -EINVAL;
 
@@ -1255,7 +1255,7 @@
 		sk->protinfo.af_at.src_node=addr->sat_addr.s_node=ap->s_node;
 	}
 	else
-	{			
+	{
 		if ( atalk_find_interface( addr->sat_addr.s_net, addr->sat_addr.s_node ) == NULL )
 			return -EADDRNOTAVAIL;
 		sk->protinfo.af_at.src_net=addr->sat_addr.s_net;
@@ -1273,7 +1273,7 @@
 		sk->protinfo.af_at.src_port=addr->sat_port;
 
 	if(atalk_find_socket(addr)!=NULL)
-		return -EADDRINUSE;	   
+		return -EADDRINUSE;
 
 	atalk_insert_socket(sk);
 	sk->zapped=0;
@@ -1283,35 +1283,35 @@
 /*
  *	Set the address we talk to.
  */
- 
+
 static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
 	int addr_len, int flags)
 {
 	struct sock *sk=sock->sk;
 	struct sockaddr_at *addr;
-	
-	sk->state = TCP_CLOSE;	
+
+	sk->state = TCP_CLOSE;
 	sock->state = SS_UNCONNECTED;
 
 	if(addr_len!=sizeof(*addr))
 		return(-EINVAL);
 	addr=(struct sockaddr_at *)uaddr;
-	
+
 	if(addr->sat_family!=AF_APPLETALK)
 		return -EAFNOSUPPORT;
 #if 0 	/* Netatalk doesn't check this - fix netatalk first!*/
 	if(addr->sat_addr.s_node==ATADDR_BCAST && !sk->broadcast)
 		return -EACCES;
-#endif		
+#endif
 	if(sk->zapped)
 	{
 		if(atalk_autobind(sk)<0)
 			return -EBUSY;
-	}	
-	
+	}
+
 	if(atrtr_get_dev(&addr->sat_addr)==NULL)
 		return -ENETUNREACH;
-		
+
 	sk->protinfo.af_at.dest_port=addr->sat_port;
 	sk->protinfo.af_at.dest_net=addr->sat_addr.s_net;
 	sk->protinfo.af_at.dest_node=addr->sat_addr.s_node;
@@ -1323,7 +1323,7 @@
 /*
  *	Not relevant
  */
- 
+
 static int atalk_socketpair(struct socket *sock1, struct socket *sock2)
 {
 	return(-EOPNOTSUPP);
@@ -1332,10 +1332,10 @@
 /*
  *	Not relevant
  */
- 
+
 static int atalk_accept(struct socket *sock, struct socket *newsock, int flags)
 {
-	if(newsock->sk) {	  
+	if(newsock->sk) {
 		sk_free(newsock->sk);
 		MOD_DEC_USE_COUNT;
 	}
@@ -1346,22 +1346,22 @@
  *	Find the name of an appletalk socket. Just copy the right
  *	fields into the sockaddr.
  */
- 
+
 static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
 	int *uaddr_len, int peer)
 {
 	struct sockaddr_at sat;
 	struct sock *sk;
-	
+
 	sk=sock->sk;
 	if(sk->zapped)
 	{
 		if(atalk_autobind(sk)<0)
 			return -ENOBUFS;
-	}	
-	
+	}
+
 	*uaddr_len = sizeof(struct sockaddr_at);
-		
+
 	if(peer)
 	{
 		if(sk->state!=TCP_ESTABLISHED)
@@ -1383,11 +1383,11 @@
 
 /*
  *	Receive a packet (in skb) from device dev. This has come from the SNAP decoder, and on entry
- *	skb->h.raw is the DDP header, skb->len is the DDP length. The physical headers have been 
+ *	skb->h.raw is the DDP header, skb->len is the DDP length. The physical headers have been
  *	extracted. PPP should probably pass frames marked as for this layer
  *	[ie ARPHRD_ETHERTALK]
  */
- 
+
 static int atalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 {
 	struct sock *sock;
@@ -1395,15 +1395,15 @@
 	struct atalk_iface *atif;
 	struct sockaddr_at tosat;
         int origlen;
-	
+
 	/* Size check */
 	if(skb->len<sizeof(*ddp))
 	{
 		kfree_skb(skb,FREE_READ);
 		return(0);
 	}
-	
-	
+
+
 	/*
 	 *	Fix up the length field	[Ok this is horrible but otherwise
 	 *	I end up with unions of bit fields and messy bit field order
@@ -1419,9 +1419,9 @@
 	/*
 	 *	Trim buffer in case of stray trailing data
 	 */
-	   
+
 	origlen = skb->len;
-	
+
 	skb_trim(skb,min(skb->len,ddp->deh_len));
 
 	/*
@@ -1429,7 +1429,7 @@
 	 *	(Otherwise we'll detonate most spectacularly
 	 *	 in the middle of recvmsg()).
 	 */
-	 
+
 	if(skb->len<sizeof(*ddp))
 	{
 		kfree_skb(skb,FREE_READ);
@@ -1438,7 +1438,7 @@
 
 	/*
 	 *	Any checksums. Note we don't do htons() on this == is assumed to be
-	 *	valid for net byte orders all over the networking code... 
+	 *	valid for net byte orders all over the networking code...
 	 */
 
 	if(ddp->deh_sum && atalk_checksum(ddp, ddp->deh_len)!= ddp->deh_sum)
@@ -1449,15 +1449,15 @@
 	}
 
 #ifdef CONFIG_FIREWALL
-	
+
 	if(call_in_firewall(AF_APPLETALK, skb->dev, ddp, NULL)!=FW_ACCEPT)
 	{
 		kfree_skb(skb, FREE_READ);
 		return 0;
 	}
-	
-#endif	
-	
+
+#endif
+
 	/* Check the packet is aimed at us */
 
 	if(ddp->deh_dnet == 0)	/* Net 0 is 'this network' */
@@ -1466,24 +1466,24 @@
 		atif=atalk_find_interface(ddp->deh_dnet,ddp->deh_dnode);
 
 	/* Not ours */
-	if(atif==NULL)		
+	if(atif==NULL)
 	{
 		struct atalk_route *rt;
 		struct at_addr ta;
 
 		/* Don't route multicast, etc., packets, or packets
 		   sent to "this network" */
-		if (skb->pkt_type != PACKET_HOST || ddp->deh_dnet == 0) 
+		if (skb->pkt_type != PACKET_HOST || ddp->deh_dnet == 0)
 		{
 			kfree_skb(skb, FREE_READ);
 			return(0);
 		}
-		
-#ifdef CONFIG_FIREWALL		
+
+#ifdef CONFIG_FIREWALL
 		/*
 		 *	Check firewall allows this routing
 		 */
-		
+
 		if(call_fw_firewall(AF_APPLETALK, skb->dev, ddp, NULL)!=FW_ACCEPT)
 		{
 			kfree_skb(skb, FREE_READ);
@@ -1506,7 +1506,7 @@
 		 *      Route goes through another gateway, so
 		 *      set the target to the gateway instead.
 		 */
- 
+
 		if(rt->flags&RTF_GATEWAY)
 		{
 			ta.s_net = rt->gateway.s_net;
@@ -1514,14 +1514,14 @@
 		}
 
                 /* Fix up skb->len field */
-                skb_trim(skb,min(origlen, rt->dev->hard_header_len + 
+                skb_trim(skb,min(origlen, rt->dev->hard_header_len +
 			ddp_dl->header_length + ddp->deh_len));
 
 		*((__u16 *)ddp)=ntohs(*((__u16 *)ddp));		/* Mend the byte order */
 		/*
 		 *	Send the buffer onwards
 		 */
-		 
+
 		skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ);
 		if(skb)
 		{
@@ -1539,18 +1539,18 @@
 	tosat.sat_port = ddp->deh_dport;
 
 	sock=atalk_search_socket( &tosat, atif );
-	
+
 	if(sock==NULL)	/* But not one of our sockets */
 	{
 		kfree_skb(skb,FREE_READ);
 		return(0);
 	}
 
-	
+
 	/*
 	 *	Queue packet (standard)
 	 */
-	 
+
 	skb->sk = sock;
 
 	if(sock_queue_rcv_skb(sock,skb)<0)
@@ -1567,7 +1567,7 @@
  *	header and append a long one.
  */
 
- 
+
 static int ltalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 {
 	struct ddpehdr *ddp;
@@ -1575,49 +1575,49 @@
 	/*
 	 *	Expand any short form frames.
 	 */
-	 
+
 	if(skb->mac.raw[2]==1)
 	{
 		/*
 		 *	Find our address.
 		 */
-		 
+
 		ap=atalk_find_dev_addr(dev);
 		if(ap==NULL || skb->len<sizeof(struct ddpshdr))
 		{
 			kfree_skb(skb, FREE_READ);
 			return 0;
 		}
-	
+
 		/*
 		 *	The push leaves us with a ddephdr not an shdr, and
 		 *	handily the port bytes in the right place preset.
 		 */
-	 
+
 		skb_push(skb, sizeof(*ddp)-4);
 		ddp=(struct ddpehdr *)skb->data;
-	
+
 		/*
 		 *	Now fill in the long header.
 		 */
-	 
+
 	 	/*
 	 	 *	These two first. The mac overlays the new source/dest
 	 	 *	network information so we MUST copy these before
 	 	 *	we write the network numbers !
 	 	 */
-	 	 
+
 		ddp->deh_dnode=skb->mac.raw[0];	/* From physical header */
 		ddp->deh_snode=skb->mac.raw[1];	/* From physical header */
-		
+
 		ddp->deh_dnet=ap->s_net;	/* Network number */
-		ddp->deh_snet=ap->s_net;	
+		ddp->deh_snet=ap->s_net;
 		ddp->deh_sum=0;			/* No checksum */
 		/*
 		 *	Not sure about this bit...
 		 */
 		ddp->deh_len=skb->len;
-		ddp->deh_hops=15;		/* Non routable, so force a drop 
+		ddp->deh_hops=15;		/* Non routable, so force a drop
 						   if we slip up later */
 		*((__u16 *)ddp)=htons(*((__u16 *)ddp));		/* Mend the byte order */
 	}
@@ -1639,13 +1639,13 @@
 	int loopback=0;
 	int err;
 	int flags = msg->msg_flags;
-	
+
 	if(flags&~MSG_DONTWAIT)
 		return -EINVAL;
 
 	if(len>587)
 		return -EMSGSIZE;
-		
+
 	if(usat)
 	{
 		if(sk->zapped)
@@ -1671,19 +1671,19 @@
 		usat->sat_addr.s_node=sk->protinfo.af_at.dest_node;
 		usat->sat_addr.s_net=sk->protinfo.af_at.dest_net;
 	}
-	
+
 	/* Build a packet */
-	
+
 	if(sk->debug)
 		printk("SK %p: Got address.\n",sk);
-	
+
 	size=sizeof(struct ddpehdr)+len+ddp_dl->header_length;	/* For headers */
 
 	if(usat->sat_addr.s_net!=0 || usat->sat_addr.s_node == ATADDR_ANYNODE)
 	{
 		rt=atrtr_find(&usat->sat_addr);
 		if(rt==NULL)
-			return -ENETUNREACH;	
+			return -ENETUNREACH;
 		dev=rt->dev;
 	}
 	else
@@ -1699,7 +1699,7 @@
 
 	if(sk->debug)
 		printk("SK %p: Size needed %d, device %s\n", sk, size, dev->name);
-	
+
 	size += dev->hard_header_len;
 
 	skb = sock_alloc_send_skb(sk, size, 0, flags&MSG_DONTWAIT, &err);
@@ -1712,10 +1712,10 @@
 	skb_reserve(skb,dev->hard_header_len);
 
 	skb->dev=dev;
-	
+
 	if(sk->debug)
 		printk("SK %p: Begin build.\n", sk);
-	
+
 	ddp=(struct ddpehdr *)skb_put(skb,sizeof(struct ddpehdr));
 	ddp->deh_pad=0;
 	ddp->deh_hops=0;
@@ -1736,34 +1736,34 @@
 
 	if(sk->debug)
 		printk("SK %p: Copy user data (%d bytes).\n", sk, len);
-		
+
 	err = memcpy_fromiovec(skb_put(skb,len),msg->msg_iov,len);
 	if (err)
 	{
 		kfree_skb(skb, FREE_WRITE);
 		return -EFAULT;
 	}
-		
+
 	if(sk->no_check==1)
 		ddp->deh_sum=0;
 	else
 		ddp->deh_sum=atalk_checksum(ddp, len+sizeof(*ddp));
-		
+
 #ifdef CONFIG_FIREWALL
 
 	if(call_out_firewall(AF_APPLETALK, skb->dev, ddp, NULL)!=FW_ACCEPT)
 	{
 		kfree_skb(skb, FREE_WRITE);
 		return -EPERM;
-	}	
-	
+	}
+
 #endif
-	
+
 	/*
 	 *	Loopback broadcast packets to non gateway targets (ie routes
 	 *	to group we are in)
 	 */
-	 
+
 	if(ddp->deh_dnode==ATADDR_BCAST)
 	{
 		if((!(rt->flags&RTF_GATEWAY))&&(!(dev->flags&IFF_LOOPBACK)))
@@ -1781,7 +1781,7 @@
 		}
 	}
 
-	if((dev->flags&IFF_LOOPBACK) || loopback) 
+	if((dev->flags&IFF_LOOPBACK) || loopback)
 	{
 		if(sk->debug)
 			printk("SK %p: Loop back.\n", sk);
@@ -1794,7 +1794,7 @@
 		skb_pull(skb,ddp_dl->header_length);
 		atalk_rcv(skb,dev,NULL);
 	}
-	else 
+	else
 	{
 		if(sk->debug)
 			printk("SK %p: send out.\n", sk);
@@ -1803,7 +1803,7 @@
 		    gsat.sat_addr = rt->gateway;
 		    usat = &gsat;
 		}
-	
+
 		if(aarp_send_ddp(dev,skb,&usat->sat_addr, NULL)==-1)
 			kfree_skb(skb, FREE_WRITE);
 		/* else queued/sent above in the aarp queue */
@@ -1814,7 +1814,7 @@
 }
 
 
-static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, 
+static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size,
 		int flags, struct scm_cookie *scm)
 {
 	struct sock *sk=sock->sk;
@@ -1850,8 +1850,8 @@
 			msg->msg_flags|=MSG_TRUNC;
 		}
 		er = skb_copy_datagram_iovec(skb,sizeof(*ddp),msg->msg_iov,copied);
-		if (er) 
-			goto out; 
+		if (er)
+			goto out;
 	}
 	if(sat)
 	{
@@ -1864,7 +1864,7 @@
 out:
 	skb_free_datagram(sk, skb);
 	return er ? er : (copied);
-}		
+}
 
 
 static int atalk_shutdown(struct socket *sk,int how)
@@ -1880,7 +1880,7 @@
 {
 	long amount=0;
 	struct sock *sk=sock->sk;
-	
+
 	switch(cmd)
 	{
 		/*
@@ -1917,7 +1917,7 @@
 			return(atrtr_ioctl(cmd,(void *)arg));
 		/*
 		 *	Interface
-		 */			
+		 */
 		case SIOCGIFADDR:
 		case SIOCSIFADDR:
 		case SIOCGIFBRDADDR:
@@ -1960,7 +1960,7 @@
 
 static struct proto_ops atalk_dgram_ops = {
 	AF_APPLETALK,
-	
+
 	atalk_dup,
 	atalk_release,
 	atalk_bind,
@@ -2033,13 +2033,13 @@
 	(void) sock_register(&atalk_family_ops);
 	if ((ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv)) == NULL)
 		printk(KERN_CRIT "Unable to register DDP with SNAP.\n");
-	
-	ltalk_packet_type.type=htons(ETH_P_LOCALTALK);	
+
+	ltalk_packet_type.type=htons(ETH_P_LOCALTALK);
 	dev_add_pack(&ltalk_packet_type);
-	
+
 	ppptalk_packet_type.type=htons(ETH_P_PPPTALK);
 	dev_add_pack(&ppptalk_packet_type);
-	
+
 	register_netdevice_notifier(&ddp_notifier);
 	aarp_proto_init();
 
@@ -2047,17 +2047,17 @@
 	proc_net_register(&proc_appletalk);
 	proc_net_register(&proc_atalk_route);
 	proc_net_register(&proc_atalk_iface);
-#endif	
+#endif
 
 	printk(KERN_INFO "Appletalk 0.18 for Linux NET3.037\n");
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
 
 int init_module(void)
 {
 	atalk_proto_init(NULL);
-	register_symtab(0);
 	return 0;
 }
 
@@ -2065,7 +2065,7 @@
  *	FIX THIS: If there are any routes/devices configured
  *	for appletalk we must not be unloaded.
  */
- 
+
 /* Remove all route entries. Interrupts must be off. */
 extern inline void free_route_list(void)
 {
@@ -2105,7 +2105,7 @@
 	proc_net_unregister(PROC_NET_ATALK);
 	proc_net_unregister(PROC_NET_AT_ROUTE);
 	proc_net_unregister(PROC_NET_ATIF);
-#endif	
+#endif
 	unregister_netdevice_notifier(&ddp_notifier);
 	dev_remove_pack(&ltalk_packet_type);
 	dev_remove_pack(&ppptalk_packet_type);
diff -u --recursive --new-file v2.1.17/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.1.17/linux/net/ax25/af_ax25.c	Wed Dec 18 15:59:14 1996
+++ linux/net/ax25/af_ax25.c	Fri Dec 27 12:04:49 1996
@@ -1,8 +1,8 @@
 /*
  *	AX.25 release 034
  *
- *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
- *	releases, misbehave and/or generally screw up. It might even work. 
+ *	This is ALPHA test software. This code may break your machine, randomly fail to work with new
+ *	releases, misbehave and/or generally screw up. It might even work.
  *
  *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
@@ -94,7 +94,7 @@
  *		copy only when needed.
  *		Consider better arbitrary protocol support.
  */
- 
+
 #include <linux/config.h>
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/module.h>
@@ -152,14 +152,14 @@
 
 		if (c != ' ') *s++ = c;
 	}
-	
+
 	*s++ = '-';
 
 	if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {
 		*s++ = '1';
 		n -= 10;
 	}
-	
+
 	*s++ = n + '0';
 	*s++ = '\0';
 
@@ -194,7 +194,7 @@
 	}
 
 	addr.ax25_call[6] = *s++ - '0';
-	
+
 	if (*s != '\0') {
 		addr.ax25_call[6] *= 10;
 		addr.ax25_call[6] += *s++ - '0';
@@ -235,7 +235,7 @@
 		kfree_s(ax25->digipeat, sizeof(ax25_digi));
 		ax25->digipeat = NULL;
 	}
-	
+
 	kfree_s(ax25, sizeof(ax25_cb));
 
 	MOD_DEC_USE_COUNT;
@@ -248,7 +248,7 @@
 {
 	ax25_cb *s;
 	unsigned long flags;
-	
+
 	save_flags(flags);
 	cli();
 
@@ -277,7 +277,7 @@
 static void ax25_kill_by_device(struct device *dev)
 {
 	ax25_cb *s;
-	
+
 	for (s = ax25_list; s != NULL; s = s->next) {
 		if (s->device == dev) {
 			s->state  = AX25_STATE_0;
@@ -390,7 +390,7 @@
  *	Find an AX.25 control block given both ends. It will only pick up
  *	floating AX.25 control blocks or non Raw socket bound control blocks.
  */
- 
+
 static ax25_cb *ax25_find_cb(ax25_address *my_addr, ax25_address *dest_addr, struct device *dev)
 {
 	ax25_cb *s;
@@ -416,7 +416,7 @@
 /*
  *	Look for any matching address - RAW sockets can bind to arbitrary names
  */
- 
+
 static struct sock *ax25_addr_match(ax25_address *addr)
 {
 	unsigned long flags;
@@ -440,7 +440,7 @@
 static void ax25_send_to_raw(struct sock *sk, struct sk_buff *skb, int proto)
 {
 	struct sk_buff *copy;
-	
+
 	while (sk != NULL) {
 		if (sk->type == SOCK_RAW && sk->protocol == proto && sk->rmem_alloc <= sk->rcvbuf) {
 			if ((copy = skb_clone(skb, GFP_ATOMIC)) == NULL)
@@ -454,7 +454,7 @@
 
 		sk = sk->next;
 	}
-}	
+}
 
 /*
  *	Deferred destroy.
@@ -479,15 +479,15 @@
 {
 	struct sk_buff *skb;
 	unsigned long flags;
-	
+
 	save_flags(flags);
 	cli();
-	
+
 	del_timer(&ax25->timer);
-	
+
 	ax25_remove_socket(ax25);
 	ax25_clear_queues(ax25);	/* Flush the queues */
-	
+
 	if (ax25->sk != NULL) {
 		while ((skb = skb_dequeue(&ax25->sk->receive_queue)) != NULL) {
 			if (skb->sk != ax25->sk) {			/* A pending connection */
@@ -499,7 +499,7 @@
 			kfree_skb(skb, FREE_READ);
 		}
 	}
-	
+
 	if (ax25->sk != NULL) {
 		if (ax25->sk->wmem_alloc || ax25->sk->rmem_alloc) { /* Defer: outstanding buffers */
 			init_timer(&ax25->timer);
@@ -529,7 +529,7 @@
 ax25_address *ax25_findbyuid(uid_t uid)
 {
 	ax25_uid_assoc *a;
-	
+
 	for (a = ax25_uid_list; a != NULL; a = a->next) {
 		if (a->uid == uid)
 			return &a->call;
@@ -541,7 +541,7 @@
 static int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
 {
 	ax25_uid_assoc *a;
-	
+
 	switch (cmd) {
 		case SIOCAX25GETUID:
 			for (a = ax25_uid_list; a != NULL; a = a->next) {
@@ -568,7 +568,7 @@
 
 		case SIOCAX25DELUID: {
 			ax25_uid_assoc **l;
-			
+
 			if (!suser())
 				return -EPERM;
 			l = &ax25_uid_list;
@@ -579,12 +579,12 @@
 					kfree_s(a, sizeof(*a));
 					return 0;
 				}
-				
+
 				l = &((*l)->next);
 			}
 			return -ENOENT;
 		}
-		
+
 		default:
 			return -EINVAL;
 	}
@@ -604,12 +604,12 @@
 	ax25_cb *ax25;
 	unsigned long flags;
 	int err;
-	
+
 	if ((err = verify_area(VERIFY_READ, arg, sizeof(ax25_ctl))) != 0)
 		return err;
 
 	copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl));
-	
+
 	if ((dev = ax25rtr_get_dev(&ax25_ctl.port_addr)) == NULL)
 		return -ENODEV;
 
@@ -620,7 +620,7 @@
 		case AX25_KILL:
 			ax25_clear_queues(ax25);
 			ax25_send_control(ax25, DISC, POLLON, C_COMMAND);
-				
+
 			ax25->state = AX25_STATE_0;
 			if (ax25->sk != NULL) {
 				ax25->sk->state     = TCP_CLOSE;
@@ -637,17 +637,17 @@
 
 	  	case AX25_WINDOW:
 	  		if (ax25->modulus == MODULUS) {
-	  			if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7) 
+	  			if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7)
 	  				return -EINVAL;
 	  		} else {
-	  			if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63) 
+	  			if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63)
 	  				return -EINVAL;
 	  		}
 	  		ax25->window = ax25_ctl.arg;
 	  		break;
 
 	  	case AX25_T1:
-  			if (ax25_ctl.arg < 1) 
+  			if (ax25_ctl.arg < 1)
   				return -EINVAL;
   			ax25->rtt = (ax25_ctl.arg * PR_SLOWHZ) / 2;
   			ax25->t1 = ax25_ctl.arg * PR_SLOWHZ;
@@ -658,7 +658,7 @@
   			break;
 
 	  	case AX25_T2:
-	  		if (ax25_ctl.arg < 1) 
+	  		if (ax25_ctl.arg < 1)
 	  			return -EINVAL;
 	  		save_flags(flags); cli();
 	  		ax25->t2 = ax25_ctl.arg * PR_SLOWHZ;
@@ -668,14 +668,14 @@
 	  		break;
 
 	  	case AX25_N2:
-	  		if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31) 
+	  		if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31)
 	  			return -EINVAL;
 	  		ax25->n2count = 0;
 	  		ax25->n2 = ax25_ctl.arg;
 	  		break;
 
 	  	case AX25_T3:
-	  		if (ax25_ctl.arg < 0) 
+	  		if (ax25_ctl.arg < 0)
 	  			return -EINVAL;
 	  		save_flags(flags); cli();
 	  		ax25->t3 = ax25_ctl.arg * PR_SLOWHZ;
@@ -685,7 +685,7 @@
 	  		break;
 
 	  	case AX25_IDLE:
-	  		if (ax25_ctl.arg < 0) 
+	  		if (ax25_ctl.arg < 0)
 	  			return -EINVAL;
 			save_flags(flags); cli();
 	  		ax25->idle = ax25_ctl.arg * PR_SLOWHZ * 60;
@@ -695,12 +695,12 @@
 	  		break;
 
 	  	case AX25_PACLEN:
-	  		if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535) 
+	  		if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535)
 	  			return -EINVAL;
 #if 0
 	  		if (ax25_ctl.arg > 256) /* we probably want this */
 	  			printk(KERN_WARNING "ax25_ctl_ioctl: Warning --- huge paclen %d\n", (int)ax25_ctl.arg);
-#endif	  			
+#endif
 	  		ax25->paclen = ax25_ctl.arg;
 	  		break;
 
@@ -713,7 +713,7 @@
 	  	default:
 	  		return -EINVAL;
 	  }
-	  
+
 	  return 0;
 }
 
@@ -792,14 +792,14 @@
 {
 	ax25_cb *ax25;
 	int count = 0;
-	
+
 	for (ax25 = ax25_list; ax25 != NULL; ax25 = ax25->next) {
 		if (ax25->device == dev && ax25->dama_slave) {
 			count++;
 			break;
 		}
 	}
-		
+
 	return count;
 }
 
@@ -885,7 +885,7 @@
 	/* idle timeouts only for mode vc connections */
 
 	ax25->idletimer = ax25->idle;
-		
+
 	ax25_insert_socket(ax25);
 
 	ax25->state = AX25_STATE_1;
@@ -893,8 +893,8 @@
 	ax25_set_timer(ax25);
 
 	ax25_output(ax25, skb);
-			
-	return 1;			/* We had to create it */	
+
+	return 1;			/* We had to create it */
 }
 
 /*
@@ -922,7 +922,7 @@
 struct device *ax25rtr_get_dev(ax25_address *addr)
 {
 	struct device *dev;
-	
+
 	for (dev = dev_base; dev != NULL; dev = dev->next)
 		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25 &&
 		    ax25cmp(addr, (ax25_address*) dev->dev_addr) == 0)
@@ -947,7 +947,7 @@
 	int err, opt;
 
 	sk = (struct sock *)sock->sk;
-	
+
 	if (level != SOL_AX25)
 		return -EOPNOTSUPP;
 
@@ -994,7 +994,7 @@
 				return -EINVAL;
 			sk->protinfo.ax25->t3 = opt * PR_SLOWHZ;
 			return 0;
-			
+
 		case AX25_IDLE:
 			if (opt < 0)
 				return -EINVAL;
@@ -1012,7 +1012,7 @@
 		case AX25_HDRINCL:
 			sk->protinfo.ax25->hdrincl = opt ? 1 : 0;
 			return 0;
-			
+
 		case AX25_PACLEN:
 			if (opt < 16 || opt > 65535)
 				return -EINVAL;
@@ -1029,10 +1029,10 @@
 {
 	struct sock *sk;
 	int val = 0;
-	int err; 
+	int err;
 
 	sk = (struct sock *)sock->sk;
-	
+
 	if (level != SOL_AX25)
 		return -EOPNOTSUPP;
 
@@ -1056,7 +1056,7 @@
 		case AX25_T3:
 			val = sk->protinfo.ax25->t3 / PR_SLOWHZ;
 			break;
-			
+
 		case AX25_IDLE:
 			val = sk->protinfo.ax25->idle / (PR_SLOWHZ * 60);
 			break;
@@ -1072,7 +1072,7 @@
 		case AX25_HDRINCL:
 			val = sk->protinfo.ax25->hdrincl;
 			break;
-			
+
 		case AX25_PACLEN:
 			val = sk->protinfo.ax25->paclen;
 			break;
@@ -1195,7 +1195,7 @@
 
 	ax25->sk          = sk;
 	sk->protinfo.ax25 = ax25;
-	
+
 	return 0;
 }
 
@@ -1263,14 +1263,14 @@
 	ax25->maxqueue = osk->protinfo.ax25->maxqueue;
 
 	ax25->source_addr = osk->protinfo.ax25->source_addr;
-	
+
 	if (osk->protinfo.ax25->digipeat != NULL) {
 		if ((ax25->digipeat = (ax25_digi *)kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
 			sk_free(sk);
 			ax25_free_cb(ax25);
 			return NULL;
 		}
-		
+
 		*ax25->digipeat = *osk->protinfo.ax25->digipeat;
 	}
 
@@ -1324,7 +1324,7 @@
 				sk->state_change(sk);
 				sk->dead                 = 1;
 				ax25_destroy_socket(sk->protinfo.ax25);
-				break;			
+				break;
 
 			case AX25_STATE_3:
 			case AX25_STATE_4:
@@ -1374,19 +1374,19 @@
 	struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr;
 	struct device *dev;
 	ax25_address *call;
-	
+
 	sk = (struct sock *)sock->sk;
-	
+
 	if (sk->zapped == 0)
 		return -EINVAL;
-		
+
 	if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))
 		return -EINVAL;
 
 	call = ax25_findbyuid(current->euid);
 	if (call == NULL && ax25_uid_policy && !suser())
 		return -EACCES;
-		
+
 	if (call == NULL)
 		sk->protinfo.ax25->source_addr = addr->fsa_ax25.sax25_call;
 	else
@@ -1436,21 +1436,21 @@
 	struct sock *sk = (struct sock *)sock->sk;
 	struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr;
 	int err;
-	
+
 	if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
 		sock->state = SS_CONNECTED;
 		return 0;	/* Connect completed during a ERESTARTSYS event */
 	}
-	
+
 	if (sk->state == TCP_CLOSE && sock->state == SS_CONNECTING) {
 		sock->state = SS_UNCONNECTED;
 		return -ECONNREFUSED;
 	}
-	
+
 	if (sk->state == TCP_ESTABLISHED && sk->type == SOCK_SEQPACKET)
 		return -EISCONN;	/* No reconnect on a seqpacket socket */
-		
-	sk->state   = TCP_CLOSE;	
+
+	sk->state   = TCP_CLOSE;
 	sock->state = SS_UNCONNECTED;
 
 	if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))
@@ -1497,35 +1497,35 @@
 		if (sk->protinfo.ax25->device == NULL)
 			return -EHOSTUNREACH;
 	}
-		
+
 	if (sk->type == SOCK_SEQPACKET && ax25_find_cb(&sk->protinfo.ax25->source_addr, &addr->sax25_call, sk->protinfo.ax25->device) != NULL)
 		return -EADDRINUSE;			/* Already such a connection */
 
 	sk->protinfo.ax25->dest_addr = addr->sax25_call;
-	
+
 	/* First the easy one */
 	if (sk->type != SOCK_SEQPACKET) {
 		sock->state = SS_CONNECTED;
 		sk->state   = TCP_ESTABLISHED;
 		return 0;
 	}
-	
-	/* Move to connecting socket, ax.25 lapb WAIT_UA.. */	
+
+	/* Move to connecting socket, ax.25 lapb WAIT_UA.. */
 	sock->state        = SS_CONNECTING;
 	sk->state          = TCP_SYN_SENT;
-	
+
 	if (ax25_dev_is_dama_slave(sk->protinfo.ax25->device))
 		dama_establish_data_link(sk->protinfo.ax25);
 	else
 		ax25_establish_data_link(sk->protinfo.ax25);
-		
+
 	sk->protinfo.ax25->state = AX25_STATE_1;
 	ax25_set_timer(sk->protinfo.ax25);		/* Start going SABM SABM until a UA or a give up and DM */
-	
+
 	/* Now the loop */
 	if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
 		return -EINPROGRESS;
-		
+
 	cli();	/* To avoid races on the sleep */
 
 	/* A DM or timeout will go to closed, a UA will go to ABM */
@@ -1543,14 +1543,14 @@
 		sock->state = SS_UNCONNECTED;
 		return sock_error(sk);	/* Always set at this point */
 	}
-	
+
 	sock->state = SS_CONNECTED;
 
 	sti();
-	
+
 	return 0;
 }
-	
+
 static int ax25_socketpair(struct socket *sock1, struct socket *sock2)
 {
 	return -EOPNOTSUPP;
@@ -1566,15 +1566,15 @@
 		sk_free(newsock->sk);
 
 	newsock->sk = NULL;
-	
+
 	sk = (struct sock *)sock->sk;
 
 	if (sk->type != SOCK_SEQPACKET)
 		return -EOPNOTSUPP;
-	
+
 	if (sk->state != TCP_LISTEN)
 		return -EINVAL;
-		
+
 	/*
 	 *	The write queue this time is holding sockets ready to use
 	 *	hooked into the SABM we saved
@@ -1613,9 +1613,9 @@
 	struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr;
 	struct sock *sk;
 	unsigned char ndigi, i;
-	
+
 	sk = (struct sock *)sock->sk;
-	
+
 	if (peer != 0) {
 		if (sk->state != TCP_ESTABLISHED)
 			return -ENOTCONN;
@@ -1642,10 +1642,10 @@
 		else
 			sax->fsa_digipeater[0] = null_ax25_address;
 	}
-	
+
 	return 0;
 }
- 
+
 static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_addr, struct packet_type *ptype)
 {
 	struct sock *make;
@@ -1661,20 +1661,20 @@
 	/*
 	 *	Process the AX.25/LAPB frame.
 	 */
-	 
+
 	skb->h.raw = skb->data;
-	
+
 #ifdef CONFIG_FIREWALL
 	if (call_in_firewall(PF_AX25, skb->dev, skb->h.raw, NULL) != FW_ACCEPT) {
 		kfree_skb(skb, FREE_READ);
 		return 0;
 	}
-#endif	
+#endif
 
 	/*
 	 *	Parse the address header.
 	 */
-	 
+
 	if (ax25_parse_addr(skb->data, skb->len, &src, &dest, &dp, &type, &dama) == NULL) {
 		kfree_skb(skb, FREE_READ);
 		return 0;
@@ -1686,7 +1686,7 @@
 	if (dp.lastrepeat + 1 < dp.ndigi) {		/* Not yet digipeated completely */
 		if (ax25cmp(&dp.calls[dp.lastrepeat + 1], dev_addr) == 0) {
 			struct device *dev_out = dev;
-			
+
 			skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ);
 			if(skb==NULL)
 				return 0;
@@ -1747,7 +1747,7 @@
 	/* Also match on any registered callsign from L3/4 */
 	if (!mine && ax25_listen_mine(&dest, dev))
 		mine = 1;
-	
+
 	if ((*skb->data & ~0x10) == LAPB_UI) {	/* UI frame - bypass LAPB processing */
 		skb->h.raw = skb->data + 2;		/* skip control and pid */
 
@@ -1761,7 +1761,7 @@
 
 		/* Now we are pointing at the pid byte */
 		switch (skb->data[1]) {
-#ifdef CONFIG_INET		
+#ifdef CONFIG_INET
 			case AX25_P_IP:
 				skb_pull(skb,2);		/* drop PID/CTRL */
 				ip_rcv(skb, dev, ptype);	/* Note ptype here is the wrong one, fix me later */
@@ -1771,7 +1771,7 @@
 				skb_pull(skb,2);
 				arp_rcv(skb, dev, ptype);	/* Note ptype here is wrong... */
 				break;
-#endif				
+#endif
 			case AX25_P_TEXT:
 				/* Now find a suitable dgram socket */
 				if ((sk = ax25_find_socket(&dest, &src, SOCK_DGRAM)) != NULL) {
@@ -1790,7 +1790,7 @@
 				} else {
 					kfree_skb(skb, FREE_READ);
 				}
-				break;	
+				break;
 
 			default:
 				kfree_skb(skb, FREE_READ);	/* Will scan SOCK_AX25 RAW sockets */
@@ -1809,14 +1809,14 @@
 		kfree_skb(skb, FREE_READ);
 		return 0;
 	}
-	
+
 	/* LAPB */
-	
+
 	/* AX.25 state 1-4 */
-	
+
 	if ((ax25 = ax25_find_cb(&dest, &src, dev)) != NULL) {
 		/*
-		 *	Process the frame. If it is queued up internally it returns one otherwise we 
+		 *	Process the frame. If it is queued up internally it returns one otherwise we
 		 *	free it immediately. This routine itself wakes the user context layers so we
 		 *	do no further work
 		 */
@@ -1829,7 +1829,7 @@
 	/* AX.25 state 0 (disconnected) */
 
 	/* a) received not a SABM(E) */
-	
+
 	if ((*skb->data & ~PF) != SABM && (*skb->data & ~PF) != SABME) {
 		/*
 		 *	Never reply to a DM. Also ignore any connects for
@@ -1843,7 +1843,7 @@
 	}
 
 	/* b) received SABM(E) */
-	
+
 	if ((sk = ax25_find_listener(&dest, dev, SOCK_SEQPACKET)) != NULL) {
 		if (sk->ack_backlog == sk->max_ack_backlog || (make = ax25_make_new(sk, dev)) == NULL) {
 			if (mine)
@@ -1852,7 +1852,7 @@
 			kfree_skb(skb, FREE_READ);
 			return 0;
 		}
-		
+
 		ax25 = make->protinfo.ax25;
 
 		skb_queue_head(&sk->receive_queue, skb);
@@ -1867,7 +1867,7 @@
 			kfree_skb(skb, FREE_READ);
 			return 0;
 		}
-		
+
 		if ((ax25 = ax25_create_cb()) == NULL) {
 			ax25_return_dm(dev, &src, &dest, &dp);
 			kfree_skb(skb, FREE_READ);
@@ -1909,7 +1909,7 @@
 	}
 
 	ax25->device = dev;
-	
+
 	ax25_send_control(ax25, UA, POLLON, C_RESPONSE);
 
 	if (dama) ax25_dama_on(ax25);	/* bke 951121 */
@@ -1950,7 +1950,7 @@
 }
 
 
-static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, 
+static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len,
 	struct scm_cookie *scm)
 {
 	struct sock *sk = (struct sock *)sock->sk;
@@ -2022,7 +2022,7 @@
 		sax.sax25_call   = sk->protinfo.ax25->dest_addr;
 		dp = sk->protinfo.ax25->digipeat;
 	}
-	
+
 	if (sk->debug)
 		printk("AX.25: sendto: Addresses built.\n");
 
@@ -2080,7 +2080,7 @@
 			printk("Built header (%d bytes)\n",lv);
 
 		skb->h.raw = asmptr;
-	
+
 		if (sk->debug)
 			printk("base=%p pos=%p\n", skb->data, asmptr);
 
@@ -2094,10 +2094,10 @@
 
 		return len;
 	}
-		
+
 }
 
-static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, 
+static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags,
 	struct scm_cookie *scm)
 {
 	struct sock *sk = (struct sock *)sock->sk;
@@ -2106,7 +2106,7 @@
 	struct sk_buff *skb;
 	int er;
 	int dama;
-	
+
 	/*
 	 * 	This works for seqpacket too. The receiver has ordered the
 	 *	queue for us! We do one quick check first though
@@ -2165,7 +2165,7 @@
 	skb_free_datagram(sk, skb);
 
 	return copied;
-}		
+}
 
 static int ax25_shutdown(struct socket *sk, int how)
 {
@@ -2238,7 +2238,7 @@
 			if (!suser())
 				return -EPERM;
 			return ax25_rt_ioctl(cmd, (void *)arg);
-			
+
 		case SIOCAX25CTLCON:
 			if (!suser())
 				return -EPERM;
@@ -2302,7 +2302,7 @@
 			ax25->rtt     / PR_SLOWHZ,
 			ax25->window,
 			ax25->paclen);
-			
+
 		len += sprintf(buffer + len, " %s", ax25->dama_slave ? " slave" : "    no");
 
 		if (ax25->sk != NULL) {
@@ -2312,14 +2312,14 @@
 		} else {
 			len += sprintf(buffer + len, "\n");
 		}
-		
+
 		pos = begin + len;
 
 		if (pos < offset) {
 			len   = 0;
 			begin = pos;
 		}
-		
+
 		if (pos > offset + length)
 			break;
 	}
@@ -2332,9 +2332,9 @@
 	if (len > length) len = length;
 
 	return(len);
-} 
+}
 
-static struct net_proto_family ax25_family_ops = 
+static struct net_proto_family ax25_family_ops =
 {
 	AF_AX25,
 	ax25_create
@@ -2342,7 +2342,7 @@
 
 static struct proto_ops ax25_proto_ops = {
 	AF_AX25,
-	
+
 	ax25_dup,
 	ax25_release,
 	ax25_bind,
@@ -2364,7 +2364,7 @@
 /*
  *	Called by socket.c on kernel start up
  */
-static struct packet_type ax25_packet_type = 
+static struct packet_type ax25_packet_type =
 {
 	0,	/* MUTTER ntohs(ETH_P_AX25),*/
 	0,		/* copy */
@@ -2378,30 +2378,25 @@
 	0
 };
 
-static struct symbol_table ax25_syms = {
-#include <linux/symtab_begin.h>
-	X(ax25_encapsulate),
-	X(ax25_rebuild_header),
+EXPORT_SYMBOL(ax25_encapsulate);
+EXPORT_SYMBOL(ax25_rebuild_header);
 #if defined(CONFIG_NETROM_MODULE) || defined(CONFIG_ROSE_MODULE)
-	X(ax25_findbyuid),
-	X(ax25_link_up),
-	X(ax25_linkfail_register),
-	X(ax25_linkfail_release),
-	X(ax25_listen_register),
-	X(ax25_listen_release),
-	X(ax25_protocol_register),
-	X(ax25_protocol_release),
-	X(ax25_send_frame),
-	X(ax25_uid_policy),
-	X(ax25cmp),
-	X(ax2asc),
-	X(asc2ax),
-	X(null_ax25_address),
-#endif
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(ax25_findbyuid);
+EXPORT_SYMBOL(ax25_link_up);
+EXPORT_SYMBOL(ax25_linkfail_register);
+EXPORT_SYMBOL(ax25_linkfail_release);
+EXPORT_SYMBOL(ax25_listen_register);
+EXPORT_SYMBOL(ax25_listen_release);
+EXPORT_SYMBOL(ax25_protocol_register);
+EXPORT_SYMBOL(ax25_protocol_release);
+EXPORT_SYMBOL(ax25_send_frame);
+EXPORT_SYMBOL(ax25_uid_policy);
+EXPORT_SYMBOL(ax25cmp);
+EXPORT_SYMBOL(ax2asc);
+EXPORT_SYMBOL(asc2ax);
+EXPORT_SYMBOL(null_ax25_address);
 
-#ifdef CONFIG_PROC_FS			  
+#ifdef CONFIG_PROC_FS
 static struct proc_dir_entry proc_ax25_route = {
 	PROC_NET_AX25_ROUTE, 10, "ax25_route",
 	S_IFREG | S_IRUGO, 1, 0, 0,
@@ -2426,16 +2421,15 @@
 {
 	sock_register(&ax25_family_ops);
 	ax25_packet_type.type = htons(ETH_P_AX25);
-	dev_add_pack(&ax25_packet_type);	
+	dev_add_pack(&ax25_packet_type);
 	register_netdevice_notifier(&ax25_dev_notifier);
-	register_symtab(&ax25_syms);
 	ax25_register_sysctl();
 
-#ifdef CONFIG_PROC_FS			  
+#ifdef CONFIG_PROC_FS
 	proc_net_register(&proc_ax25_route);
 	proc_net_register(&proc_ax25);
 	proc_net_register(&proc_ax25_calls);
-#endif	
+#endif
 
 	printk(KERN_INFO "G4KLX/GW4PTS AX.25 for Linux. Version 0.34 for Linux NET3.037 (Linux 2.1)\n");
 }
@@ -2446,13 +2440,13 @@
 void ax25_queue_xmit(struct sk_buff *skb)
 {
 	unsigned char *ptr;
-	
+
 #ifdef CONFIG_FIREWALL
 	if (call_out_firewall(PF_AX25, skb->dev, skb->data, NULL) != FW_ACCEPT) {
 		dev_kfree_skb(skb, FREE_WRITE);
 		return;
 	}
-#endif	
+#endif
 
 	skb->protocol = htons(ETH_P_AX25);
 
@@ -2471,7 +2465,7 @@
  */
 
 #ifdef CONFIG_INET
- 
+
 int ax25_encapsulate(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr,
 		void *saddr, unsigned len)
 {
@@ -2479,7 +2473,7 @@
  	unsigned char *buff = skb_push(skb, AX25_HEADER_LEN);
 
   	*buff++ = 0;	/* KISS DATA */
-  	
+
 	if (daddr != NULL)
 		memcpy(buff, daddr, dev->addr_len);	/* Address specified */
 
@@ -2514,7 +2508,7 @@
   			*buff++ = 0;
   			break;
  	}
-	
+
 	if (daddr != NULL)
 	  	return AX25_HEADER_LEN;
 
@@ -2569,7 +2563,7 @@
   	bp[14] &= ~LAPB_C;
   	bp[14] |= LAPB_E;
   	bp[14] |= SSSID_SPARE;
-  	
+
   	/*
   	 * dl1bke 960317: we use ax25_queue_xmit here to allow mode datagram
   	 *		  over ethernet. I don't know if this is valid, though.
@@ -2582,7 +2576,7 @@
 	ax25_queue_xmit(skb);
 
   	return 1;
-}	
+}
 
 #endif
 
@@ -2609,7 +2603,7 @@
 	unregister_netdevice_notifier(&ax25_dev_notifier);
 
 	ax25_packet_type.type = htons(ETH_P_AX25);
-	dev_remove_pack(&ax25_packet_type);	
+	dev_remove_pack(&ax25_packet_type);
 
 	sock_unregister(ax25_proto_ops.family);
 }
diff -u --recursive --new-file v2.1.17/linux/net/core/firewall.c linux/net/core/firewall.c
--- v2.1.17/linux/net/core/firewall.c	Sun May 19 23:40:50 1996
+++ linux/net/core/firewall.c	Fri Dec 27 12:04:49 1996
@@ -6,7 +6,7 @@
  *	much hacked by:	Alan Cox
  */
 
-#include <linux/module.h> 
+#include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/firewall.h>
 
@@ -17,24 +17,24 @@
 /*
  *	Register a firewall
  */
- 
+
 int register_firewall(int pf, struct firewall_ops *fw)
 {
 	struct firewall_ops **p;
-	
+
 	if(pf<0||pf>=NPROTO)
 		return -EINVAL;
-	
+
 	/*
 	 *	Don't allow two people to adjust at once.
 	 */
-	 
+
 	while(firewall_lock)
 		schedule();
 	firewall_lock=1;
-	
+
 	p=&firewall_chain[pf];
-	
+
 	while(*p)
 	{
 		if(fw->fw_priority > (*p)->fw_priority)
@@ -42,7 +42,7 @@
 		p=&((*p)->next);
 	}
 
-	
+
 	/*
 	 * We need to use a memory barrier to make sure that this
 	 * works correctly even in SMP with weakly ordered writes.
@@ -70,20 +70,20 @@
 int unregister_firewall(int pf, struct firewall_ops *fw)
 {
 	struct firewall_ops **nl;
-	
+
 	if(pf<0||pf>=NPROTO)
 		return -EINVAL;
-	
+
 	/*
 	 *	Don't allow two people to adjust at once.
 	 */
-	 
+
 	while(firewall_lock)
 		schedule();
 	firewall_lock=1;
 
 	nl=&firewall_chain[pf];
-	
+
 	while(*nl!=NULL)
 	{
 		if(*nl==fw)
@@ -92,7 +92,7 @@
 			*nl = f;
 			firewall_lock=0;
 			return 0;
-		}			
+		}
 		nl=&((*nl)->next);
 	}
 	firewall_lock=0;
@@ -102,7 +102,7 @@
 int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg)
 {
 	struct firewall_ops *fw=firewall_chain[pf];
-	
+
 	while(fw!=NULL)
 	{
 		int rc=fw->fw_forward(fw,pf,dev,phdr,arg);
@@ -116,11 +116,11 @@
 /*
  *	Actual invocation of the chains
  */
- 
+
 int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg)
 {
 	struct firewall_ops *fw=firewall_chain[pf];
-	
+
 	while(fw!=NULL)
 	{
 		int rc=fw->fw_input(fw,pf,dev,phdr,arg);
@@ -134,7 +134,7 @@
 int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg)
 {
 	struct firewall_ops *fw=firewall_chain[pf];
-	
+
 	while(fw!=NULL)
 	{
 		int rc=fw->fw_output(fw,pf,dev,phdr,arg);
@@ -146,20 +146,15 @@
 	return firewall_policy[pf];
 }
 
-static struct symbol_table firewall_syms = {
-#include <linux/symtab_begin.h>
-	X(register_firewall),
-	X(unregister_firewall),
-	X(call_in_firewall),
-	X(call_out_firewall),
-	X(call_fw_firewall),
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(register_firewall);
+EXPORT_SYMBOL(unregister_firewall);
+EXPORT_SYMBOL(call_in_firewall);
+EXPORT_SYMBOL(call_out_firewall);
+EXPORT_SYMBOL(call_fw_firewall);
 
 void fwchain_init(void)
 {
 	int i;
 	for(i=0;i<NPROTO;i++)
 		firewall_policy[i]=FW_ACCEPT;
-	register_symtab(&firewall_syms);
 }
diff -u --recursive --new-file v2.1.17/linux/net/ipv4/ip_masq.c linux/net/ipv4/ip_masq.c
--- v2.1.17/linux/net/ipv4/ip_masq.c	Thu Dec 12 19:37:25 1996
+++ linux/net/ipv4/ip_masq.c	Fri Dec 27 12:04:49 1996
@@ -16,7 +16,7 @@
  *	Nigel Metheringham	:	Checksum checking of masqueraded data
  *	Nigel Metheringham	:	Better handling of timeouts of TCP conns
  *
- *	
+ *
  */
 
 #include <linux/config.h>
@@ -66,7 +66,7 @@
  *
  *	Greater values could lower MASQ_EXPIRATION setting as a way to
  *	manage 'masq_entries resource'.
- *	
+ *
  */
 
 int ip_masq_free_ports[2] = {
@@ -74,15 +74,11 @@
         PORT_MASQ_END - PORT_MASQ_BEGIN 	/* TCP */
 };
 
-static struct symbol_table ip_masq_syms = {
-#include <linux/symtab_begin.h>
-	X(ip_masq_new),
-        X(ip_masq_set_expire),
-        X(ip_masq_free_ports),
-	X(ip_masq_expire),
-	X(ip_masq_out_get_2),
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(ip_masq_new);
+EXPORT_SYMBOL(ip_masq_set_expire);
+EXPORT_SYMBOL(ip_masq_free_ports);
+EXPORT_SYMBOL(ip_masq_expire);
+EXPORT_SYMBOL(ip_masq_out_get_2);
 
 /*
  *	2 ip_masq hash tables: for input and output pkts lookups.
@@ -323,7 +319,7 @@
 			masq_proto_name(ms->protocol),
 			ntohl(ms->saddr),ntohs(ms->sport));
 #endif
-	
+
 	save_flags(flags);
 	cli();
 
@@ -378,47 +374,47 @@
 
         if (proto == IPPROTO_UDP)
                 ms->flags |= IP_MASQ_F_NO_DADDR;
-        
+
         /* get masq address from rif */
         ms->maddr	   = dev->pa_addr;
 
         for (ports_tried = 0; ports_tried < *free_ports_p; ports_tried++){
                 save_flags(flags);
                 cli();
-                
+
 		/*
                  *	Try the next available port number
                  */
-                
+
 		ms->mport = htons(masq_port++);
 		if (masq_port==PORT_MASQ_END) masq_port = PORT_MASQ_BEGIN;
-                
+
                 restore_flags(flags);
-                
+
                 /*
                  *	lookup to find out if this port is used.
                  */
-                
+
                 mst = ip_masq_getbym(proto, ms->maddr, ms->mport);
                 if (mst == NULL) {
                         save_flags(flags);
                         cli();
-                
+
                         if (*free_ports_p == 0) {
                                 restore_flags(flags);
                                 break;
                         }
                         (*free_ports_p)--;
                         ip_masq_hash(ms);
-                        
+
                         restore_flags(flags);
-                        
+
                         ip_masq_bind_app(ms);
                         n_fails = 0;
                         return ms;
                 }
         }
-        
+
         if (++n_fails < 5)
                 printk("ip_masq_new(proto=%s): could not get free masq entry (free=%d).\n",
                        masq_proto_name(ms->protocol), *free_ports_p);
@@ -451,7 +447,7 @@
 	if(uh->check==0)
 		uh->check=0xFFFF;
 }
-	
+
 int ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev)
 {
 	struct sk_buff  *skb=*skb_ptr;
@@ -489,7 +485,7 @@
 	/*
 	 *	Nope, not found, create a new entry for it
 	 */
-	
+
 	if (ms==NULL)
 	{
                 ms = ip_masq_new(dev, iph->protocol,
@@ -503,7 +499,7 @@
  	/*
  	 *	Change the fragments origin
  	 */
- 	
+
  	size = skb->len - ((unsigned char *)portptr - skb->nh.raw);
         /*
          *	Set iph addr and port from ip_masq obj.
@@ -529,7 +525,7 @@
  	/*
  	 *	Adjust packet accordingly to protocol
  	 */
- 	
+
  	if (iph->protocol==IPPROTO_UDP)
  	{
                 timeout = ip_masq_expire->udp_timeout;
@@ -566,7 +562,10 @@
  		else timeout = ip_masq_expire->tcp_timeout;
 
 		skb->csum = csum_partial((void *)(th + 1), size - sizeof(*th), 0);
-		tcp_v4_check(th, size, iph->saddr, iph->daddr, skb->csum);
+		th->check = 0;
+		th->check = tcp_v4_check(th, size, iph->saddr, iph->daddr,
+					 csum_partial((char *)th, sizeof(*th),
+						      skb->csum));
  	}
         ip_masq_set_expire(ms, timeout);
  	ip_send_check(iph);
@@ -602,7 +601,7 @@
  		ntohl(iph->saddr), ntohl(iph->daddr));
 #endif
 
-	/* 
+	/*
 	 * Work through seeing if this is for us.
 	 * These checks are supposed to be in an order that
 	 * means easy things are checked first to speed up
@@ -622,8 +621,8 @@
 	if ((ciph->protocol != IPPROTO_UDP) && (ciph->protocol != IPPROTO_TCP))
 		return 0;
 
-	/* 
-	 * Find the ports involved - this packet was 
+	/*
+	 * Find the ports involved - this packet was
 	 * incoming so the ports are right way round
 	 * (but reversed relative to outer IP header!)
 	 */
@@ -633,10 +632,10 @@
  		return 0;
 
 	/* Ensure the checksum is correct */
-	if (ip_compute_csum((unsigned char *) icmph, len)) 
+	if (ip_compute_csum((unsigned char *) icmph, len))
 	{
 		/* Failed checksum! */
-		printk(KERN_INFO "MASQ: forward ICMP: failed checksum from %s!\n", 
+		printk(KERN_INFO "MASQ: forward ICMP: failed checksum from %s!\n",
 		       in_ntoa(iph->saddr));
 		return(-1);
 	}
@@ -657,11 +656,11 @@
 	/* First change the source IP address, and recalc checksum */
 	iph->saddr = ms->maddr;
 	ip_send_check(iph);
-	
+
 	/* Now change the *dest* address in the contained IP */
 	ciph->daddr = ms->maddr;
 	ip_send_check(ciph);
-	
+
 	/* the TCP/UDP dest port - cannot redo check */
 	pptr[1] = ms->mport;
 
@@ -713,8 +712,8 @@
 	if ((ciph->protocol != IPPROTO_UDP) && (ciph->protocol != IPPROTO_TCP))
 		return 0;
 
-	/* 
-	 * Find the ports involved - remember this packet was 
+	/*
+	 * Find the ports involved - remember this packet was
 	 * *outgoing* so the ports are reversed (and addresses)
 	 */
 	pptr = (__u16 *)&(((char *)ciph)[ciph->ihl*4]);
@@ -723,10 +722,10 @@
  		return 0;
 
 	/* Ensure the checksum is correct */
-	if (ip_compute_csum((unsigned char *) icmph, len)) 
+	if (ip_compute_csum((unsigned char *) icmph, len))
 	{
 		/* Failed checksum! */
-		printk(KERN_INFO "MASQ: reverse ICMP: failed checksum from %s!\n", 
+		printk(KERN_INFO "MASQ: reverse ICMP: failed checksum from %s!\n",
 		       in_ntoa(iph->saddr));
 		return(-1);
 	}
@@ -747,11 +746,11 @@
 	/* First change the dest IP address, and recalc checksum */
 	iph->daddr = ms->saddr;
 	ip_send_check(iph);
-	
+
 	/* Now change the *source* address in the contained IP */
 	ciph->saddr = ms->saddr;
 	ip_send_check(ciph);
-	
+
 	/* the TCP/UDP source port - cannot redo check */
 	pptr[0] = ms->sport;
 
@@ -803,7 +802,7 @@
 			/* No UDP checksum */
 			break;
 
-		switch (skb->ip_summed) 
+		switch (skb->ip_summed)
 		{
 			case CHECKSUM_NONE:
 				skb->csum = csum_partial((char *)portptr, len, 0);
@@ -811,7 +810,7 @@
 				if (csum_tcpudp_magic(iph->saddr, iph->daddr, len,
 						      iph->protocol, skb->csum))
 				{
-					printk(KERN_INFO "MASQ: failed TCP/UDP checksum from %s!\n", 
+					printk(KERN_INFO "MASQ: failed TCP/UDP checksum from %s!\n",
 					       in_ntoa(iph->saddr));
 					return -1;
 				}
@@ -898,10 +897,12 @@
                                                  len - sizeof(struct tcphdr), 0);
 			th = (struct tcphdr *) portptr;
 			th->check = 0;
+                        th->check = tcp_v4_check(th, len, iph->saddr,
+						 iph->daddr,
+						 csum_partial((char *)th,
+							      sizeof(*th),
+				     			      skb->csum));
 
-                        tcp_v4_check(th, len, iph->saddr, iph->daddr,
-				     skb->csum);
-			
 			/* Check if TCP FIN or RST */
 			if (th->fin)
 			{
@@ -911,7 +912,7 @@
 			{
 				ms->flags |= IP_MASQ_F_SAW_RST;
 			}
-			
+
 			/* Now set the timeouts */
 			if (ms->flags & IP_MASQ_F_SAW_RST)
 			{
@@ -948,18 +949,18 @@
 	char temp[129];
         int idx = 0;
 	int len=0;
-	
-	if (offset < 128) 
+
+	if (offset < 128)
 	{
 		sprintf(temp,
 			"Prc FromIP   FPrt ToIP     TPrt Masq Init-seq  Delta PDelta Expires (free=%d,%d)",
-			ip_masq_free_ports[0], ip_masq_free_ports[1]); 
+			ip_masq_free_ports[0], ip_masq_free_ports[1]);
 		len = sprintf(buffer, "%-127s\n", temp);
 	}
 	pos = 128;
 	save_flags(flags);
 	cli();
-        
+
         for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++)
         for(ms = ip_masq_m_tab[idx]; ms ; ms = ms->m_link)
 	{
@@ -997,24 +998,23 @@
 	return len;
 }
 
-#ifdef CONFIG_PROC_FS        
+#ifdef CONFIG_PROC_FS
 static struct proc_dir_entry proc_net_ipmsqhst = {
 	PROC_NET_IPMSQHST, 13, "ip_masquerade",
 	S_IFREG | S_IRUGO, 1, 0, 0,
 	0, &proc_net_inode_operations,
 	ip_msqhst_procinfo
 };
-#endif	
+#endif
 
 /*
  *	Initialize ip masquerading
  */
 int ip_masq_init(void)
 {
-        register_symtab (&ip_masq_syms);
-#ifdef CONFIG_PROC_FS        
+#ifdef CONFIG_PROC_FS
 	proc_net_register(&proc_net_ipmsqhst);
-#endif	
+#endif
         ip_masq_app_init();
 
         return 0;
diff -u --recursive --new-file v2.1.17/linux/net/ipv4/ip_masq_app.c linux/net/ipv4/ip_masq_app.c
--- v2.1.17/linux/net/ipv4/ip_masq_app.c	Thu Dec 12 19:37:25 1996
+++ linux/net/ipv4/ip_masq_app.c	Fri Dec 27 12:04:49 1996
@@ -19,7 +19,7 @@
  *
  * FIXME:
  *	- ip_masq_skb_replace(): use same skb if space available.
- *	
+ *
  */
 
 #include <linux/config.h>
@@ -53,13 +53,9 @@
 #define IP_MASQ_APP_PROTO(type)       ( (type>>16) & 0x00ff )
 
 
-static struct symbol_table ip_masq_app_syms = {
-#include <linux/symtab_begin.h>
-	X(register_ip_masq_app),
-	X(unregister_ip_masq_app),
-	X(ip_masq_skb_replace),
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(register_ip_masq_app);
+EXPORT_SYMBOL(unregister_ip_masq_app);
+EXPORT_SYMBOL(ip_masq_skb_replace);
 
 /*
  * 	will hold masq app. hashed list heads
@@ -83,13 +79,13 @@
         mapp->type = IP_MASQ_APP_TYPE(proto, port);
         mapp->n_attach = 0;
         hash = IP_MASQ_APP_HASH(proto, port);
-        
+
         save_flags(flags);
         cli();
         mapp->next = ip_masq_app_base[hash];
-        ip_masq_app_base[hash] = mapp; 
+        ip_masq_app_base[hash] = mapp;
         restore_flags(flags);
-        
+
         return 0;
 }
 
@@ -124,7 +120,7 @@
                         restore_flags(flags);
                         return 0;
                 }
-        
+
         restore_flags(flags);
         printk("unregister_ip_masq_app(proto=%s,port=%u): not hashed!\n",
                masq_proto_name(IP_MASQ_APP_PROTO(mapp->type)), IP_MASQ_APP_PORT(mapp->type));
@@ -191,12 +187,12 @@
                 /*
                  *	don't allow binding if already bound
                  */
-                
+
                 if (ms->app != NULL) {
                         printk("ip_masq_bind_app() called for already bound object.\n");
                         return ms->app;
                 }
-                
+
                 ms->app = mapp;
                 if (mapp->masq_init_1) mapp->masq_init_1(mapp, ms);
                 ip_masq_app_bind_chg(mapp, +1);
@@ -227,9 +223,9 @@
 static __inline__ void masq_fix_seq(const struct ip_masq_seq *ms_seq, struct tcphdr *th)
 {
         __u32 seq;
-        
+
         seq = ntohl(th->seq);
-        
+
 	/*
 	 * 	Adjust seq with delta-offset for all packets after
          * 	the most recent resized pkt seq and with previous_delta offset
@@ -249,7 +245,7 @@
 #endif
 		}
 	}
-        
+
 
 }
 
@@ -260,15 +256,15 @@
 static __inline__ void masq_fix_ack_seq(const struct ip_masq_seq *ms_seq, struct tcphdr *th)
 {
         __u32 ack_seq;
-        
+
         ack_seq=ntohl(th->ack_seq);
-        
+
         /*
          * Adjust ack_seq with delta-offset for
          * the packets AFTER most recent resized pkt has caused a shift
          * for packets before most recent resized pkt, use previous_delta
          */
-        
+
         if (ms_seq->delta || ms_seq->previous_delta) {
                 if(after(ack_seq,ms_seq->init_seq)) {
                         th->ack_seq = htonl(ack_seq-ms_seq->delta);
@@ -282,7 +278,7 @@
 #endif
                 }
         }
-        
+
 }
 
 /*
@@ -293,7 +289,7 @@
 static __inline__ void masq_seq_update(struct ip_masq *ms, struct ip_masq_seq *ms_seq, unsigned mflag, __u32 seq, int diff)
 {
         /* if (diff == 0) return; */
-        
+
         if ( !(ms->flags & mflag) || after(seq, ms_seq->init_seq))
         {
                 ms_seq->previous_delta=ms_seq->delta;
@@ -316,50 +312,50 @@
 	struct tcphdr *th;
         int diff;
         __u32 seq;
-        
+
         /*
          *	check if application masquerading is bound to
          *	this ip_masq.
          *	assumes that once an ip_masq is bound,
          *	it will not be unbound during its life.
          */
-        
+
         if ( (mapp = ms->app) == NULL)
                 return 0;
-        
+
         iph = (*skb_p)->nh.iph;
         th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
-        
+
         /*
          *	Remember seq number in case this pkt gets resized
          */
-        
+
         seq = ntohl(th->seq);
-        
+
         /*
          *	Fix seq stuff if flagged as so.
          */
-        
+
         if (ms->protocol == IPPROTO_TCP) {
                 if (ms->flags & IP_MASQ_F_OUT_SEQ)
                         masq_fix_seq(&ms->out_seq, th);
                 if (ms->flags & IP_MASQ_F_IN_SEQ)
                         masq_fix_ack_seq(&ms->in_seq, th);
         }
-        
+
         /*
-         *	Call private output hook function 
+         *	Call private output hook function
          */
-        
+
         if ( mapp->pkt_out == NULL )
                 return 0;
-        
+
         diff = mapp->pkt_out(mapp, ms, skb_p, dev);
-        
+
         /*
          *	Update ip_masq seq stuff if len has changed.
          */
-        
+
         if (diff != 0 && ms->protocol == IPPROTO_TCP)
                 masq_seq_update(ms, &ms->out_seq, IP_MASQ_F_OUT_SEQ, seq, diff);
 
@@ -379,50 +375,50 @@
 	struct tcphdr *th;
         int diff;
         __u32 seq;
-        
+
         /*
          *	check if application masquerading is bound to
          *	this ip_masq.
          *	assumes that once an ip_masq is bound,
          *	it will not be unbound during its life.
          */
-        
+
         if ( (mapp = ms->app) == NULL)
                 return 0;
-        
+
         iph = (*skb_p)->nh.iph;
         th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
-        
+
         /*
          *	Remember seq number in case this pkt gets resized
          */
-        
+
         seq = ntohl(th->seq);
-        
+
         /*
          *	Fix seq stuff if flagged as so.
          */
-        
+
         if (ms->protocol == IPPROTO_TCP) {
                 if (ms->flags & IP_MASQ_F_IN_SEQ)
                         masq_fix_seq(&ms->in_seq, th);
                 if (ms->flags & IP_MASQ_F_OUT_SEQ)
                         masq_fix_ack_seq(&ms->out_seq, th);
         }
-        
+
         /*
-         *	Call private input hook function 
+         *	Call private input hook function
          */
-        
+
         if ( mapp->pkt_in == NULL )
                 return 0;
-        
+
         diff = mapp->pkt_in(mapp, ms, skb_p, dev);
 
         /*
          *	Update ip_masq seq stuff if len has changed.
          */
-        
+
         if (diff != 0 && ms->protocol == IPPROTO_TCP)
                 masq_seq_update(ms, &ms->in_seq, IP_MASQ_F_IN_SEQ, seq, diff);
 
@@ -446,7 +442,7 @@
 
         for (idx=0 ; idx < IP_MASQ_APP_TAB_SIZE; idx++)
                 for (mapp = ip_masq_app_base[idx]; mapp ; mapp = mapp->next) {
-			/* 
+			/*
 			 * If you change the length of this sprintf, then all
 			 * the length calculations need fixing too!
 			 * Line length = 40 (3 + 2 + 7 + 1 + 7 + 1 + 2 + 17)
@@ -468,19 +464,19 @@
         *start = buffer + begin;
         len -= begin;
         if (len > length)
-                len = length;	
+                len = length;
         return len;
 }
 
 
-#ifdef CONFIG_PROC_FS        
+#ifdef CONFIG_PROC_FS
 static struct proc_dir_entry proc_net_ip_masq_app = {
 	PROC_NET_IP_MASQ_APP, 11, "ip_masq_app",
 	S_IFREG | S_IRUGO, 1, 0, 0,
 	0, &proc_net_inode_operations,
 	ip_masq_app_getinfo
 };
-#endif        
+#endif
 
 /*
  *	Initialization routine
@@ -488,11 +484,9 @@
 
 int ip_masq_app_init(void)
 {
-
-        register_symtab (&ip_masq_app_syms);
-#ifdef CONFIG_PROC_FS        
+#ifdef CONFIG_PROC_FS
 	proc_net_register(&proc_net_ip_masq_app);
-#endif        
+#endif
         return 0;
 }
 
@@ -531,7 +525,7 @@
                  *
                  *	FIXME: move this to core/sbuff.c:skb_grow()
                  */
-        
+
                 n_skb = alloc_skb(MAX_HEADER + skb->len + diff, pri);
                 if (n_skb == NULL) {
                         printk("skb_replace(): no room left (from %p)\n",
@@ -561,17 +555,17 @@
                 /*
                  * Copy pkt in new buffer
                  */
-                
+
                 memcpy(n_skb->data, skb->data, o_offset);
                 memcpy(n_skb->data + o_offset, n_buf, n_len);
                 memcpy(n_skb->data + o_offset + n_len, o_buf + o_len,
                        skb->len - (o_offset + o_len) );
-                
+
                 /*
                  * Problem, how to replace the new skb with old one,
                  * preferably inplace
                  */
-                
+
                 kfree_skb(skb, FREE_WRITE);
         }
         return n_skb;
@@ -590,7 +584,7 @@
         diff = n_len - o_len;
         n_skb = skb_replace(skb, pri, o_buf, o_len, n_buf, n_len);
         skb_len = skb->len;
-                
+
         if (diff)
         {
                 struct iphdr *iph;
diff -u --recursive --new-file v2.1.17/linux/net/ipv4/ip_masq_ftp.c linux/net/ipv4/ip_masq_ftp.c
--- v2.1.17/linux/net/ipv4/ip_masq_ftp.c	Thu Dec 12 19:37:25 1996
+++ linux/net/ipv4/ip_masq_ftp.c	Fri Dec 27 12:04:49 1996
@@ -5,19 +5,19 @@
  * Version:	@(#)ip_masq_ftp.c 0.01   02/05/96
  *
  * Author:	Wouter Gadeyne
- *		
+ *
  *
  * Fixes:
  *	Wouter Gadeyne		:	Fixed masquerading support of ftp PORT commands
  * 	Juan Jose Ciarlante	:	Code moved and adapted from ip_fw.c
- *	
+ *
  *
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
  *	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
- *	
+ *
  */
 
 #include <linux/module.h>
@@ -100,14 +100,14 @@
 		port = (p5<<8) | p6;
 #if DEBUG_CONFIG_IP_MASQ_FTP
 		printk("PORT %X:%X detected\n",from,port);
-#endif	
+#endif
 		/*
 		 * Now update or create an masquerade entry for it
 		 */
 #if DEBUG_CONFIG_IP_MASQ_FTP
 		printk("protocol %d %lX:%X %X:%X\n", iph->protocol, htonl(from), htons(port), iph->daddr, 0);
 
-#endif	
+#endif
 		n_ms = ip_masq_out_get_2(iph->protocol,
 					 htonl(from), htons(port),
 					 iph->daddr, 0);
@@ -120,7 +120,7 @@
 					   htonl(from), htons(port),
 					   iph->daddr, 0,
 					   IP_MASQ_F_NO_DPORT);
-					
+
 			if (n_ms==NULL)
 				return 0;
 		}
@@ -142,18 +142,18 @@
 		buf_len = strlen(buf);
 #if DEBUG_CONFIG_IP_MASQ_FTP
 		printk("new PORT %X:%X\n",from,port);
-#endif	
+#endif
 
 		/*
 		 * Calculate required delta-offset to keep TCP happy
 		 */
-		
+
 		diff = buf_len - (data-p);
-		
+
 		/*
 		 *	No shift.
 		 */
-		
+
 		if (diff==0)
 		{
 			/*
@@ -201,12 +201,12 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
 
 int init_module(void)
 {
         if (ip_masq_ftp_init() != 0)
                 return -EIO;
-        register_symtab(0);
         return 0;
 }
 
diff -u --recursive --new-file v2.1.17/linux/net/ipv4/ip_masq_irc.c linux/net/ipv4/ip_masq_irc.c
--- v2.1.17/linux/net/ipv4/ip_masq_irc.c	Thu Dec 12 19:37:25 1996
+++ linux/net/ipv4/ip_masq_irc.c	Fri Dec 27 12:04:49 1996
@@ -5,7 +5,7 @@
  * Version:	@(#)ip_masq_irc.c 0.01   03/20/96
  *
  * Author:	Juan Jose Ciarlante
- *		
+ *
  *
  * Fixes:
  *	- set NO_DADDR flag in ip_masq_new().
@@ -17,7 +17,7 @@
  *	modify it under the terms of the GNU General Public License
  *	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
- *	
+ *
  */
 
 #include <linux/module.h>
@@ -77,29 +77,29 @@
          *		AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits)
          *		P:         bound port (min 1 d )
          *		F:         filename   (min 1 d )
-         *		S:         size       (min 1 d ) 
+         *		S:         size       (min 1 d )
          *		0x01, \n:  terminators
          */
 
         data_limit = skb->h.raw + skb->len;
-        
+
 	while (data < (data_limit - 25) )
 	{
 		if (memcmp(data,"DCC ",4))  {
 			data ++;
 			continue;
 		}
-                
+
                 dcc_p = data;
 		data += 4;     /* point to DCC cmd */
-                
+
                 if (memcmp(data, "CHAT ", 5) == 0 ||
                     memcmp(data, "SEND ", 5) == 0)
                 {
                         /*
                          *	extra arg (file_size) req. for "SEND"
                          */
-                        
+
                         if (*data == 'S') xtra_args++;
                         data += 5;
                 }
@@ -109,22 +109,22 @@
                 /*
                  *	skip next string.
                  */
-                
+
                 while( *data++ != ' ')
-                        
+
                         /*
                          *	must still parse, at least, "AAAAAAAA P\x01\n",
                          *      12 bytes left.
                          */
                         if (data > (data_limit-12)) return 0;
 
-                
+
                 addr_beg_p = data;
-                
+
                 /*
                  *	client bound address in dec base
                  */
-                
+
  		s_addr = simple_strtoul(data,&data,10);
 		if (*data++ !=' ')
 			continue;
@@ -132,14 +132,14 @@
                 /*
                  *	client bound port in dec base
                  */
-                
+
 		s_port = simple_strtoul(data,&data,10);
                 addr_end_p = data;
-                
+
                 /*
                  *	should check args consistency?
                  */
-                
+
                 while(xtra_args) {
                         if (*data != ' ')
                                 break;
@@ -147,24 +147,24 @@
                         simple_strtoul(data,&data,10);
                         xtra_args--;
                 }
-                
+
                 if (xtra_args != 0) continue;
-                
+
                 /*
                  *	terminators.
                  */
-                
+
                 if (data[0] != 0x01)
                         continue;
 		if (data[1]!='\r' && data[1]!='\n')
 			continue;
-                
+
 		/*
 		 *	Now create an masquerade entry for it
                  * 	must set NO_DPORT and NO_DADDR because
                  *	connection is requested by another client.
 		 */
-                
+
 		n_ms = ip_masq_new(dev, IPPROTO_TCP,
                                    htonl(s_addr),htons(s_port),
                                    0, 0,
@@ -174,29 +174,29 @@
 			return 0;
 
                 ip_masq_set_expire(n_ms, ip_masq_expire->tcp_fin_timeout);
-                
+
 		/*
 		 * Replace the old "address port" with the new one
 		 */
-                
+
 		buf_len = sprintf(buf,"%lu %u",
                         ntohl(n_ms->maddr),ntohs(n_ms->mport));
-                
+
 		/*
 		 * Calculate required delta-offset to keep TCP happy
 		 */
-		
+
 		diff = buf_len - (addr_end_p-addr_beg_p);
 
 #if DEBUG_CONFIG_IP_MASQ_IRC
                 *addr_beg_p = '\0';
 		printk("masq_irc_out(): '%s' %X:%X detected (diff=%d)\n", dcc_p, s_addr,s_port, diff);
-#endif	
+#endif
 		/*
 		 *	No shift.
 		 */
-		 
-		if (diff==0) 
+
+		if (diff==0)
 		{
 			/*
 			 * simple case, just copy.
@@ -219,7 +219,7 @@
  *     	You need 1 object per port in case you need
  *	to offer also other used irc ports (6665,6666,etc),
  *	they will share methods but they need own space for
- *	data. 
+ *	data.
  */
 
 struct ip_masq_app ip_masq_irc = {
@@ -252,12 +252,12 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
 
 int init_module(void)
 {
         if (ip_masq_irc_init() != 0)
                 return -EIO;
-        register_symtab(NULL);
         return 0;
 }
 
diff -u --recursive --new-file v2.1.17/linux/net/ipv4/ip_masq_raudio.c linux/net/ipv4/ip_masq_raudio.c
--- v2.1.17/linux/net/ipv4/ip_masq_raudio.c	Thu Dec 12 19:37:25 1996
+++ linux/net/ipv4/ip_masq_raudio.c	Fri Dec 27 12:04:49 1996
@@ -31,10 +31,10 @@
  *
  *	At present the "first packet" is defined as a packet starting with
  *	the protocol ID string - "PNA".
- *	When the link is up there appears to be enough control data 
+ *	When the link is up there appears to be enough control data
  *	crossing the control link to keep it open even if a long audio
  *	piece is playing.
- *	
+ *
  */
 
 #include <linux/module.h>
@@ -64,11 +64,11 @@
 {
         MOD_INC_USE_COUNT;
 	if ((ms->app_data = kmalloc(sizeof(struct raudio_priv_data),
-				    GFP_ATOMIC)) == NULL) 
+				    GFP_ATOMIC)) == NULL)
 		printk(KERN_INFO "RealAudio: No memory for application data\n");
-	else 
+	else
 	{
-		struct raudio_priv_data *priv = 
+		struct raudio_priv_data *priv =
 			(struct raudio_priv_data *)ms->app_data;
 		priv->seen_start = 0;
 		priv->data_conn = NULL;
@@ -94,7 +94,7 @@
 	char *p, *data, *data_limit;
 	struct ip_masq *n_ms;
 	unsigned short version, msg_id, msg_len, udp_port;
-	struct raudio_priv_data *priv = 
+	struct raudio_priv_data *priv =
 		(struct raudio_priv_data *)ms->app_data;
 
 	/* Everything running correctly already */
@@ -156,7 +156,7 @@
 					   ms->saddr, udp_port,
 					   ms->daddr, 0,
 					   IP_MASQ_F_NO_DPORT);
-					
+
 			if (n_ms==NULL)
 				return 0;
 
@@ -171,7 +171,7 @@
 			if (priv)
 				priv->data_conn = n_ms;
 
-			/* 
+			/*
 			 * There is nothing else useful we can do
 			 * Maybe a development could do more, but for now
 			 * we exit gracefully!
@@ -214,12 +214,12 @@
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
 
 int init_module(void)
 {
         if (ip_masq_raudio_init() != 0)
                 return -EIO;
-        register_symtab(0);
         return 0;
 }
 
diff -u --recursive --new-file v2.1.17/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v2.1.17/linux/net/ipx/af_ipx.c	Wed Dec 18 15:59:15 1996
+++ linux/net/ipx/af_ipx.c	Fri Dec 27 12:04:49 1996
@@ -12,17 +12,17 @@
  *
  *	All the material in this file is subject to the Gnu license version 2.
  *	Neither Alan Cox nor the Swansea University Computer Society admit liability
- *	nor provide warranty for any of this software. This material is provided 
- *	as is and at no charge.		
+ *	nor provide warranty for any of this software. This material is provided
+ *	as is and at no charge.
  *
  *	Revision 0.21:	Uses the new generic socket option code.
  *	Revision 0.22:	Gcc clean ups and drop out device registration. Use the
- *			new multi-protocol edition of hard_header 
+ *			new multi-protocol edition of hard_header
  *	Revision 0.23:  IPX /proc by Mark Evans.
  *     			Adding a route will overwrite any existing route to the same
  *			network.
  *	Revision 0.24:	Supports new /proc with no 4K limit
- *	Revision 0.25:	Add ephemeral sockets, passive local network 
+ *	Revision 0.25:	Add ephemeral sockets, passive local network
  *			identification, support for local net 0 and
  *			multiple datalinks <Greg Page>
  *	Revision 0.26:  Device drop kills IPX routes via it. (needed for modules)
@@ -56,9 +56,9 @@
  *
  *
  * 	Portions Copyright (c) 1995 Caldera, Inc. <greg@caldera.com>
- *	Neither Greg Page nor Caldera, Inc. admit liability nor provide 
- *	warranty for any of this software. This material is provided 
- *	"AS-IS" and at no charge.		
+ *	Neither Greg Page nor Caldera, Inc. admit liability nor provide
+ *	warranty for any of this software. This material is provided
+ *	"AS-IS" and at no charge.
  */
 
 #include <linux/module.h>
@@ -128,7 +128,7 @@
 	}
 	return 0;
 }
-		
+
 static int
 ipxcfg_set_auto_select(char val)
 {
@@ -142,7 +142,7 @@
 ipxcfg_get_config_data(ipx_config_data *arg)
 {
 	ipx_config_data	vals;
-	
+
 	vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces;
 	vals.ipxcfg_auto_select_primary = ipxcfg_auto_select_primary;
 	return copy_to_user(arg, &vals, sizeof(vals)) ? -EFAULT : 0;
@@ -160,8 +160,8 @@
  *	handler using this technique. They can be added although we do not
  *	use this facility.
  */
- 
-static void 
+
+static void
 ipx_remove_socket(struct sock *sk)
 {
 	struct sock	*s;
@@ -170,7 +170,7 @@
 
 	save_flags(flags);
 	cli();
-	
+
 	/* Determine interface with which socket is associated */
 	intrfc = sk->protinfo.af_ipx.intrfc;
 	if (intrfc == NULL) {
@@ -183,7 +183,7 @@
 		intrfc->if_sklist=s->next;
 		restore_flags(flags);
 		return;
-	} 
+	}
 
 	while(s && s->next) {
 		if(s->next==sk) {
@@ -202,8 +202,8 @@
  *	Once it is removed from the queue no interrupt or bottom half will
  *	touch it and we are (fairly 8-) ) safe.
  */
- 
-static void 
+
+static void
 ipx_destroy_socket(struct sock *sk)
 {
 	struct sk_buff	*skb;
@@ -212,11 +212,11 @@
 	while((skb=skb_dequeue(&sk->receive_queue))!=NULL) {
 		kfree_skb(skb,FREE_READ);
 	}
-	
+
 	sk_free(sk);
 	MOD_DEC_USE_COUNT;
 }
-	
+
 /* The following code is used to support IPX Interfaces (IPXITF).  An
  * IPX interface is defined by a physical device and a frame type.
  */
@@ -237,8 +237,8 @@
 {
 	ipx_interface	*i;
 
-	for (i=ipx_interfaces; 
-		i && ((i->if_dev!=dev) || (i->if_dlink_type!=datalink)); 
+	for (i=ipx_interfaces;
+		i && ((i->if_dev!=dev) || (i->if_dlink_type!=datalink));
 		i=i->if_next)
 		;
 	return i;
@@ -280,8 +280,8 @@
 {
 	struct sock	*s;
 
-	for (s=intrfc->if_sklist; 
-		(s != NULL) && (s->protinfo.af_ipx.port != port); 
+	for (s=intrfc->if_sklist;
+		(s != NULL) && (s->protinfo.af_ipx.port != port);
 		s=s->next)
 		;
 
@@ -306,7 +306,7 @@
 		s = s->next;
 	}
 	return s;
-}	
+}
 #endif
 
 static void ipxrtr_del_routes(ipx_interface *);
@@ -337,11 +337,11 @@
 	if (intrfc == ipx_interfaces) {
 		ipx_interfaces = intrfc->if_next;
 	} else {
-		for (i = ipx_interfaces; 
+		for (i = ipx_interfaces;
 			(i != NULL) && (i->if_next != intrfc);
 			i = i->if_next)
 			;
-		if ((i != NULL) && (i->if_next == intrfc)) 
+		if ((i != NULL) && (i->if_next == intrfc))
 			i->if_next = intrfc->if_next;
 	}
 
@@ -359,7 +359,7 @@
 	return;
 }
 
-static int 
+static int
 ipxitf_device_event(struct notifier_block *notifier, unsigned long event, void *ptr)
 {
 	struct device *dev = ptr;
@@ -369,9 +369,9 @@
 		return NOTIFY_DONE;
 
 	for (i = ipx_interfaces; i != NULL; ) {
-	
+
 		tmp = i->if_next;
-		if (i->if_dev == dev) 
+		if (i->if_dev == dev)
 			ipxitf_down(i);
 		i = tmp;
 
@@ -384,7 +384,7 @@
 {
 	int	retval;
 
-	if((retval = sock_queue_rcv_skb(sock, skb))<0) 
+	if((retval = sock_queue_rcv_skb(sock, skb))<0)
 	{
 		/*
 		 * skb->sk is NULL here, so FREE_WRITE does not hurt
@@ -401,7 +401,7 @@
 
 #ifdef CONFIG_IPX_INTERN
 static int
-ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy) 
+ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
 {
 	struct ipxhdr	*ipx = skb->nh.ipxh;
 	struct sock	*s;
@@ -465,7 +465,7 @@
 #else
 
 static int
-ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy) 
+ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
 {
 	struct ipxhdr	*ipx = skb->nh.ipxh;
 	struct sock	*sock1 = NULL, *sock2 = NULL;
@@ -480,10 +480,10 @@
 	 *	The *SPECIAL* socket list contains: 0x452(SAP), 0x453(RIP) and
 	 *	0x456(Diagnostic).
 	 */
-	 
-	if (ipx_primary_net && (intrfc != ipx_primary_net)) 
+
+	if (ipx_primary_net && (intrfc != ipx_primary_net))
 	{
-		switch (ntohs(ipx->ipx_dest.sock)) 
+		switch (ntohs(ipx->ipx_dest.sock))
 		{
 			case 0x452:
 			case 0x453:
@@ -494,7 +494,7 @@
 				 *	interface via ipxitf_send; however, we'll cheat
 				 *	and just demux it here.
 				 */
-				sock2 = ipxitf_find_socket(ipx_primary_net, 
+				sock2 = ipxitf_find_socket(ipx_primary_net,
 					ipx->ipx_dest.sock);
 				break;
 			default:
@@ -502,57 +502,57 @@
 		}
 	}
 
-	/* 
+	/*
 	 *	if there is nothing to do, return. The kfree will
 	 *	cancel any charging.
 	 */
-	 
-	if (sock1 == NULL && sock2 == NULL) 
+
+	if (sock1 == NULL && sock2 == NULL)
 	{
-		if (!copy) 
+		if (!copy)
 			kfree_skb(skb,FREE_WRITE);
 		return 0;
 	}
 
 	/*
 	 * This next segment of code is a little awkward, but it sets it up
-	 * so that the appropriate number of copies of the SKB are made and 
-	 * that skb1 and skb2 point to it (them) so that it (they) can be 
+	 * so that the appropriate number of copies of the SKB are made and
+	 * that skb1 and skb2 point to it (them) so that it (they) can be
 	 * demuxed to sock1 and/or sock2.  If we are unable to make enough
 	 * copies, we do as much as is possible.
 	 */
-	 
-	if (copy) 
+
+	if (copy)
 	{
 		skb1 = skb_clone(skb, GFP_ATOMIC);
-		if (skb1) 
+		if (skb1)
 			skb1->arp=1;
-	} 
-	else 
+	}
+	else
 	{
 		skb1 = skb;
 	}
-	
-	if (skb1 == NULL) 
-		return -ENOMEM; 
+
+	if (skb1 == NULL)
+		return -ENOMEM;
 
 	/*
-	 *	Do we need 2 SKBs? 
+	 *	Do we need 2 SKBs?
 	 */
-	 
-	if (sock1 && sock2) 
+
+	if (sock1 && sock2)
 	{
 		skb2 = skb_clone(skb1, GFP_ATOMIC);
-		if (skb2 != NULL) 
+		if (skb2 != NULL)
 			skb2->arp = 1;
 	}
-	else 
+	else
 		skb2 = skb1;
-		
+
 	if (sock1)
 		(void) ipxitf_def_skb_handler(sock1, skb1);
 
-	if (skb2 == NULL) 
+	if (skb2 == NULL)
 		return -ENOMEM;
 
 	if (sock2)
@@ -635,35 +635,35 @@
 		/*
 		 *	Broadcast, loop and possibly keep to send on.
 		 */
-		if (memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0) 
+		if (memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0)
 		{
 			if (!send_to_wire)
 				skb_orphan(skb);
 			ipxitf_demux_socket(intrfc, skb, send_to_wire);
-			if (!send_to_wire) 
+			if (!send_to_wire)
 				return 0;
 		}
 	}
 
 	/*
-	 *	If the originating net is not equal to our net; this is routed 
+	 *	If the originating net is not equal to our net; this is routed
 	 *	We are still charging the sender. Which is right - the driver
 	 *	free will handle this fairly.
 	 */
-	 
-	if (ipx->ipx_source.net != intrfc->if_netnum) 
+
+	if (ipx->ipx_source.net != intrfc->if_netnum)
 	{
-		if (++(ipx->ipx_tctrl) > ipxcfg_max_hops) 
+		if (++(ipx->ipx_tctrl) > ipxcfg_max_hops)
 			send_to_wire = 0;
 	}
 
-	if (!send_to_wire) 
+	if (!send_to_wire)
 	{
 		/*
 		 *	We do a FREE_WRITE here because this indicates how
-		 *	to treat the socket with which the packet is 
+		 *	to treat the socket with which the packet is
 	 	 *	associated.  If this packet is associated with a
-		 *	socket at all, it must be the originator of the 
+		 *	socket at all, it must be the originator of the
 		 *	packet.   Routed packets will have no socket associated
 		 *	with them.
 		 */
@@ -672,21 +672,21 @@
 	}
 
 	/*
-	 *	Determine the appropriate hardware address 
+	 *	Determine the appropriate hardware address
 	 */
-	 
+
 	addr_len = dev->addr_len;
-	if (memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0) 
+	if (memcmp(ipx_broadcast_node, node, IPX_NODE_LEN) == 0)
 		memcpy(dest_node, dev->broadcast, addr_len);
 	else
 		memcpy(dest_node, &(node[IPX_NODE_LEN-addr_len]), addr_len);
 
 	/*
-	 *	Make any compensation for differing physical/data link size 
+	 *	Make any compensation for differing physical/data link size
 	 */
-	 
+
 	skb = ipxitf_adjust_skbuff(intrfc, skb);
-	if (skb == NULL) 
+	if (skb == NULL)
 		return 0;
 
 	/* set up data link and physical headers */
@@ -726,37 +726,37 @@
 	struct ipxhdr	*ipx = skb->nh.ipxh;
 	ipx_interface	*i;
 
-#ifdef CONFIG_FIREWALL	
+#ifdef CONFIG_FIREWALL
 	/*
 	 *	We firewall first, ask questions later.
 	 */
-	 
+
 	if (call_in_firewall(PF_IPX, skb->dev, ipx, NULL)!=FW_ACCEPT)
 	{
 		kfree_skb(skb, FREE_READ);
 		return 0;
 	}
-	
-#endif	
+
+#endif
 
 	/* See if we should update our network number */
-	if ((intrfc->if_netnum == 0L) && 
+	if ((intrfc->if_netnum == 0L) &&
 		(ipx->ipx_source.net == ipx->ipx_dest.net) &&
-		(ipx->ipx_source.net != 0L)) 
+		(ipx->ipx_source.net != 0L))
 	{
 		/* NB: NetWare servers lie about their hop count so we
 		 * dropped the test based on it.  This is the best way
 		 * to determine this is a 0 hop count packet.
 		 */
-		if ((i=ipxitf_find_using_net(ipx->ipx_source.net))==NULL) 
+		if ((i=ipxitf_find_using_net(ipx->ipx_source.net))==NULL)
 		{
 			intrfc->if_netnum = ipx->ipx_source.net;
 			(void) ipxitf_add_local_route(intrfc);
-		} 
-		else 
+		}
+		else
 		{
 			printk(KERN_WARNING "IPX: Network number collision %lx\n        %s %s and %s %s\n",
-				htonl(ipx->ipx_source.net), 
+				htonl(ipx->ipx_source.net),
 				ipx_device_name(i),
 				ipx_frame_name(i->if_dlink_type),
 				ipx_device_name(intrfc),
@@ -837,9 +837,9 @@
 	if (ipx->ipx_source.net == 0L)
 		ipx->ipx_source.net = intrfc->if_netnum;
 
-	if (intrfc->if_netnum != ipx->ipx_dest.net) 
+	if (intrfc->if_netnum != ipx->ipx_dest.net)
 	{
-#ifdef CONFIG_FIREWALL	
+#ifdef CONFIG_FIREWALL
 		/*
 		 *	See if we are allowed to firewall forward
 		 */
@@ -848,7 +848,7 @@
 			kfree_skb(skb, FREE_READ);
 			return 0;
 		}
-#endif		
+#endif
 		/* We only route point-to-point packets. */
 		if ((skb->pkt_type != PACKET_BROADCAST) &&
 			(skb->pkt_type != PACKET_MULTICAST))
@@ -864,8 +864,8 @@
 	}
 
 	/* see if we should keep it */
-	if ((memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0) 
-		|| (memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0)) 
+	if ((memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0)
+		|| (memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0))
 	{
 		return ipxitf_demux_socket(intrfc, skb, 0);
 	}
@@ -895,7 +895,7 @@
 	return;
 }
 
-static int 
+static int
 ipxitf_create_internal(ipx_interface_definition *idef)
 {
 	ipx_interface	*intrfc;
@@ -939,7 +939,7 @@
 	return 0;
 }
 
-static int 
+static int
 ipxitf_create(ipx_interface_definition *idef)
 {
 	struct device	*dev;
@@ -947,7 +947,7 @@
 	struct datalink_proto	*datalink = NULL;
 	ipx_interface	*intrfc;
 
-	if (idef->ipx_special == IPX_INTERNAL) 
+	if (idef->ipx_special == IPX_INTERNAL)
 		return ipxitf_create_internal(idef);
 
 	if ((idef->ipx_special == IPX_PRIMARY) && (ipx_primary_net != NULL))
@@ -958,7 +958,7 @@
 		return -EADDRINUSE;
 
 	switch (idef->ipx_dlink_type) {
-	case IPX_FRAME_ETHERII: 
+	case IPX_FRAME_ETHERII:
 		dlink_type = htons(ETH_P_IPX);
 		datalink = pEII_datalink;
 		break;
@@ -983,11 +983,11 @@
 		break;
 	}
 
-	if (datalink == NULL) 
+	if (datalink == NULL)
 		return -EPROTONOSUPPORT;
 
 	dev=dev_get(idef->ipx_device);
-	if (dev==NULL) 
+	if (dev==NULL)
 		return -ENODEV;
 
 	if (!(dev->flags & IFF_UP))
@@ -997,7 +997,7 @@
 	if(dev->addr_len>IPX_NODE_LEN)
 		return -EINVAL;
 
-	if ((intrfc = ipxitf_find_using_phys(dev, dlink_type)) == NULL) 
+	if ((intrfc = ipxitf_find_using_phys(dev, dlink_type)) == NULL)
 	{
 		/* Ok now create */
 		intrfc=(ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
@@ -1010,14 +1010,14 @@
 		intrfc->if_sklist = NULL;
 		intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET;
 		/* Setup primary if necessary */
-		if ((idef->ipx_special == IPX_PRIMARY)) 
+		if ((idef->ipx_special == IPX_PRIMARY))
 			ipx_primary_net = intrfc;
 		intrfc->if_internal = 0;
 		intrfc->if_ipx_offset = dev->hard_header_len + datalink->header_length;
 		if(memcmp(idef->ipx_node, "\000\000\000\000\000\000", IPX_NODE_LEN)==0)
 		{
 			memset(intrfc->if_node, 0, IPX_NODE_LEN);
-			memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]), 
+			memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
 				dev->dev_addr, dev->addr_len);
 		}
 		else
@@ -1026,13 +1026,13 @@
 	}
 
 	/* If the network number is known, add a route */
-	if (intrfc->if_netnum == 0L) 
+	if (intrfc->if_netnum == 0L)
 		return 0;
 
 	return ipxitf_add_local_route(intrfc);
 }
 
-static int 
+static int
 ipxitf_delete(ipx_interface_definition *idef)
 {
 	struct device	*dev = NULL;
@@ -1076,7 +1076,7 @@
 	case ETH_P_802_3: datalink = p8023_datalink; break;
 	default: return NULL;
 	}
-	
+
 	if (dev == NULL)
 		return NULL;
 
@@ -1092,10 +1092,10 @@
 		intrfc->if_sklist = NULL;
 		intrfc->if_internal = 0;
 		intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET;
-		intrfc->if_ipx_offset = dev->hard_header_len + 
+		intrfc->if_ipx_offset = dev->hard_header_len +
 			datalink->header_length;
 		memset(intrfc->if_node, 0, IPX_NODE_LEN);
-		memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]), 
+		memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
 			dev->dev_addr, dev->addr_len);
 		ipxitf_insert(intrfc);
 	}
@@ -1103,7 +1103,7 @@
 	return intrfc;
 }
 
-static int 
+static int
 ipxitf_ioctl_real(unsigned int cmd, void *arg)
 {
 	switch(cmd)
@@ -1134,7 +1134,7 @@
 			ipx_interface *ipxif;
 			struct device *dev;
 			int err;
-			
+
 			if (copy_from_user(&ifr,arg,sizeof(ifr)))
 				return -EFAULT;
 			sipx=(struct sockaddr_ipx *)&ifr.ifr_addr;
@@ -1171,7 +1171,7 @@
 	}
 }
 
-static int 
+static int
 ipxitf_ioctl(unsigned int cmd, void *arg)
 {
 	int ret;
@@ -1241,7 +1241,7 @@
 	}
 }
 
-static int 
+static int
 ipxrtr_create(ipx_route_definition *rd)
 {
 	ipx_interface *intrfc;
@@ -1255,7 +1255,7 @@
 }
 
 
-static int 
+static int
 ipxrtr_delete(long net)
 {
 	ipx_route	**r;
@@ -1270,7 +1270,7 @@
 			*r = tmp->ir_next;
 			kfree_s(tmp, sizeof(ipx_route));
 			return 0;
-		} 
+		}
 		r = &(tmp->ir_next);
 	}
 
@@ -1300,42 +1300,42 @@
 	__u16 *p=(__u16 *)&packet->ipx_pktsize;
 
 	/*
-	 *	Number of complete words 
+	 *	Number of complete words
 	 */
 
 	__u32 i=length>>1;
 
 	/*
-	 *	Loop through all complete words except the checksum field 
+	 *	Loop through all complete words except the checksum field
 	 */
 
 	while(--i)
 		sum+=*p++;
 
 	/*
-	 *	Add on the last part word if it exists 
+	 *	Add on the last part word if it exists
 	 */
 
 	if(packet->ipx_pktsize&htons(1))
 		sum+=ntohs(0xff00)&*p;
 
 	/*
-	 *	Do final fixup 
+	 *	Do final fixup
 	 */
-	 
+
 	sum=(sum&0xffff)+(sum>>16);
 
 	/*
-	 *	It's a pity there's no concept of carry in C 
+	 *	It's a pity there's no concept of carry in C
 	 */
 
 	if(sum>=0x10000)
 		sum++;
-		
+
 	return ~sum;
 };
 
- 
+
 /*
  *	Route an outgoing frame from a socket.
  */
@@ -1349,14 +1349,14 @@
 	int ipx_offset;
 	ipx_route *rt = NULL;
 	int err;
-	
+
 	/* Find the appropriate interface on which to send packet */
-	if ((usipx->sipx_network == 0L) && (ipx_primary_net != NULL)) 
+	if ((usipx->sipx_network == 0L) && (ipx_primary_net != NULL))
 	{
 		usipx->sipx_network = ipx_primary_net->if_netnum;
 		intrfc = ipx_primary_net;
-	} 
-	else 
+	}
+	else
 	{
 		rt = ipxrtr_lookup(usipx->sipx_network);
 		if (rt==NULL) {
@@ -1364,7 +1364,7 @@
 		}
 		intrfc = rt->ir_intrfc;
 	}
-	
+
 	ipx_offset = intrfc->if_ipx_offset;
 	size=sizeof(struct ipxhdr)+len;
 	size += ipx_offset;
@@ -1388,7 +1388,7 @@
 #ifdef CONFIG_IPX_INTERN
 	memcpy(ipx->ipx_source.node, sk->protinfo.af_ipx.node, IPX_NODE_LEN);
 #else
-	if ((err = ntohs(sk->protinfo.af_ipx.port)) == 0x453 || err == 0x452)  
+	if ((err = ntohs(sk->protinfo.af_ipx.port)) == 0x453 || err == 0x452)
 	{
 		/* RIP/SAP special handling for mars_nwe */
 		ipx->ipx_source.net = intrfc->if_netnum;
@@ -1447,7 +1447,7 @@
 		return 0;
 	}
 	i = r->ir_intrfc;
-	(void)ipxitf_send(i, skb, (r->ir_routed) ? 
+	(void)ipxitf_send(i, skb, (r->ir_routed) ?
 			r->ir_router_node : ipx->ipx_dest.node);
 	return 0;
 }
@@ -1461,21 +1461,21 @@
 	int err;
 	struct rtentry rt;	/* Use these to behave like 'other' stacks */
 	struct sockaddr_ipx *sg,*st;
-		
+
 	err = copy_from_user(&rt,arg,sizeof(rt));
 	if (err)
-		return -EFAULT; 
+		return -EFAULT;
 
 	sg=(struct sockaddr_ipx *)&rt.rt_gateway;
 	st=(struct sockaddr_ipx *)&rt.rt_dst;
-	
+
 	if(!(rt.rt_flags&RTF_GATEWAY))
 		return -EINVAL;		/* Direct routes are fixed */
 	if(sg->sipx_family!=AF_IPX)
 		return -EINVAL;
 	if(st->sipx_family!=AF_IPX)
 		return -EINVAL;
-		
+
 	switch(cmd)
 	{
 		case SIOCDELRT:
@@ -1524,22 +1524,22 @@
 
 	/* Theory.. Keep printing in the same place until we pass offset */
 
-	len += sprintf (buffer,"%-11s%-15s%-9s%-11s%s\n", "Network", 
+	len += sprintf (buffer,"%-11s%-15s%-9s%-11s%s\n", "Network",
 		"Node_Address", "Primary", "Device", "Frame_Type");
 	for (i = ipx_interfaces; i != NULL; i = i->if_next) {
 		len += sprintf(buffer+len, "%08lX   ", ntohl(i->if_netnum));
-		len += sprintf (buffer+len,"%02X%02X%02X%02X%02X%02X   ", 
+		len += sprintf (buffer+len,"%02X%02X%02X%02X%02X%02X   ",
 				i->if_node[0], i->if_node[1], i->if_node[2],
 				i->if_node[3], i->if_node[4], i->if_node[5]);
 		len += sprintf(buffer+len, "%-9s", (i == ipx_primary_net) ?
 			"Yes" : "No");
 		len += sprintf (buffer+len, "%-11s", ipx_device_name(i));
-		len += sprintf (buffer+len, "%s\n", 
+		len += sprintf (buffer+len, "%s\n",
 			ipx_frame_name(i->if_dlink_type));
 
 		/* Are we still dumping unwanted data then discard the record */
 		pos=begin+len;
-		
+
 		if(pos<offset) {
 			len=0;			/* Keep dumping into the buffer start */
 			begin=pos;
@@ -1547,13 +1547,13 @@
 		if(pos>offset+length)		/* We have dumped enough */
 			break;
 	}
-	
+
 	/* The data in question runs from begin to begin+len */
 	*start=buffer+(offset-begin);	/* Start of wanted data */
 	len-=(offset-begin);		/* Remove unwanted header data from length */
 	if(len>length)
 		len=length;		/* Remove unwanted tail data from length */
-	
+
 	return len;
 }
 
@@ -1568,28 +1568,28 @@
 
 	/* Theory.. Keep printing in the same place until we pass offset */
 
-#ifdef CONFIG_IPX_INTERN	
-	len += sprintf (buffer,"%-28s%-28s%-10s%-10s%-7s%s\n", "Local_Address", 
+#ifdef CONFIG_IPX_INTERN
+	len += sprintf (buffer,"%-28s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
 #else
-	len += sprintf (buffer,"%-15s%-28s%-10s%-10s%-7s%s\n", "Local_Address", 
+	len += sprintf (buffer,"%-15s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
 #endif
-			"Remote_Address", "Tx_Queue", "Rx_Queue", 
+			"Remote_Address", "Tx_Queue", "Rx_Queue",
 			"State", "Uid");
 	for (i = ipx_interfaces; i != NULL; i = i->if_next) {
 		for (s = i->if_sklist; s != NULL; s = s->next) {
 #ifdef CONFIG_IPX_INTERN
 			len += sprintf(buffer+len,
-				       "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ", 
+				       "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
 				 htonl(s->protinfo.af_ipx.intrfc->if_netnum),
 				       s->protinfo.af_ipx.node[0],
-				       s->protinfo.af_ipx.node[1], 
-				       s->protinfo.af_ipx.node[2], 
-				       s->protinfo.af_ipx.node[3], 
-				       s->protinfo.af_ipx.node[4], 
+				       s->protinfo.af_ipx.node[1],
+				       s->protinfo.af_ipx.node[2],
+				       s->protinfo.af_ipx.node[3],
+				       s->protinfo.af_ipx.node[4],
 				       s->protinfo.af_ipx.node[5],
 				       htons(s->protinfo.af_ipx.port));
 #else
-			len += sprintf(buffer+len,"%08lX:%04X  ", 
+			len += sprintf(buffer+len,"%08lX:%04X  ",
 				       htonl(i->if_netnum),
 				       htons(s->protinfo.af_ipx.port));
 #endif
@@ -1597,24 +1597,24 @@
 				len += sprintf(buffer+len, "%-28s", "Not_Connected");
 			} else {
 				len += sprintf (buffer+len,
-					"%08lX:%02X%02X%02X%02X%02X%02X:%04X  ", 
+					"%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
 					htonl(s->protinfo.af_ipx.dest_addr.net),
 					s->protinfo.af_ipx.dest_addr.node[0],
-					s->protinfo.af_ipx.dest_addr.node[1], 
+					s->protinfo.af_ipx.dest_addr.node[1],
 					s->protinfo.af_ipx.dest_addr.node[2],
-					s->protinfo.af_ipx.dest_addr.node[3], 
+					s->protinfo.af_ipx.dest_addr.node[3],
 					s->protinfo.af_ipx.dest_addr.node[4],
 					s->protinfo.af_ipx.dest_addr.node[5],
 					htons(s->protinfo.af_ipx.dest_addr.sock));
 			}
-			len += sprintf (buffer+len,"%08X  %08X  ", 
+			len += sprintf (buffer+len,"%08X  %08X  ",
 				s->wmem_alloc, s->rmem_alloc);
-			len += sprintf (buffer+len,"%02X     %03d\n", 
+			len += sprintf (buffer+len,"%02X     %03d\n",
 				s->state, SOCK_INODE(s->socket)->i_uid);
-		
+
 			/* Are we still dumping unwanted data then discard the record */
 			pos=begin+len;
-		
+
 			if(pos<offset)
 			{
 				len=0;			/* Keep dumping into the buffer start */
@@ -1624,13 +1624,13 @@
 				break;
 		}
 	}
-	
+
 	/* The data in question runs from begin to begin+len */
 	*start=buffer+(offset-begin);	/* Start of wanted data */
 	len-=(offset-begin);		/* Remove unwanted header data from length */
 	if(len>length)
 		len=length;		/* Remove unwanted tail data from length */
-	
+
 	return len;
 }
 
@@ -1642,16 +1642,16 @@
 	off_t pos=0;
 	off_t begin=0;
 
-	len += sprintf (buffer,"%-11s%-13s%s\n", 
+	len += sprintf (buffer,"%-11s%-13s%s\n",
 			"Network", "Router_Net", "Router_Node");
 	for (rt = ipx_routes; rt != NULL; rt = rt->ir_next)
 	{
 		len += sprintf (buffer+len,"%08lX   ", ntohl(rt->ir_net));
 		if (rt->ir_routed) {
-			len += sprintf (buffer+len,"%08lX     %02X%02X%02X%02X%02X%02X\n", 
-				ntohl(rt->ir_intrfc->if_netnum), 
-				rt->ir_router_node[0], rt->ir_router_node[1], 
-				rt->ir_router_node[2], rt->ir_router_node[3], 
+			len += sprintf (buffer+len,"%08lX     %02X%02X%02X%02X%02X%02X\n",
+				ntohl(rt->ir_intrfc->if_netnum),
+				rt->ir_router_node[0], rt->ir_router_node[1],
+				rt->ir_router_node[2], rt->ir_router_node[3],
 				rt->ir_router_node[4], rt->ir_router_node[5]);
 		} else {
 			len += sprintf (buffer+len, "%-13s%s\n",
@@ -1692,16 +1692,16 @@
 {
 	struct sock *sk;
 	int err,opt;
-	
+
 	sk=sock->sk;
-	
+
 	if (optval==NULL)
 		return(-EINVAL);
 
 	err = get_user(opt, (unsigned int *)optval);
 	if (err)
 		return err;
-	
+
 	switch(level)
 	{
 		case SOL_IPX:
@@ -1714,7 +1714,7 @@
 					return -EOPNOTSUPP;
 			}
 			break;
-			
+
 		default:
 			return -EOPNOTSUPP;
 	}
@@ -1726,7 +1726,7 @@
 	struct sock *sk;
 	int val=0;
 	int err;
-	
+
 	sk=sock->sk;
 
 	switch(level)
@@ -1742,7 +1742,7 @@
 					return -ENOPROTOOPT;
 			}
 			break;
-			
+
 		default:
 			return -EOPNOTSUPP;
 	}
@@ -1798,13 +1798,13 @@
 	sk->socket=sock;
 	sk->type=sock->type;
 	sk->mtu=IPX_MTU;
-	sk->no_check = 1;		/* Checksum off by default */	
+	sk->no_check = 1;		/* Checksum off by default */
 	if(sock!=NULL)
 	{
 		sk->sleep=&sock->wait;
 		sock->sk=sk;
 	}
-	
+
 	sk->state_change=def_callback1;
 	sk->data_ready=def_callback2;
 	sk->write_space=def_callback1;
@@ -1833,7 +1833,7 @@
 	return(ipx_create(newsock,SOCK_DGRAM));
 }
 
-static unsigned short 
+static unsigned short
 ipx_first_free_socketnum(ipx_interface *intrfc)
 {
 	unsigned short	socketNum = intrfc->if_sknum;
@@ -1850,21 +1850,21 @@
 	intrfc->if_sknum = socketNum;
 	return	ntohs(socketNum);
 }
-	
+
 static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
 	struct sock *sk;
 	ipx_interface *intrfc;
 	struct sockaddr_ipx *addr=(struct sockaddr_ipx *)uaddr;
-	
+
 	sk=sock->sk;
-	
+
 	if(sk->zapped==0)
 		return -EINVAL;
-		
+
 	if(addr_len!=sizeof(struct sockaddr_ipx))
 		return -EINVAL;
-	
+
 	intrfc = ipxitf_find_using_net(addr->sipx_network);
 	if (intrfc == NULL)
 		return -EADDRNOTAVAIL;
@@ -1902,8 +1902,8 @@
 		{
 			memcpy(sk->protinfo.af_ipx.node, addr->sipx_node, IPX_NODE_LEN);
 		}
-		if (ipxitf_find_internal_socket(intrfc, 
-			sk->protinfo.af_ipx.node, 
+		if (ipxitf_find_internal_socket(intrfc,
+			sk->protinfo.af_ipx.node,
 			sk->protinfo.af_ipx.port) != NULL)
 		{
 			if(sk->debug)
@@ -1919,14 +1919,14 @@
 		 * with the ipx routing ioctl()
 		 */
 
-		memcpy(sk->protinfo.af_ipx.node, intrfc->if_node, 
+		memcpy(sk->protinfo.af_ipx.node, intrfc->if_node,
 			IPX_NODE_LEN);
-		
+
 		if(ipxitf_find_socket(intrfc, addr->sipx_port)!=NULL) {
 			if(sk->debug)
 				printk("IPX: bind failed because port %X in"
 				       " use.\n", (int)addr->sipx_port);
-			return -EADDRINUSE;	   
+			return -EADDRINUSE;
 		}
 	}
 
@@ -1939,7 +1939,7 @@
 		if(sk->debug)
 			printk("IPX: bind failed because port %X in use.\n",
 				(int)addr->sipx_port);
-		return -EADDRINUSE;	   
+		return -EADDRINUSE;
 	}
 
 #endif
@@ -1956,20 +1956,20 @@
 {
 	struct sock *sk=sock->sk;
 	struct sockaddr_ipx *addr;
-	
-	sk->state = TCP_CLOSE;	
+
+	sk->state = TCP_CLOSE;
 	sock->state = SS_UNCONNECTED;
 
 	if(addr_len!=sizeof(*addr))
 		return(-EINVAL);
 	addr=(struct sockaddr_ipx *)uaddr;
-	
+
 	if(sk->protinfo.af_ipx.port==0)
 	/* put the autobinding in */
 	{
 		struct sockaddr_ipx uaddr;
 		int ret;
-	
+
 		uaddr.sipx_port = 0;
 		uaddr.sipx_network = 0L;
 #ifdef CONFIG_IPX_INTERN
@@ -1980,7 +1980,7 @@
 				sizeof(struct sockaddr_ipx));
 		if (ret != 0) return (ret);
 	}
-	
+
 	if(ipxrtr_lookup(addr->sipx_network)==NULL)
 		return -ENETUNREACH;
 	sk->protinfo.af_ipx.dest_addr.net=addr->sipx_network;
@@ -2013,11 +2013,11 @@
 	ipx_address *addr;
 	struct sockaddr_ipx sipx;
 	struct sock *sk;
-	
+
 	sk=sock->sk;
-	
+
 	*uaddr_len = sizeof(struct sockaddr_ipx);
-		
+
 	if(peer) {
 		if(sk->state!=TCP_ESTABLISHED)
 			return -ENOTCONN;
@@ -2031,7 +2031,7 @@
 #ifdef CONFIG_IPX_INTERN
 			memcpy(sipx.sipx_node, sk->protinfo.af_ipx.node, IPX_NODE_LEN);
 #else
-			memcpy(sipx.sipx_node, 
+			memcpy(sipx.sipx_node,
 				sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);
 #endif
 
@@ -2041,7 +2041,7 @@
 		}
 		sipx.sipx_port = sk->protinfo.af_ipx.port;
 	}
-		
+
 	sipx.sipx_family = AF_IPX;
 	sipx.sipx_type = sk->protinfo.af_ipx.type;
 	memcpy(uaddr,&sipx,sizeof(sipx));
@@ -2127,13 +2127,13 @@
 			return 0;
 		}
 	}
-	
+
 	/* Determine what local ipx endpoint this is */
 	intrfc = ipxitf_find_using_phys(dev, pt->type);
-	if (intrfc == NULL) 
+	if (intrfc == NULL)
 	{
 		if (ipxcfg_auto_create_interfaces &&
-		    ntohl(ipx->ipx_dest.net)!=0L) 
+		    ntohl(ipx->ipx_dest.net)!=0L)
 		{
 			intrfc = ipxitf_auto_create(dev, pt->type);
 		}
@@ -2157,20 +2157,20 @@
 	int retval;
 	int flags = msg->msg_flags;
 
-	if (sk->zapped) 
+	if (sk->zapped)
 		return -EIO; /* Socket not bound */
 	if (flags&~MSG_DONTWAIT)
 		return -EINVAL;
 
-	if(usipx) 
+	if(usipx)
 	{
-		if(sk->protinfo.af_ipx.port == 0) 
+		if(sk->protinfo.af_ipx.port == 0)
 		{
 			struct sockaddr_ipx uaddr;
 			int ret;
 
 			uaddr.sipx_port = 0;
-			uaddr.sipx_network = 0L; 
+			uaddr.sipx_network = 0L;
 #ifdef CONFIG_IPX_INTERN
 			memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc
 				->if_node, IPX_NODE_LEN);
@@ -2185,7 +2185,7 @@
 		if(usipx->sipx_family != AF_IPX)
 			return -EINVAL;
 	}
-	else 
+	else
 	{
 		if(sk->state!=TCP_ESTABLISHED)
 			return -ENOTCONN;
@@ -2196,9 +2196,9 @@
 		usipx->sipx_network=sk->protinfo.af_ipx.dest_addr.net;
 		memcpy(usipx->sipx_node,sk->protinfo.af_ipx.dest_addr.node,IPX_NODE_LEN);
 	}
-	
+
 	retval = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len, flags&MSG_DONTWAIT);
-	if (retval < 0) 
+	if (retval < 0)
 		return retval;
 
 	return len;
@@ -2251,7 +2251,7 @@
 	skb_free_datagram(sk, skb);
 
 	return(copied);
-}		
+}
 
 static int ipx_shutdown(struct socket *sk,int how)
 {
@@ -2262,7 +2262,7 @@
 {
 	long amount=0;
 	struct sock *sk=sock->sk;
-	
+
 	switch(cmd)
 	{
 		case TIOCOUTQ:
@@ -2290,7 +2290,7 @@
 				return -EPERM;
 		case SIOCGIFADDR:
 			return(ipxitf_ioctl(cmd,(void *)arg));
-		case SIOCIPXCFGDATA: 
+		case SIOCIPXCFGDATA:
 		{
 			return(ipxcfg_get_config_data((void *)arg));
 		}
@@ -2328,7 +2328,7 @@
 
 static struct proto_ops ipx_dgram_ops = {
 	AF_IPX,
-	
+
 	ipx_dup,
 	ipx_release,
 	ipx_bind,
@@ -2349,7 +2349,7 @@
 
 /* Called by protocol.c on kernel start up */
 
-static struct packet_type ipx_8023_packet_type = 
+static struct packet_type ipx_8023_packet_type =
 
 {
 	0,	/* MUTTER ntohs(ETH_P_8023),*/
@@ -2359,7 +2359,7 @@
 	NULL,
 };
 
-static struct packet_type ipx_dix_packet_type = 
+static struct packet_type ipx_dix_packet_type =
 {
 	0,	/* MUTTER ntohs(ETH_P_IPX),*/
 	NULL,		/* All devices */
@@ -2410,23 +2410,23 @@
 	p8023_datalink = make_8023_client();
 	ipx_8023_packet_type.type=htons(ETH_P_802_3);
 	dev_add_pack(&ipx_8023_packet_type);
-	
+
 	if ((p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv)) == NULL)
 		printk(KERN_CRIT "IPX: Unable to register with 802.2\n");
 
 	if ((p8022tr_datalink = register_8022tr_client(ipx_8022_type, ipx_rcv)) == NULL)
 		printk(KERN_CRIT "IPX: Unable to register with 802.2TR\n");
- 
+
 	if ((pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv)) == NULL)
 		printk(KERN_CRIT "IPX: Unable to register with SNAP\n");
-	
+
 	register_netdevice_notifier(&ipx_dev_notifier);
 #ifdef CONFIG_PROC_FS
 	proc_net_register(&ipx_procinfo);
 	proc_net_register(&ipx_if_procinfo);
 	proc_net_register(&ipx_rt_procinfo);
-#endif	
-		
+#endif
+
 	printk(KERN_INFO "Swansea University Computer Society IPX 0.35 for NET3.037\n");
 	printk(KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
 }
@@ -2436,13 +2436,13 @@
  *
  * Use counts are incremented/decremented when
  * sockets are created/deleted.
- * 
+ *
  * Routes are always associated with an interface, and
  * allocs/frees will remain properly accounted for by
  * their associated interfaces.
- * 
+ *
  * Ergo, before the ipx module can be removed, all IPX
- * sockets be closed from user space. 
+ * sockets be closed from user space.
  */
 
 static void
@@ -2460,7 +2460,7 @@
 	proc_net_unregister(PROC_NET_IPX_ROUTE);
 	proc_net_unregister(PROC_NET_IPX_INTERFACE);
 	proc_net_unregister(PROC_NET_IPX);
-#endif	
+#endif
 
 	unregister_netdevice_notifier(&ipx_dev_notifier);
 
@@ -2486,10 +2486,11 @@
 	return;
 }
 
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
 	ipx_proto_init(NULL);
-	register_symtab(0);
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.17/linux/net/netbeui/netbeui.c linux/net/netbeui/netbeui.c
--- v2.1.17/linux/net/netbeui/netbeui.c	Thu Dec 12 19:37:31 1996
+++ linux/net/netbeui/netbeui.c	Fri Dec 27 12:04:49 1996
@@ -1,4 +1,4 @@
- 
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <asm/uaccess.h>
@@ -56,15 +56,15 @@
  *	handler using this technique. They can be added although we do not
  *	use this facility.
  */
- 
+
 static void netbeui_remove_socket(netbeui_socket *sk)
 {
 	unsigned long flags;
 	netbeui_socket *s;
-	
+
 	save_flags(flags);
 	cli();
-	
+
 	s=netbeui_socket_list;
 	if(s==sk)
 	{
@@ -107,7 +107,7 @@
 /*
  *	Handler for deferred kills.
  */
- 
+
 static void netbeui_destroy_timer(unsigned long data)
 {
 	netbeui_destroy_socket((netbeui_socket *)data);
@@ -117,12 +117,12 @@
 {
 	struct sk_buff *skb;
 	netbeui_remove_socket(sk);
-	
+
 	while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
 	{
 		kfree_skb(skb,FREE_READ);
 	}
-	
+
 	if(sk->wmem_alloc == 0 && sk->rmem_alloc == 0 && sk->dead)
 	{
 		sk_free(sk);
@@ -143,9 +143,9 @@
 
 
 /*
- *	Called from proc fs 
+ *	Called from proc fs
  */
- 
+
 int netbeui_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
 	netbeui_socket *s;
@@ -171,10 +171,10 @@
 			s->protinfo.af_at.dest_port);
 		len += sprintf (buffer+len,"%08X:%08X ", s->wmem_alloc, s->rmem_alloc);
 		len += sprintf (buffer+len,"%02X %d\n", s->state, SOCK_INODE(s->socket)->i_uid);
-		
+
 		/* Are we still dumping unwanted data then discard the record */
 		pos=begin+len;
-		
+
 		if(pos<offset)
 		{
 			len=0;			/* Keep dumping into the buffer start */
@@ -183,13 +183,13 @@
 		if(pos>offset+length)		/* We have dumped enough */
 			break;
 	}
-	
+
 	/* The data in question runs from begin to begin+len */
 	*start=buffer+(offset-begin);	/* Start of wanted data */
 	len-=(offset-begin);		/* Remove unwanted header data from length */
 	if(len>length)
 		len=length;		/* Remove unwanted tail data from length */
-	
+
 	return len;
 }
 
@@ -218,7 +218,7 @@
  *	Generic fcntl calls are already dealt with. If we don't need funny ones
  *	this is the all you need. Async I/O is also separate.
  */
-  
+
 static int netbeui_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 /*	netbeui_socket *sk=(netbeui_socket *)sock->data;*/
@@ -230,24 +230,24 @@
 }
 
 /*
- *	Set 'magic' options for netbeui. If we don't have any this is fine 
+ *	Set 'magic' options for netbeui. If we don't have any this is fine
  *	as it is.
  */
- 
+
 static int netbeui_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
 {
 	netbeui_socket *sk;
 	int err,opt;
-	
+
 	sk=(netbeui_socket *)sock->data;
-	
+
 	if(optval==NULL)
 		return(-EINVAL);
 
 	err = get_user(opt, (int *)optval);
 	if (err)
 		return err;
-	
+
 	switch(level)
 	{
 		case SOL_NETBEUI:
@@ -257,7 +257,7 @@
 					return -EOPNOTSUPP;
 			}
 			break;
-			
+
 		case SOL_SOCKET:
 			return sock_setsockopt(sk,level,optname,optval,optlen);
 
@@ -270,14 +270,14 @@
 /*
  *	Get any magic options. Comment above applies.
  */
- 
+
 static int netbeui_getsockopt(struct socket *sock, int level, int optname,
 	char *optval, int *optlen)
 {
 	netbeui_socket *sk;
 	int val=0;
 	int err;
-	
+
 	sk=(netbeui_socket *)sock->data;
 
 	switch(level)
@@ -290,10 +290,10 @@
 					return -ENOPROTOOPT;
 			}
 			break;
-			
+
 		case SOL_SOCKET:
 			return sock_getsockopt(sk,level,optname,optval,optlen);
-			
+
 		default:
 			return -EOPNOTSUPP;
 	}
@@ -306,7 +306,7 @@
 /*
  *	Only for connection oriented sockets - ignore
  */
- 
+
 static int netbeui_listen(struct socket *sock, int backlog)
 {
 	struct sock *sk=(netbeui_socket *)sock->data;
@@ -321,13 +321,13 @@
 	sk->state=TCP_LISTEN;
 	sk->state_change(sk);
 	netbeui_llc_listen(sk);
-	return 0;	
+	return 0;
 }
 
 /*
  *	These are standard.
  */
- 
+
 static void def_callback1(struct sock *sk)
 {
 	if(!sk->dead)
@@ -347,7 +347,7 @@
  *	Create a socket. Initialise the socket, blank the addresses
  *	set the state.
  */
- 
+
 static int netbeui_create(struct socket *sock, int protocol)
 {
 	netbeui_socket *sk;
@@ -364,14 +364,14 @@
 			sk_free((void *)sk);
 			return(-ESOCKTNOSUPPORT);
 	}
-	
+
 	sk->llc802=llc_alloc(GFP_KERNEL);
 	if(sk->llc802==NULL)
 	{
 		sk_free((void *)sk);
 		return -ENOBUFS:
 	}
-	
+
 	MOD_INC_USE_COUNT;
 
 	sk->allocation=GFP_KERNEL;
@@ -386,13 +386,13 @@
 	sk->socket=sock;
 	sk->type=sock->type;
 	sk->mtu=1500;
-	
+
 	if(sock!=NULL)
 	{
 		sock->data=(void *)sk;
 		sk->sleep=sock->wait;
 	}
-	
+
 	sk->state_change=def_callback1;
 	sk->data_ready=def_callback2;
 	sk->write_space=def_callback1;
@@ -404,7 +404,7 @@
 /*
  *	Copy a socket. No work needed.
  */
- 
+
 static int netbeui_dup(struct socket *newsock,struct socket *oldsock)
 {
 	return(netbeui_create(newsock,oldsock->type));
@@ -413,7 +413,7 @@
 /*
  *	Free a socket. No work needed
  */
- 
+
 static int netbeui_release(struct socket *sock, struct socket *peer)
 {
 	netbeui_socket *sk=(netbeui_socket *)sock->data;
@@ -426,21 +426,21 @@
 	netbeui_destroy_socket(sk);
 	return(0);
 }
-		
+
 /*
  *	Set the address 'our end' of the connection.
  */
- 
+
 static int netbeui_bind(struct socket *sock, struct sockaddr *uaddr,size_t addr_len)
 {
 	netbeui_socket *sk;
 	struct sockaddr_netbeui *addr=(struct sockaddr_netbeui *)uaddr;
-	
+
 	sk=(netbeui_socket *)sock->data;
-	
+
 	if(sk->zapped==0)
 		return(-EINVAL);
-		
+
 	if(addr_len!=sizeof(struct sockaddr_at))
 		return -EINVAL;
 
@@ -448,7 +448,7 @@
 		return -EAFNOSUPPORT;
 
 	if(netbeui_find_socket(addr)!=NULL)
-		return -EADDRINUSE;	   
+		return -EADDRINUSE;
 
 	netbeui_insert_socket(sk);
 	sk->zapped=0;
@@ -458,20 +458,20 @@
 /*
  *	Set the address we talk to.
  */
- 
+
 static int netbeui_connect(struct socket *sock, struct sockaddr *uaddr,
 	size_t addr_len, int flags)
 {
 	netbeui_socket *sk=(netbeui_socket *)sock->data;
 	struct sockaddr_netbeui *addr;
-	
-	sk->state = TCP_CLOSE;	
+
+	sk->state = TCP_CLOSE;
 	sock->state = SS_UNCONNECTED;
 
 	if(addr_len!=sizeof(*addr))
 		return(-EINVAL);
 	addr=(struct sockaddr_netbeui *)uaddr;
-	
+
 	if(addr->sat_family!=AF_NETBEUI)
 		return -EAFNOSUPPORT;
 
@@ -481,16 +481,16 @@
 
 	if(sk->zapped)
 		return -EINVAL;
-	
+
 	if(atrtr_get_dev(&addr->sat_addr)==NULL)
 		return -ENETUNREACH;
-		
+
 }
 
 /*
  *	Not relevant
  */
- 
+
 static int netbeui_socketpair(struct socket *sock1, struct socket *sock2)
 {
 	return(-EOPNOTSUPP);
@@ -499,7 +499,7 @@
 /*
  *	WRITE ME
  */
- 
+
 static int netbeui_accept(struct socket *sock, struct socket *newsock, int flags)
 {
 	if(newsock->data)
@@ -511,21 +511,21 @@
  *	Find the name of a netbeui socket. Just copy the right
  *	fields into the sockaddr.
  */
- 
+
 static int netbeui_getname(struct socket *sock, struct sockaddr *uaddr,
 	size_t *uaddr_len, int peer)
 {
 	struct sockaddr_netbeui snb;
 	netbeui_socket *sk;
-	
+
 	sk=(netbeui_socket *)sock->data;
 	if(sk->zapped)
 	{
 		return -EINVAL;
-	}	
-	
+	}
+
 	*uaddr_len = sizeof(struct sockaddr_netbeui);
-		
+
 	if(peer)
 	{
 		if(sk->state!=TCP_ESTABLISHED)
@@ -542,7 +542,7 @@
 /*
  *	Receive a packet (in skb) from device dev.
  */
- 
+
 static int netbeui_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 {
 	netbeui_socket *sock;
@@ -560,13 +560,13 @@
 	struct netbeui_route *rt;
 	int loopback=0;
 	int err;
-	
+
 	if(flags)
 		return -EINVAL;
-		
+
 	if(len>587)
 		return -EMSGSIZE;
-		
+
 	if(usat)
 	{
 		if(sk->zapped)
@@ -582,7 +582,7 @@
 #if 0 	/* netnetbeui doesn't implement this check */
 		if(usat->sat_addr.s_node==ATADDR_BCAST && !sk->broadcast)
 			return -EPERM;
-#endif			
+#endif
 	}
 	else
 	{
@@ -594,19 +594,19 @@
 		usat->sat_addr.s_node=sk->protinfo.af_at.dest_node;
 		usat->sat_addr.s_net=sk->protinfo.af_at.dest_net;
 	}
-	
+
 	/* Build a packet */
-	
+
 	if(sk->debug)
 		printk("SK %p: Got address.\n",sk);
-	
+
 	size=sizeof(struct ddpehdr)+len+nb_dl->header_length;	/* For headers */
 
 	if(usat->sat_addr.s_net!=0 || usat->sat_addr.s_node == ATADDR_ANYNODE)
 	{
 		rt=atrtr_find(&usat->sat_addr);
 		if(rt==NULL)
-			return -ENETUNREACH;	
+			return -ENETUNREACH;
 		dev=rt->dev;
 	}
 	else
@@ -622,7 +622,7 @@
 
 	if(sk->debug)
 		printk("SK %p: Size needed %d, device %s\n", sk, size, dev->name);
-	
+
 	size += dev->hard_header_len;
 
 	skb = sock_alloc_send_skb(sk, size, 0, 0 , &err);
@@ -636,10 +636,10 @@
 	skb_reserve(skb,dev->hard_header_len);
 
 	skb->dev=dev;
-	
+
 	if(sk->debug)
 		printk("SK %p: Begin build.\n", sk);
-	
+
 	ddp=(struct ddpehdr *)skb_put(skb,sizeof(struct ddpehdr));
 	ddp->deh_pad=0;
 	ddp->deh_hops=0;
@@ -660,34 +660,34 @@
 
 	if(sk->debug)
 		printk("SK %p: Copy user data (%d bytes).\n", sk, len);
-		
+
 	err = memcpy_fromiovec(skb_put(skb,len),msg->msg_iov,len);
 	if (err)
 	{
 		kfree_skb(skb, FREE_WRITE);
 		return -EFAULT;
 	}
-		
+
 	if(sk->no_check==1)
 		ddp->deh_sum=0;
 	else
 		ddp->deh_sum=netbeui_checksum(ddp, len+sizeof(*ddp));
-		
+
 #ifdef CONFIG_FIREWALL
 
 	if(call_out_firewall(AF_NETBEUI, skb->dev, ddp, NULL)!=FW_ACCEPT)
 	{
 		kfree_skb(skb, FREE_WRITE);
 		return -EPERM;
-	}	
-	
+	}
+
 #endif
-	
+
 	/*
 	 *	Loopback broadcast packets to non gateway targets (ie routes
 	 *	to group we are in)
 	 */
-	 
+
 	if(ddp->deh_dnode==ATADDR_BCAST)
 	{
 		if((!(rt->flags&RTF_GATEWAY))&&(!(dev->flags&IFF_LOOPBACK)))
@@ -705,7 +705,7 @@
 		}
 	}
 
-	if((dev->flags&IFF_LOOPBACK) || loopback) 
+	if((dev->flags&IFF_LOOPBACK) || loopback)
 	{
 		if(sk->debug)
 			printk("SK %p: Loop back.\n", sk);
@@ -719,7 +719,7 @@
 		skb_pull(skb,nb_dl->header_length);
 		netbeui_rcv(skb,dev,NULL);
 	}
-	else 
+	else
 	{
 		if(sk->debug)
 			printk("SK %p: send out.\n", sk);
@@ -728,7 +728,7 @@
 		    gsat.sat_addr = rt->gateway;
 		    usat = &gsat;
 		}
-	
+
 		if(nb_send_low(dev,skb,&usat->sat_addr, NULL)==-1)
 			kfree_skb(skb, FREE_WRITE);
 		/* else queued/sent above in the aarp queue */
@@ -747,7 +747,7 @@
 	int copied = 0;
 	struct sk_buff *skb;
 	int er = 0;
-	
+
 	if(addr_len)
 		*addr_len=sizeof(*sat);
 
@@ -777,8 +777,8 @@
 			msg->msg_flags|=MSG_TRUNC;
 		}
 		er = skb_copy_datagram_iovec(skb,sizeof(*ddp),msg->msg_iov,copied);
-		if (er) 
-			goto out; 
+		if (er)
+			goto out;
 	}
 	if(sat)
 	{
@@ -790,7 +790,7 @@
 out:
 	skb_free_datagram(sk, skb);
 	return er ? er : (copied);
-}		
+}
 
 
 static int netbeui_shutdown(struct socket *sk,int how)
@@ -801,7 +801,7 @@
 static int netbeui_select(struct socket *sock , int sel_type, select_table *wait)
 {
 	netbeui_socket *sk=(netbeui_socket *)sock->data;
-	
+
 	return datagram_select(sk,sel_type,wait);
 }
 
@@ -813,7 +813,7 @@
 {
 	long amount=0;
 	netbeui_socket *sk=(netbeui_socket *)sock->data;
-	
+
 	switch(cmd)
 	{
 		/*
@@ -850,7 +850,7 @@
 			return(atrtr_ioctl(cmd,(void *)arg));
 		/*
 		 *	Interface
-		 */			
+		 */
 		case SIOCGIFADDR:
 		case SIOCSIFADDR:
 		case SIOCGIFBRDADDR:
@@ -888,7 +888,7 @@
 
 static struct proto_ops netbeui_proto_ops = {
 	AF_NETBEUI,
-	
+
 	netbeui_create,
 	netbeui_dup,
 	netbeui_release,
@@ -933,22 +933,22 @@
 /* ddp?  isn't it atalk too? 8) */
 	if ((nb_dl = register_snap_client(nb_snap_id, netbeui_rcv)) == NULL)
 		printk(KERN_CRIT "Unable to register DDP with SNAP.\n");
-	
+
 	register_netdevice_notifier(&nb_notifier);
 
 #ifdef CONFIG_PROC_FS
 	proc_net_register(&proc_netbeui);
-#endif	
+#endif
 
 	printk(KERN_INFO "NetBEUI 0.02 for Linux NET3.037\n");
 }
 
 #ifdef MODULE
+EXPORT_NO_SYMBOLS;
 
 int init_module(void)
 {
 	netbeui_proto_init(NULL);
-	register_symtab(0);
 	return 0;
 }
 
@@ -957,7 +957,7 @@
 	unsigned long flags;
 #ifdef CONFIG_PROC_FS
 	proc_net_unregister(PROC_NET_NETBEUI);
-#endif	
+#endif
 	unregister_netdevice_notifier(&nb_notifier);
 	unregister_snap_client(nb_snap_id);
 	sock_unregister(netbeui_proto_ops.family);
diff -u --recursive --new-file v2.1.17/linux/net/netrom/nr_dev.c linux/net/netrom/nr_dev.c
--- v2.1.17/linux/net/netrom/nr_dev.c	Wed Dec 18 15:59:15 1996
+++ linux/net/netrom/nr_dev.c	Fri Dec 27 12:04:49 1996
@@ -1,8 +1,8 @@
 /*
  *	NET/ROM release 004
  *
- *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
- *	releases, misbehave and/or generally screw up. It might even work. 
+ *	This is ALPHA test software. This code may break your machine, randomly fail to work with new
+ *	releases, misbehave and/or generally screw up. It might even work.
  *
  *	This code REQUIRES 1.3.0 or higher/ NET3.029
  *
@@ -106,8 +106,8 @@
 
 	if (daddr != NULL)
 		return 37;
-	
-	return -37;	
+
+	return -37;
 }
 
 static int nr_rebuild_header(struct sk_buff *skb)
@@ -126,7 +126,7 @@
 	bp[6] &= ~LAPB_E;
 	bp[6] |= SSSID_SPARE;
 	bp    += AX25_ADDR_LEN;
-	
+
 	bp[6] &= ~LAPB_C;
 	bp[6] |= LAPB_E;
 	bp[6] |= SSSID_SPARE;
@@ -158,7 +158,7 @@
 	ax25_listen_release((ax25_address *)dev->dev_addr, NULL);
 
 	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
-	
+
 	ax25_listen_register((ax25_address *)dev->dev_addr, NULL);
 
 	return 0;
@@ -279,6 +279,8 @@
 	{"nr3", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, nr_init}
 };
 
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
 	int i;
@@ -286,10 +288,8 @@
 	for (i = 0; i < 4; i++)
 		register_netdev(&dev_nr[i]);
 
-	register_symtab(NULL);
-
 	nr_proto_init(NULL);
-	
+
 	return 0;
 }
 
@@ -312,7 +312,7 @@
 	nr_unregister_sysctl();
 
 	sock_unregister(nr_proto_ops.family);
-	
+
 	for (i = 0; i < 4; i++) {
 		if (dev_nr[i].priv != NULL) {
 			kfree(dev_nr[i].priv);
diff -u --recursive --new-file v2.1.17/linux/net/netsyms.c linux/net/netsyms.c
--- v2.1.17/linux/net/netsyms.c	Sun Dec 22 16:37:44 1996
+++ linux/net/netsyms.c	Fri Dec 27 12:04:49 1996
@@ -69,140 +69,136 @@
 extern char *skb_push_errstr;
 extern char *skb_put_errstr;
 
-static struct symbol_table net_syms = {
-#include <linux/symtab_begin.h>
-
-	/* Skbuff symbols. */
-	X(skb_push_errstr),
-	X(skb_put_errstr),
-
-	/* Socket layer registration */
-	X(sock_register),
-	X(sock_unregister),
-
-	/* Socket layer support routines */
-	X(memcpy_fromiovec),
-	X(sock_setsockopt),
-	X(sock_getsockopt),
-	X(sock_sendmsg),
-	X(sock_recvmsg),
-	X(sk_alloc),
-	X(sk_free),
-	X(sock_wake_async),
-	X(sock_alloc_send_skb),
-	X(sock_rfree),
-	X(sock_wfree),
-	X(skb_recv_datagram),
-	X(skb_free_datagram),
-	X(skb_copy_datagram),
-	X(skb_copy_datagram_iovec),
-	X(skb_realloc_headroom),
-	X(datagram_select),
-
-	/* Needed by smbfs.o */
-	X(__scm_destroy),
-	X(__scm_send),
+/* Skbuff symbols. */
+EXPORT_SYMBOL(skb_push_errstr);
+EXPORT_SYMBOL(skb_put_errstr);
+
+/* Socket layer registration */
+EXPORT_SYMBOL(sock_register);
+EXPORT_SYMBOL(sock_unregister);
+
+/* Socket layer support routines */
+EXPORT_SYMBOL(memcpy_fromiovec);
+EXPORT_SYMBOL(sock_setsockopt);
+EXPORT_SYMBOL(sock_getsockopt);
+EXPORT_SYMBOL(sock_sendmsg);
+EXPORT_SYMBOL(sock_recvmsg);
+EXPORT_SYMBOL(sk_alloc);
+EXPORT_SYMBOL(sk_free);
+EXPORT_SYMBOL(sock_wake_async);
+EXPORT_SYMBOL(sock_alloc_send_skb);
+EXPORT_SYMBOL(sock_rfree);
+EXPORT_SYMBOL(sock_wfree);
+EXPORT_SYMBOL(skb_recv_datagram);
+EXPORT_SYMBOL(skb_free_datagram);
+EXPORT_SYMBOL(skb_copy_datagram);
+EXPORT_SYMBOL(skb_copy_datagram_iovec);
+EXPORT_SYMBOL(skb_realloc_headroom);
+EXPORT_SYMBOL(datagram_select);
+
+/* Needed by smbfs.o */
+EXPORT_SYMBOL(__scm_destroy);
+EXPORT_SYMBOL(__scm_send);
 
 #ifdef CONFIG_IPX_MODULE
-	X(make_8023_client),
-	X(destroy_8023_client),
-	X(make_EII_client),
-	X(destroy_EII_client),
+EXPORT_SYMBOL(make_8023_client);
+EXPORT_SYMBOL(destroy_8023_client);
+EXPORT_SYMBOL(make_EII_client);
+EXPORT_SYMBOL(destroy_EII_client);
 #endif
 
 #ifdef CONFIG_INET
-	/* Internet layer registration */
-	X(get_new_socknum),
-	X(inet_add_protocol),
-	X(inet_del_protocol),
-	X(rarp_ioctl_hook),
-	X(init_etherdev),
-	X(ip_route_output),
-	X(icmp_send),
-	X(ip_options_compile),
-	X(ip_rt_put),
-	X(arp_send),
-	X(ip_id_count),
-	X(ip_send_check),
-	X(ip_fragment),
-	X(ip_dev_find_tunnel),
-	X(inet_family_ops),
+/* Internet layer registration */
+EXPORT_SYMBOL(get_new_socknum);
+EXPORT_SYMBOL(inet_add_protocol);
+EXPORT_SYMBOL(inet_del_protocol);
+EXPORT_SYMBOL(rarp_ioctl_hook);
+EXPORT_SYMBOL(init_etherdev);
+EXPORT_SYMBOL(ip_route_output);
+EXPORT_SYMBOL(icmp_send);
+EXPORT_SYMBOL(ip_options_compile);
+EXPORT_SYMBOL(ip_rt_put);
+EXPORT_SYMBOL(arp_send);
+EXPORT_SYMBOL(ip_id_count);
+EXPORT_SYMBOL(ip_send_check);
+EXPORT_SYMBOL(ip_fragment);
+EXPORT_SYMBOL(ip_dev_find_tunnel);
+EXPORT_SYMBOL(inet_family_ops);
 
 #ifdef CONFIG_IP_FORWARD
-	X(ip_forward),
+EXPORT_SYMBOL(ip_forward);
 #endif
 
 #ifdef CONFIG_IPV6_MODULE
-	/* inet functions common to v4 and v6 */
-	X(inet_stream_ops),
-	X(inet_dgram_ops),
-	X(inet_remove_sock),
-	X(inet_release),
-	X(inet_stream_connect),
-	X(inet_dgram_connect),
-	X(inet_accept),
-	X(inet_select),
-	X(inet_listen),
-	X(inet_shutdown),
-	X(inet_setsockopt),
-	X(inet_getsockopt),
-	X(inet_fcntl),
-	X(inet_sendmsg),
-	X(inet_recvmsg),
-	X(tcp_sock_array),
-	X(udp_sock_array),
-	X(destroy_sock),
-	X(ip_queue_xmit),
-	X(csum_partial),
-	X(skb_copy),
-	X(dev_lockct),
-	X(ndisc_eth_hook),
-	X(memcpy_fromiovecend),
-	X(csum_partial_copy),
-	X(csum_partial_copy_fromiovecend),
-	X(__release_sock),
-	X(net_timer),
-	X(inet_put_sock),
-	/* UDP/TCP exported functions for TCPv6 */
-	X(udp_ioctl),
-	X(udp_connect),
-	X(udp_sendmsg),
-	X(tcp_cache_zap),
-	X(tcp_close),
-	X(tcp_accept),
-	X(tcp_write_wakeup),
-	X(tcp_read_wakeup),
-	X(tcp_select),
-	X(tcp_ioctl),
-	X(tcp_shutdown),
-	X(tcp_setsockopt),
-	X(tcp_getsockopt),
-	X(tcp_recvmsg),
-	X(tcp_send_synack),
-	X(sock_wmalloc),
-	X(tcp_reset_xmit_timer),
-	X(tcp_parse_options),
-	X(tcp_rcv_established),
-	X(tcp_init_xmit_timers),
-	X(tcp_clear_xmit_timers),
-	X(tcp_slt_array),
-	X(__tcp_inc_slow_timer),
-	X(tcp_statistics),
-	X(tcp_rcv_state_process),
-	X(tcp_do_sendmsg),
-	X(tcp_v4_build_header),
-	X(tcp_v4_rebuild_header),
-	X(tcp_v4_send_check),
-	X(tcp_v4_conn_request),
-	X(tcp_v4_syn_recv_sock),
-	X(tcp_v4_backlog_rcv),
-	X(tcp_v4_connect),
-	X(__ip_chk_addr),
-	X(net_reset_timer),
-	X(net_delete_timer),
-	X(udp_prot),
-	X(tcp_prot),
-	X(ipv4_specific),
+/* inet functions common to v4 and v6 */
+EXPORT_SYMBOL(inet_stream_ops);
+EXPORT_SYMBOL(inet_dgram_ops);
+EXPORT_SYMBOL(inet_remove_sock);
+EXPORT_SYMBOL(inet_release);
+EXPORT_SYMBOL(inet_stream_connect);
+EXPORT_SYMBOL(inet_dgram_connect);
+EXPORT_SYMBOL(inet_accept);
+EXPORT_SYMBOL(inet_select);
+EXPORT_SYMBOL(inet_listen);
+EXPORT_SYMBOL(inet_shutdown);
+EXPORT_SYMBOL(inet_setsockopt);
+EXPORT_SYMBOL(inet_getsockopt);
+EXPORT_SYMBOL(inet_fcntl);
+EXPORT_SYMBOL(inet_sendmsg);
+EXPORT_SYMBOL(inet_recvmsg);
+EXPORT_SYMBOL(tcp_sock_array);
+EXPORT_SYMBOL(udp_sock_array);
+EXPORT_SYMBOL(destroy_sock);
+EXPORT_SYMBOL(ip_queue_xmit);
+EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(dev_lockct);
+EXPORT_SYMBOL(ndisc_eth_hook);
+EXPORT_SYMBOL(memcpy_fromiovecend);
+EXPORT_SYMBOL(csum_partial_copy);
+EXPORT_SYMBOL(csum_partial_copy_fromiovecend);
+EXPORT_SYMBOL(__release_sock);
+EXPORT_SYMBOL(net_timer);
+EXPORT_SYMBOL(inet_put_sock);
+/* UDP/TCP exported functions for TCPv6 */
+EXPORT_SYMBOL(udp_ioctl);
+EXPORT_SYMBOL(udp_connect);
+EXPORT_SYMBOL(udp_sendmsg);
+EXPORT_SYMBOL(tcp_cache_zap);
+EXPORT_SYMBOL(tcp_close);
+EXPORT_SYMBOL(tcp_accept);
+EXPORT_SYMBOL(tcp_write_wakeup);
+EXPORT_SYMBOL(tcp_read_wakeup);
+EXPORT_SYMBOL(tcp_select);
+EXPORT_SYMBOL(tcp_ioctl);
+EXPORT_SYMBOL(tcp_shutdown);
+EXPORT_SYMBOL(tcp_setsockopt);
+EXPORT_SYMBOL(tcp_getsockopt);
+EXPORT_SYMBOL(tcp_recvmsg);
+EXPORT_SYMBOL(tcp_send_synack);
+EXPORT_SYMBOL(sock_wmalloc);
+EXPORT_SYMBOL(tcp_reset_xmit_timer);
+EXPORT_SYMBOL(tcp_parse_options);
+EXPORT_SYMBOL(tcp_rcv_established);
+EXPORT_SYMBOL(tcp_init_xmit_timers);
+EXPORT_SYMBOL(tcp_clear_xmit_timers);
+EXPORT_SYMBOL(tcp_slt_array);
+EXPORT_SYMBOL(__tcp_inc_slow_timer);
+EXPORT_SYMBOL(tcp_statistics);
+EXPORT_SYMBOL(tcp_rcv_state_process);
+EXPORT_SYMBOL(tcp_do_sendmsg);
+EXPORT_SYMBOL(tcp_v4_build_header);
+EXPORT_SYMBOL(tcp_v4_rebuild_header);
+EXPORT_SYMBOL(tcp_v4_send_check);
+EXPORT_SYMBOL(tcp_v4_conn_request);
+EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
+EXPORT_SYMBOL(tcp_v4_backlog_rcv);
+EXPORT_SYMBOL(tcp_v4_connect);
+EXPORT_SYMBOL(__ip_chk_addr);
+EXPORT_SYMBOL(net_reset_timer);
+EXPORT_SYMBOL(net_delete_timer);
+EXPORT_SYMBOL(udp_prot);
+EXPORT_SYMBOL(tcp_prot);
+EXPORT_SYMBOL(ipv4_specific);
 #endif
 
 #if	defined(CONFIG_ULTRA)	||	defined(CONFIG_WD80x3)		|| \
@@ -210,21 +206,21 @@
 	defined(CONFIG_E2100)	||	defined(CONFIG_HPLAN_PLUS)	|| \
 	defined(CONFIG_HPLAN)	||	defined(CONFIG_AC3200)		|| \
 	defined(CONFIG_ES3210)
-	/* If 8390 NIC support is built in, we will need these. */
-	X(ei_open),
-	X(ei_close),
-	X(ei_debug),
-	X(ei_interrupt),
-	X(ethdev_init),
-	X(NS8390_init),
+/* If 8390 NIC support is built in, we will need these. */
+EXPORT_SYMBOL(ei_open);
+EXPORT_SYMBOL(ei_close);
+EXPORT_SYMBOL(ei_debug);
+EXPORT_SYMBOL(ei_interrupt);
+EXPORT_SYMBOL(ethdev_init);
+EXPORT_SYMBOL(NS8390_init);
 #endif
 
 #ifdef CONFIG_TR
-	X(tr_setup),
-	X(tr_type_trans),
-	X(register_trdev),
-	X(unregister_trdev),
-	X(init_trdev),
+EXPORT_SYMBOL(tr_setup);
+EXPORT_SYMBOL(tr_type_trans);
+EXPORT_SYMBOL(register_trdev);
+EXPORT_SYMBOL(unregister_trdev);
+EXPORT_SYMBOL(init_trdev);
 #endif
                           
 #ifdef CONFIG_NET_ALIAS
@@ -233,59 +229,50 @@
 
 #endif  /* CONFIG_INET */
 
-	/* Device callback registration */
-	X(register_netdevice_notifier),
-	X(unregister_netdevice_notifier),
+/* Device callback registration */
+EXPORT_SYMBOL(register_netdevice_notifier);
+EXPORT_SYMBOL(unregister_netdevice_notifier);
 
 #ifdef CONFIG_NET_ALIAS
-	X(register_net_alias_type),
-	X(unregister_net_alias_type),
+EXPORT_SYMBOL(register_net_alias_type);
+EXPORT_SYMBOL(unregister_net_alias_type);
 #endif
 
-        /* support for loadable net drivers */
+/* support for loadable net drivers */
 #ifdef CONFIG_INET
-	X(register_netdev),
-	X(unregister_netdev),
-	X(ether_setup),
-	X(eth_type_trans),
-	X(eth_copy_and_sum),
-	X(arp_query),
-	X(alloc_skb),
-	X(__kfree_skb),
-	X(skb_clone),
-	X(skb_copy),
-	X(dev_alloc_skb),
-	X(netif_rx),
-	X(dev_tint),
-	X(irq2dev_map),
-	X(dev_add_pack),
-	X(dev_remove_pack),
-	X(dev_get),
-	X(dev_ioctl),
-	X(dev_queue_xmit),
-	X(dev_base),
-	X(dev_close),
-	X(dev_mc_add),
-	X(arp_find),
-	X(n_tty_ioctl),
-	X(tty_register_ldisc),
-	X(kill_fasync),
-	X(arp_query),
-	X(ip_rcv),
-	X(arp_rcv),
+EXPORT_SYMBOL(register_netdev);
+EXPORT_SYMBOL(unregister_netdev);
+EXPORT_SYMBOL(ether_setup);
+EXPORT_SYMBOL(eth_type_trans);
+EXPORT_SYMBOL(eth_copy_and_sum);
+EXPORT_SYMBOL(arp_query);
+EXPORT_SYMBOL(alloc_skb);
+EXPORT_SYMBOL(__kfree_skb);
+EXPORT_SYMBOL(skb_clone);
+EXPORT_SYMBOL(skb_copy);
+EXPORT_SYMBOL(dev_alloc_skb);
+EXPORT_SYMBOL(netif_rx);
+EXPORT_SYMBOL(dev_tint);
+EXPORT_SYMBOL(irq2dev_map);
+EXPORT_SYMBOL(dev_add_pack);
+EXPORT_SYMBOL(dev_remove_pack);
+EXPORT_SYMBOL(dev_get);
+EXPORT_SYMBOL(dev_ioctl);
+EXPORT_SYMBOL(dev_queue_xmit);
+EXPORT_SYMBOL(dev_base);
+EXPORT_SYMBOL(dev_close);
+EXPORT_SYMBOL(dev_mc_add);
+EXPORT_SYMBOL(arp_find);
+EXPORT_SYMBOL(n_tty_ioctl);
+EXPORT_SYMBOL(tty_register_ldisc);
+EXPORT_SYMBOL(kill_fasync);
+EXPORT_SYMBOL(ip_rcv);
+EXPORT_SYMBOL(arp_rcv);
 #endif  /* CONFIG_INET */
 
 #ifdef CONFIG_NETLINK
-	X(netlink_attach),
-	X(netlink_detach),
-	X(netlink_donothing),
-	X(netlink_post),
+EXPORT_SYMBOL(netlink_attach);
+EXPORT_SYMBOL(netlink_detach);
+EXPORT_SYMBOL(netlink_donothing);
+EXPORT_SYMBOL(netlink_post);
 #endif /* CONFIG_NETLINK */
-	
-#include <linux/symtab_end.h>
-};
-
-void export_net_symbols(void)
-{
-	register_symtab(&net_syms);
-}
diff -u --recursive --new-file v2.1.17/linux/net/rose/rose_dev.c linux/net/rose/rose_dev.c
--- v2.1.17/linux/net/rose/rose_dev.c	Wed Dec 18 15:59:15 1996
+++ linux/net/rose/rose_dev.c	Fri Dec 27 12:04:49 1996
@@ -1,8 +1,8 @@
 /*
  *	Rose release 001
  *
- *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
- *	releases, misbehave and/or generally screw up. It might even work. 
+ *	This is ALPHA test software. This code may break your machine, randomly fail to work with new
+ *	releases, misbehave and/or generally screw up. It might even work.
  *
  *	This code REQUIRES 2.1.0 or higher/ NET3.029
  *
@@ -87,8 +87,8 @@
 
 	if (daddr != NULL)
 		return 37;
-	
-	return -37;	
+
+	return -37;
 }
 
 static int rose_rebuild_header(struct sk_buff *skb)
@@ -130,7 +130,7 @@
 	ax25_listen_release((ax25_address *)dev->dev_addr, NULL);
 
 	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
-	
+
 	ax25_listen_register((ax25_address *)dev->dev_addr, NULL);
 
 	return 0;
@@ -249,15 +249,15 @@
 	{"rose1", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init}
 };
 
+EXPORT_NO_SYMBOLS;
+
 int init_module(void)
 {
 	register_netdev(&dev_rose[0]);
 	register_netdev(&dev_rose[1]);
 
-	register_symtab(NULL);
-
 	rose_proto_init(NULL);
-	
+
 	return 0;
 }
 
@@ -281,7 +281,7 @@
 	unregister_netdevice_notifier(&rose_dev_notifier);
 
 	sock_unregister(rose_proto_ops.family);
-	
+
 	for (i = 0; i < 2; i++) {
 		if (dev_rose[i].priv != NULL) {
 			kfree(dev_rose[i].priv);
diff -u --recursive --new-file v2.1.17/linux/net/socket.c linux/net/socket.c
--- v2.1.17/linux/net/socket.c	Wed Dec 18 15:59:15 1996
+++ linux/net/socket.c	Fri Dec 27 12:04:49 1996
@@ -94,10 +94,6 @@
 #include <net/scm.h>
 
 
-#if defined(CONFIG_MODULES) && defined(CONFIG_NET)
-extern void export_net_symbols(void);
-#endif
-
 static long long sock_lseek(struct inode *inode, struct file *file,
 			    long long offset, int whence);
 static long sock_read(struct inode *inode, struct file *file,
@@ -1512,14 +1508,6 @@
 	 */
 
 	proto_init();
-
-	/*
-	 *	Export networking symbols to the world.
-	 */
-
-#if defined(CONFIG_MODULES) && defined(CONFIG_NET)
-	export_net_symbols();
-#endif
 }
 
 int socket_get_info(char *buffer, char **start, off_t offset, int length)
