diff -u --recursive --new-file v2.1.71/linux/CREDITS linux/CREDITS
--- v2.1.71/linux/CREDITS	Tue Dec  2 16:45:16 1997
+++ linux/CREDITS	Fri Dec  5 11:01:02 1997
@@ -1342,6 +1342,14 @@
 D: Generic Z8530 driver, AX.25 DAMA slave implementation
 D: Several AX.25 hacks
 
+N: Francois-Rene Rideau
+E: rideau@ens.fr
+W: http://www.eleves.ens.fr:8080/home/rideau/
+D: petty kernel janitor (byteorder, ufs)
+S: 6, rue Augustin Thierry
+S: 75019 Paris
+S: France
+
 N: William E. Roadcap
 E: roadcapw@cfw.com
 W: http://www.cfw.com/~roadcapw
diff -u --recursive --new-file v2.1.71/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.71/linux/Documentation/Configure.help	Thu Dec  4 14:53:54 1997
+++ linux/Documentation/Configure.help	Tue Dec  9 09:49:58 1997
@@ -1494,9 +1494,9 @@
   a second or   satellite links this option will make no difference to
   performance.
 
-BSD Unix domain sockets
+Unix domain sockets
 CONFIG_UNIX
-  Y if you want BSD Unix domain sockets.  Unless you are working on an
+  Y if you want Unix domain sockets.  Unless you are working on an
   embedded system or somthing, you probably want to say Y.  If you try
   building this as a module and you are running kerneld, you need to make
   sure and add 'alias net-pf-1 unix' to your /etc/conf.module file.
@@ -2795,6 +2795,28 @@
   running kernel whenever you want), say M here and read
   Documentation/modules.txt. The module will be called scc.o.
 
+High-speed (DMA) SCC driver for AX.25
+CONFIG_DMASCC
+  This is a driver for high-speed SCC boards, i.e. those supporting
+  DMA on one port. Currently, only Ottawa PI/PI2 boards (see
+  http://hydra.carleton.ca/info/pi2.html) and Gracilis PackeTwin
+  boards (see http://www.paccomm.com/) are supported and detected
+  automatically. Multiple boards are operated simultaneously. If
+  you compile this driver as a module, it will be called dmascc.o.
+  If you don't give any parameter to the driver, all possible I/O
+  addresses are probed. This could irritate other devices that are
+  currently not in use. You may specify the list of addresses to be
+  probed by "dmascc=addr1,addr2,..." (when compiled into the kernel
+  image) or "io=addr1,addr2,..." (when loaded as a module).
+  The network interfaces will be called dmascc0 and dmascc1 for the
+  board detected first, dmascc2 and dmascc3 for the second one, and
+  so on. Before you configure each interface with ifconfig, you MUST
+  set certain parameters, such as channel access timing, clock mode,
+  and DMA channel. This is accomplished with a small utility program
+  called dmascc_cfg, which is part of the ax25-utils package.
+  Alternatively, you may download the utility from
+  http://www.oevsv.at/~oe1kib/Linux.html.
+
 BAYCOM picpar and par96 driver for AX.25
 CONFIG_BAYCOM_PAR
   This is a driver for Baycom style simple amateur radio
@@ -3582,36 +3604,6 @@
   ni65.o. If you plan to use more than one network card under linux,
   read the Multiple-Ethernet-mini-HOWTO, available from
   sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
-
-Ottawa PI and PI/2 support
-CONFIG_PI
-  This is a driver for the Ottawa Amateur Radio Club PI and PI2 cards,
-  which are commonly used to send internet traffic over amateur radio.
-  More information about these cards is on the WWW at
-  http://hydra.carleton.ca/info/pi2.html (To browse the WWW, you need
-  to have access to a machine on the Internet that has a program like
-  lynx or netscape). If you have one of these cards, you can say Y
-  here and should read the HAM-HOWTO, available via ftp (user:
-  anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also, you
-  should have said Y to "AX.25 support" above, because AX.25 is the
-  protocol used for digital traffic over radio links. 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 here and
-  read Documentation/modules.txt. The module will be called pi2.o.
-
-Gracilis PackeTwin support
-CONFIG_PT
-  This is a card used mainly by amateur radio operators for packet
-  radio.  You should have already said Y to "AX.25 support" as this
-  card uses that protocol.  More information about this driver can be
-  found in the file drivers/net/README.pt.  NOTE: The card is capable
-  of DMA and full duplex but neither of these have been coded in the
-  driver as yet.  This driver is also available as a module ( = code
-  which can be inserted in and removed from the running kernel
-  whenever you want). If you want to compile it as a module, say M
-  here and read Documentation/modules.txt as well as
-  Documentation/networking/net-modules.txt. The module will be called
-  pt.o.
 
 AT&T WaveLAN & DEC RoamAbout DS support
 CONFIG_WAVELAN
diff -u --recursive --new-file v2.1.71/linux/Documentation/devices.tex linux/Documentation/devices.tex
--- v2.1.71/linux/Documentation/devices.tex	Sat Nov 29 11:25:08 1997
+++ linux/Documentation/devices.tex	Thu Dec  4 17:37:00 1997
@@ -4,7 +4,7 @@
 % pages to print... :-)  If you're actually putting this in print, you
 % may wish to change these.
 %
-% $Id: devices.tex,v 1.28 1997/11/12 23:59:41 davem Exp $
+% $Id: devices.tex,v 1.4 1997/12/05 01:34:21 hpa Exp $
 %
 \oddsidemargin=0in
 \textwidth=6.5in
@@ -50,7 +50,7 @@
 %
 \title{{\bf Linux Allocated Devices}}
 \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$}
-\date{Last revised: November 9, 1997}
+\date{Last revised: December 4, 1997}
 \maketitle
 %
 \noindent
@@ -193,8 +193,11 @@
 \major{44}{}{char }{isdn4linux virtual modem -- alternate devices}
 \major{  }{}{block}{Flash Translation Layer (FTL) filesystems}
 \major{45}{}{char }{isdn4linux ISDN BRI driver}
+\major{  }{}{block}{Reserved for parallel port IDE disk}
 \major{46}{}{char }{Comtrol Rocketport serial card}
+\major{  }{}{block}{Reserved for parallel port ATAPI CD-ROM}
 \major{47}{}{char }{Comtrol Rocketport serial card -- alternate devices}
+\major{  }{}{block}{Reserved for parallel port ATAPI disk}
 \major{48}{}{char }{SDL RISCom serial card}
 \major{49}{}{char }{SDL RISCom serial card -- alternate devices}
 \major{50}{}{char }{Reserved for GLINT}
@@ -240,7 +243,8 @@
 \major{93}{}{char }{IBM Smart Capture Card frame grabber}
 \major{94}{}{char }{miroVIDEO DC10/30 capture/playback device}
 \major{95}{}{char }{IP Filter}
-\major{96}{--119}{}{Unallocated}
+\major{96}{}{char }{Reserved for parallel port ATAPI tape}
+\major{97}{--119}{}{Unallocated}
 \major{120}{--127}{}{Local/experimental use}
 \major{128}{--239}{}{Unallocated}
 \major{240}{--254}{}{Local/experimental use}
@@ -407,15 +411,15 @@
 \begin{devicelist}
 \major{ 5}{}{char }{Alternate TTY devices}
 	\minor{0}{/dev/tty}{Current TTY device}
-	\minor{1}{}{Reserved for console device}
+	\minor{1}{/dev/console}{System console}
 	\minor{64}{/dev/cua0}{Callout device corresponding to {\file ttyS0}}
 	\minordots
 	\minor{127}{/dev/cua63}{Callout device corresponding to {\file ttyS63}}
 \end{devicelist}
 
 \noindent
-Minor number 1 is reserved for a kernel-managed
-{\file /dev/console} in a future version of Linux.
+(5,1) is {\file /dev/console} starting with Linux 2.1.71.  See the
+section on terminal devices for more information on {\file /dev/console}.
 
 \begin{devicelist}
 \major{ 6}{}{char }{Parallel printer devices}
@@ -550,6 +554,7 @@
 	\minor{149}{/dev/input/mouse}{Linux/SGI Irix emulation mouse}
 	\minor{150}{/dev/input/keyboard}{Linux/SGI Irix emulation keyboard}
 	\minor{151}{/dev/led}{Front panel LEDs}
+	\minor{152}{/dev/radio}{Radio card (type?)}
 \end{devicelist}
 
 \begin{devicelist}
@@ -797,30 +802,30 @@
 
 \begin{devicelist}
 \major{27}{}{char }{QIC-117 tape}
-        \minor{0}{/dev/qft0}{Unit 0, rewind-on-close}
-        \minor{1}{/dev/qft1}{Unit 1, rewind-on-close}
-        \minor{2}{/dev/qft2}{Unit 2, rewind-on-close}
-        \minor{3}{/dev/qft3}{Unit 3, rewind-on-close}
-        \minor{4}{/dev/nqft0}{Unit 0, no rewind-on-close}
-        \minor{5}{/dev/nqft1}{Unit 1, no rewind-on-close}
-        \minor{6}{/dev/nqft2}{Unit 2, no rewind-on-close}
-        \minor{7}{/dev/nqft3}{Unit 3, no rewind-on-close}
-        \minor{16}{/dev/zqft0}{Unit 0, rewind-on-close, compression}
-        \minor{17}{/dev/zqft1}{Unit 1, rewind-on-close, compression}
-        \minor{18}{/dev/zqft2}{Unit 2, rewind-on-close, compression}
-        \minor{19}{/dev/zqft3}{Unit 3, rewind-on-close, compression}
-        \minor{20}{/dev/nzqft0}{Unit 0, no-rewind-on-close, compression}
-        \minor{21}{/dev/nzqft1}{Unit 1, no-rewind-on-close, compression}
-        \minor{22}{/dev/nzqft2}{Unit 2, no-rewind-on-close, compression}
-        \minor{23}{/dev/nzqft3}{Unit 3, no-rewind-on-close, compression}
-        \minor{32}{/dev/rawft0}{Unit 0, rewind-on-close, no file marks}
-        \minor{33}{/dev/rawft1}{Unit 1, rewind-on-close, no file marks}
-        \minor{34}{/dev/rawft2}{Unit 2, rewind-on-close, no file marks}
-        \minor{35}{/dev/rawft3}{Unit 3, rewind-on-close, no file marks}
-        \minor{36}{/dev/zqft0}{Unit 0, no-rewind-on-close, no file marks}
-        \minor{37}{/dev/zqft1}{Unit 1, no-rewind-on-close, no file marks}
-        \minor{38}{/dev/zqft2}{Unit 2, no-rewind-on-close, no file marks}
-        \minor{39}{/dev/zqft3}{Unit 3, no-rewind-on-close, no file marks}
+	\minor{0}{/dev/qft0}{Unit 0, rewind-on-close}
+	\minor{1}{/dev/qft1}{Unit 1, rewind-on-close}
+	\minor{2}{/dev/qft2}{Unit 2, rewind-on-close}
+	\minor{3}{/dev/qft3}{Unit 3, rewind-on-close}
+	\minor{4}{/dev/nqft0}{Unit 0, no rewind-on-close}
+	\minor{5}{/dev/nqft1}{Unit 1, no rewind-on-close}
+	\minor{6}{/dev/nqft2}{Unit 2, no rewind-on-close}
+	\minor{7}{/dev/nqft3}{Unit 3, no rewind-on-close}
+	\minor{16}{/dev/zqft0}{Unit 0, rewind-on-close, compression}
+	\minor{17}{/dev/zqft1}{Unit 1, rewind-on-close, compression}
+	\minor{18}{/dev/zqft2}{Unit 2, rewind-on-close, compression}
+	\minor{19}{/dev/zqft3}{Unit 3, rewind-on-close, compression}
+	\minor{20}{/dev/nzqft0}{Unit 0, no rewind-on-close, compression}
+	\minor{21}{/dev/nzqft1}{Unit 1, no rewind-on-close, compression}
+	\minor{22}{/dev/nzqft2}{Unit 2, no rewind-on-close, compression}
+	\minor{23}{/dev/nzqft3}{Unit 3, no rewind-on-close, compression}
+	\minor{32}{/dev/rawqft0}{Unit 0, rewind-on-close, no file marks}
+	\minor{33}{/dev/rawqft1}{Unit 1, rewind-on-close, no file marks}
+	\minor{34}{/dev/rawqft2}{Unit 2, rewind-on-close, no file marks}
+	\minor{35}{/dev/rawqft3}{Unit 3, rewind-on-close, no file marks}
+	\minor{36}{/dev/nrawqft0}{Unit 0, no rewind-on-close, no file marks}
+	\minor{37}{/dev/nrawqft1}{Unit 1, no rewind-on-close, no file marks}
+	\minor{38}{/dev/nrawqft2}{Unit 2, no rewind-on-close, no file marks}
+	\minor{39}{/dev/nrawqft3}{Unit 3, no rewind-on-close, no file marks}
 \\
 \major{  }{}{block}{Third Matsushita (Panasonic/SoundBlaster) CD-ROM}
 	\minor{0}{/dev/sbpcd8}{Panasonic CD-ROM controller 2 unit 0}
@@ -1629,8 +1634,7 @@
 \begin{nodelist}
 \link{/dev/core}{/proc/kcore}{symbolic}{Backward compatibility}
 \link{/dev/ramdisk}{ram0}{symbolic}{Backward compatibility}
-\link{/dev/rft0}{qft0}{symbolic}{Backward compatibility}
-\link{/dev/ftape}{rft0}{symbolic}{Backward compatibility}
+\link{/dev/ftape}{qft0}{symbolic}{Backward compatibility}
 \link{/dev/scd?}{sr?}{hard}{Alternate name for CD-ROMs}
 \link{/dev/fd?D*}{fd?u*}{hard}{Backward compatibility}
 \link{/dev/fd?H*}{fd?u*}{hard}{Backward compatibility}
@@ -1715,10 +1719,11 @@
 
 The {\em console device\/}, {\file /dev/console}, is the device to
 which system messages should be sent, and on which logins should be
-permitted in single-user mode.  {\file /dev/console} should be a
-symbolic link to either {\file /dev/tty0}, a specific virtual console
-such as {\file /dev/tty1}, or to a serial port primary ({\file tty})
-device, depending on the configuration of the system.
+permitted in single-user mode.  Starting with Linux 2.1.71, {\file
+/dev/console} is managed by the kernel; for previous versions it
+should be a symbolic link to either {\file /dev/tty0}, a specific
+virtual console such as {\file /dev/tty1}, or to a serial port primary
+({\file tty}) device, depending on the configuration of the system.
 
 \subsection{Serial ports}
 
diff -u --recursive --new-file v2.1.71/linux/Documentation/devices.txt linux/Documentation/devices.txt
--- v2.1.71/linux/Documentation/devices.txt	Wed Nov 26 16:24:01 1997
+++ linux/Documentation/devices.txt	Thu Dec  4 17:37:00 1997
@@ -1,7 +1,7 @@
 		       LINUX ALLOCATED DEVICES
 	     Maintained by H. Peter Anvin <hpa@zytor.com>
 
-		    Last revised: November 9, 1997
+		    Last revised: December 4, 1997
 
 This list is the Linux Device List, the official registry of allocated
 device numbers and /dev directory nodes for the Linux operating
@@ -191,13 +191,14 @@
 
   5 char	Alternate TTY devices
 		  0 = /dev/tty		Current TTY device
-		  1			Reserved for console device
+		  1 = /dev/console	System console
 		 64 = /dev/cua0		Callout device corresponding to ttyS0
 		      ...
 		127 = /dev/cua63	Callout device corresponding to ttyS63
 
-		Minor number 1 is reserved for a kernel-managed
-		/dev/console in a future version of Linux.
+		(5,1) is /dev/console starting with Linux 2.1.71.  See
+		the section on terminal devices for more information
+		on /dev/console.
 
   6 char	Parallel printer devices
 		  0 = /dev/lp0		First parallel printer (0x3bc)
@@ -315,6 +316,7 @@
 		149 = /dev/input/mouse	Linux/SGI Irix emulation mouse
 		150 = /dev/input/keyboard Linux/SGI Irix emulation keyboard
 		151 = /dev/led		Front panel LEDs
+		152 = /dev/radio	Radio card (type?)
 
  11 char	Raw keyboard device
 		  0 = /dev/kbd		Raw keyboard device
@@ -515,22 +517,22 @@
 		  5 = /dev/nqft1	Unit 1, no rewind-on-close
 		  6 = /dev/nqft2	Unit 2, no rewind-on-close
 		  7 = /dev/nqft3	Unit 3, no rewind-on-close
-		  16 = /dev/zqft0	Unit 0, rewind-on-close, compression
-		  17 = /dev/zqft1	Unit 1, rewind-on-close, compression
-		  18 = /dev/zqft2	Unit 2, rewind-on-close, compression
-		  19 = /dev/zqft3	Unit 3, rewind-on-close, compression
-		  20 = /dev/nzqft0	Unit 0, no-rewind, compression
-		  21 = /dev/nzqft1	Unit 1, no-rewind, compression
-		  22 = /dev/nzqft2	Unit 2, no-rewind, compression
-		  23 = /dev/nzqft3	Unit 3, no-rewind, compression
-		  32 = /dev/rawft0	Unit 0, rewind-on-close, no file marks
-		  33 = /dev/rawft1	Unit 1, rewind-on-close, no file marks
-		  34 = /dev/rawft2	Unit 2, rewind-on-close, no file marks
-		  35 = /dev/rawft3	Unit 3, rewind-on-close, no file marks
-		  36 = /dev/zqft0	Unit 0, no-rewind, no file marks
-		  37 = /dev/zqft1	Unit 1, no-rewind, no file marks
-		  38 = /dev/zqft2	Unit 2, no-rewind, no file marks
-		  39 = /dev/zqft3	Unit 3, no-rewind, no file marks
+		 16 = /dev/zqft0	Unit 0, rewind-on-close, compression
+		 17 = /dev/zqft1	Unit 1, rewind-on-close, compression
+		 18 = /dev/zqft2	Unit 2, rewind-on-close, compression
+		 19 = /dev/zqt3		Unit 3, rewind-on-close, compression
+		 20 = /dev/nzqft0	Unit 0, no rewind-on-close, compression
+		 21 = /dev/nzqft1	Unit 1, no rewind-on-close, compression
+		 22 = /dev/nzqft2	Unit 2, no rewind-on-close, compression
+		 23 = /dev/nzqft3	Unit 3, no rewind-on-close, compression
+		 32 = /dev/rawqft0	Unit 0, rewind-on-close, no file marks
+		 33 = /dev/rawqft1	Unit 1, rewind-on-close, no file marks
+		 34 = /dev/rawqft2	Unit 2, rewind-on-close, no file marks
+		 35 = /dev/rawqft3	Unit 3, rewind-on-close, no file marks
+		 32 = /dev/nrawqft0	Unit 0, no rewind-on-close, no file marks
+		 33 = /dev/nrawqft1	Unit 1, no rewind-on-close, no file marks
+		 34 = /dev/nrawqft2	Unit 2, no rewind-on-close, no file marks
+		 35 = /dev/nrawqft3	Unit 3, no rewind-on-close, no file marks
     block	Third Matsushita (Panasonic/SoundBlaster) CD-ROM
 		  0 = /dev/sbpcd8	Panasonic CD-ROM controller 2 unit 0
 		  1 = /dev/sbpcd9	Panasonic CD-ROM controller 2 unit 1
@@ -1153,7 +1155,6 @@
 
 /dev/core	/proc/kcore	symbolic	Backward compatibility
 /dev/ramdisk	ram0		symbolic	Backward compatibility
-/dev/rft0	qft0		symbolic	Backward compatibility
 /dev/ftape	qft0		symbolic	Backward compatibility
 /dev/scd?	sr?		hard		Alternate SCSI CD-ROM name
 
@@ -1228,9 +1229,10 @@
 
 The console device, /dev/console, is the device to which system
 messages should be sent, and on which logins should be permitted in
-single-user mode.  /dev/console should be a symbolic link to either
-/dev/tty0, a specific virtual console such as /dev/tty1, or to a
-serial port primary (tty*, not cu*) device, depending on the
+single-user mode.  Starting with Linux 2.1.71, /dev/console is managed
+by the kernel; for previous versions it should be a symbolic link to
+either /dev/tty0, a specific virtual console such as /dev/tty1, or to
+a serial port primary (tty*, not cu*) device, depending on the
 configuration of the system.
 
 	Serial ports
diff -u --recursive --new-file v2.1.71/linux/Documentation/filesystems/coda.txt linux/Documentation/filesystems/coda.txt
--- v2.1.71/linux/Documentation/filesystems/coda.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/filesystems/coda.txt	Sun Dec  7 11:51:01 1997
@@ -0,0 +1,1427 @@
+  The Venus kernel interface
+  Peter J. Braam
+  v1.0, Nov 9, 1997
+
+  This document describes the communication between Venus and kernel
+  level file system code needed for the operation of the Coda filesys-
+  tem.  This version document is meant to describe the current interface
+  (version 1.0) as well as improvements we envisage.
+  ______________________________________________________________________
+
+  Table of Contents:
+
+  1.      Introduction
+
+  2.      Servicing Coda filesystem calls
+
+  3.      The message layer
+
+  3.1.    Implementation details
+
+  4.      The interface at the call level
+
+  4.1.    Data structures shared by the kernel and Venus
+
+  4.2.    The pioctl interface
+
+  4.3.    root
+
+  4.4.    lookup
+
+  4.5.    getattr
+
+  4.6.    setattr
+
+  4.7.    access
+
+  4.8.    create
+
+  4.9.    mkdir
+
+  4.10.   link
+
+  4.11.   synlink
+
+  4.12.   remove
+
+  4.13.   rmdir
+
+  4.14.   readlink
+
+  4.15.   open
+
+  4.16.   close
+
+  4.17.   ioctl
+
+  4.18.   rename
+
+  4.19.   readdir
+
+  4.20.   vget
+
+  4.21.   fsync
+
+  4.22.   inactive
+
+  4.23.   rdwr
+
+  4.24.   odymount
+
+  4.25.   ody_lookup
+
+  4.26.   ody_expand
+
+  4.27.   prefetch
+
+  4.28.   signal
+
+  5.      The minicache and downcalls
+
+  5.1.    INVALIDATE
+
+  5.2.    FLUSH
+
+  5.3.    PURGEUSER
+
+  5.4.    ZAPFILE
+
+  5.5.    ZAPDIR
+
+  5.6.    ZAPVNODE
+
+  5.7.    PURGEFID
+
+  5.8.    REPLACE
+
+  6.      Initialization and cleanup
+
+  6.1.    Requirements
+  ______________________________________________________________________
+  0wpage
+
+  11..  IInnttrroodduuccttiioonn
+
+  A key component in the Coda Distributed File System is the cache
+  manager, _V_e_n_u_s.
+
+  When processes on a Coda enabled system access files in the Coda
+  filesystem, requests are directed at the filesystem layer in the
+  operating system. The operating system will communicate with Venus to
+  service the request for the process.  Venus manages a persistent
+  client cache and makes remote procedure calls to Coda file servers and
+  related servers (such as authentication servers) to service these
+  requests it receives from the operating system.  When Venus has
+  serviced a request it replies to the operating system with appropiate
+  return codes, and other data related to the request.  Optionally the
+  kernel support for Coda may maintain a minicache of recently processed
+  requests to limit the number of interactions with Venus.  Venus
+  possesses the facility to inform the kernel when elements from its
+  minicache are no longer valid.
+
+  This document describes precisely this communication between the
+  kernel and Venus.  The definitions of so called upcalls and downcalls
+  will be given with the format of the data they handle. We shall also
+  describe the semantic invariants resulting from the calls.
+
+  Historically Coda was implemented in a BSD file system in Mach 2.6.
+  The interface between the kernel and Venus is very similar to the BSD
+  VFS interface.  Similar functionality is provided, and the format of
+  the parameters and returned data is very similar to the BSD VFS.  This
+  leads to an almost natural environment for implementing a kernel level
+  filesystem driver for Coda in a BSD system.  However, other operating
+  systems such as Linux and Windows 95 and NT have virtual filesystem
+  with different interfaces.
+
+  To implement Coda on these systems some reverse engineering of the
+  Venus/Kernel protocol is necessary.  Also it came to light that other
+  systems could profit significantly from certain small optimizations
+  and modifications to the protocol. To facilitate this work as well as
+  to make future ports easier, communication between Venus and the
+  kernel should be documented in great detail.  This is the aim of this
+  document.
+
+  0wpage
+
+  22..  SSeerrvviicciinngg CCooddaa ffiilleessyysstteemm ccaallllss
+
+  The service of a request for a Coda file system service originates in
+  a process PP which accessing a Coda file. It makes a system call which
+  traps to the OS kernel. Examples of such calls trapping to the kernel
+  are _r_e_a_d_, _w_r_i_t_e_, _o_p_e_n_, _c_l_o_s_e_, _c_r_e_a_t_e_, _m_k_d_i_r_, _r_m_d_i_r_, _c_h_m_o_d in a Unix
+  context.  Similar calls exist in the Win32 environment, and are named
+  _C_r_e_a_t_e_F_i_l_e_, .
+
+  Generally the operating system handles the request in a virtual
+  filesystem (VFS) layer, which is named I/O Manager in NT and IFS
+  manager in Windows 95.  The VFS is responsible for partial processing
+  of the request and for locating the specific filesystem(s) which will
+  service parts of the request.  Usually the information in the path
+  assists in locating the correct FS drivers.  Sometimes after extensive
+  pre-processing, the VFS starts invoking exported routines in the FS
+  driver.  This is the point where the FS specific processing of the
+  request starts, and here the Coda specific kernel code comes into
+  play.
+
+  The FS layer for Coda must expose and implement several interfaces.
+  First and foremost the VFS must be able to make all necessary calls to
+  the Coda FS layer, so the Coda FS driver must expose the VFS interface
+  as applicable in the operating system. These differ very significantly
+  among operating systems, but share features such as facilities to
+  read/write and create and remove object.  The Coda FS layer services
+  such VFS requests in by invoking on or more well defined services
+  offered by the cache manager Venus.  When the replies from Venus have
+  come back to the FS driver, servicing of the VFS call continues and
+  finishes with a reply to the kernels VFS. Finally the VFS layer
+  returns to the process.
+
+  As a result of this design a basic interface exposed by the FS driver
+  must allow Venus to handle manage message traffic.  In particular
+  Venus must be able to retrieve and place messages and to be notified
+  of the arrival of a new message. The notification must be through a
+  mechanism which does not block Venus since Venus must attend to other
+  tasks even when no messages are waiting or being processed.
+
+                       Interfaces of Coda FS Driver
+
+  Furthermore the FS layer provides for a special path of communication
+  between a user process and Venus, called the pioctl interface. The
+  pioctl interface is used for Coda specific services, such as
+  requesting detailed information about the persistent cache managed by
+  Venus. Here the involvement of the kernel is minimal.  It identifies
+  the calling process and passes the information on to Venus.  When
+  Venus replies the response is passed back to the caller in unmodified
+  form.
+
+  Finally Venus allows the kernel FS driver to cache the results from
+  certain services.  This is done to avoid excessive context switches
+  and results in an efficient system.  However, Venus may acquire
+  information, for example from the network which implies that cached
+  information must be flushed or replaced. Venus then makes a downcall
+  to the Coda FS layer to request flushes or updates in the cache.  The
+  kernel FS driver handles such requests synchronously.
+
+  Among these interfaces the VFS interface and the facility to place,
+  receive and be notified of messages are platform specific.  We will
+  not go into the calls exported to the VFS layer but we will state the
+  requirements of the message exchange mechanism.
+
+  0wpage
+
+  33..  TThhee mmeessssaaggee llaayyeerr
+
+  At the lowest level the communication between Venus and the FS driver
+  proceeds through messages.  The synchronization of between processes
+  requesting Coda file service and Venus relies on blocking and waking
+  up processes.  The Coda FS driver processes VFS- and pioctl-requests
+  on behalf of a process P, creates messages for Venus, awaits replies
+  and finally returns to the caller.  The implementation of the exchange
+  of messages is platform specific, but the semantics have (so far)
+  appeared to be generally applicable.  Data buffers are created by the
+  FS Driver in kernel memory on behalf of P and copied to user memory in
+  Venus.
+
+  The FS Driver while servicing P makes upcall's to Venus.  Such an
+  upcall is dispatched to Venus by creating a message structure.  The
+  structure contains the identification of P, the message sequence
+  number, the size of the request and a pointer to the data in kernel
+  memory for the request.  Since the data buffer is re-used to hold the
+  reply from Venus, there is a field for the size of the reply.  A flags
+  field is used in the message to precisely record the status of the
+  message.  Additional platform dependent structures involve pointers to
+  determine the position of the message on queues and pointers to
+  synchronization objects.  In the upcall routine the message structure
+  is filled in, flags are set to 0, and it is placed on the _p_e_n_d_i_n_g
+  queue.  The routine calling upcall is responsible for allocating the
+  data buffer; it's structure will be described in the next section.
+
+  A facility must exist to notify Venus that the message has been
+  created, and implemented using available synchronization objects in
+  the OS. This notification is done in the upcall context of the process
+  P. When the message is on the pending queue, process P cannot proceed
+  in upcall.  The (kernel mode) processing of P in the filesystem
+  request routine must be suspended until Venus has replied.  Therefore
+  the calling thread in P is blocked in upcall.  A pointer in the
+  message structure will locate the synchronization object on which P is
+  sleeping.
+
+  Venus detects the notification that a message has arrived, and the FS
+  driver allow Venus to retrieve the message with a getmsg_from_kernel
+  call. This action finishes in the kernel by putting the message on the
+  queue of processing messages and setting flags to READ.  Venus is
+  passed the contents of the data buffer. The getmsg_from_kernel call
+  now returns and Venus processes the request.
+
+  At some later point the FS driver receives a message from Venus,
+  namely when Venus calls sendmsg_to_kernel.  At this moment the Coda FS
+  driver looks at the contents of the message and decides if:
+
+  +o  the message is a reply for a suspended thread P.  If so it removes
+     the message from the processing queue and marks the message as
+     WRITTEN.  Finally, the FS driver unblocks P (still in the kernel
+     mode context of Venus) and the sendmsg_to_kernel call returns to
+     Venus.  The process P will be scheduled at some point and continues
+     processing its upcall with the data buffer replaced with the reply
+     from Venus.
+
+  +o  The message is a _d_o_w_n_c_a_l_l.  A downcall is a request from Venus to
+     the FS Driver. The FS driver processes the request immediately
+     (usually a cach eviction or replacement) and when finishes
+     sendmsg_to_kernel returns.
+
+  Now P awakes and continues processing upcall.  There are some
+  subtleties to take account off. First P will determine if it was woken
+  up in upcall by a signal from some other source (for example an
+  attempt to terminate P) or as is normally the case by Venus in its
+  sendmsg_to_kernel call.  In the normal case, the upcall routine will
+  deallocate message structure and return.  The FS routine can proceed
+  with its processing.
+
+                      Sleeping and IPC arrangements
+
+  In case P is woken up by a signal and not by Venus, it will first look
+  at the flags field.  If the message is not yet READ, the process P can
+  handle it's signal without notifying Venus.  If Venus has READ, and
+  the request should not be processed, P can send Venus a signal message
+  to indicate that it should disregard the previous message.  Such
+  signals are put in the queue at the head, and read first by Venus.  If
+  the message is already marked as WRITTEN it is too late to stop the
+  processing.  The VFS routine will now continue.  (-- If a VFS request
+  involves more than one upcall, this can lead to complicated state, an
+  extra field "handle_signals" could be added in the message structure
+  to indicate points of no return have been passed.--)
+
+  33..11..  IImmpplleemmeennttaattiioonn ddeettaaiillss
+
+  The Unix implementation of this mechanism has been through the
+  implemenation of a character device associated with Coda.  Venus
+  retrieves messages by doing a read on the device, replies are sent
+  with a write and notification is through the select system call on the
+  file descriptor for the device.  The process P is kept waiting on an
+  interruptible wait queue object.
+
+  In Windows NT and the DPMI Windows 95 implementation a DeviceIoControl
+  call is used.  The DeviceIoControl call is designed to copy buffers
+  from user memory to kernel memory with OPCODES. The sendmsg_to_kernel
+  is issued as a synchronous call, while the getmsg_from_kernel call is
+  asynchrounous.  Windows EventObjects are used for notification of
+  message arrival.  The process P is kept waiting on a KernelEvent
+  object in NT and a semaphore in Windows 95.
+
+  0wpage
+
+  44..  TThhee iinntteerrffaaccee aatt tthhee ccaallll lleevveell
+
+  This section describes the upcalls a Coda FS driver can make to Venus.
+  Each of these upcalls make use of two structures: inputArgs and
+  outputArgs.   In pseudo BNF form the structures take the following
+  form:
+
+  struct inputArgs {
+      u_long opcode;
+      u_long unique;     /* Keep multiple outstanding msgs distinct */
+      u_short pid;                 /* Common to all */
+      u_short pgid;                /* Common to all */
+      struct CodaCred cred;        /* Common to all */
+
+      <union "in" of call dependent parts of inputArgs>
+  };
+
+  struct outputArgs {
+      u_long opcode;
+      u_long unique;       /* Keep multiple outstanding msgs distinct */
+      u_long result;
+
+      <union "out" of call dependent parts of inputArgs>
+  };
+
+  Before going on let us elucidate the role of the various fields. The
+  inputArgs start with the opcode which defines the type of service
+  requested from Venus. There are approximately 30 upcalls at present
+  which we will discuss.   The unique field labels the inputArg with
+  unique number which will identify the message uniquely.  A process and
+  process group id are passed.  Finally the credentials of the caller
+  are included.
+
+  Before delving into the specific calls we need to discuss a variety of
+  data structures shared by the kernel and Venus.
+
+  44..11..  DDaattaa ssttrruuccttuurreess sshhaarreedd bbyy tthhee kkeerrnneell aanndd VVeennuuss
+
+  The CodaCred structure defines a variety of user and group id's as
+  they are set for the calling process. The vuid_t and guid_t are 32 bit
+  unsigned integers.  It also defines group member ship in an array.  On
+  Unix the CodaCred has proven sufficient to implement good security
+  semantics for Coda but the structure may have to undergo modification
+  for the Windows environment when these mature.
+
+  struct CodaCred {
+      vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, efftve, set, fs uid*/
+      vgid_t cr_gid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */
+      vgid_t cr_groups[NGROUPS];        /* Group membership for caller */
+  };
+
+  NNOOTTEE It is questionable if we need CodaCreds in Venus. Finally Venus
+  doesn't know about groups, although it does create files with the
+  default uid/gid.  Perhaps the list of group membership is superfluous.
+
+  The next item is the fundamental identifier used to identify Coda
+  files, the ViceFid.  A fid of a file uniquely defines a file or
+  directory in the Coda filesystem within a _c_e_l_l.   (-- A _c_e_l_l is a
+  group of Coda servers acting under the aegis of a single system
+  control machine or SCM. See the Coda Administration manual for a
+  detailed description of the role of the SCM.--)
+
+  typedef struct ViceFid {
+      VolumeId Volume;
+      VnodeId Vnode;
+      Unique_t Unique;
+  } ViceFid;
+
+  Each of the constituent fields: VolumeId, VnodeId and Unique_t are
+  unsigned 32 bit integers.  We envisage that a further field will need
+  to be prefixed to identify the Coda cell; this will probably take the
+  form of a Ipv6 size IP address naming the Coda cell through DNS.
+
+  The next important structure shared between Venus and the kernel are
+  the attributes of the file.  The following structure is used to
+  exchange information.  It has room for future extensions such as
+  support for device files (currently not present in Coda).
+
+  struct coda_vattr {
+          enum coda_vtype va_type;        /* vnode type (for create) */
+          u_short         va_mode;        /* files access mode and type */
+          short           va_nlink;       /* number of references to file */
+          vuid_t          va_uid;         /* owner user id */
+          vgid_t          va_gid;         /* owner group id */
+          long            va_fsid;        /* file system id (dev for now) */
+          long            va_fileid;      /* file id */
+          u_quad_t        va_size;        /* file size in bytes */
+          long            va_blocksize;   /* blocksize preferred for i/o */
+          struct timespec va_atime;       /* time of last access */
+          struct timespec va_mtime;       /* time of last modification */
+          struct timespec va_ctime;       /* time file changed */
+          u_long          va_gen;         /* generation number of file */
+          u_long          va_flags;       /* flags defined for file */
+          dev_t           va_rdev;        /* device special file represents */
+          u_quad_t        va_bytes;       /* bytes of disk space held by file */
+          u_quad_t        va_filerev;     /* file modification number */
+          u_int           va_vaflags;     /* operations flags, see below */
+          long            va_spare;       /* remain quad aligned */
+  };
+
+  44..22..  TThhee ppiiooccttll iinntteerrffaaccee
+
+  Coda specific requests can be made by application through a pioctl
+  interface. The pioctl is implemented as an ordinary ioctl on a
+  ficticious file /coda/.CONTROL.  The piocl call opens this file, gets
+  a file handle and makes the ioctl call. Finally it closes the file.
+
+  The kernel involvement in this is limited to providing the facility to
+  open and close and pass the ioctl message _a_n_d to verify that a path in
+  the pioctl data buffers is a file in a Coda filesystem.
+
+  The kernel is handed a data packet of the form:
+
+      struct {
+          const char *path;
+          struct ViceIoctl vidata;
+          int follow;
+      } data;
+
+  where
+
+  struct ViceIoctl {
+          caddr_t in, out;        /* Data to be transferred in, or out */
+          short in_size;          /* Size of input buffer <= 2K */
+          short out_size;         /* Maximum size of output buffer, <= 2K */
+  };
+
+  The path must be a Coda file, otherwise the ioctl upcall will not be
+  made.
+
+  NNOOTTEE  The data structures and code are a mess.  We need to clean this
+  up.
+
+  We now proceed to document the individual calls:
+
+  0wpage
+
+  44..33..  rroooott
+
+  AArrgguummeennttss
+
+     iinn empty
+
+     oouutt
+
+                struct cfs_root_out {
+                    ViceFid VFid;
+                } cfs_root;
+
+  DDeessccrriippttiioonn This call is made to Venus during the initialization of
+  the Coda filesystem. If the result is zero, the cfs_root structure
+  contains the ViceFid of the root of the Coda filesystem. If a non-zero
+  result is generated, its value is a platform dependent error code
+  indicating the difficulty Venus encountered in locating the root of
+  the Coda filesystem.
+
+  0wpage
+
+  44..44..  llooookkuupp
+
+  SSuummmmaarryy Find the ViceFid and type of an object in a directory if it
+  exists.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct  cfs_lookup_in {
+                    ViceFid     VFid;
+                    char        *name;          /* Place holder for data. */
+                } cfs_lookup;
+
+     oouutt
+
+                struct cfs_lookup_out {
+                    ViceFid VFid;
+                    int vtype;
+                } cfs_lookup;
+
+  DDeessccrriippttiioonn This call is made to determine the ViceFid and filetype of
+  a directory entry.  The directory entry requested carries name name
+  and Venus will search the directory identified by cfs_lookup_in.VFid.
+  The result may indicate that the name does not exist, or that
+  difficulty was encountered in finding it (e.g. due to disconnection).
+  If the result is zero, the field cfs_lookup_out.VFid contains the
+  targets ViceFid and cfs_lookup_out.vtype the coda_vtype giving the
+  type of object the name designates.
+
+  The name of the object is an 8 bit character string of maximum length
+  CFS_MAXNAMLEN, currently set to 256 (including a 0 terminator.)
+
+  It is extremely important to realize that Venus bitwise or's the field
+  cfs_lookup.vtype with CFS_NOCACHE to indicate that the object should
+  not be put in the kernel name cache.
+
+  NNOOTTEE The type of the vtype is currently wrong.  It should be
+  coda_vtype. Linux does not take note of CFS_NOCACHE.  It should.
+
+  0wpage
+
+  44..55..  ggeettaattttrr
+
+  SSuummmmaarryy Get the attributes of a file.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_getattr_in {
+                    ViceFid VFid;
+                    struct coda_vattr attr; /* XXXXX */
+                } cfs_getattr;
+
+     oouutt
+
+                struct cfs_getattr_out {
+                    struct coda_vattr attr;
+                } cfs_getattr;
+
+  DDeessccrriippttiioonn This call returns the attributes of the file identified by
+  fid.
+
+  EErrrroorrss Errors can occur if the object with fid does not exist, are
+  unaccessible or if the caller does not have permission to fetch
+  attributes.
+
+  NNoottee Many kernel FS drivers (Linux, NT and Windows 95 need to acquire
+  the attributes as well as the Fid for the instantiation of an internal
+  "inode" or "FileHandle".  A significant improvement in performance on
+  such systems could be made by combining the _l_o_o_k_u_p and _g_e_t_a_t_t_r calls
+  both at the Venus/kernel interaction level and at the RPC level.
+
+  The vattr structure included in the input arguments is superfluous and
+  should be removed.
+
+  0wpage
+
+  44..66..  sseettaattttrr
+
+  SSuummmmaarryy Set the attributes of a file.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_setattr_in {
+                    ViceFid VFid;
+                    struct coda_vattr attr;
+                } cfs_setattr;
+
+     oouutt
+        empty
+
+  DDeessccrriippttiioonn The structure attr is filled with attributes to be changed
+  in BSD style.  Attributes not to be changed are set to -1, apart from
+  vtype which is set to VNON. Other are set to the value to be assigned.
+  The only attributes which the FS driver may request to change are the
+  mode, ownner, groupid, atime, mtime and ctime.  The return value
+  indicates success or failure.
+
+  EErrrroorrss A variety of errors can occur.  The object may not exist, may
+  be inaccessible, or permission may not be granted by Venus.
+
+  0wpage
+
+  44..77..  aacccceessss
+
+  SSuummmmaarryy
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_access_in {
+                    ViceFid     VFid;
+                    int flags;
+                } cfs_access;
+
+     oouutt
+        empty
+
+  DDeessccrriippttiioonn Verify if access to the object identified by VFid for
+  operetions described by flags is permitted.  The result indicates if
+  access will be granted.  It is important to remember that Coda uses
+  ACL's to enforce protection and that ultimately the servers, not the
+  clients enforce the security of the system.  The result of this call
+  will depend on wether a _t_o_k_e_n is held by the user.
+
+  EErrrroorrss The object may not exist, or the ACL describing the protection
+  may not be accessible.
+
+  0wpage
+
+  44..88..  ccrreeaattee
+
+  SSuummmmaarryy Invoked to create a file
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_create_in {
+                    ViceFid VFid;
+                    struct coda_vattr attr;
+                    int excl;
+                    int mode;
+                    char        *name;          /* Place holder for data. */
+                } cfs_create;
+
+     oouutt
+
+                struct cfs_create_out {
+                    ViceFid VFid;
+                    struct coda_vattr attr;
+                } cfs_create;
+
+  DDeessccrriippttiioonn  This upcall is invoked to request creation of a file.
+  The file will be created in the directory identified by VFid, its name
+  will be name, and the mode will be mode.  If excl is set an error will
+  be returned if the file already exists.  If the size field in attr is
+  set to zero the file will be truncated.  The uid and gid of the file
+  are set by converting the CodaCred to a uid using a macro CRTOUID
+  (this macro is platform dependent).  Upon success the VFid and
+  attributes of the file are returned.  The Coda FS Driver will normally
+  instantiate a vnode, inode or filehandle at kernel level for the new
+  object.
+
+  EErrrroorrss A variety of errors can occur. Permissions may be insufficient.
+  If the object exists and is not a file the error EISDIR is returned
+  under Unix.
+
+  NNOOTTEE The packing of parameters is very inefficient and appears to
+  indicate confusion between the system call creat and the VFS operation
+  create. The VFS operation create is only called to create new objects.
+  This create call differs from the Unix one in that it is not invoked
+  to return a file descriptor. The trunctate and exclusive options,
+  together with the mode, could simply be part of the mode as it is
+  under Unix.  There should be no flags argument; this is used in open
+  (2) to return a filedescriptor for READ or WRITE mode.
+
+  The attributes of the directory should be returned too, since the size
+  and mtime changed.
+
+  0wpage
+
+  44..99..  mmkkddiirr
+
+  SSuummmmaarryy Create a new directory.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_mkdir_in {
+                    ViceFid     VFid;
+                    struct coda_vattr attr;
+                    char        *name;          /* Place holder for data. */
+                } cfs_mkdir;
+
+     oouutt
+
+                struct cfs_mkdir_out {
+                    ViceFid VFid;
+                    struct coda_vattr attr;
+                } cfs_mkdir;
+
+  DDeessccrriippttiioonn This call is similar to create but creates a directory.
+  Only the mode field in the input parameters is used for creation.
+  Upon successful creation, the attr returned contains the attributes of
+  the new directory.
+
+  EErrrroorrss As for create.
+
+  NNOOTTEE The input parameter should be changed to mode instead of
+  attributes.
+
+  The attributes of the parent should be returned since the size and
+  mtime changes.
+
+  0wpage
+
+  44..1100..  lliinnkk
+
+  SSuummmmaarryy Create a link to an existing file.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_link_in {
+                    ViceFid sourceFid;          /* cnode to link *to* */
+                    ViceFid destFid;            /* Directory in which to place link */
+                    char        *tname;         /* Place holder for data. */
+                } cfs_link;
+
+     oouutt
+        empty
+
+  DDeessccrriippttiioonn This call creates a link to the sourceFid in the directory
+  identified by destFid with name tname.  The source must reside in the
+  targets parent, i.e. the source must be have parent destFid, i.e. Coda
+  does not support cross directory hard links.  Only the return value is
+  relevant.  It indicates success or the type of failure.
+
+  EErrrroorrss The usual errors can occur.0wpage
+
+  44..1111..  ssyynnlliinnkk
+
+  SSuummmmaarryy create a symbolic link
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_symlink_in {
+                    ViceFid     VFid;          /* Directory to put symlink in */
+                    char        *srcname;
+                    struct coda_vattr attr;
+                    char        *tname;
+                } cfs_symlink;
+
+     oouutt
+        none
+
+  DDeessccrriippttiioonn Create a symbolic link. The link is to be placed in the
+  directory identified by VFid and named tname.  It should point to the
+  pathname srcname.  The attributes of the newly creaeted object are to
+  be set to attr.
+
+  EErrrroorrss
+
+  NNOOTTEE The attributes of the target directory should be returned since
+  its size changed.
+
+  0wpage
+
+  44..1122..  rreemmoovvee
+
+  SSuummmmaarryy Remove a file
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_remove_in {
+                    ViceFid     VFid;
+                    char        *name;          /* Place holder for data. */
+                } cfs_remove;
+
+     oouutt
+        none
+
+  DDeessccrriippttiioonn  Remove file named cfs_remove_in.name in directory
+  identified by   VFid.
+
+  EErrrroorrss
+
+  NNOOTTEE The attributes of the directory should be returned since its
+  mtime and size may change.
+
+  0wpage
+
+  44..1133..  rrmmddiirr
+
+  SSuummmmaarryy Remove a directory
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_rmdir_in {
+                    ViceFid     VFid;
+                    char        *name;          /* Place holder for data. */
+                } cfs_rmdir;
+
+     oouutt
+        none
+
+  DDeessccrriippttiioonn Remove the directory with name name from the directory
+  identified by VFid.
+
+  EErrrroorrss
+
+  NNOOTTEE The attributes of the parent directory should be returned since
+  its mtime and size may change.
+
+  0wpage
+
+  44..1144..  rreeaaddlliinnkk
+
+  SSuummmmaarryy Read the value of a symbolic link.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_readlink_in {
+                    ViceFid VFid;
+                } cfs_readlink;
+
+     oouutt
+
+                struct cfs_readlink_out {
+                    int count;
+                    caddr_t     data;           /* Place holder for data. */
+                } cfs_readlink;
+
+  DDeessccrriippttiioonn This routine reads the contents of symbolic link
+  identified by VFid into the buffer data.  The buffer data must be able
+  to hold any name up to CFS_MAXNAMLEN (PATH or NAM??).
+
+  EErrrroorrss No unusual errors.
+
+  0wpage
+
+  44..1155..  ooppeenn
+
+  SSuummmmaarryy Open a file.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_open_in {
+                    ViceFid     VFid;
+                    int flags;
+                } cfs_open;
+
+     oouutt
+
+                struct cfs_open_out {
+                    dev_t       dev;
+                    ino_t       inode;
+                } cfs_open;
+
+  DDeessccrriippttiioonn  This request asks Venus to place the file identified by
+  VFid in its cache and to note that the calling process wishes to open
+  it with flags as in open(2).  The return value to the kernel differs
+  for Unix and Windows systems.  For Unix systems the Coda FS Driver is
+  informed of the device and inode number of the container file in the
+  fields dev and inode.  For Windows the path of the container file is
+  returned to the kernel.
+
+  EErrrroorrss
+
+  NNOOTTEE Currently the cfs_open_out structure is not properly adapted to
+  deal with the windows case.  It might be best to implement two
+  upcalls, one to open aiming at a container file name, the other at a
+  container file inode.
+
+  0wpage
+
+  44..1166..  cclloossee
+
+  SSuummmmaarryy Close a file, update it on the servers.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_close_in {
+                    ViceFid     VFid;
+                    int flags;
+                } cfs_close;
+
+     oouutt
+        none
+
+  DDeessccrriippttiioonn Close the file identified by VFid.
+
+  EErrrroorrss
+
+  NNOOTTEE The flags argument is bogus and not used.  However, Venus' code
+  has room to deal with an execp input field, probably this field should
+  be used to inform Venus that the file was closed but is still memory
+  mapped for execution.  There are comments about fetching versus not
+  fetching the data in Venus vproc_vfscalls.  This seems silly.  If a
+  file is being closed, the data in the container file is to be the new
+  data.  Here again the execp flag might be in play to create confusion:
+  presently Venus might think a file can be flushed from the cache when
+  it is still memory mapped.  This needs to be understood.
+
+  0wpage
+
+  44..1177..  iiooccttll
+
+  SSuummmmaarryy Do an ioctl on a file. This includes the piocl interface.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_ioctl_in {
+                    ViceFid VFid;
+                    int cmd;
+                    int len;
+                    int rwflag;
+                    char *data;                 /* Place holder for data. */
+                } cfs_ioctl;
+
+     oouutt
+
+                struct cfs_ioctl_out {
+                    int len;
+                    caddr_t     data;           /* Place holder for data. */
+                } cfs_ioctl;
+
+  DDeessccrriippttiioonn Do an ioctl operation on a file.  The command, len and
+  data arguments are filled as usual.  flags is not used by Venus.
+
+  EErrrroorrss
+
+  NNOOTTEE Another bogus parameter.  flags is not used.  What is the
+  business about PREFETCHING in the Venus' code?
+
+  0wpage
+
+  44..1188..  rreennaammee
+
+  SSuummmmaarryy Rename a fid.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_rename_in {
+                    ViceFid     sourceFid;
+                    char        *srcname;
+                    ViceFid destFid;
+                    char        *destname;
+                } cfs_rename;
+
+     oouutt
+        none
+
+  DDeessccrriippttiioonn  Rename the object with name srcname in directory
+  sourceFid to destname in destFid.   It is important that the names
+  srcname and destname are 0 terminated strings.  Strings in Unix
+  kernels are not always null terminated.
+
+  EErrrroorrss
+
+  0wpage
+
+  44..1199..  rreeaaddddiirr
+
+  SSuummmmaarryy Read directory entries.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_readdir_in {
+                    ViceFid     VFid;
+                    int count;
+                    int offset;
+                } cfs_readdir;
+
+     oouutt
+
+                struct cfs_readdir_out {
+                    int size;
+                    caddr_t     data;           /* Place holder for data. */
+                } cfs_readdir;
+
+  DDeessccrriippttiioonn Read directory entries from VFid starting at offset and
+  read at most count bytes.  Returns the data into data and indicates
+  the size returned size.
+
+  EErrrroorrss
+
+  NNOOTTEE This call is not used.  Readdir operations exploit container
+  files.  We will re-evaluate this during the directory revamp which is
+  about to take place.
+
+  0wpage
+
+  44..2200..  vvggeett
+
+  SSuummmmaarryy instructs Venus to do an FSDB->Get.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_fsync_in {
+                    ViceFid VFid;
+                } cfs_fsync;
+
+     oouutt
+
+                struct cfs_vget_out {
+                    ViceFid VFid;
+                    int vtype;
+                } cfs_vget;
+
+  DDeessccrriippttiioonn This upcall asks Venus to do a get operation on an fsobj
+  labelled by VFid.
+
+  EErrrroorrss
+
+  NNOOTTEE This operation is not used.  However, it is extremely useful
+  since it can be used to deal with read/write memory mapped files.
+  These can be "pinned" in the Venus cache using vget and release with
+  inactive.
+
+  0wpage
+
+  44..2211..  ffssyynncc
+
+  SSuummmmaarryy Tell Venus to update the RVM attributes of a file.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_fsync_in {
+                    ViceFid VFid;
+                } cfs_fsync;
+
+     oouutt
+        none
+
+  DDeessccrriippttiioonn  Ask Venus to update RVM attributes of object VFid. This
+  should be called as  part of kernel level fsync type calls.  The
+  result indicates if the synching was successful.
+
+  EErrrroorrss
+
+  NNOOTTEE Linux does not implement this call. It should.
+
+  0wpage
+
+  44..2222..  iinnaaccttiivvee
+
+  SSuummmmaarryy Tell Venus a vnode is no longer in use.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_inactive_in {
+                    ViceFid VFid;
+                } cfs_inactive;
+
+     oouutt
+        none
+
+  DDeessccrriippttiioonn This operation returns EOPNOTSUPP.
+
+  EErrrroorrss
+
+  NNOOTTEE This should perhaps be removed.
+
+  0wpage
+
+  44..2233..  rrddwwrr
+
+  SSuummmmaarryy Read or write from a file
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct cfs_rdwr_in {
+                    ViceFid     VFid;
+                    int rwflag;
+                    int count;
+                    int offset;
+                    int ioflag;
+                    caddr_t     data;           /* Place holder for data. */
+                } cfs_rdwr;
+
+     oouutt
+
+                struct cfs_rdwr_out {
+                    int rwflag;
+                    int count;
+                    caddr_t     data;   /* Place holder for data. */
+                } cfs_rdwr;
+
+  DDeessccrriippttiioonn This upcall asks Venus to read or write from a file.
+
+  EErrrroorrss
+
+  NNOOTTEE It should be removed since it is against the Coda philosophy that
+  read/write operations never reach Venus.  I have been told the
+  operation does not work.  It is not currently used.
+
+  0wpage
+
+  44..2244..  ooddyymmoouunntt
+
+  SSuummmmaarryy Allows mounting multiple Coda "filesystems" on one Unix mount
+  point.
+
+  AArrgguummeennttss
+
+     iinn
+
+                struct ody_mount_in {
+                    char        *name;          /* Place holder for data. */
+                } ody_mount;
+
+     oouutt
+
+                struct ody_mount_out {
+                    ViceFid VFid;
+                } ody_mount;
+
+  DDeessccrriippttiioonn  Asks Venus to return the rootfid of a Coda system named
+  name.  The fid is returned in VFid.
+
+  EErrrroorrss
+
+  NNOOTTEE This call was used by David for dynamic sets.  It should be
+  removed since it causes a jungle of pointers in the VFS mounting area.
+  It is not used by Coda proper.  Call is not implemented by Venus.
+
+  0wpage
+
+  44..2255..  ooddyy__llooookkuupp
+
+  SSuummmmaarryy Looks up something.
+
+  AArrgguummeennttss
+
+     iinn irrelevant
+
+     oouutt
+        irrelevant
+
+  DDeessccrriippttiioonn
+
+  EErrrroorrss
+
+  NNOOTTEE Gut it. Call is not implemented by Venus.
+
+  0wpage
+
+  44..2266..  ooddyy__eexxppaanndd
+
+  SSuummmmaarryy expands something in a dynamic set.
+
+  AArrgguummeennttss
+
+     iinn irrelevant
+
+     oouutt
+        irrelevant
+
+  DDeessccrriippttiioonn
+
+  EErrrroorrss
+
+  NNOOTTEE Gut it.  Call is not implemented by Venus.
+
+  0wpage
+
+  44..2277..  pprreeffeettcchh
+
+  SSuummmmaarryy Prefetch a dynamic set.
+
+  AArrgguummeennttss
+
+     iinn Not documented.
+
+     oouutt
+        Not documented.
+
+  DDeessccrriippttiioonn  Venus worker.cc has support for this call, although it is
+  noted that it doesn't work.  Not surprising, since the kernel does not
+  have support for it. (ODY_PREFETCH is not a defined operation).
+
+  EErrrroorrss
+
+  NNOOTTEE Gut it. It isn't working and isn't used by Coda.
+
+  0wpage
+
+  44..2288..  ssiiggnnaall
+
+  SSuummmmaarryy Send Venus a signal about an upcall.
+
+  AArrgguummeennttss
+
+     iinn none
+
+     oouutt
+        not applicable.
+
+  DDeessccrriippttiioonn  This is an out-of-band upcall to Venus to inform Venus
+  that the calling process received a signal after Venus read the
+  message from the input queue.  Venus is supposed to clean up the
+  operation.
+
+  EErrrroorrss No reply is given.
+
+  NNOOTTEE We need to better understand what Venus needs to clean up and if
+  it is doing this correctly.  Also we need to handle multiple upcall
+  per system call situations correctly.  It would be important to know
+  what state changes in Venus take place after an upcall for which the
+  kernel is responsible for notifying Venus to clean up (e.g. open
+  definitely is such a state change, but many others are maybe not).
+
+  0wpage
+
+  55..  TThhee mmiinniiccaacchhee aanndd ddoowwnnccaallllss
+
+  The Coda FS Driver can cache results of lookup and access upcalls, to
+  limit the frequency of upcalls.  Upcalls carry a price since a process
+  context switch needs to take place.  The counterpart of caching the
+  information is that Venus will notify the FS Driver that cached
+  entries must be flushed or renamed.
+
+  The kernel code generally has to maintain a structure which links the
+  internal file handles (called vnodes in BSD, inodes in Linux and
+  FileHandles in Windows) with the ViceFid's which Venus maintains.
+  Ther reason is that frequent translations back and forth are needed in
+  order to make upcalls and use the results of upcalls.  Such linking
+  objects are called ccnnooddeess.
+
+  The current minicache implementations have cache entries which record
+  the following:
+
+  1. the name of the file
+
+  2. the cnode of the directory containing the object
+
+  3. a list of CodaCred's for which the lookup is permitted.
+
+  4. the cnode of the object
+
+  The lookup call in the Coda FS Driver may request the cnode of the
+  desired object from the cache, by passing it's name, directory and the
+  CodaCred's of the caller.  The cache will return the cnode or indicate
+  and it cannot be found.  The Coda FS Driver must be careful to
+  invalidate cache entries when it modifies or removes objects.
+
+  When Venus obtains information that indicates that cache entries are
+  no longer valid, it will make a downcall to the kernel.  Downcalls are
+  intercepted by the Coda FS Driver and lead to cache invalidations of
+  the kind described below.  The Coda FS Driver does not return an error
+  unless the downcall data could not be read into kernel memory.
+
+  55..11..  IINNVVAALLIIDDAATTEE
+
+  No information is available on this call.
+
+  55..22..  FFLLUUSSHH
+
+  AArrgguummeennttss None
+
+  SSuummmmaarryy Flush the name cache entirely.
+
+  DDeessccrriippttiioonn Venus issues this call upon startup and when it dies. This
+  is to prevent stale cache information being held.  Some operating
+  systems allow the kernel name cache to be switched off dynamically.
+  When this is done, this downcall is made.
+
+  55..33..  PPUURRGGEEUUSSEERR
+
+  AArrgguummeennttss
+
+          struct cfs_purgeuser_out {/* CFS_PURGEUSER is a venus->kernel call */
+              struct CodaCred cred;
+          } cfs_purgeuser;
+
+  DDeessccrriippttiioonn Remove all entries in the cache carrying the Cred.  This
+  call is issued when tokes for a user expire or are flushed.
+
+  55..44..  ZZAAPPFFIILLEE
+
+  AArrgguummeennttss
+
+          struct cfs_zapfile_out {  /* CFS_ZAPFILE is a venus->kernel call */
+              ViceFid CodaFid;
+          } cfs_zapfile;
+
+  DDeessccrriippttiioonn Remove all entries which have the (dir vnode, name) pair.
+  This is issued as a result of an invalidation of cached attributes of
+  a vnode.
+
+  NNOOTTEE Call is not named correctly in NetBSD and Mach.  The minicache
+  zapfile routine takes different arguments. Linux does not implement
+  the invalidation of attributes correctly.
+
+  55..55..  ZZAAPPDDIIRR
+
+  AArrgguummeennttss
+
+          struct cfs_zapdir_out {   /* CFS_ZAPDIR is a venus->kernel call */
+              ViceFid CodaFid;
+          } cfs_zapdir;
+
+  DDeessccrriippttiioonn Remove all entries in the cache lying in a directory
+  CodaFid, and all children of this directory. This call is issed when
+  Venus receives a callback on the this directory.
+
+  55..66..  ZZAAPPVVNNOODDEE
+
+  AArrgguummeennttss
+
+          struct cfs_zapvnode_out { /* CFS_ZAPVNODE is a venus->kernel call */
+              struct CodaCred cred;
+              ViceFid VFid;
+          } cfs_zapvnode;
+
+  DDeessccrriippttiioonn Remove all entries in the cache carrying the cred and VFid
+  as in the arguments. This downcall is probably never issued.
+
+  55..77..  PPUURRGGEEFFIIDD
+
+  SSuummmmaarryy
+
+  AArrgguummeennttss
+
+          struct cfs_purgefid_out { /* CFS_PURGEFID is a venus->kernel call */
+              ViceFid CodaFid;
+          } cfs_purgefid;
+
+  DDeessccrriippttiioonn Flush the attribute for the file. If it is a dir (odd
+  vnode), purge its children from the namecache remove the file from the
+  namecache.
+
+  55..88..  RREEPPLLAACCEE
+
+  SSuummmmaarryy Replace the Fid's for a collection of names.
+
+  AArrgguummeennttss
+
+          struct cfs_replace_out { /* cfs_replace is a venus->kernel call */
+              ViceFid NewFid;
+              ViceFid OldFid;
+          } cfs_replace;
+
+  DDeessccrriippttiioonn This routine replaces a ViceFid in the name cache with
+  another.  It is added to allow Venus during reintegration to replace
+  locally allocated temp fids while disconnected with global fids even
+  when the reference count on those fids are not zero.
+
+  0wpage
+
+  66..  IInniittiiaalliizzaattiioonn aanndd cclleeaannuupp
+
+  This section gives brief hints as to desirable features for the Coda
+  FS Driver at startup and upon shutdown or Venus failures.  Before
+  entering the discussion it is useful to repeat that the Coda FS Driver
+  maintains the following data:
+
+  1. message queues
+
+  2. cnodes
+
+  3. name cache entries
+
+     The name cache entries are entirely private to the driver, so they
+     can easily be manipulated.   The message queues will generally have
+     clear points of initialization and destruction.  The cnodes are
+     much more delicate.  User processes hold reference counts in Coda
+     filesystems and it can be difficult to clean up the cnodes.
+
+  It can expect requests through:
+
+  1. the message subsystem
+
+  2. the VFS layer
+
+  3. pioctl interface
+
+     Currently the _p_i_o_c_t_l passes through the VFS for Coda so we can
+     treat these similarly.
+
+  66..11..  RReeqquuiirreemmeennttss
+
+  The following requirements should be accomodated:
+
+  1. The message queueus should have open and close routines.  On Unix
+     the opening of the character devices are such routines.
+
+  +o  Before opening, no messages can be placed.
+
+  +o  Opening will remove any old messages still pending.
+
+  +o  Close will notify any sleeping processes that their upcall cannot
+     be completed.
+
+  +o  Close will free all memory allocated by the message queues.
+
+  2. At open the namecache shall be initialized to empty state.
+
+  3. Before the message queues are open, all VFS operations will fail.
+     Fortunately this can be achieved by making sure than mounting the
+     Coda filesystem cannot succeed before opening.
+
+  4. After closing of the queues, no VFS operations can succeed.  Here
+     one needs to be careful, since a few operations (lookup,
+     read/write, readdir) can proceed without upcalls.  These must be
+     explicitly blocked.
+
+  5. Upon closing the namecache shall be flushed and disabled.
+
+  6. All memory held by cnodes can be freed without relying on upcalls.
+
+  7. Unmounting the file system can be done without relying on upcalss.
+
+  8. Mounting the Coda filesystem should fail gracefully if Venus cannot
+     get the rootfid or the attributes of the rootfid.  The latter is
+     best implemented by Venus fetching these objects before attempting
+     to mount.
+
+  NNOOTTEE  NetBSD in particular but also Linux have not implemented the
+  above requirements fully.  For smooth operation this needs to be
+  corrected.
+
diff -u --recursive --new-file v2.1.71/linux/MAINTAINERS linux/MAINTAINERS
--- v2.1.71/linux/MAINTAINERS	Tue Dec  2 16:45:17 1997
+++ linux/MAINTAINERS	Tue Dec  9 09:49:58 1997
@@ -173,6 +173,12 @@
 L:	linux-hams@vger.rutgers.edu
 S:	Maintained
 
+HIGH-SPEED SCC DRIVER FOR AX.25
+P:	Klaus Kudielka
+M:	oe1kib@oe1xtu.ampr.org
+L:	linux-hams@vger.rutgers.edu
+S:	Maintained
+
 BAYCOM/HDLCDRV/SOUNDMODEM DRIVERS FOR AX.25
 P:	Thomas Sailer
 M:	sailer@ife.ee.ethz.ch
diff -u --recursive --new-file v2.1.71/linux/Makefile linux/Makefile
--- v2.1.71/linux/Makefile	Thu Dec  4 14:53:54 1997
+++ linux/Makefile	Tue Dec  9 09:49:58 1997
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 71
+SUBLEVEL = 72
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
@@ -157,6 +157,10 @@
 DRIVERS := $(DRIVERS) drivers/pnp/pnp.a
 endif
 
+ifdef CONFIG_HAMRADIO
+DRIVERS := $(DRIVERS) drivers/net/hamradio/hamradio.a
+endif
+
 include arch/$(ARCH)/Makefile
 
 ifdef SMP
@@ -363,8 +367,8 @@
 	rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
                 -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
                 -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS
-	rm -f drivers/sound/Config.in
-	cp drivers/sound/Config.std drivers/sound/Config.in
+#	rm -f drivers/sound/Config.in
+#	cp drivers/sound/Config.std drivers/sound/Config.in
 
 backup: mrproper
 	cd .. && tar cf - linux/ | gzip -9 > backup.gz
diff -u --recursive --new-file v2.1.71/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.1.71/linux/arch/alpha/kernel/entry.S	Tue Dec  2 16:45:17 1997
+++ linux/arch/alpha/kernel/entry.S	Mon Dec  8 23:58:03 1997
@@ -727,7 +727,7 @@
 	.quad sys_write
 	.quad alpha_ni_syscall			/* 5 */
 	.quad sys_close
-	.quad sys_wait4
+	.quad osf_wait4
 	.quad alpha_ni_syscall
 	.quad sys_link
 	.quad sys_unlink			/* 10 */
@@ -804,17 +804,17 @@
 	.quad sys_setgroups			/* 80 */
 	.quad alpha_ni_syscall
 	.quad sys_setpgid
-	.quad sys_setitimer
+	.quad osf_setitimer
 	.quad alpha_ni_syscall
 	.quad alpha_ni_syscall			/* 85 */
-	.quad sys_getitimer
+	.quad osf_getitimer
 	.quad sys_gethostname
 	.quad sys_sethostname
 	.quad sys_getdtablesize
 	.quad sys_dup2				/* 90 */
 	.quad sys_newfstat
 	.quad sys_fcntl
-	.quad sys_select
+	.quad osf_select
 	.quad sys_poll
 	.quad sys_fsync				/* 95 */
 	.quad sys_setpriority
@@ -837,13 +837,13 @@
 	.quad sys_recvmsg
 	.quad sys_sendmsg
 	.quad alpha_ni_syscall			/* 115 */
-	.quad sys_gettimeofday
-	.quad sys_getrusage
+	.quad osf_gettimeofday
+	.quad osf_getrusage
 	.quad sys_getsockopt
 	.quad alpha_ni_syscall
 	.quad sys_readv				/* 120 */
 	.quad sys_writev
-	.quad sys_settimeofday
+	.quad osf_settimeofday
 	.quad sys_fchown
 	.quad sys_fchmod
 	.quad sys_recvfrom			/* 125 */
@@ -859,7 +859,7 @@
 	.quad sys_socketpair			/* 135 */
 	.quad sys_mkdir
 	.quad sys_rmdir
-	.quad sys_utimes
+	.quad osf_utimes
 	.quad alpha_ni_syscall
 	.quad alpha_ni_syscall			/* 140 */
 	.quad sys_getpeername
diff -u --recursive --new-file v2.1.71/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.1.71/linux/arch/alpha/kernel/osf_sys.c	Tue Sep 23 16:48:46 1997
+++ linux/arch/alpha/kernel/osf_sys.c	Mon Dec  8 23:58:03 1997
@@ -28,6 +28,7 @@
 #include <linux/stat.h>
 #include <linux/mman.h>
 #include <linux/shm.h>
+#include <linux/poll.h>
 
 #include <asm/fpu.h>
 #include <asm/io.h>
@@ -167,6 +168,9 @@
 	return error;
 }
 
+#undef ROUND_UP
+#undef NAME_OFFSET
+
 /*
  * Alpha syscall convention has no problem returning negative
  * values:
@@ -202,24 +206,24 @@
 /*
  * No need to acquire the kernel lock, we're local..
  */
-asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, int a5,
-				     struct pt_regs regs)
+asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4,
+				     int a5, struct pt_regs regs)
 {
 	struct task_struct * tsk = current;
 	(&regs)->r20 = tsk->euid;
 	return tsk->uid;
 }
 
-asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4, int a5,
-				     struct pt_regs regs)
+asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4,
+				     int a5, struct pt_regs regs)
 {
 	struct task_struct * tsk = current;
 	(&regs)->r20 = tsk->egid;
 	return tsk->gid;
 }
 
-asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, int a5,
-				     struct pt_regs regs)
+asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4,
+				     int a5, struct pt_regs regs)
 {
 	struct task_struct *tsk = current;
 
@@ -524,47 +528,6 @@
 	return ret;
 }
 
-/*
- * I don't know what the parameters are: the first one
- * seems to be a timeval pointer, and I suspect the second
- * one is the time remaining.. Ho humm.. No documentation.
- */
-asmlinkage int osf_usleep_thread(struct timeval *sleep, struct timeval *remain)
-{
-	struct timeval tmp;
-	unsigned long ticks;
-	int retval;
-
-	lock_kernel();
-	retval = verify_area(VERIFY_READ, sleep, sizeof(*sleep));
-	if (retval)
-		goto out;
-	if (remain && (retval = verify_area(VERIFY_WRITE, remain, sizeof(*remain))))
-		goto out;
-	copy_from_user(&tmp, sleep, sizeof(*sleep));
-	ticks = tmp.tv_usec;
-	ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
-	ticks += tmp.tv_sec * HZ;
-	current->timeout = ticks + jiffies;
-	current->state = TASK_INTERRUPTIBLE;
-	schedule();
-	retval = 0;
-	if (!remain)
-		goto out;
-	ticks = jiffies;
-	if (ticks < current->timeout)
-		ticks = current->timeout - ticks;
-	else
-		ticks = 0;
-	current->timeout = 0;
-	tmp.tv_sec = ticks / HZ;
-	tmp.tv_usec = ticks % HZ;
-	copy_to_user(remain, &tmp, sizeof(*remain));
-out:
-	unlock_kernel();
-	return retval;
-}
-
 asmlinkage int osf_utsname(char *name)
 {
 	int error;
@@ -955,4 +918,359 @@
 	}
 
 	return -EOPNOTSUPP;
+}
+
+/* Translations due to the fact that OSF's time_t is an int.  Which
+   affects all sorts of things, like timeval and itimerval.  */
+
+extern struct timezone sys_tz;
+extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+extern int do_getitimer(int which, struct itimerval *value);
+extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
+asmlinkage int sys_utimes(char *, struct timeval *);
+extern int sys_wait4(pid_t, int *, int, struct rusage *);
+
+struct timeval32
+{
+    int tv_sec, tv_usec;
+};
+
+struct itimerval32
+{
+    struct timeval32 it_interval;
+    struct timeval32 it_value;
+};
+
+static inline long get_tv32(struct timeval *o, struct timeval32 *i)
+{
+	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
+		(__get_user(o->tv_sec, &i->tv_sec) |
+		 __get_user(o->tv_usec, &i->tv_usec)));
+}
+
+static inline long put_tv32(struct timeval32 *o, struct timeval *i)
+{
+	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
+		(__put_user(i->tv_sec, &o->tv_sec) |
+		 __put_user(i->tv_usec, &o->tv_usec)));
+}
+
+static inline long get_it32(struct itimerval *o, struct itimerval32 *i)
+{
+	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
+		(__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
+		 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
+		 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
+		 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
+}
+
+static inline long put_it32(struct itimerval32 *o, struct itimerval *i)
+{
+	return (!access_ok(VERIFY_WRITE, i, sizeof(*i)) ||
+		(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
+		 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
+		 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
+		 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
+}
+
+asmlinkage int osf_gettimeofday(struct timeval32 *tv, struct timezone *tz)
+{
+	if (tv) {
+		struct timeval ktv;
+		do_gettimeofday(&ktv);
+		if (put_tv32(tv, &ktv))
+			return -EFAULT;
+	}
+	if (tz) {
+		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+asmlinkage int osf_settimeofday(struct timeval32 *tv, struct timezone *tz)
+{
+	struct timeval ktv;
+	struct timezone ktz;
+
+ 	if (tv) {
+		if (get_tv32(&ktv, tv))
+			return -EFAULT;
+	}
+	if (tz) {
+		if (copy_from_user(&ktz, tz, sizeof(*tz)))
+			return -EFAULT;
+	}
+
+	return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
+}
+
+asmlinkage int osf_getitimer(int which, struct itimerval32 *it)
+{
+	struct itimerval kit;
+	int error;
+
+	error = do_getitimer(which, &kit);
+	if (!error && put_it32(it, &kit))
+		error = -EFAULT;
+
+	return error;
+}
+
+asmlinkage int osf_setitimer(int which, struct itimerval32 *in,
+			     struct itimerval32 *out)
+{
+	struct itimerval kin, kout;
+	int error;
+
+	if (in) {
+		if (get_it32(&kin, in))
+			return -EFAULT;
+	} else
+		memset(&kin, 0, sizeof(kin));
+
+	error = do_setitimer(which, &kin, out ? &kout : NULL);
+	if (error || !out)
+		return error;
+
+	if (put_it32(out, &kout))
+		return -EFAULT;
+
+	return 0;
+
+}
+
+asmlinkage int osf_utimes(const char *filename, struct timeval32 *tvs)
+{
+	char *kfilename;
+	struct timeval ktvs[2];
+	mm_segment_t old_fs;
+	int ret;
+
+	kfilename = getname(filename);
+	if (IS_ERR(kfilename))
+		return PTR_ERR(kfilename);
+
+	if (tvs) {
+		if (get_tv32(&ktvs[0], &tvs[0]) ||
+		    get_tv32(&ktvs[1], &tvs[1]))
+			return -EFAULT;
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_utimes(kfilename, tvs ? ktvs : 0);
+	set_fs(old_fs);
+
+	putname(kfilename);
+
+	return ret;
+}
+
+asmlinkage int
+osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp,
+	   struct timeval32 *tvp)
+{
+	fd_set_buffer *fds;
+	unsigned long timeout;
+	int ret;
+
+	timeout = ~0UL;
+	if (tvp) {
+		time_t sec, usec;
+
+		if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
+		    || (ret = __get_user(sec, &tvp->tv_sec))
+		    || (ret = __get_user(usec, &tvp->tv_usec)))
+			goto out_nofds;
+
+		timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
+		timeout += sec * HZ;
+		if (timeout)
+			timeout += jiffies + 1;
+	}
+
+	ret = -ENOMEM;
+	fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL);
+	if (!fds)
+		goto out_nofds;
+	ret = -EINVAL;
+	if (n < 0)
+		goto out;
+	if (n > KFDS_NR)
+		n = KFDS_NR;
+	if ((ret = get_fd_set(n, inp->fds_bits, fds->in)) ||
+	    (ret = get_fd_set(n, outp->fds_bits, fds->out)) ||
+	    (ret = get_fd_set(n, exp->fds_bits, fds->ex)))
+		goto out;
+	zero_fd_set(n, fds->res_in);
+	zero_fd_set(n, fds->res_out);
+	zero_fd_set(n, fds->res_ex);
+
+	ret = do_select(n, fds, timeout);
+
+	/* OSF does not copy back the remaining time.  */
+
+	if (ret < 0)
+		goto out;
+	if (!ret) {
+		ret = -ERESTARTNOHAND;
+		if (signal_pending(current))
+			goto out;
+		ret = 0;
+	}
+
+	set_fd_set(n, inp->fds_bits, fds->res_in);
+	set_fd_set(n, outp->fds_bits, fds->res_out);
+	set_fd_set(n, exp->fds_bits, fds->res_ex);
+
+out:
+	free_page((unsigned long) fds);
+out_nofds:
+	return ret;
+}
+
+struct rusage32 {
+	struct timeval32 ru_utime;	/* user time used */
+	struct timeval32 ru_stime;	/* system time used */
+	long	ru_maxrss;		/* maximum resident set size */
+	long	ru_ixrss;		/* integral shared memory size */
+	long	ru_idrss;		/* integral unshared data size */
+	long	ru_isrss;		/* integral unshared stack size */
+	long	ru_minflt;		/* page reclaims */
+	long	ru_majflt;		/* page faults */
+	long	ru_nswap;		/* swaps */
+	long	ru_inblock;		/* block input operations */
+	long	ru_oublock;		/* block output operations */
+	long	ru_msgsnd;		/* messages sent */
+	long	ru_msgrcv;		/* messages received */
+	long	ru_nsignals;		/* signals received */
+	long	ru_nvcsw;		/* voluntary context switches */
+	long	ru_nivcsw;		/* involuntary " */
+};
+
+asmlinkage int osf_getrusage(int who, struct rusage32 *ru)
+{
+	struct rusage32 r;
+
+	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
+		return -EINVAL;
+
+	memset(&r, 0, sizeof(r));
+	switch (who) {
+	case RUSAGE_SELF:
+		r.ru_utime.tv_sec = CT_TO_SECS(current->times.tms_utime);
+		r.ru_utime.tv_usec = CT_TO_USECS(current->times.tms_utime);
+		r.ru_stime.tv_sec = CT_TO_SECS(current->times.tms_stime);
+		r.ru_stime.tv_usec = CT_TO_USECS(current->times.tms_stime);
+		r.ru_minflt = current->min_flt;
+		r.ru_majflt = current->maj_flt;
+		r.ru_nswap = current->nswap;
+		break;
+	case RUSAGE_CHILDREN:
+		r.ru_utime.tv_sec = CT_TO_SECS(current->times.tms_cutime);
+		r.ru_utime.tv_usec = CT_TO_USECS(current->times.tms_cutime);
+		r.ru_stime.tv_sec = CT_TO_SECS(current->times.tms_cstime);
+		r.ru_stime.tv_usec = CT_TO_USECS(current->times.tms_cstime);
+		r.ru_minflt = current->cmin_flt;
+		r.ru_majflt = current->cmaj_flt;
+		r.ru_nswap = current->cnswap;
+		break;
+	default:
+		r.ru_utime.tv_sec = CT_TO_SECS(current->times.tms_utime +
+					       current->times.tms_cutime);
+		r.ru_utime.tv_usec = CT_TO_USECS(current->times.tms_utime +
+						 current->times.tms_cutime);
+		r.ru_stime.tv_sec = CT_TO_SECS(current->times.tms_stime +
+					       current->times.tms_cstime);
+		r.ru_stime.tv_usec = CT_TO_USECS(current->times.tms_stime +
+						 current->times.tms_cstime);
+		r.ru_minflt = current->min_flt + current->cmin_flt;
+		r.ru_majflt = current->maj_flt + current->cmaj_flt;
+		r.ru_nswap = current->nswap + current->cnswap;
+		break;
+	}
+
+	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
+}
+
+asmlinkage int osf_wait4(pid_t pid, int *ustatus, int options,
+			 struct rusage32 *ur)
+{
+	if (!ur) {
+		return sys_wait4(pid, ustatus, options, NULL);
+	} else {
+		struct rusage r;
+		int ret, status;
+		mm_segment_t old_fs = get_fs();
+		
+		set_fs (KERNEL_DS);
+		ret = sys_wait4(pid, &status, options, &r);
+		set_fs (old_fs);
+
+		if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
+			return -EFAULT;
+		__put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
+		__put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
+		__put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
+		__put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec);
+		__put_user(r.ru_maxrss, &ur->ru_maxrss);
+		__put_user(r.ru_ixrss, &ur->ru_ixrss);
+		__put_user(r.ru_idrss, &ur->ru_idrss);
+		__put_user(r.ru_isrss, &ur->ru_isrss);
+		__put_user(r.ru_minflt, &ur->ru_minflt);
+		__put_user(r.ru_majflt, &ur->ru_majflt);
+		__put_user(r.ru_nswap, &ur->ru_nswap);
+		__put_user(r.ru_inblock, &ur->ru_inblock);
+		__put_user(r.ru_oublock, &ur->ru_oublock);
+		__put_user(r.ru_msgsnd, &ur->ru_msgsnd);
+		__put_user(r.ru_msgrcv, &ur->ru_msgrcv);
+		__put_user(r.ru_nsignals, &ur->ru_nsignals);
+		__put_user(r.ru_nvcsw, &ur->ru_nvcsw);
+		if (__put_user(r.ru_nivcsw, &ur->ru_nivcsw))
+			return -EFAULT;
+
+		if (ustatus && put_user(status, ustatus))
+			return -EFAULT;
+		return ret;
+	}
+}
+
+/*
+ * I don't know what the parameters are: the first one
+ * seems to be a timeval pointer, and I suspect the second
+ * one is the time remaining.. Ho humm.. No documentation.
+ */
+asmlinkage int osf_usleep_thread(struct timeval *sleep, struct timeval *remain)
+{
+	struct timeval tmp;
+	unsigned long ticks;
+
+	if (get_tv32(&tmp, sleep))
+		goto fault;
+
+	ticks = tmp.tv_usec;
+	ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
+	ticks += tmp.tv_sec * HZ;
+	current->timeout = ticks + jiffies;
+	current->state = TASK_INTERRUPTIBLE;
+
+	schedule();
+
+	if (remain) {
+		ticks = jiffies;
+		if (ticks < current->timeout)
+			ticks = current->timeout - ticks;
+		else
+			ticks = 0;
+		current->timeout = 0;
+		tmp.tv_sec = ticks / HZ;
+		tmp.tv_usec = ticks % HZ;
+		if (put_tv32(remain, &tmp))
+			goto fault;
+	}
+	
+	return 0;
+fault:
+	return -EFAULT;
 }
diff -u --recursive --new-file v2.1.71/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c
--- v2.1.71/linux/arch/alpha/kernel/signal.c	Thu Dec  4 14:53:54 1997
+++ linux/arch/alpha/kernel/signal.c	Tue Dec  9 09:31:18 1997
@@ -75,6 +75,7 @@
 		if (_NSIG_WORDS > 1 && sign > 0)
 			sigemptyset(&current->blocked);
 		current->blocked.sig[0] = newmask;
+		recalc_sigpending(current);
 		spin_unlock_irq(&current->sigmask_lock);
 
 		(&regs)->r0 = 0;		/* special no error return */
@@ -570,21 +571,23 @@
 do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
 	  unsigned long r0, unsigned long r19)
 {
-	sigset_t _oldset;
-	siginfo_t info;
-	unsigned long signr, single_stepping, core = 0;
-	struct k_sigaction *ka;
+	unsigned long single_stepping = ptrace_cancel_bpt(current);
 
-	single_stepping = ptrace_cancel_bpt(current);
+	if (!oldset)
+		oldset = &current->blocked;
 
-	spin_lock_irq(&current->sigmask_lock);
-	if (!oldset) {
-		_oldset = current->blocked;
-		oldset = &_oldset;
-	}
-	while ((signr = dequeue_signal(&current->blocked, &info)) != 0) {
+	while (1) {
+		unsigned long signr;
+		struct k_sigaction *ka;
+		siginfo_t info;
+
+		spin_lock_irq(&current->sigmask_lock);
+		signr = dequeue_signal(&current->blocked, &info);
 		spin_unlock_irq(&current->sigmask_lock);
 
+		if (!signr)
+			break;
+
 		if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
 			/* Let the debugger run.  */
 			current->exit_code = signr;
@@ -595,12 +598,12 @@
 
 			/* We're back.  Did the debugger cancel the sig?  */
 			if (!(signr = current->exit_code))
-				goto skip_signal;
+				continue;
 			current->exit_code = 0;
 
 			/* The debugger continued.  Ignore SIGSTOP.  */
 			if (signr == SIGSTOP)
-				goto skip_signal;
+				continue;
 
 			/* Update the siginfo structure.  Is this good?  */
 			if (signr != info.si_signo) {
@@ -614,23 +617,34 @@
 			/* If the (new) signal is now blocked, requeue it.  */
 			if (sigismember(&current->blocked, signr)) {
 				send_sig_info(signr, &info, current);
-				goto skip_signal;
+				continue;
 			}
 		}
 
 		ka = &current->sig->action[signr-1];
+		if (ka->sa.sa_handler == SIG_IGN) {
+			if (signr != SIGCHLD)
+				continue;
+			/* Check for SIGCHLD: it's special.  */
+			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+				/* nothing */;
+			continue;
+		}
+
 		if (ka->sa.sa_handler == SIG_DFL) {
+			int exit_code = signr & 0x7f;
+
 			/* Init gets no signals it doesn't want.  */
 			if (current->pid == 1)
-				goto skip_signal;
+				continue;
 
 			switch (signr) {
 			case SIGCONT: case SIGCHLD: case SIGWINCH:
-				goto skip_signal;
+				continue;
 
 			case SIGTSTP: case SIGTTIN: case SIGTTOU:
 				if (is_orphaned_pgrp(current->pgrp))
-					goto skip_signal;
+					continue;
 				/* FALLTHRU */
 
 			case SIGSTOP:
@@ -641,15 +655,15 @@
 					notify_parent(current, SIGCHLD);
 				schedule();
 				single_stepping |= ptrace_cancel_bpt(current);
-				break;
+				continue;
 
 			case SIGQUIT: case SIGILL: case SIGTRAP:
 			case SIGABRT: case SIGFPE: case SIGSEGV:
 				lock_kernel();
 				if (current->binfmt
 				    && current->binfmt->core_dump
-				    &&current->binfmt->core_dump(signr, regs))
-					core = 0x80;
+				    && current->binfmt->core_dump(signr, regs))
+					exit_code |= 0x80;
 				unlock_kernel();
 				/* FALLTHRU */
 
@@ -657,26 +671,19 @@
 				lock_kernel();
 				sigaddset(&current->signal, signr);
 				current->flags |= PF_SIGNALED;
-				do_exit((signr & 0x7f) | core);
-			}
-		} else if (ka->sa.sa_handler == SIG_IGN) {
-			if (signr == SIGCHLD) {
-				/* Check for SIGCHLD: it's special.  */
-				while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
-					/* nothing */;
+				do_exit(exit_code);
+				/* NOTREACHED */
 			}
-		} else {
-			/* Whee!  Actually deliver the signal.  */
-			if (r0) syscall_restart(r0, r19, regs, ka);
-			handle_signal(signr, ka, &info, oldset, regs, sw);
-			if (single_stepping) 
-				ptrace_set_bpt(current); /* re-set bpt */
-			return 1;
+			continue;
 		}
-	skip_signal:
-		spin_lock_irq(&current->sigmask_lock);
+
+		/* Whee!  Actually deliver the signal.  */
+		if (r0) syscall_restart(r0, r19, regs, ka);
+		handle_signal(signr, ka, &info, oldset, regs, sw);
+		if (single_stepping) 
+			ptrace_set_bpt(current); /* re-set bpt */
+		return 1;
 	}
-	spin_unlock_irq(&current->sigmask_lock);
 
 	if (r0 &&
 	    (regs->r0 == ERESTARTNOHAND ||
diff -u --recursive --new-file v2.1.71/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.1.71/linux/arch/i386/kernel/process.c	Tue Dec  2 09:49:39 1997
+++ linux/arch/i386/kernel/process.c	Sat Dec  6 11:21:17 1997
@@ -281,22 +281,19 @@
 {
 
 	if(!reboot_thru_bios) {
-#if 0
-		sti();
-#endif
 		/* rebooting needs to touch the page at absolute addr 0 */
 		*((unsigned short *)__va(0x472)) = reboot_mode;
 		for (;;) {
 			int i;
 			for (i=0; i<100; i++) {
-				int j;
 				kb_wait();
-				for(j = 0; j < 100000 ; j++)
-					/* nothing */;
+				udelay(10);
 				outb(0xfe,0x64);         /* pulse reset low */
 				udelay(10);
 			}
-			__asm__ __volatile__("\tlidt %0": "=m" (no_idt));
+			/* That didn't work - force a triple fault.. */
+			__asm__ __volatile__("lidt %0": :"m" (no_idt));
+			__asm__ __volatile__("int3");
 		}
 	}
 
diff -u --recursive --new-file v2.1.71/linux/arch/i386/kernel/sys_i386.c linux/arch/i386/kernel/sys_i386.c
--- v2.1.71/linux/arch/i386/kernel/sys_i386.c	Tue Dec  2 09:49:39 1997
+++ linux/arch/i386/kernel/sys_i386.c	Mon Dec  8 14:58:44 1997
@@ -225,15 +225,16 @@
 		return -EFAULT;
   
 	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
-	error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
-	error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
-	error -= __put_user(0,name->release+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
-	error -= __put_user(0,name->version+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
-	error = __put_user(0,name->machine+__OLD_UTS_LEN);
+	error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+	error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+	error |= __put_user(0,name->release+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+	error |= __put_user(0,name->version+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+	error |= __put_user(0,name->machine+__OLD_UTS_LEN);
+
 	error = error ? -EFAULT : 0;
 
 	return error;
diff -u --recursive --new-file v2.1.71/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.1.71/linux/arch/sparc64/kernel/sys_sparc32.c	Thu Sep  4 17:07:30 1997
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Mon Dec  8 23:58:03 1997
@@ -38,9 +38,9 @@
 #include <linux/nfsd/xdr.h>
 #include <linux/nfsd/syscall.h>
 #include <linux/module.h>
+#include <linux/poll.h>
 
 #include <asm/types.h>
-#include <asm/poll.h>
 #include <asm/ipc.h>
 #include <asm/uaccess.h>
 #include <asm/fpumacro.h>
@@ -1075,104 +1075,139 @@
 
 /* end of readdir & getdents */
 
-extern asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp,
-				 fd_set *exp, struct timeval *tvp);
+/*
+ * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
+ * 64-bit unsigned longs.
+ */
 
-asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp)
+static inline int
+get_fd_set32(unsigned long n, unsigned long *fdset, u32 ufdset_x)
 {
-	struct timeval kern_tv, *ktvp;
-	unsigned long old_fs;
-	char *p;
-	u32 *q, *Inp, *Outp, *Exp;
-	int i, ret = -EINVAL, nn;
-	
-	if (n < 0 || n > PAGE_SIZE*2)
-		return -EINVAL;
-
-	lock_kernel ();
-	p = (char *)__get_free_page (GFP_KERNEL);
-	if (!p)
-		goto out_nofree;
+	u32 *ufdset = (u32 *)A(ufdset_x);
 
-	q = (u32 *)p;
-	Inp = (u32 *)A(inp);
-	Outp = (u32 *)A(outp);
-	Exp = (u32 *)A(exp);
+	if (ufdset) {
+		unsigned long odd;
 
-	ret = -EFAULT;
+		if (verify_area(VERIFY_WRITE, ufdset, nn*sizeof(u32)))
+			return -EFAULT;
 
-	nn = (n + (8 * sizeof(long)) - 1) / (8 * sizeof(long));
-	if (inp && verify_area(VERIFY_WRITE, Inp, nn*sizeof(long)))
-		goto out;
-	if (outp && verify_area(VERIFY_WRITE, Outp, nn*sizeof(long)))
-		goto out;
-	if (exp && verify_area(VERIFY_WRITE, Exp, nn*sizeof(long)))
-		goto out;
-	for (i = 0; i < nn; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) {
-		if(inp && (__get_user (q[1], Inp) || __get_user (q[0], Inp+1)))
-			goto out;
-		if(outp && (__get_user (q[1+(PAGE_SIZE/4/sizeof(u32))], Outp) ||
-			    __get_user (q[(PAGE_SIZE/4/sizeof(u32))], Outp+1)))
-			goto out;
-		if(exp && (__get_user (q[1+(PAGE_SIZE/2/sizeof(u32))], Exp) ||
-			   __get_user (q[(PAGE_SIZE/2/sizeof(u32))], Exp+1)))
-			goto out;
+		odd = n & 1UL;
+		n &= ~1UL;
+		while (n) {
+			unsigned long h, l;
+			__get_user(l, ufdset);
+			__get_user(h, ufdset+1);
+			ufdset += 2;
+			*fdset++ = h << 32 | l;
+			n -= 2;
+		}
+		if (odd)
+			__get_user(*fdset, ufdset);
+	} else {
+		/* Tricky, must clear full unsigned long in the kernel
+		   fdset at the end, this makes sure that actually
+		   happens.  */
+		memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
 	}
 
-	ktvp = NULL;
-	if(tvp) {
-		if (get_tv32(&kern_tv, (struct timeval32 *)A(tvp)))
-			goto out;
-		ktvp = &kern_tv;
+	return 0;
+}
+
+static inline void
+set_fd_set32(unsigned long n, u32 ufdset_x, unsigned long *fdset)
+{
+	unsigned long odd;
+	u32 *ufdset = (u32 *)A(ufdset_x);
+
+	if (!ufdset)
+		return;
+
+	odd = n & 1UL;
+	n &= ~1UL;
+	while (n) {
+		unsigned long h, l;
+		l = *fdset++;
+		h = l >> 32;
+		__put_user(l, ufdset);
+		__put_user(h, ufdset+1);
+		ufdset += 2;
+		n -= 2;
 	}
+	if (odd)
+		__put_user(*fdset, ufdset);
+}
 
-	old_fs = get_fs ();
-	set_fs (KERNEL_DS);
-	q = (u32 *) p;
-	ret = sys_select(n,
-			 inp ? (fd_set *)&q[0] : (fd_set *)0,
-			 outp ? (fd_set *)&q[PAGE_SIZE/4/sizeof(u32)] : (fd_set *)0,
-			 exp ? (fd_set *)&q[PAGE_SIZE/2/sizeof(u32)] : (fd_set *)0,
-			 ktvp);
-	set_fs (old_fs);
+asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp_x)
+{
+	fd_set_buffer *fds;
+	struct timeval32 *tvp = (struct timeval32 *)A(tvp_x);
+	unsigned long timeout, nn;
+	int ret;
 
-	if(tvp && !(current->personality & STICKY_TIMEOUTS)) {
-		if (put_tv32((struct timeval32 *)A(tvp), &kern_tv)) {
-			ret = -EFAULT;
-			goto out;
-		}
+	timeout = ~0UL;
+	if (tvp) {
+		time_t sec, usec;
+
+		if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
+		    || (ret = __get_user(sec, &tvp->tv_sec))
+		    || (ret = __get_user(usec, &tvp->tv_usec)))
+			goto out_nofds;
+
+		timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
+		timeout += sec * HZ;
+		if (timeout)
+			timeout += jiffies + 1;
 	}
 
-	q = (u32 *)p;
-	Inp = (u32 *)A(inp);
-	Outp = (u32 *)A(outp);
-	Exp = (u32 *)A(exp);
-
-	if(ret < 0)
+	ret = -ENOMEM;
+	fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL);
+	if (!fds)
+		goto out_nofds;
+	ret = -EINVAL;
+	if (n < 0)
 		goto out;
-
-	for (i = 0;
-	     i < nn;
-	     i++, Inp += 2, Outp += 2, Exp += 2, q += 2) {
-		if(inp && (__put_user (q[1], Inp) || __put_user (q[0], Inp+1))) {
-			ret = -EFAULT;
-			goto out;
-		}
-		if(outp && (__put_user (q[1+(PAGE_SIZE/4/sizeof(u32))], Outp) ||
-			    __put_user (q[(PAGE_SIZE/4/sizeof(u32))], Outp+1))) {
-			ret = -EFAULT;
-			goto out;
+	if (n > KFDS_NR)
+		n = KFDS_NR;
+ 
+	nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
+	if ((ret = get_fd_set32(nn, fds->in, inp)) ||
+	    (ret = get_fd_set32(nn, fds->out, outp)) ||
+	    (ret = get_fd_set32(nn, fds->ex, exp)))
+		goto out;
+	zero_fd_set(n, fds->res_in);
+	zero_fd_set(n, fds->res_out);
+	zero_fd_set(n, fds->res_ex);
+
+	ret = do_select(n, fds, timeout);
+
+	if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
+		unsigned long timeout = current->timeout - jiffies - 1;
+		time_t sec = 0, usec = 0;
+		if ((long) timeout > 0) {
+			sec = timeout / HZ;
+			usec = timeout % HZ;
+			usec *= (1000000/HZ);
 		}
-		if(exp && (__put_user (q[1+(PAGE_SIZE/2/sizeof(u32))], Exp) ||
-			   __put_user (q[(PAGE_SIZE/2/sizeof(u32))], Exp+1))) {
-		    	ret = -EFAULT;
+		put_user(sec, &tvp->tv_sec);
+		put_user(usec, &tvp->tv_usec);
+	}
+
+	if (ret < 0)
+		goto out;
+	if (!ret) {
+		ret = -ERESTARTNOHAND;
+		if (current->signal & ~current->blocked)
 			goto out;
-		}
+		ret = 0;
 	}
+
+	set_fd_set32(nn, inp, fds->res_in);
+	set_fd_set32(nn, outp, fds->res_out);
+	set_fd_set32(nn, exp, fds->res_ex);
+
 out:
-	free_page ((unsigned long)p);
-out_nofree:
-	unlock_kernel();
+	free_page ((unsigned long)fds);
+out_nofds:
 	return ret;
 }
 
diff -u --recursive --new-file v2.1.71/linux/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c
--- v2.1.71/linux/drivers/char/acquirewdt.c	Sat Nov 29 11:25:09 1997
+++ linux/drivers/char/acquirewdt.c	Tue Dec  9 09:49:58 1997
@@ -64,6 +64,10 @@
 
 static ssize_t acq_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
+	/*  Can't seek (pwrite) on this device  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
 	if(count)
 	{
 		acq_ping();
diff -u --recursive --new-file v2.1.71/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- v2.1.71/linux/drivers/char/n_tty.c	Thu Dec  4 14:53:55 1997
+++ linux/drivers/char/n_tty.c	Sat Dec  6 11:26:26 1997
@@ -54,7 +54,7 @@
  * unthrottling the TTY driver.  These watermarks are used for
  * controlling the space in the read buffer.
  */
-#define TTY_THRESHOLD_THROTTLE		(N_TTY_BUF_SIZE - 128)
+#define TTY_THRESHOLD_THROTTLE		128 /* now based on remaining room */
 #define TTY_THRESHOLD_UNTHROTTLE 	128
 
 static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
@@ -66,21 +66,42 @@
 	}
 }
 
+/* 
+ * Check whether to call the driver.unthrottle function.
+ * We test the TTY_THROTTLED bit first so that it always
+ * indicates the current state.
+ */
+static void check_unthrottle(struct tty_struct * tty)
+{
+	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && 
+	    tty->driver.unthrottle)
+		tty->driver.unthrottle(tty);
+}
+
 /*
- * Flush the input buffer
+ * Reset the read buffer counters, clear the flags, 
+ * and make sure the driver is unthrottled. Called
+ * from n_tty_open() and n_tty_flush_buffer().
  */
-void n_tty_flush_buffer(struct tty_struct * tty)
+static void reset_buffer_flags(struct tty_struct *tty)
 {
 	tty->read_head = tty->read_tail = tty->read_cnt = 0;
 	tty->canon_head = tty->canon_data = tty->erasing = 0;
 	memset(&tty->read_flags, 0, sizeof tty->read_flags);
+	check_unthrottle(tty);
+}
+
+/*
+ * Flush the input buffer
+ */
+void n_tty_flush_buffer(struct tty_struct * tty)
+{
+	/* clear everything and unthrottle the driver */
+	reset_buffer_flags(tty);
 	
 	if (!tty->link)
 		return;
 
-	if (tty->driver.unthrottle &&
-	    test_and_clear_bit(TTY_THROTTLED, &tty->flags))
-		tty->driver.unthrottle(tty);
 	if (tty->link->packet) {
 		tty->ctrl_status |= TIOCPKT_FLUSHREAD;
 		wake_up_interruptible(&tty->link->read_wait);
@@ -508,7 +529,7 @@
 			return;
 		}
 	}
-	if (L_ICANON(tty)) {
+	if (tty->icanon) {
 		if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
 		    (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
 			eraser(c, tty);
@@ -611,11 +632,29 @@
 	put_tty_queue(c, tty);
 }	
 
+static int n_tty_receive_room(struct tty_struct *tty)
+{
+	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+
+	/*
+	 * If we are doing input canonicalization, and there are no
+	 * pending newlines, let characters through without limit, so
+	 * that erase characters will be handled.  Other excess
+	 * characters will be beeped.
+	 */
+	if (tty->icanon && !tty->canon_data)
+		return N_TTY_BUF_SIZE;
+
+	if (left > 0)
+		return left;
+	return 0;
+}
+
 static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 			      char *fp, int count)
 {
 	const unsigned char *p;
-	char *f, flags = 0;
+	char *f, flags = TTY_NORMAL;
 	int	i;
 
 	if (!tty->read_buf)
@@ -670,28 +709,17 @@
 			wake_up_interruptible(&tty->read_wait);
 	}
 
-	if ((tty->read_cnt >= TTY_THRESHOLD_THROTTLE) &&
-	    tty->driver.throttle &&
-	    !test_and_set_bit(TTY_THROTTLED, &tty->flags))
-		tty->driver.throttle(tty);
-}
-
-static int n_tty_receive_room(struct tty_struct *tty)
-{
-	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
-
 	/*
-	 * If we are doing input canonicalization, and there are no
-	 * pending newlines, let characters through without limit, so
-	 * that erase characters will be handled.  Other excess
-	 * characters will be beeped.
+	 * Check the remaining room for the input canonicalization
+	 * mode.  We don't want to throttle the driver if we're in
+	 * canonical mode and don't have a newline yet!
 	 */
-	if (tty->icanon && !tty->canon_data)
-		return N_TTY_BUF_SIZE;
-
-	if (left > 0)
-		return left;
-	return 0;
+	if (n_tty_receive_room(tty) < TTY_THRESHOLD_THROTTLE) {
+		/* check TTY_THROTTLED first so it indicates our state */
+		if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
+		    tty->driver.throttle)
+			tty->driver.throttle(tty);
+	}
 }
 
 int is_ignored(int sig)
@@ -786,10 +814,8 @@
 			return -ENOMEM;
 	}
 	memset(tty->read_buf, 0, N_TTY_BUF_SIZE);
-	tty->read_head = tty->read_tail = tty->read_cnt = 0;
-	tty->canon_head = tty->canon_data = tty->erasing = 0;
+	reset_buffer_flags(tty);
 	tty->column = 0;
-	memset(tty->read_flags, 0, sizeof(tty->read_flags));
 	n_tty_set_termios(tty, 0);
 	tty->minimum_to_wake = 1;
 	tty->closing = 0;
@@ -798,7 +824,7 @@
 
 static inline int input_available_p(struct tty_struct *tty, int amt)
 {
-	if (L_ICANON(tty)) {
+	if (tty->icanon) {
 		if (tty->canon_data)
 			return 1;
 	} else if (tty->read_cnt >= (amt ? amt : 1))
@@ -825,7 +851,8 @@
 	n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail));
 	if (!n)
 		return;
-	copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
+	/* N.B. copy_to_user may work only partially */
+	n -= copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
 	tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
 	tty->read_cnt -= n;
 	*b += n;
@@ -868,7 +895,7 @@
 		}
 	}
 
-	if (L_ICANON(tty)) {
+	if (tty->icanon) {
 		minimum = time = 0;
 		current->timeout = (unsigned long) -1;
 	} else {
@@ -897,9 +924,10 @@
 	while (1) {
 		/* First test for status change. */
 		if (tty->packet && tty->link->ctrl_status) {
-			if (b != buf)
+			if (b != buf || !nr)
 				break;
 			put_user(tty->link->ctrl_status, b++);
+			nr--;
 			tty->link->ctrl_status = 0;
 			break;
 		}
@@ -937,50 +965,52 @@
 		current->state = TASK_RUNNING;
 
 		/* Deal with packet mode. */
-		if (tty->packet && b == buf) {
+		if (tty->packet && b == buf && nr) {
 			put_user(TIOCPKT_DATA, b++);
 			nr--;
 		}
 
-		if (L_ICANON(tty)) {
-			while (1) {
-				int eol;
+		if (tty->icanon) {
+			/* N.B. avoid overrun if nr == 0 */
+			while (nr && tty->read_cnt) {
+ 				int eol;
 
-				if (!tty->read_cnt) {
-					break;
-				}
 				eol = test_and_clear_bit(tty->read_tail,
 						&tty->read_flags);
 				c = tty->read_buf[tty->read_tail];
 				tty->read_tail = ((tty->read_tail+1) &
 						  (N_TTY_BUF_SIZE-1));
 				tty->read_cnt--;
-				if (!eol) {
-					put_user(c, b++);
-					if (--nr)
-						continue;
-					break;
-				}
-				if (--tty->canon_data < 0) {
-					tty->canon_data = 0;
-				}
-				if (c != __DISABLED_CHAR) {
+
+				if (!eol || (c != __DISABLED_CHAR)) {
 					put_user(c, b++);
 					nr--;
 				}
-				break;
+				if (eol) {
+					/* this test should be redundant:
+					 * we shouldn't be reading data if
+					 * canon_data is 0
+					 */
+					if (--tty->canon_data < 0)
+						tty->canon_data = 0;
+					break;
+				}
 			}
 		} else {
+			/* N.B. check for errors writing to user space? */
 			copy_from_read_buf(tty, &b, &nr);
 			copy_from_read_buf(tty, &b, &nr);
 		}
 
 		/* If there is enough space in the read buffer now, let the
-		   low-level driver know. */
-		if (tty->driver.unthrottle &&
-		    (tty->read_cnt <= TTY_THRESHOLD_UNTHROTTLE)
-		    && test_and_clear_bit(TTY_THROTTLED, &tty->flags))
-			tty->driver.unthrottle(tty);
+		 * low-level driver know. We use n_tty_chars_in_buffer() to
+		 * check the buffer, as it now knows about canonical mode.
+		 * Otherwise, if the driver is throttled and the line is
+		 * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
+		 * we won't get any more characters.
+		 */
+		if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE)
+			check_unthrottle(tty);
 
 		if (b - buf >= minimum || !nr)
 			break;
@@ -1048,6 +1078,10 @@
 				tty->driver.flush_chars(tty);
 		} else {
 			c = tty->driver.write(tty, 1, b, nr);
+			if (c < 0) {
+				retval = c;
+				break;
+			}
 			b += c;
 			nr -= c;
 		}
diff -u --recursive --new-file v2.1.71/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.1.71/linux/drivers/char/rtc.c	Sat Oct 25 02:44:15 1997
+++ linux/drivers/char/rtc.c	Mon Dec  8 23:58:04 1997
@@ -52,11 +52,11 @@
 #include <linux/fcntl.h>
 #include <linux/mc146818rtc.h>
 #include <linux/init.h>
+#include <linux/poll.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
-#include <asm/poll.h>
 
 /* Adjust starting epoch if ARC console time is being used */
 #ifdef CONFIG_RTC_ARC
diff -u --recursive --new-file v2.1.71/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.1.71/linux/drivers/char/serial.c	Thu Dec  4 14:53:55 1997
+++ linux/drivers/char/serial.c	Sun Dec  7 12:06:56 1997
@@ -3522,8 +3522,9 @@
  *	Setup initial baud/bits/parity. We do two things here:
  *	- construct a cflag setting for the first rs_open()
  *	- initialize the serial port
+ *	Return non-zero if we didn't find a serial port.
  */
-__initfunc(static void serial_console_setup(struct console *co, char *options))
+__initfunc(static int serial_console_setup(struct console *co, char *options))
 {
 	struct serial_state *ser;
 	unsigned cval;
@@ -3619,6 +3620,12 @@
 	outb(quot >> 8, ser->port + UART_DLM);		/* MS of divisor */
 	outb(cval, ser->port + UART_LCR);		/* reset DLAB */
 
+	/*
+	 *	If we read 0xff from the LSR, there is no UART here.
+	 */
+	if (inb(ser->port + UART_LSR) == 0xff)
+		return -1;
+	return 0;
 }
 
 static struct console sercons = {
diff -u --recursive --new-file v2.1.71/linux/drivers/char/softdog.c linux/drivers/char/softdog.c
--- v2.1.71/linux/drivers/char/softdog.c	Sat Nov 29 11:25:09 1997
+++ linux/drivers/char/softdog.c	Tue Dec  9 09:49:58 1997
@@ -115,6 +115,10 @@
 
 static ssize_t softdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
 {
+	/*  Can't seek (pwrite) on this device  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
 	/*
 	 *	Refresh the timer.
 	 */
diff -u --recursive --new-file v2.1.71/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v2.1.71/linux/drivers/char/stallion.c	Wed Sep 24 20:05:47 1997
+++ linux/drivers/char/stallion.c	Tue Dec  9 09:33:12 1997
@@ -101,11 +101,34 @@
 	int		irqtype;
 } stlconf_t;
 
+/*static stlconf_t	stl_brdconf[] = {
+	{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
+};*/
+
+#ifdef MODULE
+static char *brdtype[STL_MAXBRDS] = {"\0", };
+static int io[STL_MAXBRDS] = { 0, };
+static int secio[STL_MAXBRDS] = { 0, };
+static int irq[STL_MAXBRDS] = { 0, };
+
+MODULE_PARM(brdtype, "1-" __MODULE_STRING(STL_MAXBRDS) "s");
+MODULE_PARM(io, "1-" __MODULE_STRING(STL_MAXBRDS) "i");
+MODULE_PARM(secio, "1-" __MODULE_STRING(STL_MAXBRDS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(STL_MAXBRDS) "i");
+
+static stlconf_t	stl_brdconf[STL_MAXBRDS];
+static int	stl_nrbrds = 0;
+
+#else
 static stlconf_t	stl_brdconf[] = {
 	{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
+	{ BRD_EASYIO, 0x2a8, 0, 0, 10, 0 },
+	{ BRD_EASYIO, 0x2b0, 0, 0, 10, 0 },
+	{ BRD_ECH, 0x2a0, 0x240, 0, 10, 0 },
 };
 
 static int	stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
+#endif
 
 /*****************************************************************************/
 
@@ -616,9 +639,22 @@
  *	Loadable module initialization stuff.
  */
 
+struct board_type_elem
+{
+	int type_id;
+	char *name;
+};
+
+struct board_type_elem board_types[] = {
+	{ BRD_EASYIO, "easyio" },
+	{ BRD_ECH, "ech" },
+	{ BRD_ECHMC, "echmc" },
+	{ BRD_ECHPCI, "echpci" } };
+
 int init_module()
 {
 	unsigned long	flags;
+	int i, j, num_board_types;
 
 #if DEBUG
 	printk("init_module()\n");
@@ -626,6 +662,25 @@
 
 	save_flags(flags);
 	cli();
+
+	num_board_types = sizeof(board_types) / sizeof(struct board_type_elem);
+	for (i = 0; (i < STL_MAXBRDS && io[i]); i++)
+	{
+		stl_brdconf[stl_nrbrds].brdtype = 0;
+		for (j = 0; j < num_board_types; j++)
+			if(strcmp(board_types[j].name, brdtype[i]) == 0)
+				stl_brdconf[stl_nrbrds].brdtype = board_types[j].type_id;
+		if(stl_brdconf[stl_nrbrds].brdtype != 0)
+		{
+			stl_brdconf[stl_nrbrds].ioaddr1 = io[i];
+			stl_brdconf[stl_nrbrds].ioaddr2 = secio[i];
+			stl_brdconf[stl_nrbrds].memaddr = 0;
+			stl_brdconf[stl_nrbrds].irq = irq[i];
+			stl_brdconf[stl_nrbrds].irqtype = 0;
+			stl_nrbrds++;
+		}
+	}
+
 	stl_init();
 	restore_flags(flags);
 
@@ -823,7 +878,10 @@
 				return(-EBUSY);
 		} else {
 			if ((rc = stl_waitcarrier(portp, filp)) != 0)
+			{
+				MOD_INC_USE_COUNT;
 				return(rc);
+			}
 		}
 		portp->flags |= ASYNC_NORMAL_ACTIVE;
 	}
@@ -838,6 +896,7 @@
 
 	portp->session = current->session;
 	portp->pgrp = current->pgrp;
+	MOD_INC_USE_COUNT;
 	return(0);
 }
 
@@ -925,6 +984,7 @@
 		restore_flags(flags);
 		return;
 	}
+	MOD_DEC_USE_COUNT;
 	if (portp->refcount-- > 1) {
 		restore_flags(flags);
 		return;
@@ -2237,10 +2297,12 @@
 	printk("stl_initbrds()\n");
 #endif
 
+#ifndef MODULE
 	if (stl_nrbrds > STL_MAXBRDS) {
 		printk("STALLION: too many boards in configuration table, truncating to %d\n", STL_MAXBRDS);
 		stl_nrbrds = STL_MAXBRDS;
 	}
+#endif
 
 /*
  *	Firstly scan the list of static boards configured. Allocate
diff -u --recursive --new-file v2.1.71/linux/drivers/char/vga.c linux/drivers/char/vga.c
--- v2.1.71/linux/drivers/char/vga.c	Thu Dec  4 14:53:55 1997
+++ linux/drivers/char/vga.c	Tue Dec  9 12:23:52 1997
@@ -162,8 +162,7 @@
 	 *	Find out if there is a graphics card present.
 	 *	Are there smarter methods around?
 	 */
-	p = (unsigned short *)(((ORIG_VIDEO_MODE == 7) ? 0xb0000 : 0xb8000) +
-			       + VGA_OFFSET);
+	p = (unsigned short *) video_mem_base;
 	saved = scr_readw(p);
 	scr_writew(0xAA55, p);
 	if (scr_readw(p) != 0xAA55) {
diff -u --recursive --new-file v2.1.71/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
--- v2.1.71/linux/drivers/char/wdt.c	Sat Nov 29 11:25:09 1997
+++ linux/drivers/char/wdt.c	Tue Dec  9 09:49:58 1997
@@ -53,7 +53,7 @@
  */
  
 static int io=0x240;
-static int irq=14;
+static int irq=11;
 
 #define WD_TIMO (100*60)		/* 1 minute */
 
@@ -171,6 +171,10 @@
 
 static ssize_t wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
+	/*  Can't seek (pwrite) on this device  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
 	if(count)
 	{
 		wdt_ping();
@@ -189,6 +193,10 @@
 	unsigned char cp;
 	int err;
 	
+	/*  Can't seek (pread) on this device  */
+	if (ptr != &file->f_pos)
+		return -ESPIPE;
+
 	switch(MINOR(file->f_dentry->d_inode->i_rdev))
 	{
 		case TEMP_MINOR:
diff -u --recursive --new-file v2.1.71/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- v2.1.71/linux/drivers/isdn/avmb1/capi.c	Mon Nov  3 13:04:26 1997
+++ linux/drivers/isdn/avmb1/capi.c	Mon Dec  8 23:58:04 1997
@@ -47,8 +47,7 @@
 #include <linux/skbuff.h>
 #include <linux/capi.h>
 #include <linux/kernelcapi.h>
-
-#include <asm/poll.h>
+#include <linux/poll.h>
 
 #include "compat.h"
 #include "capiutil.h"
diff -u --recursive --new-file v2.1.71/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.1.71/linux/drivers/isdn/isdn_common.c	Mon Nov  3 13:04:26 1997
+++ linux/drivers/isdn/isdn_common.c	Mon Dec  8 23:58:04 1997
@@ -201,7 +201,7 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #if (LINUX_VERSION_CODE >= 0x020117)
-#include <asm/poll.h>
+#include <linux/poll.h>
 #endif
 #include <linux/isdn.h>
 #include "isdn_common.h"
diff -u --recursive --new-file v2.1.71/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.1.71/linux/drivers/isdn/isdn_ppp.c	Mon Aug 11 14:47:04 1997
+++ linux/drivers/isdn/isdn_ppp.c	Mon Dec  8 23:58:04 1997
@@ -129,7 +129,7 @@
 #include <linux/version.h>
 #include <linux/isdn.h>
 #if (LINUX_VERSION_CODE >= 0x020117)
-#include <asm/poll.h>
+#include <linux/poll.h>
 #endif
 #include "isdn_common.h"
 #include "isdn_ppp.h"
diff -u --recursive --new-file v2.1.71/linux/drivers/misc/parport_ax.c linux/drivers/misc/parport_ax.c
--- v2.1.71/linux/drivers/misc/parport_ax.c	Mon Dec  1 12:04:12 1997
+++ linux/drivers/misc/parport_ax.c	Sat Dec  6 11:58:23 1997
@@ -171,7 +171,7 @@
 {
 	if (p->irq != PARPORT_IRQ_NONE) {
 		ax_disable_irq(p);
-		free_irq(p->irq, p);
+		free_irq(p->irq, NULL);
 	}
 	release_region(p->base, p->size);
 	if (p->modes & PARPORT_MODE_PCECR)
@@ -185,7 +185,7 @@
 {
 	/* FIXME check that resources are free */
 	if (p->irq != PARPORT_IRQ_NONE) {
-		request_irq(p->irq, ax_null_intr_func, 0, p->name, p);
+		request_irq(p->irq, ax_null_intr_func, 0, p->name, NULL);
 		ax_enable_irq(p);
 	}
 	request_region(p->base, p->size, p->name);
diff -u --recursive --new-file v2.1.71/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c
--- v2.1.71/linux/drivers/misc/parport_pc.c	Mon Dec  1 12:04:12 1997
+++ linux/drivers/misc/parport_pc.c	Sat Dec  6 11:58:23 1997
@@ -141,7 +141,7 @@
 static void pc_release_resources(struct parport *p)
 {
 	if (p->irq != PARPORT_IRQ_NONE)
-		free_irq(p->irq, p);
+		free_irq(p->irq, NULL);
 	release_region(p->base, p->size);
 	if (p->modes & PARPORT_MODE_PCECR)
 		release_region(p->base+0x400, 3);
@@ -151,7 +151,7 @@
 {
 	/* FIXME check that resources are free */
 	if (p->irq != PARPORT_IRQ_NONE)
-		request_irq(p->irq, pc_null_intr_func, 0, p->name, p);
+		request_irq(p->irq, pc_null_intr_func, 0, p->name, NULL);
 	request_region(p->base, p->size, p->name);
 	if (p->modes & PARPORT_MODE_PCECR)
 		request_region(p->base+0x400, 3, p->name);
diff -u --recursive --new-file v2.1.71/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.1.71/linux/drivers/net/Config.in	Thu Dec  4 14:53:55 1997
+++ linux/drivers/net/Config.in	Tue Dec  9 09:49:58 1997
@@ -180,6 +180,7 @@
       bool '  WANPIPE Frame Relay support' CONFIG_WANPIPE_FR
       bool '  WANPIPE PPP support' CONFIG_WANPIPE_PPP
     fi
+    dep_tristate 'High-speed (DMA) SCC driver for AX.25' CONFIG_DMASCC $CONFIG_AX25
   fi
 fi
 #
diff -u --recursive --new-file v2.1.71/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.1.71/linux/drivers/net/Space.c	Sat Nov 29 11:25:09 1997
+++ linux/drivers/net/Space.c	Tue Dec  9 09:49:58 1997
@@ -31,6 +31,7 @@
 #include <linux/netdevice.h>
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/netlink.h>
 
 #define	NEXT_DEV	NULL
 
diff -u --recursive --new-file v2.1.71/linux/drivers/net/dmascc.c linux/drivers/net/dmascc.c
--- v2.1.71/linux/drivers/net/dmascc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/dmascc.c	Tue Dec  9 09:49:58 1997
@@ -0,0 +1,1260 @@
+/*
+ * $Id: dmascc.c,v 1.2 1997/12/02 16:49:49 oe1kib Exp $
+ *
+ * Driver for high-speed SCC boards (those with DMA support)
+ * Copyright (C) 1997 Klaus Kudielka
+ *
+ * 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.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <linux/module.h>
+#include <linux/dmascc.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/netdevice.h>
+#include <linux/sockios.h>
+#include <linux/tqueue.h>
+#include <linux/version.h>
+#include <asm/atomic.h>
+#include <asm/bitops.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <net/ax25.h>
+#include <stdio.h>
+#include "z8530.h"
+
+
+/* Number of buffers per channel */
+
+#define NUM_TX_BUF      2          /* NUM_TX_BUF >= 1 (2 recommended) */
+#define NUM_RX_BUF      2          /* NUM_RX_BUF >= 1 (2 recommended) */
+#define BUF_SIZE        2016
+
+
+/* Cards supported */
+
+#define HW_PI           { "Ottawa PI", 0x300, 0x20, 0x10, 8, \
+                            0, 8, 1843200, 3686400 }
+#define HW_PI2          { "Ottawa PI2", 0x300, 0x20, 0x10, 8, \
+			    0, 8, 3686400, 7372800 }
+#define HW_TWIN         { "Gracilis PackeTwin", 0x200, 0x10, 0x10, 32, \
+			    0, 4, 6144000, 6144000 }
+
+#define HARDWARE        { HW_PI, HW_PI2, HW_TWIN }
+
+#define TYPE_PI         0
+#define TYPE_PI2        1
+#define TYPE_TWIN       2
+#define NUM_TYPES       3
+
+#define MAX_NUM_DEVS    32
+
+
+/* SCC chips supported */
+
+#define Z8530           0
+#define Z85C30          1
+#define Z85230          2
+
+#define CHIPNAMES       { "Z8530", "Z85C30", "Z85230" }
+
+
+/* I/O registers */
+
+/* 8530 registers relative to card base */
+#define SCCB_CMD        0x00
+#define SCCB_DATA       0x01
+#define SCCA_CMD        0x02
+#define SCCA_DATA       0x03
+
+/* 8254 registers relative to card base */
+#define TMR_CNT0        0x00
+#define TMR_CNT1        0x01
+#define TMR_CNT2        0x02
+#define TMR_CTRL        0x03
+
+/* Additional PI/PI2 registers relative to card base */
+#define PI_DREQ_MASK    0x04
+
+/* Additional PackeTwin registers relative to card base */
+#define TWIN_INT_REG    0x08
+#define TWIN_CLR_TMR1   0x09
+#define TWIN_CLR_TMR2   0x0a
+#define TWIN_SPARE_1    0x0b
+#define TWIN_DMA_CFG    0x08
+#define TWIN_SERIAL_CFG 0x09
+#define TWIN_DMA_CLR_FF 0x0a
+#define TWIN_SPARE_2    0x0b
+
+
+/* PackeTwin I/O register values */
+
+/* INT_REG */
+#define TWIN_SCC_MSK       0x01
+#define TWIN_TMR1_MSK      0x02
+#define TWIN_TMR2_MSK      0x04
+#define TWIN_INT_MSK       0x07
+
+/* SERIAL_CFG */
+#define TWIN_DTRA_ON       0x01
+#define TWIN_DTRB_ON       0x02
+#define TWIN_EXTCLKA       0x04
+#define TWIN_EXTCLKB       0x08
+#define TWIN_LOOPA_ON      0x10
+#define TWIN_LOOPB_ON      0x20
+#define TWIN_EI            0x80
+
+/* DMA_CFG */
+#define TWIN_DMA_HDX_T1    0x08
+#define TWIN_DMA_HDX_R1    0x0a
+#define TWIN_DMA_HDX_T3    0x14
+#define TWIN_DMA_HDX_R3    0x16
+#define TWIN_DMA_FDX_T3R1  0x1b
+#define TWIN_DMA_FDX_T1R3  0x1d
+
+
+/* Status values */
+
+/* tx_state */
+#define TX_IDLE    0
+#define TX_OFF     1
+#define TX_TXDELAY 2
+#define TX_ACTIVE  3
+#define TX_SQDELAY 4
+
+
+/* Data types */
+
+struct scc_hardware {
+  char *name;
+  int io_region;
+  int io_delta;
+  int io_size;
+  int num_devs;
+  int scc_offset;
+  int tmr_offset;
+  int tmr_hz;
+  int pclk_hz;
+};
+
+struct scc_priv {
+  char name[10];
+  struct enet_statistics stats;
+  struct scc_info *info;
+  int channel;
+  int cmd, data, tmr;
+  struct scc_param param;
+  char rx_buf[NUM_RX_BUF][BUF_SIZE];
+  int rx_len[NUM_RX_BUF];
+  int rx_ptr;
+  struct tq_struct rx_task;
+  int rx_head, rx_tail, rx_count;
+  int rx_over;
+  char tx_buf[NUM_TX_BUF][BUF_SIZE];
+  int tx_len[NUM_TX_BUF];
+  int tx_ptr;
+  int tx_head, tx_tail, tx_count;
+  int tx_sem, tx_state;
+  unsigned long tx_start;
+  int status;
+};
+
+struct scc_info {
+  int type;
+  int chip;
+  int open;
+  int scc_base;
+  int tmr_base;
+  int twin_serial_cfg;
+  struct device dev[2];
+  struct scc_priv priv[2];
+  struct scc_info *next;
+};
+
+
+/* Function declarations */
+
+int dmascc_init(void) __init;
+static int setup_adapter(int io, int h, int n) __init;
+
+static inline void write_scc(int ctl, int reg, int val);
+static inline int read_scc(int ctl, int reg);
+static int scc_open(struct device *dev);
+static int scc_close(struct device *dev);
+static int scc_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
+static int scc_send_packet(struct sk_buff *skb, struct device *dev);
+static struct enet_statistics *scc_get_stats(struct device *dev);
+static int scc_set_mac_address(struct device *dev, void *sa);
+static void scc_isr(int irq, void *dev_id, struct pt_regs * regs);
+static inline void z8530_isr(struct scc_info *info);
+static void rx_isr(struct device *dev);
+static void special_condition(struct device *dev, int rc);
+static void rx_bh(void *arg);
+static void tx_isr(struct device *dev);
+static void es_isr(struct device *dev);
+static void tm_isr(struct device *dev);
+static inline void delay(struct device *dev, int t);
+static inline unsigned char random(void);
+
+
+/* Initialization variables */
+
+static int io[MAX_NUM_DEVS] __initdata = { 0, };
+/* Beware! hw[] is also used in cleanup_module(). If __initdata also applies
+   to modules, we may not declare hw[] as __initdata */
+static struct scc_hardware hw[NUM_TYPES] __initdata = HARDWARE;
+static char ax25_broadcast[7] __initdata =
+  { 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1 };
+static char ax25_test[7] __initdata =
+  { 'L'<<1, 'I'<<1, 'N'<<1, 'U'<<1, 'X'<<1, ' '<<1, '1'<<1 };
+
+
+/* Global variables */
+
+static struct scc_info *first = NULL;
+static unsigned long rand;
+
+
+
+/* Module functions */
+
+#ifdef MODULE
+
+
+MODULE_AUTHOR("Klaus Kudielka <oe1kib@oe1xtu.ampr.org>");
+MODULE_DESCRIPTION("Driver for high-speed SCC boards");
+MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NUM_DEVS) "i");
+
+
+int init_module(void)
+{
+  return dmascc_init();
+}
+
+
+void cleanup_module(void)
+{
+  int i;
+  struct scc_info *info;
+
+  while (first) {
+    info = first;
+
+    /* Unregister devices */
+    for (i = 0; i < 2; i++) {
+      if (info->dev[i].name)
+	unregister_netdev(&info->dev[i]);
+    }
+
+    /* Reset board */
+    if (info->type == TYPE_TWIN)
+      outb_p(0, info->dev[0].base_addr + TWIN_SERIAL_CFG);
+    write_scc(info->priv[0].cmd, R9, FHWRES);
+    release_region(info->dev[0].base_addr,
+		   hw[info->type].io_size);
+
+    /* Free memory */
+    first = info->next;
+    kfree_s(info, sizeof(struct scc_info));
+  }
+}
+
+
+#else
+
+
+__initfunc(void dmascc_setup(char *str, int *ints))
+{
+   int i;
+
+   for (i = 0; i < MAX_NUM_DEVS && i < ints[0]; i++)
+      io[i] = ints[i+1];
+}
+
+
+#endif
+
+
+/* Initialization functions */
+
+__initfunc(int dmascc_init(void))
+{
+  int h, i, j, n, base[MAX_NUM_DEVS], tcmd, t0, t1, status;
+  unsigned long time, start[MAX_NUM_DEVS], stop[MAX_NUM_DEVS];
+
+  /* Initialize random number generator */
+  rand = jiffies;
+
+  /* Cards found = 0 */
+  n = 0;
+
+  /* Run autodetection for each card type */
+  for (h = 0; h < NUM_TYPES; h++) {
+
+    if (io[0]) {
+      /* User-specified I/O address regions */
+      for (i = 0; i < hw[h].num_devs; i++) base[i] = 0;
+      for (i = 0; i < MAX_NUM_DEVS && io[i]; i++) {
+	j = (io[i] - hw[h].io_region) / hw[h].io_delta;
+	if (j >= 0 &&
+	    j < hw[h].num_devs && 
+	    hw[h].io_region + j * hw[h].io_delta == io[i])
+	  base[j] = io[i];
+      }
+    } else {
+      /* Default I/O address regions */
+      for (i = 0; i < hw[h].num_devs; i++)
+	base[i] = hw[h].io_region + i * hw[h].io_delta;
+    }
+
+    /* Check valid I/O address regions */
+    for (i = 0; i < hw[h].num_devs; i++)
+      if (base[i] && check_region(base[i], hw[h].io_size))
+	base[i] = 0;
+
+    /* Start timers */
+    for (i = 0; i < hw[h].num_devs; i++)
+      if (base[i]) {
+	tcmd = base[i] + hw[h].tmr_offset + TMR_CTRL;
+	t0   = base[i] + hw[h].tmr_offset + TMR_CNT0;
+	t1   = base[i] + hw[h].tmr_offset + TMR_CNT1;
+	/* Timer 0: LSB+MSB, Mode 3, TMR_0_HZ */
+	outb_p(0x36, tcmd);
+	outb_p((hw[h].tmr_hz/TMR_0_HZ) & 0xFF, t0);
+	outb_p((hw[h].tmr_hz/TMR_0_HZ) >> 8, t0);
+	/* Timer 1: LSB+MSB, Mode 0, HZ/10 */
+	outb_p(0x70, tcmd);
+	outb_p((TMR_0_HZ/HZ*10) & 0xFF, t1);
+	outb_p((TMR_0_HZ/HZ*10) >> 8, t1);
+	/* Timer 2: LSB+MSB, Mode 0 */
+	outb_p(0xb0, tcmd);
+      }
+
+    /* Initialize start values in case we miss the null count bit */
+    time = jiffies;
+    for (i = 0; i < hw[h].num_devs; i++) start[i] = time;
+
+    /* Timing loop */
+    while (jiffies - time < 12) {
+      for (i = 0; i < hw[h].num_devs; i++)
+	if (base[i]) {
+	  /* Read back Timer 1: Status */
+	  outb_p(0xE4, base[i] + hw[h].tmr_offset + TMR_CTRL);
+	  status = inb_p(base[i] + hw[h].tmr_offset + TMR_CNT1);
+	  if ((status & 0x3F) != 0x30) base[i] = 0;
+	  if (status & 0x40) start[i] = jiffies;
+	  if (~status & 0x80) stop[i] = jiffies;
+	}
+    }
+
+    /* Evaluate measurements */
+    for (i = 0; i < hw[h].num_devs; i++)
+      if (base[i]) {
+	time = stop[i] - start[i];
+	if (time < 9 || time > 11)
+	  /* The time expired doesn't match */
+	  base[i] = 0;
+	else {
+	  /* Ok, we have found an adapter */
+	  if (setup_adapter(base[i], h, n) == 0)
+	    n++;
+	}
+      }
+
+  } /* NUM_TYPES */
+
+  /* If any adapter was successfully initialized, return ok */
+  if (n) return 0;
+
+  /* If no adapter found, return error */
+  printk("dmascc: no adapters found\n");
+  return -EIO;
+}
+
+
+__initfunc(int setup_adapter(int io, int h, int n))
+{
+  int i, irq, chip;
+  struct scc_info *info;
+  struct device *dev;
+  struct scc_priv *priv;
+  unsigned long time;
+  unsigned int irqs;
+  int tmr = io + hw[h].tmr_offset;
+  int scc = io + hw[h].scc_offset;
+  int cmd = scc + SCCA_CMD;
+  char *chipnames[] = CHIPNAMES;
+
+  /* Reset 8530 */
+  write_scc(cmd, R9, FHWRES | MIE | NV);
+
+  /* Determine type of chip */
+  write_scc(cmd, R15, 1);
+  if (!read_scc(cmd, R15)) {
+    /* WR7' not present. This is an ordinary Z8530 SCC. */
+    chip = Z8530;
+  } else {
+    /* Put one character in TX FIFO */
+    write_scc(cmd, R8, 0);
+    if (read_scc(cmd, R0) & Tx_BUF_EMP) {
+      /* TX FIFO not full. This is a Z85230 ESCC with a 4-byte FIFO. */
+      chip = Z85230;
+    } else {
+      /* TX FIFO full. This is a Z85C30 SCC with a 1-byte FIFO. */
+      chip = Z85C30;
+    }
+  }
+  write_scc(cmd, R15, 0);
+
+  /* Start IRQ auto-detection */
+  sti();
+  irqs = probe_irq_on();
+
+  /* Enable interrupts */
+  switch (h) {
+  case TYPE_PI:
+  case TYPE_PI2:
+    outb_p(0, io + PI_DREQ_MASK);
+    write_scc(cmd, R15, CTSIE);
+    write_scc(cmd, R0, RES_EXT_INT);
+    write_scc(cmd, R1, EXT_INT_ENAB);
+    break;
+  case TYPE_TWIN:
+    outb_p(0, io + TWIN_DMA_CFG);
+    inb_p(io + TWIN_CLR_TMR1);
+    inb_p(io + TWIN_CLR_TMR2);
+    outb_p(TWIN_EI, io + TWIN_SERIAL_CFG);
+    break;
+  }
+
+  /* Start timer */
+  outb_p(1, tmr + TMR_CNT1);
+  outb_p(0, tmr + TMR_CNT1);
+  /* Wait and detect IRQ */
+  time = jiffies; while (jiffies - time < 2 + HZ / TMR_0_HZ);
+  irq = probe_irq_off(irqs);
+
+  /* Clear pending interrupt, disable interrupts */
+  switch (h) {
+  case TYPE_PI:
+  case TYPE_PI2:
+    write_scc(cmd, R1, 0);
+    write_scc(cmd, R15, 0);
+    write_scc(cmd, R0, RES_EXT_INT);
+    break;
+  case TYPE_TWIN:
+    inb_p(io + TWIN_CLR_TMR1);
+    outb_p(0, io + TWIN_SERIAL_CFG);
+    break;
+  }
+
+  if (irq <= 0) {
+    printk("dmascc: could not find irq of %s at %#3x (irq=%d)\n",
+	   hw[h].name, io, irq);
+    return -1;
+  }
+
+  /* Allocate memory */
+  info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA);
+  if (!info) {
+    printk("dmascc: could not allocate memory for %s at %#3x\n",
+	   hw[h].name, io);
+    return -1;
+  }
+
+  /* Set up data structures */
+  memset(info, 0, sizeof(struct scc_info));
+  info->type = h;
+  info->chip = chip;
+  info->scc_base = io + hw[h].scc_offset;
+  info->tmr_base = io + hw[h].tmr_offset;
+  info->twin_serial_cfg = 0;
+  for (i = 0; i < 2; i++) {
+    dev = &info->dev[i];
+    priv = &info->priv[i];
+    sprintf(priv->name, "dmascc%i", 2*n+i);
+    priv->info = info;
+    priv->channel = i;
+    priv->cmd = info->scc_base + (i ? SCCB_CMD : SCCA_CMD);
+    priv->data = info->scc_base + (i ? SCCB_DATA : SCCA_DATA);
+    priv->tmr = info->tmr_base + (i ? TMR_CNT2 : TMR_CNT1);
+    priv->param.pclk_hz = hw[h].pclk_hz;
+    priv->param.brg_tc = -1;
+    priv->param.clocks = TCTRxCP | RCRTxCP;
+    priv->param.txdelay = TMR_0_HZ * 10 / 1000;
+    priv->param.txtime = HZ * 3;
+    priv->param.sqdelay = TMR_0_HZ * 1 / 1000;
+    priv->param.slottime = TMR_0_HZ * 10 / 1000;
+    priv->param.waittime = TMR_0_HZ * 100 / 1000;
+    priv->param.persist = 32;
+    priv->rx_task.routine = rx_bh;
+    priv->rx_task.data = dev;
+    dev->priv = priv;
+    dev->name = priv->name;
+    dev->base_addr = io;
+    dev->irq = irq;
+    dev->open = scc_open;
+    dev->stop = scc_close;
+    dev->do_ioctl = scc_ioctl;
+    dev->hard_start_xmit = scc_send_packet;
+    dev->get_stats = scc_get_stats;
+    dev->hard_header = ax25_encapsulate;
+    dev->rebuild_header = ax25_rebuild_header;
+    dev->set_mac_address = scc_set_mac_address;
+    dev->type = ARPHRD_AX25;
+    dev->hard_header_len = 73;
+    dev->mtu = 1500;
+    dev->addr_len = 7;
+    dev->tx_queue_len = 64;
+    memcpy(dev->broadcast, ax25_broadcast, 7);
+    memcpy(dev->dev_addr, ax25_test, 7);
+    dev->flags = 0;
+    dev_init_buffers(dev);
+    if (register_netdev(dev)) {
+      printk("dmascc: could not register %s\n", dev->name);
+      dev->name = NULL;
+    }
+  }
+
+  request_region(io, hw[h].io_size, "dmascc");
+
+  info->next = first;
+  first = info;
+  printk("dmascc: found %s (%s) at %#3x, irq %d\n", hw[h].name,
+	 chipnames[chip], io, irq);
+  return 0;
+}
+
+
+/* Driver functions */
+
+static inline void write_scc(int ctl, int reg, int val)
+{
+  outb_p(reg, ctl);
+  outb_p(val, ctl);
+}
+
+
+static inline int read_scc(int ctl, int reg)
+{
+  outb_p(reg, ctl);
+  return inb_p(ctl);
+}
+
+
+static int scc_open(struct device *dev)
+{
+  struct scc_priv *priv = dev->priv;
+  struct scc_info *info = priv->info;
+  int io = dev->base_addr;
+  int cmd = priv->cmd;
+
+  /* Request IRQ if not already used by other channel */
+  if (!info->open) {
+    if (request_irq(dev->irq, scc_isr, SA_INTERRUPT, "dmascc", info))
+      return -EAGAIN;
+  }
+
+  /* Request DMA if required */
+  if (dev->dma && request_dma(dev->dma, "dmascc")) {
+    if (!info->open) free_irq(dev->irq, info);
+    return -EAGAIN;
+  }
+
+  /* Initialize local variables */
+  dev->tbusy = 0;
+  priv->rx_ptr = 0;
+  priv->rx_over = 0;
+  priv->rx_head = priv->rx_tail = priv->rx_count = 0;
+  priv->tx_state = TX_IDLE;
+  priv->tx_head = priv->tx_tail = priv->tx_count = 0;
+  priv->tx_ptr = 0;
+  priv->tx_sem = 0;
+
+  /* Reset channel */
+  write_scc(cmd, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
+  /* X1 clock, SDLC mode */
+  write_scc(cmd, R4, SDLC | X1CLK);
+  /* DMA */
+  write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+  /* 8 bit RX char, RX disable */
+  write_scc(cmd, R3, Rx8);
+  /* 8 bit TX char, TX disable */
+  write_scc(cmd, R5, Tx8);
+  /* SDLC address field */
+  write_scc(cmd, R6, 0);
+  /* SDLC flag */
+  write_scc(cmd, R7, FLAG);
+  switch (info->chip) {
+  case Z85C30:
+    /* Select WR7' */
+    write_scc(cmd, R15, 1);
+    /* Auto EOM reset */
+    write_scc(cmd, R7, 0x02);
+    write_scc(cmd, R15, 0);
+    break;
+  case Z85230:
+    /* Select WR7' */
+    write_scc(cmd, R15, 1);
+    /* RX FIFO half full (interrupt only), Auto EOM reset,
+       TX FIFO empty (DMA only) */
+    write_scc(cmd, R7, dev->dma ? 0x22 : 0x0a);
+    write_scc(cmd, R15, 0);
+    break;
+  }
+  /* Preset CRC, NRZ(I) encoding */
+  write_scc(cmd, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ));
+
+  /* Configure baud rate generator */
+  if (priv->param.brg_tc >= 0) {
+    /* Program BR generator */
+    write_scc(cmd, R12, priv->param.brg_tc & 0xFF);
+    write_scc(cmd, R13, (priv->param.brg_tc>>8) & 0xFF);
+    /* BRG source = SYS CLK; enable BRG; DTR REQ function (required by
+       PackeTwin, not connected on the PI2); set DPLL source to BRG */
+    write_scc(cmd, R14, SSBR | DTRREQ | BRSRC | BRENABL);
+    /* Enable DPLL */
+    write_scc(cmd, R14, SEARCH | DTRREQ | BRSRC | BRENABL);
+  } else {
+    /* Disable BR generator */
+    write_scc(cmd, R14, DTRREQ | BRSRC);
+  }
+
+  /* Configure clocks */
+  if (info->type == TYPE_TWIN) {
+    /* Disable external TX clock receiver */
+    outb_p((info->twin_serial_cfg &=
+	    ~(priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)), 
+	   io + TWIN_SERIAL_CFG);
+  }
+  write_scc(cmd, R11, priv->param.clocks);
+  if ((info->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) {
+    /* Enable external TX clock receiver */
+    outb_p((info->twin_serial_cfg |=
+	    (priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
+	   io + TWIN_SERIAL_CFG);
+  }
+
+  /* Configure PackeTwin */
+  if (info->type == TYPE_TWIN) {
+    /* Assert DTR, enable interrupts */
+    outb_p((info->twin_serial_cfg |= TWIN_EI |
+	    (priv->channel ? TWIN_DTRB_ON : TWIN_DTRA_ON)),
+	   io + TWIN_SERIAL_CFG);
+  }
+
+  /* Read current status */
+  priv->status = read_scc(cmd, R0);
+  /* Enable SYNC, DCD, and CTS interrupts */
+  write_scc(cmd, R15, DCDIE | CTSIE | SYNCIE);
+
+  /* Configure PI2 DMA */
+  if (info->type <= TYPE_PI2) outb_p(1, io + PI_DREQ_MASK);
+
+  dev->start = 1;
+  info->open++;
+  MOD_INC_USE_COUNT;
+
+  return 0;
+}
+
+
+static int scc_close(struct device *dev)
+{
+  struct scc_priv *priv = dev->priv;
+  struct scc_info *info = priv->info;
+  int io = dev->base_addr;
+  int cmd = priv->cmd;
+
+  dev->start = 0;
+  info->open--;
+  MOD_DEC_USE_COUNT;
+
+  if (info->type == TYPE_TWIN)
+    /* Drop DTR */
+    outb_p((info->twin_serial_cfg &=
+	    (priv->channel ? ~TWIN_DTRB_ON : ~TWIN_DTRA_ON)),
+	   io + TWIN_SERIAL_CFG);
+
+  /* Reset channel, free DMA */
+  write_scc(cmd, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
+  if (dev->dma) {
+    if (info->type == TYPE_TWIN) outb_p(0, io + TWIN_DMA_CFG);
+    free_dma(dev->dma);
+  }
+
+  if (!info->open) {
+    if (info->type <= TYPE_PI2) outb_p(0, io + PI_DREQ_MASK);
+    free_irq(dev->irq, info);
+  }
+  return 0;
+}
+
+
+static int scc_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+{
+  int rc;
+  struct scc_priv *priv = dev->priv;
+  
+  switch (cmd) {
+  case SIOCGSCCPARAM:
+    rc = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct scc_param));
+    if (rc) return rc;
+    copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param));
+    return 0;
+  case SIOCSSCCPARAM:
+    if (!suser()) return -EPERM;
+    rc = verify_area(VERIFY_READ, ifr->ifr_data, sizeof(struct scc_param));
+    if (rc) return rc;
+    if (dev->start) return -EAGAIN;
+    copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param));
+    dev->dma = priv->param.dma;
+    return 0;
+  default:
+    return -EINVAL;
+  }
+}
+
+
+static int scc_send_packet(struct sk_buff *skb, struct device *dev)
+{
+  struct scc_priv *priv = dev->priv;
+  struct scc_info *info = priv->info;
+  int cmd = priv->cmd;
+  unsigned long flags;
+  int i;
+
+  /* Block a timer-based transmit from overlapping */
+  if (test_and_set_bit(0, (void *) &priv->tx_sem) != 0) {
+    atomic_inc((void *) &priv->stats.tx_dropped);
+    dev_kfree_skb(skb, FREE_WRITE);
+    return 0;
+  }
+
+  /* Return with an error if we cannot accept more data */
+  if (dev->tbusy) {
+    priv->tx_sem = 0;
+    return -1;
+  }
+
+  /* Transfer data to DMA buffer */
+  i = priv->tx_head;
+  memcpy(priv->tx_buf[i], skb->data+1, skb->len-1);
+  priv->tx_len[i] = skb->len-1;
+
+  save_flags(flags);
+  cli();
+
+  /* Set the busy flag if we just filled up the last buffer */
+  priv->tx_head = (i + 1) % NUM_TX_BUF;
+  priv->tx_count++;
+  if (priv->tx_count == NUM_TX_BUF) dev->tbusy = 1;
+
+  /* Set new TX state */
+  if (priv->tx_state == TX_IDLE) {
+    /* Assert RTS, start timer */
+    priv->tx_state = TX_TXDELAY;
+    if (info->type <= TYPE_PI2) outb_p(0, dev->base_addr + PI_DREQ_MASK);
+    write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
+    if (info->type <= TYPE_PI2) outb_p(1, dev->base_addr + PI_DREQ_MASK);
+    priv->tx_start = jiffies;
+    delay(dev, priv->param.txdelay);
+  }
+
+  restore_flags(flags);
+
+  dev_kfree_skb(skb, FREE_WRITE);
+
+  priv->tx_sem = 0;
+  return 0;
+}
+
+
+static struct enet_statistics *scc_get_stats(struct device *dev)
+{
+  struct scc_priv *priv = dev->priv;
+
+  return &priv->stats;
+}
+
+
+static int scc_set_mac_address(struct device *dev, void *sa)
+{
+  memcpy(dev->dev_addr, ((struct sockaddr *)sa)->sa_data, dev->addr_len);
+  return 0;
+}
+
+
+static void scc_isr(int irq, void *dev_id, struct pt_regs * regs)
+{
+  struct scc_info *info = dev_id;
+  int is, io = info->dev[0].base_addr;
+
+  /* We're a fast IRQ handler and are called with interrupts disabled */
+
+  /* IRQ sharing doesn't make sense due to ISA's edge-triggered
+     interrupts, hence it is safe to return if we have found and
+     processed a single device. */
+
+  /* Interrupt processing: We loop until we know that the IRQ line is
+     low. If another positive edge occurs afterwards during the ISR,
+     another interrupt will be triggered by the interrupt controller
+     as soon as the IRQ level is enabled again (see asm/irq.h). */
+
+  switch (info->type) {
+  case TYPE_PI:
+  case TYPE_PI2:
+    outb_p(0, io + PI_DREQ_MASK);
+    z8530_isr(info);
+    outb_p(1, io + PI_DREQ_MASK);
+    return;
+  case TYPE_TWIN:
+    while ((is = ~inb_p(io + TWIN_INT_REG)) &
+	   TWIN_INT_MSK) {
+      if (is & TWIN_SCC_MSK) {
+	z8530_isr(info);
+      } else if (is & TWIN_TMR1_MSK) {
+	inb_p(io + TWIN_CLR_TMR1);
+	tm_isr(&info->dev[0]);
+      } else {
+	inb_p(io + TWIN_CLR_TMR2);
+	tm_isr(&info->dev[1]);
+      }
+    }
+    /* No interrupts pending from the PackeTwin */
+    return;
+  }
+}
+
+
+static inline void z8530_isr(struct scc_info *info)
+{
+  int is, a_cmd;
+  
+  a_cmd = info->scc_base + SCCA_CMD;
+
+  while ((is = read_scc(a_cmd, R3))) {
+    if (is & CHARxIP) {
+      rx_isr(&info->dev[0]);
+    } else if (is & CHATxIP) {
+      tx_isr(&info->dev[0]);
+    } else if (is & CHAEXT) {
+      es_isr(&info->dev[0]);
+    } else if (is & CHBRxIP) {
+      rx_isr(&info->dev[1]);
+    } else if (is & CHBTxIP) {
+      tx_isr(&info->dev[1]);
+    } else {
+      es_isr(&info->dev[1]);
+    }
+  }
+  /* Ok, no interrupts pending from this 8530. The INT line should
+     be inactive now. */
+}
+
+
+static void rx_isr(struct device *dev)
+{
+  struct scc_priv *priv = dev->priv;
+  int cmd = priv->cmd;
+
+  if (dev->dma) {
+    /* Check special condition and perform error reset. See 2.4.7.5. */
+    special_condition(dev, read_scc(cmd, R1));
+    write_scc(cmd, R0, ERR_RES);
+  } else {
+    /* Check special condition for each character. Error reset not necessary.
+       Same algorithm for SCC and ESCC. See 2.4.7.1 and 2.4.7.4. */
+    int rc;
+    while (read_scc(cmd, R0) & Rx_CH_AV) {
+      rc = read_scc(cmd, R1);
+      if (priv->rx_ptr < BUF_SIZE)
+	priv->rx_buf[priv->rx_head][priv->rx_ptr++] = read_scc(cmd, R8);
+      else {
+	priv->rx_over = 2;
+	read_scc(cmd, R8);
+      }
+      special_condition(dev, rc);
+    }
+  }
+}
+
+
+static void special_condition(struct device *dev, int rc)
+{
+  struct scc_priv *priv = dev->priv;
+  int cb, cmd = priv->cmd;
+
+  /* See Figure 2-15. Only overrun and EOF need to be checked. */
+  
+  if (rc & Rx_OVR) {
+    /* Receiver overrun */
+    priv->rx_over = 1;
+    if (!dev->dma) write_scc(cmd, R0, ERR_RES);
+  } else if (rc & END_FR) {
+    /* End of frame. Get byte count */
+    if (dev->dma) {
+	disable_dma(dev->dma);
+	clear_dma_ff(dev->dma);
+	cb = BUF_SIZE - get_dma_residue(dev->dma) - 2;
+    } else {
+	cb = priv->rx_ptr - 2;
+    }
+    if (priv->rx_over) {
+      /* We had an overrun */
+      priv->stats.rx_errors++;
+      if (priv->rx_over == 2) priv->stats.rx_length_errors++;
+      else priv->stats.rx_fifo_errors++;
+      priv->rx_over = 0;
+    } else if (rc & CRC_ERR) {
+      /* Count invalid CRC only if packet length >= minimum */
+      if (cb >= 8) {
+	priv->stats.rx_errors++;
+	priv->stats.rx_crc_errors++;
+      }
+    } else {
+      if (cb >= 8) {
+	/* Put good frame in FIFO */
+	priv->rx_len[priv->rx_head] = cb;
+	priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF;
+	priv->rx_count++;
+	if (priv->rx_count == NUM_RX_BUF) {
+	  /* Disable receiver if FIFO full */
+	  write_scc(cmd, R3, Rx8);
+	  priv->stats.rx_errors++;
+	  priv->stats.rx_over_errors++;
+	}
+	/* Mark bottom half handler */
+	queue_task(&priv->rx_task, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+      }
+    }
+    /* Get ready for new frame */
+    if (dev->dma) {
+      set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
+      set_dma_count(dev->dma, BUF_SIZE);
+      enable_dma(dev->dma);
+    } else {
+      priv->rx_ptr = 0;
+    }
+  }
+}
+
+
+static void rx_bh(void *arg)
+{
+  struct device *dev = arg;
+  struct scc_priv *priv = dev->priv;
+  struct scc_info *info = priv->info;
+  int cmd = priv->cmd;
+  int i = priv->rx_tail;
+  int cb;
+  unsigned long flags;
+  struct sk_buff *skb;
+  unsigned char *data;
+
+  save_flags(flags);
+  cli();
+
+  while (priv->rx_count) {
+    restore_flags(flags);
+    cb = priv->rx_len[i];
+    /* Allocate buffer */
+    skb = dev_alloc_skb(cb+1);
+    if (skb == NULL) {
+      /* Drop packet */
+      priv->stats.rx_dropped++;
+    } else {
+      /* Fill buffer */
+      data = skb_put(skb, cb+1);
+      data[0] = 0;
+      memcpy(&data[1], priv->rx_buf[i], cb);
+      skb->dev = dev;
+      skb->protocol = ntohs(ETH_P_AX25);
+      skb->mac.raw = skb->data;
+      netif_rx(skb);
+      priv->stats.rx_packets++;
+    }
+    save_flags(flags);
+    cli();
+    /* Enable receiver if RX buffers have been unavailable */
+    if ((priv->rx_count == NUM_RX_BUF) && (priv->status & DCD)) {
+      if (info->type <= TYPE_PI2) outb_p(0, dev->base_addr + PI_DREQ_MASK);
+      write_scc(cmd, R3, RxENABLE | Rx8 | RxCRC_ENAB);
+      if (info->type <= TYPE_PI2) outb_p(1, dev->base_addr + PI_DREQ_MASK);
+    }
+    /* Move tail */
+    priv->rx_tail = i = (i + 1) % NUM_RX_BUF;
+    priv->rx_count--;
+  }
+
+  restore_flags(flags);
+}
+
+
+static void tx_isr(struct device *dev)
+{
+  struct scc_priv *priv = dev->priv;
+  int cmd = priv->cmd;
+  int i = priv->tx_tail, p = priv->tx_ptr;
+
+  /* Suspend TX interrupts if we don't want to send anything.
+     See Figure 2-22. */
+  if (p ==  priv->tx_len[i]) {
+    write_scc(cmd, R0, RES_Tx_P);
+    return;
+  }
+
+  /* Write characters */
+  while ((read_scc(cmd, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) {
+    write_scc(cmd, R8, priv->tx_buf[i][p++]);
+  }
+  priv->tx_ptr = p;
+
+}
+
+
+static void es_isr(struct device *dev)
+{
+  struct scc_priv *priv = dev->priv;
+  struct scc_info *info = priv->info;
+  int i, cmd = priv->cmd;
+  int st, dst, res;
+
+  /* Read status and reset interrupt bit */
+  st = read_scc(cmd, R0);
+  write_scc(cmd, R0, RES_EXT_INT);
+  dst = priv->status ^ st;
+  priv->status = st;
+
+  /* Since the EOM latch is reset automatically, we assume that
+     it has been zero if and only if we are in the TX_ACTIVE state.
+     Otherwise we follow 2.4.9.6. */
+
+  /* Transmit underrun */
+  if ((priv->tx_state == TX_ACTIVE) && (st & TxEOM)) {
+    /* Get remaining bytes */
+    i = priv->tx_tail;
+    if (dev->dma) {
+      disable_dma(dev->dma);
+      clear_dma_ff(dev->dma);
+      res = get_dma_residue(dev->dma);
+    } else {
+      res = priv->tx_len[i] - priv->tx_ptr;
+      if (res) write_scc(cmd, R0, RES_Tx_P);
+      priv->tx_ptr = 0;
+    }
+    /* Remove frame from FIFO */
+    priv->tx_tail = (i + 1) % NUM_TX_BUF;
+    priv->tx_count--;
+    dev->tbusy = 0;
+    /* Check if another frame is available and we are allowed to transmit */
+    if (priv->tx_count && (jiffies - priv->tx_start) < priv->param.txtime) {
+      if (dev->dma) {
+	set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]);
+	set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]);
+	enable_dma(dev->dma);
+      } else {
+	/* If we have an ESCC, we are allowed to write data bytes
+	   immediately. Otherwise we have to wait for the next
+	   TX interrupt. See Figure 2-22. */
+	if (info->chip == Z85230) {
+	  tx_isr(dev);
+	}
+      }
+    } else {
+      /* No frame available. Disable interrupts. */
+      priv->tx_state = TX_SQDELAY;
+      delay(dev, priv->param.sqdelay);
+      write_scc(cmd, R15, DCDIE | CTSIE | SYNCIE);
+      write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+    }
+    /* Update packet statistics */
+    if (res) {
+      priv->stats.tx_errors++;
+      priv->stats.tx_fifo_errors++;
+    } else {
+      priv->stats.tx_packets++;
+    }
+    /* Inform upper layers */
+    mark_bh(NET_BH);
+  }
+
+  /* DCD transition */
+  if ((priv->tx_state < TX_TXDELAY) && (dst & DCD)) {
+    /* Transmitter state change */
+    priv->tx_state = TX_OFF;
+    /* Enable or disable receiver */
+    if (st & DCD) {
+      if (dev->dma) {
+	/* Program DMA controller */
+	disable_dma(dev->dma);
+	clear_dma_ff(dev->dma);
+	set_dma_mode(dev->dma, DMA_MODE_READ);
+	set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
+	set_dma_count(dev->dma, BUF_SIZE);
+	enable_dma(dev->dma);
+	/* Configure PackeTwin DMA */
+	if (info->type == TYPE_TWIN) {
+	  outb_p((dev->dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
+		 dev->base_addr + TWIN_DMA_CFG);
+	}
+	/* Sp. cond. intr. only, ext int enable */
+	write_scc(cmd, R1, EXT_INT_ENAB | INT_ERR_Rx |
+		  WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
+      } else {
+	/* Intr. on all Rx characters and Sp. cond., ext int enable */
+	write_scc(cmd, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
+		  WT_FN_RDYFN);
+      }
+      if (priv->rx_count < NUM_RX_BUF) {
+	/* Enable receiver */
+	write_scc(cmd, R3, RxENABLE | Rx8 | RxCRC_ENAB);
+      }
+    } else {
+      /* Disable DMA */
+      if (dev->dma) disable_dma(dev->dma);
+      /* Disable receiver */
+      write_scc(cmd, R3, Rx8);
+      /* DMA disable, RX int disable, Ext int enable */
+      write_scc(cmd, R1, EXT_INT_ENAB | WT_RDY_RT | WT_FN_RDYFN);
+      /* Transmitter state change */
+      if (random() > priv->param.persist)
+	delay(dev, priv->param.slottime);
+      else {
+	if (priv->tx_count) {
+	  priv->tx_state = TX_TXDELAY;
+	  write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
+	  priv->tx_start = jiffies;
+	  delay(dev, priv->param.txdelay);
+	} else {
+	  priv->tx_state = TX_IDLE;
+	}
+      }
+    }
+  }
+
+  /* CTS transition */
+  if ((info->type <= TYPE_PI2) && (dst & CTS) && (~st & CTS)) {
+    /* Timer has expired */
+    tm_isr(dev);
+  }
+
+  /* /SYNC/HUNT transition */
+  if ((dst & SYNC_HUNT) && (~st & SYNC_HUNT)) {
+    /* Reset current frame and clear RX FIFO */
+    while (read_scc(cmd, R0) & Rx_CH_AV) read_scc(cmd, R8);
+    priv->rx_over = 0;
+    if (dev->dma) {
+      disable_dma(dev->dma);
+      clear_dma_ff(dev->dma);
+      set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
+      set_dma_count(dev->dma, BUF_SIZE);
+      enable_dma(dev->dma);
+    } else {
+      priv->rx_ptr = 0;
+    }
+  }
+}
+
+
+static void tm_isr(struct device *dev)
+{
+  struct scc_priv *priv = dev->priv;
+  struct scc_info *info = priv->info;
+  int cmd = priv->cmd;
+
+  switch (priv->tx_state) {
+  case TX_OFF:
+    if (~priv->status & DCD) {
+      if (random() > priv->param.persist) delay(dev, priv->param.slottime);
+      else {
+	if (priv->tx_count) {
+	  priv->tx_state = TX_TXDELAY;
+	  write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
+	  priv->tx_start = jiffies;
+	  delay(dev, priv->param.txdelay);
+	} else {
+	  priv->tx_state = TX_IDLE;
+	}
+      }
+    }
+    break;
+  case TX_TXDELAY:
+    priv->tx_state = TX_ACTIVE;
+    if (dev->dma) {
+      /* Program DMA controller */
+      disable_dma(dev->dma);
+      clear_dma_ff(dev->dma);
+      set_dma_mode(dev->dma, DMA_MODE_WRITE);
+      set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]);
+      set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]);
+      enable_dma(dev->dma);
+      /* Configure PackeTwin DMA */
+      if (info->type == TYPE_TWIN) {
+	outb_p((dev->dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
+	       dev->base_addr + TWIN_DMA_CFG);
+      }
+      /* Enable interrupts and DMA. On the PackeTwin, the DTR//REQ pin
+	 is used for TX DMA requests, but we enable the WAIT/DMA request
+	 pin, anyway */
+      write_scc(cmd, R15, TxUIE | DCDIE | CTSIE | SYNCIE);
+      write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
+    } else {
+      write_scc(cmd, R15, TxUIE | DCDIE | CTSIE | SYNCIE);
+      write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
+      tx_isr(dev);
+    }
+    if (info->chip == Z8530) write_scc(cmd, R0, RES_EOM_L);
+    break;
+  case TX_SQDELAY:
+    /* Disable transmitter */
+    write_scc(cmd, R5, TxCRC_ENAB | Tx8);
+    /* Transmitter state change: Switch to TX_OFF and wait at least
+       1 slottime. */
+    priv->tx_state = TX_OFF;    
+    if (~priv->status & DCD) delay(dev, priv->param.waittime);
+  }
+}
+
+
+static inline void delay(struct device *dev, int t)
+{
+  struct scc_priv *priv = dev->priv;
+  int tmr = priv->tmr;
+
+  outb_p(t & 0xFF, tmr);
+  outb_p((t >> 8) & 0xFF, tmr);
+}
+
+
+static inline unsigned char random(void)
+{
+  /* See "Numerical Recipes in C", second edition, p. 284 */
+  rand = rand * 1664525L + 1013904223L;
+  return (unsigned char) (rand >> 24);
+}
+
+
diff -u --recursive --new-file v2.1.71/linux/drivers/net/e2100.c linux/drivers/net/e2100.c
--- v2.1.71/linux/drivers/net/e2100.c	Mon Dec  1 12:04:12 1997
+++ linux/drivers/net/e2100.c	Tue Dec  9 09:49:58 1997
@@ -44,6 +44,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
diff -u --recursive --new-file v2.1.71/linux/drivers/net/eql.c linux/drivers/net/eql.c
--- v2.1.71/linux/drivers/net/eql.c	Sat Nov 29 11:25:10 1997
+++ linux/drivers/net/eql.c	Tue Dec  9 09:49:58 1997
@@ -329,7 +329,7 @@
 
 static int eql_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
 {  
-	if(!suser() && cmd!=EQL_GETMASTRCFG && cmd!=EQL_GETSLAVECFG)
+	if(cmd!=EQL_GETMASTRCFG && cmd!=EQL_GETSLAVECFG && !suser())
 	  	return -EPERM;
 	switch (cmd)
 	{
diff -u --recursive --new-file v2.1.71/linux/drivers/net/hamradio/Config.in linux/drivers/net/hamradio/Config.in
--- v2.1.71/linux/drivers/net/hamradio/Config.in	Thu Dec  4 14:53:55 1997
+++ linux/drivers/net/hamradio/Config.in	Tue Dec  9 09:49:58 1997
@@ -25,8 +25,6 @@
       tristate 'Serial port KISS driver' CONFIG_MKISS
 #     tristate 'Serial port 6PACK driver' CONFIG_6PACK
       tristate 'BPQ Ethernet driver' CONFIG_BPQETHER
-      tristate 'Gracilis PackeTwin driver' CONFIG_PT
-      tristate 'Ottawa PI and PI2 driver' CONFIG_PI
     
       tristate 'Z8530 SCC driver' CONFIG_SCC
       if [ "$CONFIG_SCC" != "n" ]; then
diff -u --recursive --new-file v2.1.71/linux/drivers/net/hamradio/soundmodem/sm_sbc.c linux/drivers/net/hamradio/soundmodem/sm_sbc.c
--- v2.1.71/linux/drivers/net/hamradio/soundmodem/sm_sbc.c	Thu Dec  4 14:53:55 1997
+++ linux/drivers/net/hamradio/soundmodem/sm_sbc.c	Tue Dec  9 09:49:58 1997
@@ -32,6 +32,7 @@
 #include <asm/dma.h>
 #include <linux/ioport.h>
 #include <linux/soundmodem.h>
+#include <linux/delay.h>
 #include "sm.h"
 #include "smdma.h"
 
@@ -144,8 +145,7 @@
 	int i;
 
 	outb(1, DSP_RESET(dev->base_addr));
-	for (i = 0; i < 0x100; i++)
-		SLOW_DOWN_IO;
+	udelay(300);
 	outb(0, DSP_RESET(dev->base_addr));
 	for (i = 0; i < 0xffff; i++)
 		if (inb(DSP_DATA_AVAIL(dev->base_addr)) & 0x80)
diff -u --recursive --new-file v2.1.71/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- v2.1.71/linux/drivers/net/ne.c	Wed Nov 12 13:34:26 1997
+++ linux/drivers/net/ne.c	Tue Dec  9 09:49:58 1997
@@ -665,9 +665,7 @@
     outb_p(0x00, nic_base + EN0_RSARHI);
     outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
     /* Make certain that the dummy read has occurred. */
-    SLOW_DOWN_IO;
-    SLOW_DOWN_IO;
-    SLOW_DOWN_IO;
+    udelay(6);
 #endif
 
     outb_p(ENISR_RDC, nic_base + EN0_ISR);
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v2.1.71/linux/drivers/sound/Config.in	Sat Nov 29 11:25:10 1997
+++ linux/drivers/sound/Config.in	Tue Dec  9 09:49:59 1997
@@ -1,13 +1,13 @@
 dep_tristate 'ProAudioSpectrum 16 support' CONFIG_PAS $CONFIG_SOUND
-dep_tristate '100%% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SB $CONFIG_SOUND
+dep_tristate '100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SB $CONFIG_SOUND
 dep_tristate 'Generic OPL2/OPL3 FM synthesizer support' CONFIG_ADLIB $CONFIG_SOUND
 dep_tristate 'Gravis Ultrasound support' CONFIG_GUS $CONFIG_SOUND
-dep_tristate 'MPU-401 support (NOT for SB16)' CONFIG_MPU401 $CONFIG_SOUND
-dep_tristate 'PSS (ECHO-ADI2111) support' CONFIG_PSS $CONFIG_SOUND
 if [ "$CONFIG_GUS" != "n" ]; then
 	bool '16 bit sampling option of GUS (_NOT_ GUS MAX)' CONFIG_GUS16 
 	bool 'GUS MAX support' CONFIG_GUSMAX
 fi
+dep_tristate 'MPU-401 support (NOT for SB16)' CONFIG_MPU401 $CONFIG_SOUND
+dep_tristate 'PSS (ECHO-ADI2111) support' CONFIG_PSS $CONFIG_SOUND
 dep_tristate 'Microsoft Sound System support' CONFIG_MSS $CONFIG_SOUND
 dep_tristate 'Ensoniq SoundScape support' CONFIG_SSCAPE $CONFIG_SOUND
 dep_tristate 'MediaTrix AudioTrix Pro support' CONFIG_TRIX $CONFIG_SOUND
@@ -18,294 +18,125 @@
 dep_tristate 'SoftOSS software wave table engine' CONFIG_SOFTOSS $CONFIG_SOUND
 dep_tristate 'FM synthesizer (YM3812/OPL-3) support' CONFIG_YM3812 $CONFIG_SOUND
 
-if [ "$CONFIG_AEDSP16" = "y" ]; then
-hex 'I/O base for Audio Excel DSP 16 220 or 240' AEDSP16_BASE 220
-fi
-
-if [ "$CONFIG_SB" = "y" ]; then
-hex 'I/O base for SB Check from manual of the card' SBC_BASE 220
-fi
-
-if [ "$CONFIG_SB" = "y" ]; then
-int 'Sound Blaster IRQ Check from manual of the card' SBC_IRQ 7
-fi
-
-if [ "$CONFIG_SB" = "y" ]; then
-int 'Sound Blaster DMA 0, 1 or 3' SBC_DMA 1
-fi
-
-if [ "$CONFIG_SB" = "y" ]; then
-int 'Sound Blaster 16 bit DMA (SB16, Jazz16, SMW) 5, 6 or 7 (use 1 for 8 bit cards)' SB_DMA2 5
-fi
-
-if [ "$CONFIG_SB" = "y" ]; then
-hex 'MPU401 I/O base of SB16, Jazz16 and ES1688 Check from manual of the card' SB_MPU_BASE 330
-fi
-
-
-if [ "$CONFIG_SB" = "y" ]; then
-comment 'MPU401 IRQ is only required with Jazz16, SM Wave and ESS1688.'
-fi
-
-
-if [ "$CONFIG_SB" = "y" ]; then
-comment 'Enter -1 to the following question if you have something else such as SB16/32.'
-fi
-
-if [ "$CONFIG_SB" = "y" ]; then
-int 'SB MPU401 IRQ (Jazz16, SM Wave and ES1688) Check from manual of the card' SB_MPU_IRQ -1
-fi
-
-if [ "$CONFIG_PAS" = "y" ]; then
-int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' PAS_IRQ 10
-fi
-
-if [ "$CONFIG_PAS" = "y" ]; then
-int 'PAS16 DMA 0, 1, 3, 5, 6 or 7' PAS_DMA 3
-fi
-
-if [ "$CONFIG_GUS" = "y" ]; then
-hex 'I/O base for GUS 210, 220, 230, 240, 250 or 260' GUS_BASE 220
-fi
-
-if [ "$CONFIG_GUS" = "y" ]; then
-int 'GUS IRQ 3, 5, 7, 9, 11, 12 or 15' GUS_IRQ 15
-fi
-
-if [ "$CONFIG_GUS" = "y" ]; then
-int 'GUS DMA 1, 3, 5, 6 or 7' GUS_DMA 6
-fi
-
-if [ "$CONFIG_GUS" = "y" ]; then
-int 'Second DMA channel for GUS 1, 3, 5, 6 or 7' GUS_DMA2 -1
-fi
-
-if [ "$CONFIG_GUS16" = "y" ]; then
-hex 'I/O base for the 16 bit daughtercard of GUS 530, 604, E80 or F40' GUS16_BASE 530
+if [ "$CONFIG_AEDSP16" = "y" -o "$CONFIG_AEDSP16" = "m" ]; then
+    hex 'I/O base for Audio Excel DSP 16 220 or 240' AEDSP16_BASE 220
 fi
 
-if [ "$CONFIG_GUS16" = "y" ]; then
-int 'GUS 16 bit daughtercard IRQ 3, 4, 5, 7, or 9' GUS16_IRQ 7
+if [ "$CONFIG_SB" = "y" -o "$CONFIG_SB" = "m" ]; then
+    hex 'I/O base for SB Check from manual of the card' SBC_BASE 220
+    int 'Sound Blaster IRQ Check from manual of the card' SBC_IRQ 7
+    int 'Sound Blaster DMA 0, 1 or 3' SBC_DMA 1
+    int 'Sound Blaster 16 bit DMA (SB16, Jazz16, SMW) 5, 6 or 7 (use 1 for 8 bit cards)' SB_DMA2 5
+    hex 'MPU401 I/O base of SB16, Jazz16 and ES1688 Check from manual of the card' SB_MPU_BASE 330
+    comment 'MPU401 IRQ is only required with Jazz16, SM Wave and ESS1688.'
+    comment 'Enter -1 to the following question if you have something else such as SB16/32.'
+    int 'SB MPU401 IRQ (Jazz16, SM Wave and ES1688) Check from manual of the card' SB_MPU_IRQ -1
+fi
+
+if [ "$CONFIG_PAS" = "y" -o "$CONFIG_PAS" = "m" ]; then
+    int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' PAS_IRQ 10
+    int 'PAS16 DMA 0, 1, 3, 5, 6 or 7' PAS_DMA 3
+fi
+
+if [ "$CONFIG_GUS" = "y" -o "$CONFIG_GUS" = "m" ]; then
+    hex 'I/O base for GUS 210, 220, 230, 240, 250 or 260' GUS_BASE 220
+    int 'GUS IRQ 3, 5, 7, 9, 11, 12 or 15' GUS_IRQ 15
+    int 'GUS DMA 1, 3, 5, 6 or 7' GUS_DMA 6
+    int 'Second DMA channel for GUS 1, 3, 5, 6 or 7' GUS_DMA2 -1
 fi
 
 if [ "$CONFIG_GUS16" = "y" ]; then
-int 'GUS DMA 0, 1 or 3' GUS16_DMA 3
-fi
-
-if [ "$CONFIG_MPU401" = "y" ]; then
-hex 'I/O base for MPU401 Check from manual of the card' MPU_BASE 330
-fi
-
-if [ "$CONFIG_MPU401" = "y" ]; then
-int 'MPU401 IRQ Check from manual of the card' MPU_IRQ 9
-fi
-
-
-if [ "$CONFIG_MAUI" = "y" ]; then
-comment 'ERROR! You have to use old sound configuration method with Maui.'
-fi
-
-if [ "$CONFIG_MAUI" = "y" ]; then
-hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' MAUI_BASE 330
-fi
-
-if [ "$CONFIG_MAUI" = "y" ]; then
-int 'Maui IRQ 5, 9, 12 or 15' MAUI_IRQ 9
-fi
-
-if [ "$CONFIG_UART6850" = "y" ]; then
-hex 'I/O base for UART 6850 MIDI port (Unknown)' U6850_BASE 0
-fi
-
-if [ "$CONFIG_UART6850" = "y" ]; then
-int 'UART6850 IRQ (Unknown)' U6850_IRQ -1
-fi
-
-
-if [ "$CONFIG_PSS" = "y" ]; then
-comment 'ERROR! You have to use old sound configuration method with PSS cards.'
-fi
-
-if [ "$CONFIG_PSS" = "y" ]; then
-hex 'PSS I/O base 220 or 240' PSS_BASE 220
-fi
-
-if [ "$CONFIG_PSS" = "y" ]; then
-hex 'PSS audio I/O base 530, 604, E80 or F40' PSS_MSS_BASE 530
-fi
-
-if [ "$CONFIG_PSS" = "y" ]; then
-int 'PSS audio IRQ 7, 9, 10 or 11' PSS_MSS_IRQ 11
-fi
-
-if [ "$CONFIG_PSS" = "y" ]; then
-int 'PSS audio DMA 0, 1 or 3' PSS_MSS_DMA 3
-fi
-
-if [ "$CONFIG_PSS" = "y" ]; then
-hex 'PSS MIDI I/O base ' PSS_MPU_BASE 330
-fi
-
-if [ "$CONFIG_PSS" = "y" ]; then
-int 'PSS MIDI IRQ 3, 4, 5, 7 or 9' PSS_MPU_IRQ 9
-fi
-
-if [ "$CONFIG_MSS" = "y" ]; then
-hex 'MSS/WSS I/O base 530, 604, E80 or F40' MSS_BASE 530
-fi
-
-if [ "$CONFIG_MSS" = "y" ]; then
-int 'MSS/WSS IRQ 7, 9, 10 or 11' MSS_IRQ 11
-fi
-
-if [ "$CONFIG_MSS" = "y" ]; then
-int 'MSS/WSS DMA 0, 1 or 3' MSS_DMA 3
+    hex 'I/O base for the 16 bit daughtercard of GUS 530, 604, E80 or F40' GUS16_BASE 530
+    int 'GUS 16 bit daughtercard IRQ 3, 4, 5, 7, or 9' GUS16_IRQ 7
+    int 'GUS DMA 0, 1 or 3' GUS16_DMA 3
+fi
+
+if [ "$CONFIG_MPU401" = "y" -o "$CONFIG_MPU401" = "m" ]; then
+    hex 'I/O base for MPU401 Check from manual of the card' MPU_BASE 330
+    int 'MPU401 IRQ Check from manual of the card' MPU_IRQ 9
+fi
+
+if [ "$CONFIG_MAUI" = "y" -o "$CONFIG_MAUI" = "M" ]; then
+    comment 'ERROR! You have to use old sound configuration method with Maui.'
+    hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' MAUI_BASE 330
+    int 'Maui IRQ 5, 9, 12 or 15' MAUI_IRQ 9
+fi
+
+if [ "$CONFIG_UART6850" = "y" -o "$CONFIG_UART6850" = "m" ]; then
+    hex 'I/O base for UART 6850 MIDI port (Unknown)' U6850_BASE 0
+    int 'UART6850 IRQ (Unknown)' U6850_IRQ -1
+fi
+
+if [ "$CONFIG_PSS" = "y" -o "$CONFIG_PSS" = "y" ]; then
+    comment 'ERROR! You have to use old sound configuration method with PSS cards.'
+    hex 'PSS I/O base 220 or 240' PSS_BASE 220
+    hex 'PSS audio I/O base 530, 604, E80 or F40' PSS_MSS_BASE 530
+    int 'PSS audio IRQ 7, 9, 10 or 11' PSS_MSS_IRQ 11
+    int 'PSS audio DMA 0, 1 or 3' PSS_MSS_DMA 3
+    hex 'PSS MIDI I/O base ' PSS_MPU_BASE 330
+    int 'PSS MIDI IRQ 3, 4, 5, 7 or 9' PSS_MPU_IRQ 9
+fi
+
+if [ "$CONFIG_MSS" = "y" -o "$CONFIG_MSS" = "m" ]; then
+    hex 'MSS/WSS I/O base 530, 604, E80 or F40' MSS_BASE 530
+    int 'MSS/WSS IRQ 7, 9, 10 or 11' MSS_IRQ 11
+    int 'MSS/WSS DMA 0, 1 or 3' MSS_DMA 3
+    int 'MSS/WSS second DMA (if possible) 0, 1 or 3' MSS_DMA2 -1
+fi
+
+if [ "$CONFIG_SSCAPE" = "y" -o "$CONFIG_SSCAPE" = "m" ]; then
+    hex 'SoundScape MIDI I/O base 320, 330, 340 or 350' SSCAPE_BASE 330
+    int 'SoundScape MIDI IRQ ' SSCAPE_IRQ 9
+    int 'SoundScape initialization DMA 0, 1 or 3' SSCAPE_DMA 3
+    hex 'SoundScape audio I/O base 534, 608, E84 or F44' SSCAPE_MSS_BASE 534
+    int 'SoundScape audio IRQ 7, 9, 10 or 11' SSCAPE_MSS_IRQ 11
+fi
+
+if [ "$CONFIG_TRIX" = "y" -o "$CONFIG_TRIX" = "m" ]; then
+    comment 'ERROR! You have to use old sound configuration method with OPL3-SA1.'
+    hex 'OPL3-SA1 audio I/O base 530, 604, E80 or F40' TRIX_BASE 530
+    int 'OPL3-SA1 audio IRQ 7, 9, 10 or 11' TRIX_IRQ 11
+    int 'OPL3-SA1 audio DMA 0, 1 or 3' TRIX_DMA 0
+    int 'OPL3-SA1 second (duplex) DMA 0, 1 or 3' TRIX_DMA2 3
+    hex 'OPL3-SA1 MIDI I/O base 330, 370, 3B0 or 3F0' TRIX_MPU_BASE 330
+    int 'OPL3-SA1 MIDI IRQ 3, 4, 5, 7 or 9' TRIX_MPU_IRQ 9
+    hex 'OPL3-SA1 SB I/O base 220, 210, 230, 240, 250, 260 or 270' TRIX_SB_BASE 220
+    int 'OPL3-SA1 SB IRQ 3, 4, 5 or 7' TRIX_SB_IRQ 7
+    int 'OPL3-SA1 SB DMA 1 or 3' TRIX_SB_DMA 1
+fi
+
+if [ "$CONFIG_OPL3SA1" = "y" -o "$CONFIG_OPL3SA1" = "m" ]; then
+    hex 'OPL3-SA1 audio I/O base 530, 604, E80 or F40' OPL3SA1_BASE 530
+    int 'OPL3-SA1 audio IRQ 7, 9, 10 or 11' OPL3SA1_IRQ 11
+    int 'OPL3-SA1 audio DMA 0, 1 or 3' OPL3SA1_DMA 0
+    int 'OPL3-SA1 second (duplex) DMA 0, 1 or 3' OPL3SA1_DMA2 3
+    hex 'OPL3-SA1 MIDI I/O base 330, 370, 3B0 or 3F0' OPL3SA1_MPU_BASE 330
+    int 'OPL3-SA1 MIDI IRQ 3, 4, 5, 7 or 9' OPL3SA1_MPU_IRQ 9
+fi
+
+if [ "$CONFIG_CS4232" = "y" -o "$CONFIG_CS4232" = "m" ]; then
+    hex 'CS4232 audio I/O base 530, 604, E80 or F40' CS4232_BASE 530
+    int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CS4232_IRQ 11
+    int 'CS4232 audio DMA 0, 1 or 3' CS4232_DMA 0
+    int 'CS4232 second (duplex) DMA 0, 1 or 3' CS4232_DMA2 3
+    hex 'CS4232 MIDI I/O base 330, 370, 3B0 or 3F0' CS4232_MPU_BASE 330
+    int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CS4232_MPU_IRQ 9
+fi
+
+if [ "$CONFIG_MAD16" = "y" -o "$CONFIG_MAD16" = "m" ]; then
+    hex 'MAD16 audio I/O base 530, 604, E80 or F40' MAD16_BASE 530
+    int 'MAD16 audio IRQ 7, 9, 10 or 11' MAD16_IRQ 11
+    int 'MAD16 audio DMA 0, 1 or 3' MAD16_DMA 3
+    int 'MAD16 second (duplex) DMA 0, 1 or 3' MAD16_DMA2 0
+    hex 'MAD16 MIDI I/O base 300, 310, 320 or 330 (0 disables)' MAD16_MPU_BASE 330
+    int 'MAD16 MIDI IRQ 5, 7, 9 or 10' MAD16_MPU_IRQ 9
+fi
+
+if [ "$CONFIG_SOFTOSS" = "y" -o "$CONFIG_SOFTOSS" = "m" ]; then
+    int 'Sampling rate for SoftOSS 8000 to 48000' SOFTOSS_RATE 22050
+    int 'Max # of concurrent voices for SoftOSS 4 to 32' SOFTOSS_VOICES 32
 fi
 
-if [ "$CONFIG_MSS" = "y" ]; then
-int 'MSS/WSS second DMA (if possible) 0, 1 or 3' MSS_DMA2 -1
-fi
-
-if [ "$CONFIG_SSCAPE" = "y" ]; then
-hex 'SoundScape MIDI I/O base 320, 330, 340 or 350' SSCAPE_BASE 330
-fi
-
-if [ "$CONFIG_SSCAPE" = "y" ]; then
-int 'SoundScape MIDI IRQ ' SSCAPE_IRQ 9
-fi
-
-if [ "$CONFIG_SSCAPE" = "y" ]; then
-int 'SoundScape initialization DMA 0, 1 or 3' SSCAPE_DMA 3
-fi
-
-if [ "$CONFIG_SSCAPE" = "y" ]; then
-hex 'SoundScape audio I/O base 534, 608, E84 or F44' SSCAPE_MSS_BASE 534
-fi
-
-if [ "$CONFIG_SSCAPE" = "y" ]; then
-int 'SoundScape audio IRQ 7, 9, 10 or 11' SSCAPE_MSS_IRQ 11
-fi
-
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-comment 'ERROR! You have to use old sound configuration method with OPL3-SA1.'
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-hex 'OPL3-SA1 audio I/O base 530, 604, E80 or F40' TRIX_BASE 530
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-int 'OPL3-SA1 audio IRQ 7, 9, 10 or 11' TRIX_IRQ 11
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-int 'OPL3-SA1 audio DMA 0, 1 or 3' TRIX_DMA 0
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-int 'OPL3-SA1 second (duplex) DMA 0, 1 or 3' TRIX_DMA2 3
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-hex 'OPL3-SA1 MIDI I/O base 330, 370, 3B0 or 3F0' TRIX_MPU_BASE 330
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-int 'OPL3-SA1 MIDI IRQ 3, 4, 5, 7 or 9' TRIX_MPU_IRQ 9
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-hex 'OPL3-SA1 SB I/O base 220, 210, 230, 240, 250, 260 or 270' TRIX_SB_BASE 220
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-int 'OPL3-SA1 SB IRQ 3, 4, 5 or 7' TRIX_SB_IRQ 7
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-int 'OPL3-SA1 SB DMA 1 or 3' TRIX_SB_DMA 1
-fi
-
-if [ "$CONFIG_OPL3SA1" = "y" ]; then
-hex 'OPL3-SA1 audio I/O base 530, 604, E80 or F40' OPL3SA1_BASE 530
-fi
-
-if [ "$CONFIG_OPL3SA1" = "y" ]; then
-int 'OPL3-SA1 audio IRQ 7, 9, 10 or 11' OPL3SA1_IRQ 11
-fi
-
-if [ "$CONFIG_OPL3SA1" = "y" ]; then
-int 'OPL3-SA1 audio DMA 0, 1 or 3' OPL3SA1_DMA 0
-fi
-
-if [ "$CONFIG_OPL3SA1" = "y" ]; then
-int 'OPL3-SA1 second (duplex) DMA 0, 1 or 3' OPL3SA1_DMA2 3
-fi
-
-if [ "$CONFIG_OPL3SA1" = "y" ]; then
-hex 'OPL3-SA1 MIDI I/O base 330, 370, 3B0 or 3F0' OPL3SA1_MPU_BASE 330
-fi
-
-if [ "$CONFIG_OPL3SA1" = "y" ]; then
-int 'OPL3-SA1 MIDI IRQ 3, 4, 5, 7 or 9' OPL3SA1_MPU_IRQ 9
-fi
-
-if [ "$CONFIG_CS4232" = "y" ]; then
-hex 'CS4232 audio I/O base 530, 604, E80 or F40' CS4232_BASE 530
-fi
-
-if [ "$CONFIG_CS4232" = "y" ]; then
-int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CS4232_IRQ 11
-fi
-
-if [ "$CONFIG_CS4232" = "y" ]; then
-int 'CS4232 audio DMA 0, 1 or 3' CS4232_DMA 0
-fi
-
-if [ "$CONFIG_CS4232" = "y" ]; then
-int 'CS4232 second (duplex) DMA 0, 1 or 3' CS4232_DMA2 3
-fi
-
-if [ "$CONFIG_CS4232" = "y" ]; then
-hex 'CS4232 MIDI I/O base 330, 370, 3B0 or 3F0' CS4232_MPU_BASE 330
-fi
-
-if [ "$CONFIG_CS4232" = "y" ]; then
-int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CS4232_MPU_IRQ 9
-fi
-
-if [ "$CONFIG_MAD16" = "y" ]; then
-hex 'MAD16 audio I/O base 530, 604, E80 or F40' MAD16_BASE 530
-fi
-
-if [ "$CONFIG_MAD16" = "y" ]; then
-int 'MAD16 audio IRQ 7, 9, 10 or 11' MAD16_IRQ 11
-fi
-
-if [ "$CONFIG_MAD16" = "y" ]; then
-int 'MAD16 audio DMA 0, 1 or 3' MAD16_DMA 3
-fi
-
-if [ "$CONFIG_MAD16" = "y" ]; then
-int 'MAD16 second (duplex) DMA 0, 1 or 3' MAD16_DMA2 0
-fi
-
-if [ "$CONFIG_MAD16" = "y" ]; then
-hex 'MAD16 MIDI I/O base 300, 310, 320 or 330 (0 disables)' MAD16_MPU_BASE 330
-fi
-
-if [ "$CONFIG_MAD16" = "y" ]; then
-int 'MAD16 MIDI IRQ 5, 7, 9 or 10' MAD16_MPU_IRQ 9
-fi
-
-if [ "$CONFIG_SOFTOSS" = "y" ]; then
-int 'Sampling rate for SoftOSS 8000 to 48000' SOFTOSS_RATE 22050
-fi
-
-if [ "$CONFIG_SOFTOSS" = "y" ]; then
-int 'Max # of concurrent voices for SoftOSS 4 to 32' SOFTOSS_VOICES 32
-fi
 #
 $MAKE -C drivers/sound kernelconfig || exit 1
 bool 'Additional low level drivers' CONFIG_LOWLEVEL_SOUND
@@ -319,7 +150,7 @@
       comment 'SC-6600 Audio Cards have no jumper switches at all'
       bool 'SC-6600 based audio cards (new Audio Excel DSP 16)' CONFIG_SC6600
 
-      if [ "$CONFIG_SB" = "y" -a "$CONFIG_AEDSP16_MSS" != "y" ]; then
+      if [ "$CONFIG_SB" = "y" -o "$CONFIG_SB" = "m" -a "$CONFIG_AEDSP16_MSS" != "y" ]; then
          bool 'Audio Excel DSP 16 (SBPro emulation)' CONFIG_AEDSP16_SBPRO
          if [ "$CONFIG_AEDSP16_SBPRO" = "y" ]; then
 	    comment 'Audio Excel DSP 16 [Sound Blaster Pro]'
@@ -331,7 +162,7 @@
          fi
       fi
    
-      if [ "$CONFIG_MSS" = "y" -a "$CONFIG_AEDSP16_SBPRO" != "y" ]; then
+      if [ "$CONFIG_MSS" = "y" -o "$CONFIG_MSS" = "m" -a "$CONFIG_AEDSP16_SBPRO" != "y" ]; then
          bool 'Audio Excel DSP 16 (MSS emulation)' CONFIG_AEDSP16_MSS
          if [ "$CONFIG_AEDSP16_MSS" = "y" ]; then
 	    comment 'Audio Excel DSP 16 [Microsoft Sound System]'
@@ -342,7 +173,7 @@
          fi
       fi
 
-      if [ "$CONFIG_MPU401" = "y" ]; then
+      if [ "$CONFIG_MPU401" = "y" -o "$CONFIG_MPU401" = "m" ]; then
          bool 'Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401
          if [ "$CONFIG_AEDSP16_MPU401" = "y" ]; then
 	    comment 'Audio Excel DSP 16 [MPU-401]'
@@ -365,3 +196,4 @@
 
    fi
 fi
+
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v2.1.71/linux/drivers/sound/Makefile	Mon Dec  1 12:04:13 1997
+++ linux/drivers/sound/Makefile	Tue Dec  9 09:49:59 1997
@@ -35,7 +35,7 @@
 
 ifeq (.defines,$(wildcard .defines))
 include .defines
-include .objects
+#include .objects
 endif
 
 TARGET_OS=linux
@@ -66,25 +66,20 @@
   LX_OBJS += midi_synth.o
 endif
 
-ifeq ($(CONFIG_MIDI),y)
-  L_OBJS += midibuf.o
-  LX_OBJS += midi_synth.o
-endif
-
 #ifeq ($(CONFIG_AUDIO),y)
 #L_OBJS += dmabuf.o
 #endif
 
 ifeq ($(CONFIG_YM3812),y)
-LX_OBJS += opl3.o
+LX_OBJS += adlib_card.o opl3.o
 else
   ifeq ($(CONFIG_YM3812),m)
-  MX_OBJS += opl3.o
+  MX_OBJS += adlib_card.o opl3.o
   endif
 endif
 
 ifeq ($(CONFIG_PAS),y)
-L_OBJS += pas2_card.c pas2_midi.c pas2_mixer.c pas2_pcm.c
+L_OBJS += pas2.o
 else
   ifeq ($(CONFIG_PAS),m)
   M_OBJS += pas2.o
@@ -92,7 +87,7 @@
 endif
 
 ifeq ($(CONFIG_GUS),y)
-L_OBJS += gus_card.c gus_midi.c gus_vol.c gus_wave.c ics2101.c
+L_OBJS += gus.o
 else
   ifeq ($(CONFIG_GUS),m)
   M_OBJS += gus.o
@@ -105,7 +100,8 @@
 else
   ifeq ($(CONFIG_SB),m)
   M_OBJS += sb.o
-  MX_OBJS += sb_card.o uart401.o
+  MX_OBJS += uart401.o
+  MIX_OBJS += sb_card.o
   endif
 endif
 
@@ -130,6 +126,14 @@
 else
   ifeq ($(CONFIG_MPU401),m)
   MX_OBJS += mpu401.o
+  else
+    ifeq ($(CONFIG_MPU_EMU),y)
+    LX_OBJS += mpu401.o
+    else
+      ifeq ($(CONFIG_MPU_EMU),m)
+      MX_OBJS += mpu401.o
+      endif
+    endif
   endif
 endif
 
@@ -205,6 +209,16 @@
    endif
 endif
 
+ifeq ($(CONFIG_OPL3SA1),y)
+L_OBJS += opl3sa.o
+LX_OBJS += ad1848.o
+else
+  ifeq ($(CONFIG_OPL3SA1),m)
+  M_OBJS += opl3sa.o
+  MX_OBJS += ad1848.o
+  endif
+endif
+
 include $(TOPDIR)/Rules.make
 
 softoss2.o:	softoss.o softoss_rs.o
@@ -247,5 +261,14 @@
 	@echo Compiling Sound Driver v $(VERSION) for Linux
 
 mkscript:
+
+config: configure
+	@$(MAKE) setup
+	@./configure > local.h
+	@echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h
+	@echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h
+#	@echo \#define SOUND_CONFIG_HOST \"`hostname`\" >> local.h 2>/dev/null
+#	@echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null
+	@echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h
 
 endif
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/Readme linux/drivers/sound/Readme
--- v2.1.71/linux/drivers/sound/Readme	Wed Nov 12 13:34:26 1997
+++ linux/drivers/sound/Readme	Tue Dec  9 09:49:59 1997
@@ -2,7 +2,7 @@
 ----------------------------------
 
 Most up to date information about this driver is available from 
-http://www.4front-tech.com/ossfree.
+http://www.opensound.com/ossfree.
 
 
 
@@ -11,7 +11,7 @@
 date but still very useful. Information about bug fixes and such things
 is available from the web page (see above).
 
-Please check http://www.4front-tech.com/pguide for more info about programming
+Please check http://www.opensound.com/pguide for more info about programming
 with OSS API.
 
    ====================================================
@@ -20,7 +20,7 @@
 
 Packages "snd-util-3.8.tar.gz" and "snd-data-0.1.tar.Z"
 contain useful utilities to be used with this driver.
-See http://www.4front-tech.com/ossfree/getting.html for
+See http://www.opensound.com/ossfree/getting.html for
 download instructions.
 
 If you are looking for the installation instructions, please
@@ -31,7 +31,7 @@
 
 See Readme.cards.
 
-Please check http://www.4front-tech.com/ossfree if you don't find
+Please check http://www.opensound.com/ossfree if you don't find
 your soundcard there.
 
 Contributors
@@ -86,7 +86,7 @@
 very latest (development) version of OSS/Free since the change may already be
 implemented there. In general it's major waste of time to try to improve
 several months old version. Information about the latest version can be found
-from http://www.4front-tech.com/ossfree. In general there is no point in
+from http://www.opensound.com/ossfree. In general there is no point in
 sending me patches relative to production kernels.
 
 Sponsors etc.
@@ -123,7 +123,7 @@
 =========================
 
 Read the sound HOWTO (sunsite.unc.edu:/pub/Linux/docs/...?).
-Also look at the home page (http://www.4front-tech.com/ossfree). It may
+Also look at the home page (http://www.opensound.com/ossfree). It may
 contain info about some recent bug fixes.
 
 It's likely that you have some problems when trying to use the sound driver
@@ -177,8 +177,8 @@
 Hannu
 
 Hannu Savolainen
-hannu@4front-tech.com	
-(Please check http://www.4front-tech.com/ossfree before mailing me).
+hannu@opensound.com	
+(Please check http://www.opensound.com/ossfree before mailing me).
 
 Snail mail:	Hannu Savolainen
 		Hiekkalaiturintie 3 A 8
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/Readme.cards linux/drivers/sound/Readme.cards
--- v2.1.71/linux/drivers/sound/Readme.cards	Wed Nov 12 13:34:26 1997
+++ linux/drivers/sound/Readme.cards	Tue Dec  9 09:49:59 1997
@@ -4,7 +4,7 @@
 This document describes configuring soundcards with freeware version of
 Open Sound Systems (OSS/Free). Information about the commercial version
 (OSS/Linux) and it's configuration is available from 
-http://www.4front-tech.com/linux.html. Information presented here is
+http://www.opensound.com/linux.html. Information presented here is
 not valid for OSS/Linux. 
 
 If you are unsure about how to configure OSS/Free
@@ -15,7 +15,7 @@
 
 IMPORTANT!	This document covers only cards that were "known" when
 		this driver version was released. Please look at
-		http://www.4front-tech.com/ossfree for info about
+		http://www.opensound.com/ossfree for info about
 		cards introduced recently.
 
 		The following covers mainly the "old" configuration
@@ -115,7 +115,7 @@
 Cards that are not (fully) supported by this driver
 ===================================================
 
-See http://www.4front-tech.com/ossfree for information about soundcards 
+See http://www.opensound.com/ossfree for information about soundcards 
 to be supported in future. 
 
 
@@ -174,7 +174,7 @@
 versions of isapnptools so at least version 1.6 is required with soundcards.
 
 Yet another way to use PnP cards is to use (commercial) OSS/Linux drivers.
-See http://www.4front-tech.com/linux.html for more info. This is the way
+See http://www.opensound.com/linux.html for more info. This is the way
 you probably like to do it if you don't waste hours of time in recompiling
 kernel and the required tools.
 
@@ -1231,7 +1231,7 @@
 Writing a driver for a new card is not possible if there are no 
 programming information available about the card. If you don't
 find your new card from this file, look from the home page 
-(http://www.4front-tech.com/ossfree). Then please contact
+(http://www.opensound.com/ossfree). Then please contact
 manufacturer of the card and ask if they have (or are willing to)
 released technical details of the card. Do this before contacting me. I
 can only answer 'no' if there are no programming information available.
@@ -1252,7 +1252,7 @@
 There are some common audio chipsets that are not supported yet. For example
 Sierra Aria and IBM Mwave. It's possible that these architectures
 get some support in future but I can't make any promises. Just look
-at the home page (http://www.4front-tech.com/ossfree/new_cards.html)
+at the home page (http://www.opensound.com/ossfree/new_cards.html)
 for latest info.
 
 Information about unsupported soundcards and chipsets is welcome as well
@@ -1261,10 +1261,10 @@
 If you have any corrections and/or comments, please contact me.
 
 Hannu Savolainen
-hannu@4front-tech.com
+hannu@opensound.com
 
-Personal home page:	   http://personal.eunet.fi/pp/voxware/hannu.html
-www home page of OSS/Free: http://www.4front-tech.com/ossfree
+Personal home page:	   http://www.compusonic.fi/~hannu
+www home page of OSS/Free: http://www.opensound.com/ossfree
 
 www home page of commercial OSS
-(Open Sound System) drivers: http://www.4front-tech.com/oss.html
+(Open Sound System) drivers: http://www.opensound.com/oss.html
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/Readme.linux linux/drivers/sound/Readme.linux
--- v2.1.71/linux/drivers/sound/Readme.linux	Wed Nov 12 13:34:26 1997
+++ linux/drivers/sound/Readme.linux	Tue Dec  9 09:49:59 1997
@@ -67,10 +67,10 @@
 check for possible boot (insmod) time error messages in /var/adm/messages.
 
 - Other messages or problems
-Please check http://www.4front-tech.com/ossfree for more info.
+Please check http://www.opensound.com/ossfree for more info.
 
 Hannu Savolainen
-hannu@4front-tech.com
+hannu@opensound.com
 
 ----------------- cut here ------------------------------
 SURPRISE SURPRISE!!!
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/audio.c linux/drivers/sound/audio.c
--- v2.1.71/linux/drivers/sound/audio.c	Sat Nov 29 11:25:10 1997
+++ linux/drivers/sound/audio.c	Tue Dec  9 09:49:59 1997
@@ -304,6 +304,9 @@
 			    if (dev_nblock[dev] && buf_no == -EAGAIN)
 				    return p;
 
+			    if (p > 0) 		/* Avoid throwing away data */
+				return p;	/* Return it instead */
+
 			    return buf_no;
 		    }
 		  if (l > c)
@@ -958,6 +961,34 @@
 		  }
 		  break;
 
+    case SNDCTL_DSP_GETODELAY:
+      {
+	int count;
+	unsigned long   flags;
+	struct dma_buffparms *dmap = dmap_out;
+
+	if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
+	   return -EINVAL;
+	if (!(dmap->flags & DMA_ALLOC_DONE))
+	   return (*(int *) arg = 0);
+
+	save_flags (flags);
+	cli ();
+	/* Compute number of bytes that have been played */
+	count = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_OUTPUT);
+	if (count < dmap->fragment_size && dmap->qhead != 0)
+	   count += dmap->bytes_in_use;	/* Pointer wrap not handled yet */
+	count += dmap->byte_counter;
+
+	/* Substract current count from the number of bytes written by app */
+	count = dmap->user_counter - count;
+	if (count < 0)
+           count = 0;
+	restore_flags (flags);
+
+	return (*(int *) arg = count);
+      }
+      break;
 
 	  case SNDCTL_DSP_POST:
 		  ;
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/configure.c linux/drivers/sound/configure.c
--- v2.1.71/linux/drivers/sound/configure.c	Sat Nov 29 11:25:10 1997
+++ linux/drivers/sound/configure.c	Tue Dec  9 09:49:59 1997
@@ -1132,8 +1132,8 @@
 	ask_int_choice(B(OPT_CS4232), "CS4232_BASE",
 		       "CS4232 audio I/O base",
 		       FMT_HEX,
-		       0x530,
-		       "530, 604, E80 or F40");
+		       0x534,
+		       "534, 608, E84 or F44");
 
 	ask_int_choice(B(OPT_CS4232), "CS4232_IRQ",
 		       "CS4232 audio IRQ",
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c
--- v2.1.71/linux/drivers/sound/dmabuf.c	Tue Dec  2 09:49:39 1997
+++ linux/drivers/sound/dmabuf.c	Tue Dec  9 09:49:59 1997
@@ -13,6 +13,7 @@
 #include <linux/config.h>
 
 #define BE_CONSERVATIVE
+#define SAMPLE_ROUNDUP 0
 
 #include "sound_config.h"
 
@@ -896,7 +897,7 @@
 	active_offs += dmap->byte_counter;
 #endif
 
-	offs = (dmap->user_counter % dmap->bytes_in_use) & ~3;
+	offs = (dmap->user_counter % dmap->bytes_in_use) & ~SAMPLE_ROUNDUP;
 	if (offs < 0 || offs >= dmap->bytes_in_use)
 	  {
 		  printk("OSS: Got unexpected offs %ld. Giving up.\n", offs);
@@ -920,10 +921,10 @@
 	  {
 		  len = (maxfrags * dmap->fragment_size) - occupied_bytes;
 	  }
-	*size = len & ~3;
+	*size = len & ~SAMPLE_ROUNDUP;
 
 	restore_flags(flags);
-	return (len > 0);
+	return (*size > 0);
 }
 
 int
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/lowlevel/awe_wave.c linux/drivers/sound/lowlevel/awe_wave.c
--- v2.1.71/linux/drivers/sound/lowlevel/awe_wave.c	Tue Dec  2 16:45:19 1997
+++ linux/drivers/sound/lowlevel/awe_wave.c	Tue Dec  9 09:49:59 1997
@@ -564,7 +564,7 @@
 	synth_devs[my_dev] = &awe_operations;
 
 #ifdef CONFIG_AWE32_MIXER
-	if ((my_mixerdev=sound_alloc_mixerdev())!=-1) {
+	if ((my_mixerdev=sound_alloc_mixerdev())==-1) {
 		mixer_devs[my_mixerdev] = &awe_mixer_operations;
 	}
 #endif
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c
--- v2.1.71/linux/drivers/sound/mad16.c	Sat Nov 29 11:25:11 1997
+++ linux/drivers/sound/mad16.c	Tue Dec  9 09:49:59 1997
@@ -795,6 +795,18 @@
 int             opl4 = 0;
 int             joystick = 0;
 
+MODULE_PARM(io,"i");
+MODULE_PARM(dma,"i");
+MODULE_PARM(dma16,"i");
+MODULE_PARM(irq,"i");
+MODULE_PARM(cdtype,"i");
+MODULE_PARM(cdirq,"i");
+MODULE_PARM(cdport,"i");
+MODULE_PARM(cddma,"i");
+MODULE_PARM(opl4,"i");
+MODULE_PARM(joystick,"i");
+
+
 static int      found_mpu;
 
 
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/midi_synth.c linux/drivers/sound/midi_synth.c
--- v2.1.71/linux/drivers/sound/midi_synth.c	Tue Dec  2 09:49:39 1997
+++ linux/drivers/sound/midi_synth.c	Tue Dec  9 09:49:59 1997
@@ -498,15 +498,15 @@
 		return 0;
 
 	if (format != SYSEX_PATCH)
-	  {
-		  printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);
+	{
+/*		  printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);*/
 		  return -EINVAL;
-	  }
+	}
 	if (count < hdr_size)
-	  {
-		  printk("MIDI Error: Patch header too short\n");
-		  return -EINVAL;
-	  }
+	{
+/*		printk("MIDI Error: Patch header too short\n");*/
+		return -EINVAL;
+	}
 	count -= hdr_size;
 
 	/*
@@ -514,74 +514,73 @@
 	 * been transferred already.
 	 */
 
-	copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs);
-
-	if (count < sysex.len)
-	  {
-		  printk("MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);
-		  sysex.len = count;
-	  }
-	left = sysex.len;
-	src_offs = 0;
+	if(copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs))
+		return -EFAULT;
+ 
+ 	if (count < sysex.len)
+	{
+/*		printk(KERN_WARNING "MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);*/
+		sysex.len = count;
+	}
+  	left = sysex.len;
+  	src_offs = 0;
 
 	sysex_sleep_flag.opts = WK_NONE;
 
 	for (i = 0; i < left && !signal_pending(current); i++)
-	  {
-		  unsigned char   data;
+	{
+		unsigned char   data;
 
-		  get_user(*(unsigned char *) &data, (unsigned char *) &((addr)[hdr_size + i]));
+		get_user(*(unsigned char *) &data, (unsigned char *) &((addr)[hdr_size + i]));
 
-		  eox_seen = (i > 0 && data & 0x80);	/* End of sysex */
+		eox_seen = (i > 0 && data & 0x80);	/* End of sysex */
 
-		  if (eox_seen && data != 0xf7)
-			  data = 0xf7;
-
-		  if (i == 0)
-		    {
-			    if (data != 0xf0)
-			      {
-				      printk("Error: Sysex start missing\n");
-				      return -EINVAL;
-			      }
-		    }
-		  while (!midi_devs[orig_dev]->outputc(orig_dev, (unsigned char) (data & 0xff)) &&
-			 !signal_pending(current))
-
-		    {
-			    unsigned long   tlimit;
-
-			    if (1)
-				    current->timeout = tlimit = jiffies + (1);
-			    else
-				    tlimit = (unsigned long) -1;
-			    sysex_sleep_flag.opts = WK_SLEEP;
-			    interruptible_sleep_on(&sysex_sleeper);
-			    if (!(sysex_sleep_flag.opts & WK_WAKEUP))
-			      {
-				      if (jiffies >= tlimit)
-					      sysex_sleep_flag.opts |= WK_TIMEOUT;
-			      }
-			    sysex_sleep_flag.opts &= ~WK_SLEEP;
-		    };		/* Wait for timeout */
-
-		  if (!first_byte && data & 0x80)
-			  return 0;
-		  first_byte = 0;
-	  }
+		if (eox_seen && data != 0xf7)
+			data = 0xf7;
+
+		if (i == 0)
+		{
+			if (data != 0xf0)
+			{
+				printk(KERN_WARNING "midi_synth: Sysex start missing\n");
+				return -EINVAL;
+			}
+		}
+		while (!midi_devs[orig_dev]->outputc(orig_dev, (unsigned char) (data & 0xff)) &&
+			!signal_pending(current))
+
+		{
+			unsigned long   tlimit;
+
+			if (1)
+				current->timeout = tlimit = jiffies + (1);
+			else
+				tlimit = (unsigned long) -1;
+			sysex_sleep_flag.opts = WK_SLEEP;
+			interruptible_sleep_on(&sysex_sleeper);
+			if (!(sysex_sleep_flag.opts & WK_WAKEUP))
+			{
+				if (jiffies >= tlimit)
+					sysex_sleep_flag.opts |= WK_TIMEOUT;
+			}
+			sysex_sleep_flag.opts &= ~WK_SLEEP;
+		};		/* Wait for timeout */
+
+		if (!first_byte && data & 0x80)
+			return 0;
+		first_byte = 0;
+	}
 
 	if (!eox_seen)
 		midi_outc(orig_dev, 0xf7);
 	return 0;
 }
-
-void
-midi_synth_panning(int dev, int channel, int pressure)
+  
+void midi_synth_panning(int dev, int channel, int pressure)
 {
 }
-
-void
-midi_synth_aftertouch(int dev, int channel, int pressure)
+  
+void midi_synth_aftertouch(int dev, int channel, int pressure)
 {
 	int             orig_dev = synth_devs[dev]->midi_dev;
 	int             msg, chn;
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/mpu401.c linux/drivers/sound/mpu401.c
--- v2.1.71/linux/drivers/sound/mpu401.c	Sat Nov 29 11:25:11 1997
+++ linux/drivers/sound/mpu401.c	Tue Dec  9 09:49:59 1997
@@ -1844,14 +1844,5 @@
 	SOUND_LOCK_END;
 }
 
-#else
-
-void
-export_mpu401_syms(void)
-{
-	register_symtab(&mpu401_syms);
-}
-
-
 #endif
 #endif
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/soundvers.h linux/drivers/sound/soundvers.h
--- v2.1.71/linux/drivers/sound/soundvers.h	Wed Nov 12 13:34:27 1997
+++ linux/drivers/sound/soundvers.h	Tue Dec  9 09:49:59 1997
@@ -1,2 +1,2 @@
-#define SOUND_VERSION_STRING "3.8s-971110"
+#define SOUND_VERSION_STRING "3.8s2++-971130"
 #define SOUND_INTERNAL_VERSION 0x030804
diff -u --recursive --new-file v2.1.71/linux/drivers/sound/uart401.c linux/drivers/sound/uart401.c
--- v2.1.71/linux/drivers/sound/uart401.c	Sat Nov 29 11:25:11 1997
+++ linux/drivers/sound/uart401.c	Tue Dec  9 09:49:59 1997
@@ -452,8 +452,7 @@
 	if (!devc->share_irq)
 		snd_release_irq(devc->irq);
 
-	/* Free device too !! - AC FIXME: CHECK THIS IS RIGHT */
-	if (devc)
+	if (!devc)
 		vfree(devc);
 	sound_unload_mididev(hw_config->slots[4]);
 }
diff -u --recursive --new-file v2.1.71/linux/fs/Config.in linux/fs/Config.in
--- v2.1.71/linux/fs/Config.in	Tue Dec  2 16:45:19 1997
+++ linux/fs/Config.in	Tue Dec  9 09:49:59 1997
@@ -23,7 +23,7 @@
 bool '/proc filesystem support' CONFIG_PROC_FS
 if [ "$CONFIG_INET" = "y" ]; then
   tristate 'NFS filesystem support' CONFIG_NFS_FS
-  if [ "$CONFIG_NFS_FS" = "y" ]; then
+  if [ "$CONFIG_NFS_FS" = "y" -a "$CONFIG_IP_PNP" = "y" ]; then
     bool '   Root file system on NFS' CONFIG_ROOT_NFS
     if [ "$CONFIG_ROOT_NFS" = "y" ]; then
       bool '      BOOTP support' CONFIG_RNFS_BOOTP
diff -u --recursive --new-file v2.1.71/linux/fs/buffer.c linux/fs/buffer.c
--- v2.1.71/linux/fs/buffer.c	Tue Dec  2 16:45:19 1997
+++ linux/fs/buffer.c	Tue Dec  9 09:36:09 1997
@@ -582,21 +582,23 @@
  */
 struct buffer_head * get_hash_table(kdev_t dev, int block, int size)
 {
+	struct buffer_head * bh;
 	for (;;) {
-		struct buffer_head * bh;
-
-		bh=find_buffer(dev,block,size);
+		bh = find_buffer(dev,block,size);
 		if (!bh)
-			return bh;
+			break;
 		bh->b_count++;
 		bh->b_lru_time = jiffies;
-		wait_on_buffer(bh);
+		if (!test_bit(BH_Lock, &bh->b_state)) 
+			break;
+		__wait_on_buffer(bh);
 		if (bh->b_dev == dev		&&
 		    bh->b_blocknr == block	&&
 		    bh->b_size == size)
-			return bh;
+			break;
 		bh->b_count--;
 	}
+	return bh;
 }
 
 unsigned int get_hardblocksize(kdev_t dev)
@@ -835,6 +837,8 @@
 			if (!buffer_locked(bh))
 				continue;
 			if (buffer_dirty(bh) || buffer_protected(bh))
+				continue;
+			if (MAJOR(bh->b_dev) == LOOP_MAJOR)
 				continue;
 			/*
 			 * We've found an unused, locked, non-dirty buffer of
diff -u --recursive --new-file v2.1.71/linux/fs/coda/file.c linux/fs/coda/file.c
--- v2.1.71/linux/fs/coda/file.c	Tue Dec  2 16:45:19 1997
+++ linux/fs/coda/file.c	Sun Dec  7 11:51:01 1997
@@ -219,7 +219,7 @@
 {
         struct super_block *sbptr;
 
-        sbptr = coda_find_super(dev);
+        sbptr = get_super(dev);
 
         if ( !sbptr ) {
                 printk("coda_inode_grab: coda_find_super returns NULL.\n");
@@ -238,14 +238,3 @@
         return 0;
 }
 
-struct super_block *coda_find_super(kdev_t device)
-{
-        struct super_block *super;
-
-        for (super = super_blocks + 0; super < super_blocks + NR_SUPER ; 
-	     super++) {
-                if (super->s_dev == device) 
-                        return super;
-        }
-        return NULL;
-}
diff -u --recursive --new-file v2.1.71/linux/fs/coda/namecache.c linux/fs/coda/namecache.c
--- v2.1.71/linux/fs/coda/namecache.c	Tue Dec  2 16:45:19 1997
+++ linux/fs/coda/namecache.c	Sun Dec  7 11:51:01 1997
@@ -1,17 +1,12 @@
-/* 
- * Mach Operating System
- * Copyright (c) 1990 Carnegie-Mellon University
- * Copyright (c) 1989 Carnegie-Mellon University
- * All rights reserved.  The CMU software License Agreement specifies
- * the terms and conditions for use and redistribution.
- */
-
 /*
- * This code was written for the Coda file system at Carnegie Mellon University.
- * Contributers include David Steere, James Kistler, and M. Satyanarayanan.
+ * Cache operations for Coda.
+ * Original version: (C) 1996 Peter Braam 
+ * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
+ *
+ * Carnegie Mellon encourages users of this code to contribute improvements
+ * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
  */
 
-
 /*
  * This module contains the routines to implement the CFS name cache. The
  * purpose of this cache is to reduce the cost of translating pathnames 
@@ -46,7 +41,6 @@
 #include <linux/coda_linux.h>
 #include <linux/coda_cnode.h>
 #include <linux/coda_namecache.h>
-
 
 int cfsnc_use;
 
diff -u --recursive --new-file v2.1.71/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.1.71/linux/fs/coda/psdev.c	Tue Dec  2 16:45:19 1997
+++ linux/fs/coda/psdev.c	Mon Dec  8 23:58:04 1997
@@ -31,10 +31,10 @@
 #include <linux/proc_fs.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
+#include <linux/poll.h>
 #include <asm/io.h>
 #include <asm/segment.h>
 #include <asm/system.h>
-#include <asm/poll.h>
 #include <asm/uaccess.h>
 
 #include <linux/coda.h>
diff -u --recursive --new-file v2.1.71/linux/fs/coda/sysctl.c linux/fs/coda/sysctl.c
--- v2.1.71/linux/fs/coda/sysctl.c	Thu Dec  4 14:53:56 1997
+++ linux/fs/coda/sysctl.c	Sun Dec  7 11:51:50 1997
@@ -1,4 +1,13 @@
+/*
+ * Sysctl operations for Coda filesystem
+ * Original version: (C) 1996 P. Braam and M. Callahan
+ * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University
+ * 
+ * Carnegie Mellon encourages users to contribute improvements to
+ * the Coda project. Contact Peter Braam (coda@cs.cmu.edu).
+ */
 /* sysctl entries for Coda! */
+
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/sysctl.h>
diff -u --recursive --new-file v2.1.71/linux/fs/lockd/svcsubs.c linux/fs/lockd/svcsubs.c
--- v2.1.71/linux/fs/lockd/svcsubs.c	Tue Nov 18 17:22:08 1997
+++ linux/fs/lockd/svcsubs.c	Tue Dec  9 12:16:25 1997
@@ -24,24 +24,25 @@
  * Global file hash table
  */
 #define FILE_NRHASH		32
-#define FILE_HASH(dhash)	((dhash) & FILE_NRHASH)
+#define FILE_HASH_BITS		5
 static struct nlm_file *	nlm_files[FILE_NRHASH];
 static struct semaphore		nlm_file_sema = MUTEX;
 
+static unsigned int file_hash(dev_t dev, ino_t ino)
+{
+	unsigned long tmp = (unsigned long) ino | (unsigned long) dev;
+	tmp = tmp + (tmp >> FILE_HASH_BITS) + (tmp >> FILE_HASH_BITS*2);
+	return tmp & (FILE_NRHASH - 1);
+}
+
 /*
  * Lookup file info. If it doesn't exist, create a file info struct
  * and open a (VFS) file for the given inode.
  *
- * The NFS filehandle must have been validated prior to this call,
- * as we assume that the dentry pointer is valid.
- *
  * FIXME:
  * Note that we open the file O_RDONLY even when creating write locks.
  * This is not quite right, but for now, we assume the client performs
  * the proper R/W checking.
- *
- * The dentry in the FH may not be validated .. can we call this with
- * the full svc_fh?
  */
 u32
 nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
@@ -49,40 +50,38 @@
 {
 	struct nlm_file	*file;
 	struct knfs_fh	*fh = (struct knfs_fh *) f;
-	struct dentry	*dentry = fh->fh_dcookie;
-	unsigned int	hash = FILE_HASH(dentry->d_name.hash);
+	unsigned int	hash = file_hash(fh->fh_dev, fh->fh_ino);
 	u32		nfserr;
 
-	dprintk("lockd: nlm_file_lookup(%s/%s)\n",
-		dentry->d_parent->d_name.name, dentry->d_name.name);
+	dprintk("lockd: nlm_file_lookup(%s/%ld)\n",
+		kdevname(fh->fh_dev), fh->fh_ino);
 
 	/* Lock file table */
 	down(&nlm_file_sema);
 
 	for (file = nlm_files[hash]; file; file = file->f_next) {
-		if (file->f_handle.fh_dcookie == dentry
-		 && !memcmp(&file->f_handle, fh, sizeof(*fh)))
+		if (file->f_handle.fh_dcookie == fh->fh_dcookie &&
+		    !memcmp(&file->f_handle, fh, sizeof(*fh)))
 			goto found;
 	}
 
-	dprintk("lockd: creating file for %s/%s\n",
-		dentry->d_parent->d_name.name, dentry->d_name.name);
-	if (!(file = (struct nlm_file *) kmalloc(sizeof(*file), GFP_KERNEL))) {
-		up(&nlm_file_sema);
-		return nlm_lck_denied_nolocks;
-	}
+	dprintk("lockd: creating file for %s/%ld\n",
+		kdevname(fh->fh_dev), fh->fh_ino);
+	nfserr = nlm_lck_denied_nolocks;
+	file = (struct nlm_file *) kmalloc(sizeof(*file), GFP_KERNEL);
+	if (!file)
+		goto out_unlock;
 
 	memset(file, 0, sizeof(*file));
 	file->f_handle = *fh;
 	file->f_sema   = MUTEX;
 
 	/* Open the file. Note that this must not sleep for too long, else
-	 * we would lock up lockd:-) So no NFS re-exports, folks. */
+	 * we would lock up lockd:-) So no NFS re-exports, folks.
+	 */
 	if ((nfserr = nlmsvc_ops->fopen(rqstp, fh, &file->f_file)) != 0) {
 		dprintk("lockd: open failed (nfserr %ld)\n", ntohl(nfserr));
-		kfree(file);
-		up(&nlm_file_sema);
-		return nlm_lck_denied;
+		goto out_free;
 	}
 
 	file->f_next = nlm_files[hash];
@@ -91,9 +90,17 @@
 found:
 	dprintk("lockd: found file %p (count %d)\n", file, file->f_count);
 	*result = file;
-	up(&nlm_file_sema);
 	file->f_count++;
-	return 0;
+	nfserr = 0;
+
+out_unlock:
+	up(&nlm_file_sema);
+	return nfserr;
+
+out_free:
+	kfree(file);
+	nfserr = nlm_lck_denied;
+	goto out_unlock;
 }
 
 /*
@@ -102,11 +109,12 @@
 static inline void
 nlm_delete_file(struct nlm_file *file)
 {
-	struct dentry *dentry = file->f_file.f_dentry;
+	struct inode *inode = file->f_file.f_dentry->d_inode;
 	struct nlm_file	**fp, *f;
 
-	dprintk("lockd: closing file %p\n", dentry);
-	fp = nlm_files + FILE_HASH(dentry->d_name.hash);
+	dprintk("lockd: closing file %s/%ld\n",
+		kdevname(inode->i_dev), inode->i_ino);
+	fp = nlm_files + file_hash(inode->i_dev, inode->i_ino);
 	while ((f = *fp) != NULL) {
 		if (f == file) {
 			*fp = file->f_next;
diff -u --recursive --new-file v2.1.71/linux/fs/namei.c linux/fs/namei.c
--- v2.1.71/linux/fs/namei.c	Tue Dec  2 09:49:40 1997
+++ linux/fs/namei.c	Sat Dec  6 10:39:26 1997
@@ -737,10 +737,9 @@
 		goto exit;
 
 	dir = lock_parent(dentry);
-
 	error = PTR_ERR(dir);
 	if (IS_ERR(dir))
-		goto exit;
+		goto exit_dput;
 
 	error = -EEXIST;
 	if (dentry->d_inode)
@@ -765,6 +764,7 @@
 
 exit_lock:
 	unlock_dir(dir);
+exit_dput:
 	dput(dentry);
 exit:
 	return error;
@@ -798,10 +798,9 @@
 		goto exit;
 
 	dir = lock_parent(dentry);
-
 	error = PTR_ERR(dir);
 	if (IS_ERR(dir))
-		goto exit;
+		goto exit_dput;
 
 	error = -ENOENT;
 	if (!dentry->d_inode)
@@ -838,6 +837,7 @@
 
 exit_lock:
         unlock_dir(dir);
+exit_dput:
 	dput(dentry);
 exit:
 	return error;
@@ -871,10 +871,9 @@
 		goto exit;
 
 	dir = lock_parent(dentry);
-
 	error = PTR_ERR(dir);
 	if (IS_ERR(dir))
-		goto exit;
+		goto exit_dput;
 
 	error = -ENOENT;
 	if (!dentry->d_inode)
@@ -911,6 +910,7 @@
 
 exit_lock:
         unlock_dir(dir);
+exit_dput:
 	dput(dentry);
 exit:
 	return error;
@@ -945,10 +945,9 @@
 		goto exit;
 
 	dir = lock_parent(dentry);
-
 	error = PTR_ERR(dir);
 	if (IS_ERR(dir))
-		goto exit;
+		goto exit_dput;
 
 	error = -EEXIST;
 	if (dentry->d_inode)
@@ -972,6 +971,7 @@
 
 exit_lock:
 	unlock_dir(dir);
+exit_dput:
 	dput(dentry);
 exit:
 	return error;
@@ -1016,10 +1016,9 @@
 		goto exit_old;
 
 	dir = lock_parent(new_dentry);
-
 	error = PTR_ERR(dir);
 	if (IS_ERR(dir))
-		goto exit;
+		goto exit_new;
 
 	error = -ENOENT;
 	inode = old_dentry->d_inode;
@@ -1059,6 +1058,7 @@
 
 exit_lock:
 	unlock_dir(dir);
+exit_new:
 	dput(new_dentry);
 exit_old:
 	dput(old_dentry);
diff -u --recursive --new-file v2.1.71/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.1.71/linux/fs/nfs/dir.c	Thu Dec  4 14:53:56 1997
+++ linux/fs/nfs/dir.c	Sat Dec  6 11:23:06 1997
@@ -498,6 +498,12 @@
 		error = -EACCES;
 		inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
 		if (inode) {
+#ifdef NFS_PARANOIA
+if (inode->i_count > 1)
+printk("nfs_lookup: %s/%s ino=%ld in use, count=%d, nlink=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name,
+inode->i_ino, inode->i_count, inode->i_nlink);
+#endif
 	    no_entry:
 			dentry->d_op = &nfs_dentry_operations;
 			d_add(dentry, inode);
@@ -512,14 +518,20 @@
 /*
  * Code common to create, mkdir, and mknod.
  */
-static int nfs_instantiate(struct inode *dir, struct dentry *dentry,
-			struct nfs_fattr *fattr, struct nfs_fh *fhandle)
+static int nfs_instantiate(struct dentry *dentry, struct nfs_fattr *fattr,
+				struct nfs_fh *fhandle)
 {
 	struct inode *inode;
 	int error = -EACCES;
 
-	inode = nfs_fhget(dir->i_sb, fhandle, fattr);
+	inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
 	if (inode) {
+#ifdef NFS_PARANOIA
+if (inode->i_count > 1)
+printk("nfs_instantiate: %s/%s ino=%ld in use, count=%d, nlink=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name,
+inode->i_ino, inode->i_count, inode->i_nlink);
+#endif
 		d_instantiate(dentry, inode);
 		nfs_renew_times(dentry);
 		error = 0;
@@ -563,14 +575,9 @@
 	error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
 			dentry->d_name.name, &sattr, &fhandle, &fattr);
 	if (!error)
-		error = nfs_instantiate(dir, dentry, &fattr, &fhandle);
-	else {
-#ifdef NFS_PARANOIA
-printk("nfs_create: %s/%s failed, error=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, error);
-#endif
+		error = nfs_instantiate(dentry, &fattr, &fhandle);
+	else
 		d_drop(dentry);
-	}
 out:
 	return error;
 }
@@ -606,14 +613,9 @@
 	error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
 				dentry->d_name.name, &sattr, &fhandle, &fattr);
 	if (!error)
-		error = nfs_instantiate(dir, dentry, &fattr, &fhandle);
-	else {
-#ifdef NFS_PARANOIA
-printk("nfs_mknod: %s/%s failed, error=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, error);
-#endif
+		error = nfs_instantiate(dentry, &fattr, &fhandle);
+	else
 		d_drop(dentry);
-	}
 	return error;
 }
 
@@ -645,13 +647,22 @@
 	nfs_invalidate_dircache(dir);
 	error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir),
 				dentry->d_name.name, &sattr, &fhandle, &fattr);
-	if (!error)
-		error = nfs_instantiate(dir, dentry, &fattr, &fhandle);
-	else {
-#ifdef NFS_PARANOIA
-printk("nfs_mkdir: %s/%s failed, error=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, error);
-#endif
+	if (!error) {
+		/*
+		 * Some AIX servers reportedly fail to fill out the fattr.
+		 * Check for a bad mode value and complain, then drop the
+		 * dentry to force a new lookup.
+		 */
+		if (!S_ISDIR(fattr.mode)) {
+			static int complain = 0;
+			if (!complain++)
+				printk("NFS: buggy server! fattr mode=%x\n",
+					fattr.mode);
+			goto drop;
+		}
+		error = nfs_instantiate(dentry, &fattr, &fhandle);
+	} else {
+	drop:
 		d_drop(dentry);
 	}
 	return error;
@@ -662,12 +673,12 @@
  * use count prior to the operation, and return EBUSY if it has
  * multiple users.
  *
- * Update inode->i_nlink immediately after a successful operation.
- * (See comments for nfs_unlink.)
+ * We update inode->i_nlink and free the inode prior to the operation
+ * to avoid possible races if the server reuses the inode.
  */
 static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-	int error;
+	int error, rehash = 0;
 
 	dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",
 				dir->i_dev, dir->i_ino, dentry->d_name.name);
@@ -688,13 +699,31 @@
 		if (dentry->d_count > 1)
 			goto out;
 	}
-	/* Drop the dentry to force a new lookup */
-	d_drop(dentry);
-	error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name);
+#ifdef NFS_PARANOIA
+if (dentry->d_inode->i_count > 1)
+printk("nfs_rmdir: %s/%s inode busy?? i_count=%d, i_nlink=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name,
+dentry->d_inode->i_count, dentry->d_inode->i_nlink);
+#endif
+	/*
+	 * Unhash the dentry while we remove the directory.
+	 */
+	if (!list_empty(&dentry->d_hash)) {
+		d_drop(dentry);
+		rehash = 1;
+	}
+	/*
+	 * Update i_nlink and free the inode before unlinking.
+	 */
+	if (dentry->d_inode->i_nlink)
+		dentry->d_inode->i_nlink --;
+	d_delete(dentry);
+	nfs_invalidate_dircache(dir);
+	error = nfs_proc_rmdir(NFS_SERVER(dir),
+				NFS_FH(dir), dentry->d_name.name);
 	if (!error) {
-		if (dentry->d_inode->i_nlink)
-			dentry->d_inode->i_nlink --;
-		nfs_invalidate_dircache(dir);
+		if (rehash)
+			d_add(dentry, NULL);
 		nfs_renew_times(dentry);
 	}
 out:
@@ -867,6 +896,12 @@
 #endif
 		goto out;
 	}
+#ifdef NFS_PARANOIA
+if (inode && inode->i_count > 1)
+printk("nfs_safe_remove: %s/%s inode busy?? i_count=%d, i_nlink=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name,
+inode->i_count, inode->i_nlink);
+#endif
 	/*
 	 * Unhash the dentry while we remove the file ...
 	 */
@@ -874,29 +909,22 @@
 		d_drop(dentry);
 		rehash = 1;
 	}
-	error = nfs_proc_remove(NFS_SERVER(dir),
-					NFS_FH(dir), dentry->d_name.name);
 	/*
-	 * ... then restore the hashed state.  This ensures that the
-	 * dentry can't become busy after having its file deleted.
+	 * Update i_nlink and free the inode before unlinking.
 	 */
-	if (rehash) {
-		d_add(dentry, inode);
-	}
-#ifdef NFS_PARANOIA
-if (dentry->d_count > 1)
-printk("nfs_safe_remove: %s/%s busy after delete?? d_count=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count);
-if (inode && inode->i_count > 1)
-printk("nfs_safe_remove: %s/%s inode busy?? i_count=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_count);
-#endif
-	if (!error) {
-		nfs_invalidate_dircache(dir);
-		if (inode && inode->i_nlink)
+	if (inode) {
+		if (inode->i_nlink)
 			inode->i_nlink --;
 		d_delete(dentry);
 	}
+	nfs_invalidate_dircache(dir);
+	error = nfs_proc_remove(NFS_SERVER(dir),
+					NFS_FH(dir), dentry->d_name.name);
+	/*
+	 * Rehash the negative dentry if the operation succeeded.
+	 */
+	if (!error && rehash)
+		d_add(dentry, NULL);
 out:
 	return error;
 }
diff -u --recursive --new-file v2.1.71/linux/fs/nfsd/lockd.c linux/fs/nfsd/lockd.c
--- v2.1.71/linux/fs/nfsd/lockd.c	Sun Jul 27 12:11:01 1997
+++ linux/fs/nfsd/lockd.c	Tue Dec  9 12:16:25 1997
@@ -16,6 +16,9 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_LOCKD
 
+/*
+ * Note: we hold the dentry use count while the file is open.
+ */
 static u32
 nlm_fopen(struct svc_rqst *rqstp, struct knfs_fh *f, struct file *filp)
 {
@@ -27,6 +30,8 @@
 	fh.fh_dverified = 0;
 
 	nfserr = nfsd_open(rqstp, &fh, S_IFREG, 0, filp);
+	if (!nfserr)
+		dget(filp->f_dentry);
 	fh_put(&fh);
 	return nfserr;
 }
@@ -35,6 +40,7 @@
 nlm_fclose(struct file *filp)
 {
 	nfsd_close(filp);
+	dput(filp->f_dentry);
 }
 
 struct nlmsvc_binding		nfsd_nlm_ops = {
diff -u --recursive --new-file v2.1.71/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.1.71/linux/fs/nfsd/vfs.c	Tue Dec  2 09:49:40 1997
+++ linux/fs/nfsd/vfs.c	Fri Dec  5 12:59:33 1997
@@ -240,24 +240,24 @@
 	int		access, err;
 
 	access = wflag? MAY_WRITE : MAY_READ;
-	if ((err = fh_verify(rqstp, fhp, type, access)) != 0)
+	err = fh_verify(rqstp, fhp, type, access);
+	if (err)
 		goto out;
 
 	dentry = fhp->fh_dentry;
 	inode = dentry->d_inode;
 
 	/* Disallow access to files with the append-only bit set or
-	 * with mandatory locking enabled */
+	 * with mandatory locking enabled
+	 */
 	err = nfserr_perm;
 	if (IS_APPEND(inode) || IS_ISMNDLK(inode))
 		goto out;
 	if (!inode->i_op || !inode->i_op->default_file_ops)
 		goto out;
 
-	if (wflag && (err = get_write_access(inode)) != 0) {
-		err = nfserrno(-err);
-		goto out;
-	}
+	if (wflag && (err = get_write_access(inode)) != 0)
+		goto out_nfserr;
 
 	memset(filp, 0, sizeof(*filp));
 	filp->f_op    = inode->i_op->default_file_ops;
@@ -267,7 +267,7 @@
 	filp->f_dentry = dentry;
 
 	err = 0;
-	if (filp->f_op->open) {
+	if (filp->f_op && filp->f_op->open) {
 		err = filp->f_op->open(inode, filp);
 		if (err) {
 			if (wflag)
@@ -277,9 +277,11 @@
 			 * is really on callers stack frame. -DaveM
 			 */
 			filp->f_count--;
-			err = nfserrno(-err);
 		}
 	}
+out_nfserr:
+	if (err)
+		err = nfserrno(-err);
 out:
 	return err;
 }
@@ -633,14 +635,16 @@
 	struct iattr	newattrs;
 	int		err;
 
-	if ((err = fh_verify(rqstp, fhp, S_IFREG, MAY_WRITE|MAY_TRUNC)) != 0)
-		return err;
+	err = fh_verify(rqstp, fhp, S_IFREG, MAY_WRITE | MAY_TRUNC);
+	if (err)
+		goto out;
 
 	dentry = fhp->fh_dentry;
 	inode = dentry->d_inode;
 
-	if ((err = get_write_access(inode)) != 0)
-		goto out;
+	err = get_write_access(inode);
+	if (err)
+		goto out_nfserr;
 
 	/* Things look sane, lock and do it. */
 	fh_lock(fhp);
@@ -654,8 +658,11 @@
 	}
 	put_write_access(inode);
 	fh_unlock(fhp);
+out_nfserr:
+	if (err)
+		err = nfserrno(-err);
 out:
-	return (err ? nfserrno(-err) : 0);
+	return err;
 }
 
 /*
@@ -671,7 +678,8 @@
 	mm_segment_t	oldfs;
 	int		err;
 
-	if ((err = fh_verify(rqstp, fhp, S_IFLNK, MAY_READ)) != 0)
+	err = fh_verify(rqstp, fhp, S_IFLNK, MAY_READ);
+	if (err)
 		goto out;
 
 	dentry = fhp->fh_dentry;
@@ -715,7 +723,8 @@
 	if (!flen || !plen)
 		goto out;
 
-	if ((err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE)) != 0)
+	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
+	if (err)
 		goto out;
 	dentry = fhp->fh_dentry;
 
@@ -762,17 +771,20 @@
 	struct inode	*dirp, *dest;
 	int		err;
 
-	if ((err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE) != 0) ||
-	    (err = fh_verify(rqstp, tfhp, S_IFREG, MAY_NOP)) != 0)
-		return err;
+	err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE);
+	if (err)
+		goto out;
+	err = fh_verify(rqstp, tfhp, S_IFREG, MAY_NOP);
+	if (err)
+		goto out;
 
 	ddir = ffhp->fh_dentry;
 	dirp = ddir->d_inode;
 
-	dnew = lookup_dentry(fname, dget(ddir), 1);
+	dnew = lookup_dentry(fname, dget(ddir), 0);
 	err = PTR_ERR(dnew);
 	if (IS_ERR(dnew))
-		return nfserrno(-err);
+		goto out_nfserr;
 
 	err = -EEXIST;
 	if (dnew->d_inode)
@@ -805,7 +817,11 @@
 	}
 dput_and_out:
 	dput(dnew);
-	return (err ? nfserrno(-err) : 0);
+out_nfserr:
+	if (err)
+		err = nfserrno(-err);
+out:
+	return err;
 }
 
 /* More "hidden treasure" from the generic VFS. -DaveM */
@@ -836,9 +852,12 @@
 	struct inode	*fdir, *tdir;
 	int		err;
 
-	if ((err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE) != 0)
-	 || (err = fh_verify(rqstp, tfhp, S_IFDIR, MAY_CREATE)) != 0)
-		return err;
+	err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE);
+	if (err)
+		goto out;
+	err = fh_verify(rqstp, tfhp, S_IFDIR, MAY_CREATE);
+	if (err)
+		goto out;
 
 	fdentry = ffhp->fh_dentry;
 	fdir = fdentry->d_inode;
@@ -846,18 +865,19 @@
 	tdentry = tfhp->fh_dentry;
 	tdir = tdentry->d_inode;
 
+	/* N.B. We shouldn't need this ... dentry layer handles it */
 	if (!flen || (fname[0] == '.' && 
 	    (flen == 1 || (flen == 2 && fname[1] == '.'))) ||
 	    !tlen || (tname[0] == '.' && 
 	    (tlen == 1 || (tlen == 2 && tname[1] == '.'))))
 		return nfserr_perm;
 
-	odentry = lookup_dentry(fname, dget(fdentry), 1);
+	odentry = lookup_dentry(fname, dget(fdentry), 0);
 	err = PTR_ERR(odentry);
 	if (IS_ERR(odentry))
 		goto out_no_unlock;
 
-	ndentry = lookup_dentry(tname, dget(tdentry), 1);
+	ndentry = lookup_dentry(tname, dget(tdentry), 0);
 	err = PTR_ERR(ndentry);
 	if (IS_ERR(ndentry))
 		goto out_dput_old;
@@ -883,7 +903,10 @@
 out_dput_old:
 	dput(odentry);
 out_no_unlock:
-	return (err ? nfserrno(-err) : 0);
+	if (err)
+		err = nfserrno(-err);
+out:
+	return err;
 }
 
 /*
@@ -898,10 +921,13 @@
 	struct inode	*dirp;
 	int		err;
 
+	/* N.B. We shouldn't need this test ... handled by dentry layer */
+	err = nfserr_acces;
 	if (!flen || isdotent(fname, flen))
-		return nfserr_acces;
-	if ((err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE)) != 0)
-		return err;
+		goto out;
+	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE);
+	if (err)
+		goto out;
 
 	dentry = fhp->fh_dentry;
 	dirp = dentry->d_inode;
@@ -909,7 +935,7 @@
 	rdentry = lookup_dentry(fname, dget(dentry), 0);
 	err = PTR_ERR(rdentry);
 	if (IS_ERR(rdentry))
-		goto out;
+		goto out_nfserr;
 
 	fh_lock(fhp);
 	if (type == S_IFDIR) {
@@ -926,8 +952,12 @@
 	dput(rdentry);
 	if (!err && EX_ISSYNC(fhp->fh_export))
 		write_inode_now(dirp);
+
+out_nfserr:
+	if (err)
+		err = nfserrno(-err);
 out:
-	return (err ? nfserrno(-err) : 0);
+	return err;
 }
 
 /*
diff -u --recursive --new-file v2.1.71/linux/fs/pipe.c linux/fs/pipe.c
--- v2.1.71/linux/fs/pipe.c	Sat Oct 25 02:44:18 1997
+++ linux/fs/pipe.c	Mon Dec  8 23:58:04 1997
@@ -12,8 +12,8 @@
 #include <linux/termios.h>
 #include <linux/mm.h>
 #include <linux/file.h>
+#include <linux/poll.h>
 
-#include <asm/poll.h>
 #include <asm/uaccess.h>
 
 /*
diff -u --recursive --new-file v2.1.71/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.1.71/linux/fs/proc/array.c	Mon Dec  1 12:04:14 1997
+++ linux/fs/proc/array.c	Tue Dec  9 09:31:19 1997
@@ -685,6 +685,7 @@
 
 	buffer += sprintf(buffer, "SigPnd:\t");
 	buffer = render_sigset_t(&p->signal, buffer);
+	*buffer++ = '\n';
 	buffer += sprintf(buffer, "SigBlk:\t");
 	buffer = render_sigset_t(&p->blocked, buffer);
 	*buffer++ = '\n';
@@ -692,6 +693,7 @@
 	collect_sigign_sigcatch(p, &ign, &catch);
 	buffer += sprintf(buffer, "SigIgn:\t");
 	buffer = render_sigset_t(&ign, buffer);
+	*buffer++ = '\n';
 	buffer += sprintf(buffer, "SigCat:\t");
 	buffer = render_sigset_t(&catch, buffer);
 	*buffer++ = '\n';
diff -u --recursive --new-file v2.1.71/linux/fs/select.c linux/fs/select.c
--- v2.1.71/linux/fs/select.c	Tue Nov 18 17:22:08 1997
+++ linux/fs/select.c	Mon Dec  8 23:58:04 1997
@@ -24,10 +24,10 @@
 #include <linux/malloc.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/poll.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
-#include <asm/poll.h>
 
 #define ROUND_UP(x,y) (((x)+(y)-1)/(y))
 #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
@@ -39,9 +39,10 @@
  * understand what I'm doing here, then you understand how the linux
  * sleep/wakeup mechanism works.
  *
- * Two very simple procedures, poll_wait() and free_wait() make all the work.
- * poll_wait() is an inline-function defined in <linux/sched.h>, as all select/poll
- * functions have to call it to add an entry to the poll table.
+ * Two very simple procedures, poll_wait() and free_wait() make all the
+ * work.  poll_wait() is an inline-function defined in <linux/sched.h>,
+ * as all select/poll functions have to call it to add an entry to the
+ * poll table.
  */
 
 /*
@@ -61,26 +62,6 @@
 	}
 }
 
-/*
- * For the kernel fd_set we use a fixed set-size for allocation purposes.
- * This set-size doesn't necessarily bear any relation to the size the user
- * uses, but should preferably obviously be larger than any possible user
- * size (NR_OPEN bits).
- *
- * We need 6 bitmaps (in/out/ex for both incoming and outgoing), and we
- * allocate one page for all the bitmaps. Thus we have 8*PAGE_SIZE bits,
- * to be divided by 6. And we'd better make sure we round to a full
- * long-word (in fact, we'll round to 64 bytes).
- */
-#define KFDS_64BLOCK ((PAGE_SIZE/(6*64))*64)
-#define KFDS_NR (KFDS_64BLOCK*8 > NR_OPEN ? NR_OPEN : KFDS_64BLOCK*8)
-typedef unsigned long kernel_fd_set[KFDS_NR/(8*sizeof(unsigned long))];
-
-typedef struct {
-	kernel_fd_set in, out, ex;
-	kernel_fd_set res_in, res_out, res_ex;
-} fd_set_buffer;
-
 #define __IN(in)	(in)
 #define __OUT(in)	(in + sizeof(kernel_fd_set)/sizeof(unsigned long))
 #define __EX(in)	(in + 2*sizeof(kernel_fd_set)/sizeof(unsigned long))
@@ -141,11 +122,28 @@
 #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
 #define POLLEX_SET (POLLPRI)
 
-static int do_select(int n, fd_set_buffer *fds, poll_table *wait)
+int do_select(int n, fd_set_buffer *fds, unsigned long timeout)
 {
+	poll_table wait_table, *wait;
 	int retval;
 	int i;
 
+	lock_kernel();
+
+	wait = NULL;
+	current->timeout = timeout;
+	if (timeout) {
+		struct poll_table_entry *entry = (struct poll_table_entry *)
+			__get_free_page(GFP_KERNEL);
+		if (!entry) {
+			retval = -ENOMEM;
+			goto out_nowait;
+		}
+		wait_table.nr = 0;
+		wait_table.entry = entry;
+		wait = &wait_table;
+	}
+
 	retval = max_select_fd(n, fds);
 	if (retval < 0)
 		goto out;
@@ -154,33 +152,36 @@
 	for (;;) {
 		struct file ** fd = current->files->fd;
 		current->state = TASK_INTERRUPTIBLE;
-		for (i = 0 ; i < n ; i++,fd++) {
+		for (i = 0 ; i < n ; i++, fd++) {
 			unsigned long bit = BIT(i);
 			unsigned long *in = MEM(i,fds->in);
+			unsigned long mask;
+			struct file *file;
+
+			if (!(bit & BITS(in)))
+				continue;
 
-			if (bit & BITS(in)) {
-				struct file * file = *fd;
-				unsigned int mask = POLLNVAL;
-				if (file) {
-					mask = DEFAULT_POLLMASK;
-					if (file->f_op && file->f_op->poll)
-						mask = file->f_op->poll(file, wait);
-				}
-				if ((mask & POLLIN_SET) && ISSET(bit, __IN(in))) {
-					SET(bit, __RES_IN(in));
-					retval++;
-					wait = NULL;
-				}
-				if ((mask & POLLOUT_SET) && ISSET(bit, __OUT(in))) {
-					SET(bit, __RES_OUT(in));
-					retval++;
-					wait = NULL;
-				}
-				if ((mask & POLLEX_SET) && ISSET(bit, __EX(in))) {
-					SET(bit, __RES_EX(in));
-					retval++;
-					wait = NULL;
-				}
+			file = *fd;
+			mask = POLLNVAL;
+			if (file) {
+				mask = DEFAULT_POLLMASK;
+				if (file->f_op && file->f_op->poll)
+					mask = file->f_op->poll(file, wait);
+			}
+			if ((mask & POLLIN_SET) && ISSET(bit, __IN(in))) {
+				SET(bit, __RES_IN(in));
+				retval++;
+				wait = NULL;
+			}
+			if ((mask & POLLOUT_SET) && ISSET(bit, __OUT(in))) {
+				SET(bit, __RES_OUT(in));
+				retval++;
+				wait = NULL;
+			}
+			if ((mask & POLLEX_SET) && ISSET(bit, __EX(in))) {
+				SET(bit, __RES_EX(in));
+				retval++;
+				wait = NULL;
 			}
 		}
 		wait = NULL;
@@ -189,82 +190,18 @@
 		schedule();
 	}
 	current->state = TASK_RUNNING;
-out:
-	return retval;
-}
 
-/*
- * We do a VERIFY_WRITE here even though we are only reading this time:
- * we'll write to it eventually..
- *
- * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned.
- */
-static int __get_fd_set(unsigned long nr, unsigned long * fs_pointer, unsigned long * fdset)
-{
-	/* round up nr to nearest "unsigned long" */
-	nr = (nr + 8*sizeof(unsigned long)-1) / (8*sizeof(unsigned long));
-	if (fs_pointer) {
-		int error = verify_area(VERIFY_WRITE,fs_pointer,
-					nr*sizeof(unsigned long));
-		if (!error) {
-			while (nr) {
-				__get_user(*fdset, fs_pointer);
-				nr--;
-				fs_pointer++;
-				fdset++;
-			}
-		}
-		return error;
-	}
-	while (nr) {
-		*fdset = 0;
-		nr--;
-		fdset++;
-	}
-	return 0;
-}
-
-static void __set_fd_set(long nr, unsigned long * fs_pointer, unsigned long * fdset)
-{
-	if (!fs_pointer)
-		return;
-	while (nr >= 0) {
-		__put_user(*fdset, fs_pointer);
-		nr -= 8 * sizeof(unsigned long);
-		fdset++;
-		fs_pointer++;
+out:
+	if (timeout) {
+		free_wait(&wait_table);
+		free_page((unsigned long) wait_table.entry);
 	}
+out_nowait:
+	current->timeout = 0;
+	unlock_kernel();
+	return retval;
 }
 
-/* We can do long accesses here, kernel fdsets are always long-aligned */
-static inline void __zero_fd_set(long nr, unsigned long * fdset)
-{
-	while (nr >= 0) {
-		*fdset = 0;
-		nr -= 8 * sizeof(unsigned long);
-		fdset++;
-	}
-}		
-
-/*
- * Note a few subtleties: we use "long" for the dummy, not int, and we do a
- * subtract by 1 on the nr of file descriptors. The former is better for
- * machines with long > int, and the latter allows us to test the bit count
- * against "zero or positive", which can mostly be just a sign bit test..
- *
- * Unfortunately this scheme falls apart on big endian machines where
- * sizeof(long) > sizeof(int) (ie. V9 Sparc). -DaveM
- */
-
-#define get_fd_set(nr,fsp,fdp) \
-__get_fd_set(nr, (unsigned long *) (fsp), (unsigned long *) (fdp))
-
-#define set_fd_set(nr,fsp,fdp) \
-__set_fd_set((nr)-1, (unsigned long *) (fsp), (unsigned long *) (fdp))
-
-#define zero_fd_set(nr,fdp) \
-__zero_fd_set((nr)-1, (unsigned long *) (fdp))
-
 /*
  * We can actually return ERESTARTSYS instead of EINTR, but I'd
  * like to be certain this leads to no problems. So I return
@@ -273,64 +210,50 @@
  * Update: ERESTARTSYS breaks at least the xview clock binary, so
  * I'm trying ERESTARTNOHAND which restart only when you want to.
  */
-asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
+asmlinkage int
+sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
 {
-	int error;
 	fd_set_buffer *fds;
 	unsigned long timeout;
-	poll_table wait_table, *wait;
+	int ret;
 
-	lock_kernel();
 	timeout = ~0UL;
 	if (tvp) {
-		error = -EFAULT;
-		if (!access_ok(VERIFY_WRITE, tvp, sizeof(*tvp)))
-			goto out_nowait;
-		error = __get_user(timeout, &tvp->tv_usec);
-		if (error)
-			goto out_nowait;
-		timeout = ROUND_UP(timeout,(1000000/HZ));
-		{
-			unsigned long tmp;
-			error = __get_user(tmp, &tvp->tv_sec);
-			if (error)
-				goto out_nowait;
-			timeout += tmp * (unsigned long) HZ;
-		}
+		time_t sec, usec;
+
+		if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
+		    || (ret = __get_user(sec, &tvp->tv_sec))
+		    || (ret = __get_user(usec, &tvp->tv_usec)))
+			goto out_nofds;
+
+		timeout = ROUND_UP(usec, 1000000/HZ);
+		timeout += sec * (unsigned long) HZ;
 		if (timeout)
 			timeout += jiffies + 1;
 	}
-	error = -ENOMEM;
-	wait = NULL;
-	current->timeout = timeout;
-	if (timeout) {
-		struct poll_table_entry *entry;
 
-		entry = (struct poll_table_entry *) __get_free_page(GFP_KERNEL);
-		if (!entry)
-			goto out_nowait;
-		wait_table.nr = 0;
-		wait_table.entry = entry;
-		wait = &wait_table;
-	}
+	ret = -ENOMEM;
 	fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL);
 	if (!fds)
 		goto out_nofds;
-	error = -EINVAL;
+	ret = -EINVAL;
 	if (n < 0)
 		goto out;
 	if (n > KFDS_NR)
 		n = KFDS_NR;
-	if ((error = get_fd_set(n, inp, &fds->in)) ||
-	    (error = get_fd_set(n, outp, &fds->out)) ||
-	    (error = get_fd_set(n, exp, &fds->ex))) goto out;
-	zero_fd_set(n, &fds->res_in);
-	zero_fd_set(n, &fds->res_out);
-	zero_fd_set(n, &fds->res_ex);
-	error = do_select(n, fds, wait);
+	if ((ret = get_fd_set(n, inp, fds->in)) ||
+	    (ret = get_fd_set(n, outp, fds->out)) ||
+	    (ret = get_fd_set(n, exp, fds->ex)))
+		goto out;
+	zero_fd_set(n, fds->res_in);
+	zero_fd_set(n, fds->res_out);
+	zero_fd_set(n, fds->res_ex);
+
+	ret = do_select(n, fds, timeout);
+
 	if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
 		unsigned long timeout = current->timeout - jiffies - 1;
-		unsigned long sec = 0, usec = 0;
+		time_t sec = 0, usec = 0;
 		if ((long) timeout > 0) {
 			sec = timeout / HZ;
 			usec = timeout % HZ;
@@ -340,27 +263,24 @@
 		put_user(usec, &tvp->tv_usec);
 	}
 	current->timeout = 0;
-	if (error < 0)
+
+	if (ret < 0)
 		goto out;
-	if (!error) {
-		error = -ERESTARTNOHAND;
+	if (!ret) {
+		ret = -ERESTARTNOHAND;
 		if (signal_pending(current))
 			goto out;
-		error = 0;
+		ret = 0;
 	}
-	set_fd_set(n, inp, &fds->res_in);
-	set_fd_set(n, outp, &fds->res_out);
-	set_fd_set(n, exp, &fds->res_ex);
+
+	set_fd_set(n, inp, fds->res_in);
+	set_fd_set(n, outp, fds->res_out);
+	set_fd_set(n, exp, fds->res_ex);
+
 out:
 	free_page((unsigned long) fds);
 out_nofds:
-	if (wait) {
-		free_wait(&wait_table);
-		free_page((unsigned long) wait->entry);
-	}
-out_nowait:
-	unlock_kernel();
-	return error;
+	return ret;
 }
 
 static int do_poll(unsigned int nfds, struct pollfd *fds, poll_table *wait)
diff -u --recursive --new-file v2.1.71/linux/fs/sysv/namei.c linux/fs/sysv/namei.c
--- v2.1.71/linux/fs/sysv/namei.c	Thu Jul 17 10:06:08 1997
+++ linux/fs/sysv/namei.c	Sun Dec  7 11:57:03 1997
@@ -10,6 +10,11 @@
  *  sysv/namei.c
  *  Copyright (C) 1993  Bruno Haible
  */
+/*
+  7 Dec 1997 - updated to use dentries by Krzysztof G. Baranowski
+	       <kgb@manjak.knm.org.pl>
+ */
+	 
 
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -100,31 +105,29 @@
 	return NULL;
 }
 
-int sysv_lookup(struct inode * dir,const char * name, int len,
-	struct inode ** result)
+int sysv_lookup(struct inode * dir, struct dentry * dentry)
 {
 	int ino;
+	struct inode * inode = NULL;
 	struct sysv_dir_entry * de;
 	struct buffer_head * bh;
 
-	*result = NULL;
 	if (!dir)
 		return -ENOENT;
 	if (!S_ISDIR(dir->i_mode)) {
-		iput(dir);
 		return -ENOENT;
 	}
-	if (!(bh = sysv_find_entry(dir,name,len,&de))) {
-		iput(dir);
+	if (!(bh = sysv_find_entry(dir, dentry->d_name.name, 
+				   dentry->d_name.len, &de))) {
 		return -ENOENT;
 	}
 	ino = de->inode;
 	brelse(bh);
-	if (!(*result = iget(dir->i_sb,ino))) {
-		iput(dir);
+	inode = iget(dir->i_sb,ino);
+	
+	if (!inode) 
 		return -EACCES;
-	}
-	iput(dir);
+	d_add(dentry, inode);
 	return 0;
 }
 
@@ -201,42 +204,37 @@
 	return 0;
 }
 
-int sysv_create(struct inode * dir,const char * name, int len, int mode,
-	struct inode ** result)
+int sysv_create(struct inode * dir, struct dentry * dentry, int mode)
 {
 	int error;
 	struct inode * inode;
 	struct buffer_head * bh;
 	struct sysv_dir_entry * de;
 
-	*result = NULL;
 	if (!dir)
 		return -ENOENT;
 	inode = sysv_new_inode(dir);
-	if (!inode) {
-		iput(dir);
+	if (!inode) 
 		return -ENOSPC;
-	}
 	inode->i_op = &sysv_file_inode_operations;
 	inode->i_mode = mode;
 	mark_inode_dirty(inode);
-	error = sysv_add_entry(dir,name,len, &bh ,&de);
+	error = sysv_add_entry(dir,dentry->d_name.name,
+			       dentry->d_name.len, &bh, &de);
 	if (error) {
 		inode->i_nlink--;
 		mark_inode_dirty(inode);
 		iput(inode);
-		iput(dir);
 		return error;
 	}
 	de->inode = inode->i_ino;
 	mark_buffer_dirty(bh, 1);
 	brelse(bh);
-	iput(dir);
-	*result = inode;
+	d_instantiate(dentry, inode);
 	return 0;
 }
 
-int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rdev)
+int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev)
 {
 	int error;
 	struct inode * inode;
@@ -245,17 +243,15 @@
 
 	if (!dir)
 		return -ENOENT;
-	bh = sysv_find_entry(dir,name,len,&de);
+	bh = sysv_find_entry(dir,dentry->d_name.name,
+			     dentry->d_name.len,&de);
 	if (bh) {
 		brelse(bh);
-		iput(dir);
 		return -EEXIST;
 	}
 	inode = sysv_new_inode(dir);
-	if (!inode) {
-		iput(dir);
+	if (!inode)
 		return -ENOSPC;
-	}
 	inode->i_uid = current->fsuid;
 	inode->i_mode = mode;
 	inode->i_op = NULL;
@@ -277,53 +273,45 @@
 	if (S_ISBLK(mode) || S_ISCHR(mode))
 		inode->i_rdev = to_kdev_t(rdev);
 	mark_inode_dirty(inode);
-	error = sysv_add_entry(dir, name, len, &bh, &de);
+	error = sysv_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &bh, &de);
 	if (error) {
 		inode->i_nlink--;
 		mark_inode_dirty(inode);
 		iput(inode);
-		iput(dir);
 		return error;
 	}
 	de->inode = inode->i_ino;
 	mark_buffer_dirty(bh, 1);
 	brelse(bh);
-	iput(dir);
-	iput(inode);
+	d_instantiate(dentry, inode);
 	return 0;
 }
 
-int sysv_mkdir(struct inode * dir, const char * name, int len, int mode)
+int sysv_mkdir(struct inode * dir, struct dentry *dentry, int mode)
 {
 	int error;
 	struct inode * inode;
 	struct buffer_head * bh, *dir_block;
 	struct sysv_dir_entry * de;
 
-	if (!dir) {
-		iput(dir);
+	if (!dir)
 		return -EINVAL;
-	}
-	bh = sysv_find_entry(dir,name,len,&de);
+	bh = sysv_find_entry(dir, dentry->d_name.name,
+                              dentry->d_name.len, &de);
 	if (bh) {
 		brelse(bh);
-		iput(dir);
 		return -EEXIST;
 	}
 	if (dir->i_nlink >= dir->i_sb->sv_link_max) {
-		iput(dir);
 		return -EMLINK;
 	}
 	inode = sysv_new_inode(dir);
-	if (!inode) {
-		iput(dir);
+	if (!inode)
 		return -ENOSPC;
-	}
 	inode->i_op = &sysv_dir_inode_operations;
 	inode->i_size = 2 * SYSV_DIRSIZE;
 	dir_block = sysv_file_bread(inode,0,1);
 	if (!dir_block) {
-		iput(dir);
 		inode->i_nlink--;
 		mark_inode_dirty(inode);
 		iput(inode);
@@ -342,9 +330,9 @@
 	if (dir->i_mode & S_ISGID)
 		inode->i_mode |= S_ISGID;
 	mark_inode_dirty(inode);
-	error = sysv_add_entry(dir, name, len, &bh, &de);
-	if (error) {
-		iput(dir);
+	error = sysv_add_entry(dir, dentry->d_name.name,
+                               dentry->d_name.len, &bh, &de);
+ 	if (error) {
 		inode->i_nlink=0;
 		iput(inode);
 		return error;
@@ -353,10 +341,9 @@
 	mark_buffer_dirty(bh, 1);
 	dir->i_nlink++;
 	mark_inode_dirty(dir);
-	iput(dir);
-	iput(inode);
 	brelse(bh);
-	return 0;
+        d_instantiate(dentry, inode);
+ 	return 0;
 }
 
 /*
@@ -419,7 +406,7 @@
 	return 1;
 }
 
-int sysv_rmdir(struct inode * dir, const char * name, int len)
+int sysv_rmdir(struct inode * dir, struct dentry * dentry)
 {
 	int retval;
 	struct inode * inode;
@@ -427,13 +414,14 @@
 	struct sysv_dir_entry * de;
 
 	inode = NULL;
-	bh = sysv_find_entry(dir,name,len,&de);
+	bh = sysv_find_entry(dir, dentry->d_name.name,
+                             dentry->d_name.len, &de);
 	retval = -ENOENT;
 	if (!bh)
 		goto end_rmdir;
 	retval = -EPERM;
-	if (!(inode = iget(dir->i_sb, de->inode)))
-		goto end_rmdir;
+	inode = dentry->d_inode;
+
         if ((dir->i_mode & S_ISVTX) && !fsuser() &&
             current->fsuid != inode->i_uid &&
             current->fsuid != dir->i_uid)
@@ -467,15 +455,14 @@
 	dir->i_nlink--;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	mark_inode_dirty(dir);
+	d_delete(dentry);
 	retval = 0;
 end_rmdir:
-	iput(dir);
-	iput(inode);
 	brelse(bh);
 	return retval;
 }
 
-int sysv_unlink(struct inode * dir, const char * name, int len)
+int sysv_unlink(struct inode * dir, struct dentry * dentry)
 {
 	int retval;
 	struct inode * inode;
@@ -485,16 +472,16 @@
 repeat:
 	retval = -ENOENT;
 	inode = NULL;
-	bh = sysv_find_entry(dir,name,len,&de);
+	bh = sysv_find_entry(dir, dentry->d_name.name,
+                             dentry->d_name.len, &de);
 	if (!bh)
 		goto end_unlink;
-	if (!(inode = iget(dir->i_sb, de->inode)))
-		goto end_unlink;
+	inode = dentry->d_inode;
+
 	retval = -EPERM;
 	if (S_ISDIR(inode->i_mode))
 		goto end_unlink;
 	if (de->inode != inode->i_ino) {
-		iput(inode);
 		brelse(bh);
 		current->counter = 0;
 		schedule();
@@ -510,7 +497,7 @@
 	}
 	if (!inode->i_nlink) {
 		printk("Deleting nonexistent file (%s:%lu), %d\n",
-		       kdevname(inode->i_dev),
+		        kdevname(inode->i_dev),
 		       inode->i_ino, inode->i_nlink);
 		inode->i_nlink=1;
 	}
@@ -521,15 +508,15 @@
 	inode->i_nlink--;
 	inode->i_ctime = dir->i_ctime;
 	mark_inode_dirty(inode);
+	d_delete(dentry);
 	retval = 0;
 end_unlink:
 	brelse(bh);
-	iput(inode);
-	iput(dir);
 	return retval;
 }
 
-int sysv_symlink(struct inode * dir, const char * name, int len, const char * symname)
+int sysv_symlink(struct inode * dir, struct dentry * dentry, 
+		 const char * symname)
 {
 	struct sysv_dir_entry * de;
 	struct inode * inode;
@@ -540,15 +527,13 @@
 	char c;
 	struct buffer_head * bh;
 
-	if (!(inode = sysv_new_inode(dir))) {
-		iput(dir);
+	if (!(inode = sysv_new_inode(dir)))
 		return -ENOSPC;
-	}
+
 	inode->i_mode = S_IFLNK | 0777;
 	inode->i_op = &sysv_symlink_inode_operations;
 	name_block = sysv_file_bread(inode,0,1);
 	if (!name_block) {
-		iput(dir);
 		inode->i_nlink--;
 		mark_inode_dirty(inode);
 		iput(inode);
@@ -564,94 +549,81 @@
 	brelse(name_block);
 	inode->i_size = i;
 	mark_inode_dirty(inode);
-	bh = sysv_find_entry(dir,name,len,&de);
+	bh = sysv_find_entry(dir, dentry->d_name.name,
+                             dentry->d_name.len, &de);
 	if (bh) {
 		inode->i_nlink--;
 		mark_inode_dirty(inode);
 		iput(inode);
 		brelse(bh);
-		iput(dir);
 		return -EEXIST;
 	}
-	i = sysv_add_entry(dir, name, len, &bh, &de);
+	i = sysv_add_entry(dir, dentry->d_name.name,
+                           dentry->d_name.len, &bh, &de);
 	if (i) {
 		inode->i_nlink--;
 		mark_inode_dirty(inode);
 		iput(inode);
-		iput(dir);
 		return i;
 	}
 	de->inode = inode->i_ino;
 	mark_buffer_dirty(bh, 1);
 	brelse(bh);
-	iput(dir);
-	iput(inode);
+        d_instantiate(dentry, inode);
 	return 0;
 }
 
-int sysv_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
+int sysv_link(struct inode * oldinode, struct inode * dir, 
+	      struct dentry * dentry)
 {
 	int error;
 	struct sysv_dir_entry * de;
 	struct buffer_head * bh;
 
 	if (S_ISDIR(oldinode->i_mode)) {
-		iput(oldinode);
-		iput(dir);
 		return -EPERM;
 	}
 	if (oldinode->i_nlink >= oldinode->i_sb->sv_link_max) {
-		iput(oldinode);
-		iput(dir);
 		return -EMLINK;
 	}
-	bh = sysv_find_entry(dir,name,len,&de);
+	bh = sysv_find_entry(dir, dentry->d_name.name,
+                             dentry->d_name.len, &de);
 	if (bh) {
 		brelse(bh);
-		iput(dir);
-		iput(oldinode);
 		return -EEXIST;
 	}
-	error = sysv_add_entry(dir, name, len, &bh, &de);
+	error = sysv_add_entry(dir, dentry->d_name.name,
+                               dentry->d_name.len, &bh, &de);
 	if (error) {
-		iput(dir);
-		iput(oldinode);
 		return error;
 	}
 	de->inode = oldinode->i_ino;
 	mark_buffer_dirty(bh, 1);
 	brelse(bh);
-	iput(dir);
 	oldinode->i_nlink++;
 	oldinode->i_ctime = CURRENT_TIME;
 	mark_inode_dirty(oldinode);
-	iput(oldinode);
+        d_instantiate(dentry, oldinode);
 	return 0;
 }
 
 /* return 1 if `new' is a subdir of `old' on the same device */
-static int subdir(struct inode * new_inode, struct inode * old_inode)
+static int subdir(struct dentry * new_dentry, struct dentry * old_dentry)
 {
-	int ino;
-	int result;
-
-	new_inode->i_count++;
-	result = 0;
-	for (;;) {
-		if (new_inode == old_inode) {
-			result = 1;
-			break;
-		}
-		if (new_inode->i_dev != old_inode->i_dev)
-			break;
-		ino = new_inode->i_ino;
-		if (sysv_lookup(new_inode,"..",2,&new_inode))
-			break;
-		if (new_inode->i_ino == ino) /* root dir reached ? */
-			break;
-	}
-	iput(new_inode);
-	return result;
+	int result = 0;
+	
+        for (;;) {
+                if (new_dentry != old_dentry) {
+                        struct dentry * parent = new_dentry->d_parent;
+                        if (parent == new_dentry)
+                                break;
+                        new_dentry = parent;
+                        continue;
+                }
+                result = 1;
+                break;
+        }
+        return result;
 }
 
 #define PARENT_INO(buffer) \
@@ -716,7 +688,7 @@
 		if (!S_ISDIR(old_inode->i_mode))
 			goto end_rename;
 		retval = -EINVAL;
-		if (subdir(new_dir, old_inode))
+		if (subdir(new_dentry, old_dentry))
 			goto end_rename;
 		retval = -ENOTEMPTY;
 		if (!empty_dir(new_inode))
@@ -735,7 +707,7 @@
 		if (new_inode && !S_ISDIR(new_inode->i_mode))
 			goto end_rename;
 		retval = -EINVAL;
-		if (subdir(new_dir, old_inode))
+		if (subdir(new_dentry, old_dentry))
 			goto end_rename;
 		retval = -EIO;
 		dir_bh = sysv_file_bread(old_inode,0,0);
diff -u --recursive --new-file v2.1.71/linux/fs/ufs/ufs_namei.c linux/fs/ufs/ufs_namei.c
--- v2.1.71/linux/fs/ufs/ufs_namei.c	Thu Dec  4 14:53:56 1997
+++ linux/fs/ufs/ufs_namei.c	Thu Dec  4 01:27:48 1997
@@ -7,7 +7,7 @@
  * Rutgers, The State University of New Jersey
  *
  * Clean swab support by Francois-Rene Rideau <rideau@ens.fr> 19970406
- * Ported to 2.1.62 by Francois-Rene Rideau <rideau@issy.cnet.fr> 19971109
+ * Ported to 2.1.62 by Francois-Rene Rideau <rideau@ens.fr> 19971109
  *
  */
 
diff -u --recursive --new-file v2.1.71/linux/fs/ufs/ufs_super.c linux/fs/ufs/ufs_super.c
--- v2.1.71/linux/fs/ufs/ufs_super.c	Thu Dec  4 14:53:56 1997
+++ linux/fs/ufs/ufs_super.c	Fri Dec  5 07:20:44 1997
@@ -21,12 +21,14 @@
  * Francois-Rene Rideau <rideau@ens.fr>
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 #include <linux/locks.h>
+#include <linux/init.h>
 #include <asm/uaccess.h>
 
 #include "ufs_swab.h"
@@ -54,8 +56,7 @@
 	NULL
 };
 
-int
-init_ufs_fs(void)
+__initfunc(int init_ufs_fs(void))
 {
 	return(register_filesystem(&ufs_fs_type));
 }
diff -u --recursive --new-file v2.1.71/linux/fs/ufs/ufs_symlink.c linux/fs/ufs/ufs_symlink.c
--- v2.1.71/linux/fs/ufs/ufs_symlink.c	Thu Dec  4 14:53:56 1997
+++ linux/fs/ufs/ufs_symlink.c	Fri Dec  5 07:26:27 1997
@@ -6,7 +6,7 @@
  * Laboratory for Computer Science Research Computing Facility
  * Rutgers, The State University of New Jersey
  *
- * Ported to 2.1.62 by Francois-Rene Rideau <rideau@issy.cnet.fr> 19971109
+ * Ported to 2.1.62 by Francois-Rene Rideau <rideau@ens.fr> 19971109
  *
  */
 
diff -u --recursive --new-file v2.1.71/linux/include/asm-alpha/byteorder.h linux/include/asm-alpha/byteorder.h
--- v2.1.71/linux/include/asm-alpha/byteorder.h	Thu Dec  4 14:53:56 1997
+++ linux/include/asm-alpha/byteorder.h	Fri Dec  5 05:45:09 1997
@@ -47,6 +47,6 @@
 
 #define __BYTEORDER_HAS_U64__
 
-#include <linux/byteorder_little_endian.h>
+#include <linux/byteorder/little_endian.h>
 
 #endif /* _ALPHA_BYTEORDER_H */
diff -u --recursive --new-file v2.1.71/linux/include/asm-alpha/posix_types.h linux/include/asm-alpha/posix_types.h
--- v2.1.71/linux/include/asm-alpha/posix_types.h	Thu Oct 10 22:12:20 1996
+++ linux/include/asm-alpha/posix_types.h	Mon Dec  8 23:58:04 1997
@@ -20,6 +20,7 @@
 typedef long		__kernel_ssize_t;
 typedef long		__kernel_ptrdiff_t;
 typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
 typedef long		__kernel_clock_t;
 typedef int		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
diff -u --recursive --new-file v2.1.71/linux/include/asm-alpha/signal.h linux/include/asm-alpha/signal.h
--- v2.1.71/linux/include/asm-alpha/signal.h	Mon Dec  1 12:04:14 1997
+++ linux/include/asm-alpha/signal.h	Tue Dec  9 09:31:19 1997
@@ -6,6 +6,7 @@
 /* Avoid too many header ordering problems.  */
 struct siginfo;
 
+#ifdef __KERNEL__
 /* Digital Unix defines 64 signals.  Most things should be clean enough
    to redefine this at will, if care is taken to make libc match.  */
 
@@ -19,6 +20,15 @@
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG		32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+
 /*
  * Linux/AXP has different signal numbers that Linux/i386: I'm trying
  * to make it OSF/1 binary compatible, at least for normal binaries.
@@ -114,6 +124,7 @@
 #define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
 #define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
 
+#ifdef __KERNEL__
 struct osf_sigaction {
 	__sighandler_t	sa_handler;
 	old_sigset_t	sa_mask;
@@ -130,6 +141,15 @@
 	struct sigaction sa;
 	void (*ka_restorer)(void);
 };
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+	__sighandler_t	sa_handler;
+	sigset_t	sa_mask;
+	int		sa_flags;
+};
+#endif /* __KERNEL__ */
 
 typedef struct sigaltstack {
 	void *ss_sp;
diff -u --recursive --new-file v2.1.71/linux/include/asm-alpha/socket.h linux/include/asm-alpha/socket.h
--- v2.1.71/linux/include/asm-alpha/socket.h	Sat Nov  1 11:04:27 1997
+++ linux/include/asm-alpha/socket.h	Tue Dec  9 09:31:19 1997
@@ -37,10 +37,15 @@
 
 #define SO_PASSCRED	17
 #define SO_PEERCRED	18
+#define SO_BINDTODEVICE 25
+
+#define SO_BINDTODEVICE	25
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		19
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	20
 #define SO_SECURITY_ENCRYPTION_NETWORK		21
+
+#define SO_BINDTODEVICE		22
 
 #endif /* _ASM_SOCKET_H */
diff -u --recursive --new-file v2.1.71/linux/include/asm-i386/byteorder.h linux/include/asm-i386/byteorder.h
--- v2.1.71/linux/include/asm-i386/byteorder.h	Thu Dec  4 14:53:56 1997
+++ linux/include/asm-i386/byteorder.h	Tue Dec  9 12:21:32 1997
@@ -42,6 +42,6 @@
 
 #endif /* __GNUC__ */
 
-#include <linux/byteorder_little_endian.h>
+#include <linux/byteorder/little_endian.h>
 
 #endif /* _I386_BYTEORDER_H */
diff -u --recursive --new-file v2.1.71/linux/include/asm-i386/posix_types.h linux/include/asm-i386/posix_types.h
--- v2.1.71/linux/include/asm-i386/posix_types.h	Thu Oct 10 22:12:29 1996
+++ linux/include/asm-i386/posix_types.h	Mon Dec  8 23:58:04 1997
@@ -20,6 +20,7 @@
 typedef int		__kernel_ssize_t;
 typedef int		__kernel_ptrdiff_t;
 typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
 typedef long		__kernel_clock_t;
 typedef int		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
diff -u --recursive --new-file v2.1.71/linux/include/asm-i386/signal.h linux/include/asm-i386/signal.h
--- v2.1.71/linux/include/asm-i386/signal.h	Tue Dec  2 09:49:40 1997
+++ linux/include/asm-i386/signal.h	Tue Dec  9 09:31:19 1997
@@ -6,6 +6,7 @@
 /* Avoid too many header ordering problems.  */
 struct siginfo;
 
+#ifdef __KERNEL__
 /* Most things should be clean enough to redefine this at will, if care
    is taken to make libc match.  */
 
@@ -19,6 +20,14 @@
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG		32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
 #define SIGHUP		 1
 #define SIGINT		 2
 #define SIGQUIT		 3
@@ -113,6 +122,7 @@
 #define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
 #define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
 
+#ifdef __KERNEL__
 struct old_sigaction {
 	__sighandler_t sa_handler;
 	old_sigset_t sa_mask;
@@ -130,6 +140,16 @@
 struct k_sigaction {
 	struct sigaction sa;
 };
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+	__sighandler_t sa_handler;
+	sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+#endif /* __KERNEL__ */
 
 typedef struct sigaltstack {
 	void *ss_sp;
@@ -179,6 +199,6 @@
 	return word;
 }
 
-#endif
+#endif /* __KERNEL__ */
 
 #endif
diff -u --recursive --new-file v2.1.71/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
--- v2.1.71/linux/include/asm-i386/system.h	Tue Dec  2 09:49:40 1997
+++ linux/include/asm-i386/system.h	Fri Dec  5 09:52:41 1997
@@ -21,8 +21,8 @@
 #define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
 #define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
 #define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
-#define load_TR(n) __asm__("ltr %%ax": /* no output */ :"a" (_TSS(n)))
-#define load_ldt(n) __asm__("lldt %%ax": /* no output */ :"a" (_LDT(n)))
+#define load_TR(n) __asm__ __volatile__("ltr %%ax": /* no output */ :"a" (_TSS(n)))
+#define load_ldt(n) __asm__ __volatile__("lldt %%ax": /* no output */ :"a" (_LDT(n)))
 #define store_TR(n) \
 __asm__("str %%ax\n\t" \
 	"subl %2,%%eax\n\t" \
@@ -33,11 +33,9 @@
 /* This special macro can be used to load a debugging register */
 
 #define loaddebug(tsk,register) \
-		__asm__("movl %0,%%edx\n\t" \
-			"movl %%edx,%%db" #register "\n\t" \
+		__asm__("movl %0,%%db" #register  \
 			: /* no output */ \
-			:"m" (tsk->debugreg[register]) \
-			:"dx");
+			:"r" (tsk->debugreg[register]))
 
 
 /*
diff -u --recursive --new-file v2.1.71/linux/include/asm-m68k/byteorder.h linux/include/asm-m68k/byteorder.h
--- v2.1.71/linux/include/asm-m68k/byteorder.h	Thu Dec  4 14:53:56 1997
+++ linux/include/asm-m68k/byteorder.h	Fri Dec  5 05:43:57 1997
@@ -19,6 +19,6 @@
 #  define __SWAB_64_THRU_32__
 #endif
 
-#include <linux/byteorder_big_endian.h>
+#include <linux/byteorder/big_endian.h>
 
 #endif /* _M68K_BYTEORDER_H */
diff -u --recursive --new-file v2.1.71/linux/include/asm-m68k/posix_types.h linux/include/asm-m68k/posix_types.h
--- v2.1.71/linux/include/asm-m68k/posix_types.h	Fri Nov 22 05:56:36 1996
+++ linux/include/asm-m68k/posix_types.h	Mon Dec  8 23:58:04 1997
@@ -20,6 +20,7 @@
 typedef int		__kernel_ssize_t;
 typedef int		__kernel_ptrdiff_t;
 typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
 typedef long		__kernel_clock_t;
 typedef int		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
diff -u --recursive --new-file v2.1.71/linux/include/asm-mips/byteorder.h linux/include/asm-mips/byteorder.h
--- v2.1.71/linux/include/asm-mips/byteorder.h	Thu Dec  4 14:53:56 1997
+++ linux/include/asm-mips/byteorder.h	Fri Dec  5 05:43:47 1997
@@ -4,9 +4,9 @@
 #include <asm/types.h>
 
 #if defined (__MIPSEB__)
-#  include <linux/byteorder_big_endian.h>
+#  include <linux/byteorder/big_endian.h>
 #elif defined (__MIPSEL__)
-#  include <linux/byteorder_little_endian.h>
+#  include <linux/byteorder/little_endian.h>
 #else
 #  error What's that? MIPS, but neither MIPSEB, nor MIPSEL???
 #endif
diff -u --recursive --new-file v2.1.71/linux/include/asm-mips/posix_types.h linux/include/asm-mips/posix_types.h
--- v2.1.71/linux/include/asm-mips/posix_types.h	Thu Jun 26 12:33:40 1997
+++ linux/include/asm-mips/posix_types.h	Mon Dec  8 23:58:04 1997
@@ -33,6 +33,7 @@
 typedef __SSIZE_TYPE__	__kernel_ssize_t;
 typedef int		__kernel_ptrdiff_t;
 typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
 typedef long		__kernel_clock_t;
 typedef long		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
diff -u --recursive --new-file v2.1.71/linux/include/asm-ppc/byteorder.h linux/include/asm-ppc/byteorder.h
--- v2.1.71/linux/include/asm-ppc/byteorder.h	Thu Dec  4 14:53:56 1997
+++ linux/include/asm-ppc/byteorder.h	Fri Dec  5 12:47:08 1997
@@ -61,15 +61,15 @@
 #endif /* 0 */
 
 /* The same, but returns converted value from the location pointer by addr. */
-#define __arch_swab16p(addr) ld_le16(addr)
-#define __arch_swab32p(addr) ld_le32(addr)
+#define __arch__swab16p(addr) ld_le16(addr)
+#define __arch__swab32p(addr) ld_le32(addr)
 
 /* The same, but do the conversion in situ, ie. put the value back to addr. */
-#define __arch_swab16s(addr) st_le16(addr,*addr)
-#define __arch_swab32s(addr) st_le32(addr,*addr)
+#define __arch__swab16s(addr) st_le16(addr,*addr)
+#define __arch__swab32s(addr) st_le32(addr,*addr)
 
 #endif /* __GNUC__ */
 
-#include <linux/byteorder_big_endian.h>
+#include <linux/byteorder/big_endian.h>
 
 #endif /* _PPC_BYTEORDER_H */
diff -u --recursive --new-file v2.1.71/linux/include/asm-ppc/posix_types.h linux/include/asm-ppc/posix_types.h
--- v2.1.71/linux/include/asm-ppc/posix_types.h	Wed Dec 18 00:54:09 1996
+++ linux/include/asm-ppc/posix_types.h	Mon Dec  8 23:58:04 1997
@@ -19,6 +19,7 @@
 typedef long		__kernel_ssize_t;
 typedef long		__kernel_ptrdiff_t;
 typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
 typedef long		__kernel_clock_t;
 typedef int		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
diff -u --recursive --new-file v2.1.71/linux/include/asm-sparc/byteorder.h linux/include/asm-sparc/byteorder.h
--- v2.1.71/linux/include/asm-sparc/byteorder.h	Thu Dec  4 14:53:56 1997
+++ linux/include/asm-sparc/byteorder.h	Fri Dec  5 05:42:59 1997
@@ -8,6 +8,6 @@
 #  define __SWAB_64_THRU_32__
 #endif
 
-#include <linux/byteorder_big_endian.h>
+#include <linux/byteorder/big_endian.h>
 
 #endif /* _SPARC_BYTEORDER_H */
diff -u --recursive --new-file v2.1.71/linux/include/asm-sparc/posix_types.h linux/include/asm-sparc/posix_types.h
--- v2.1.71/linux/include/asm-sparc/posix_types.h	Sat Nov  9 00:29:57 1996
+++ linux/include/asm-sparc/posix_types.h	Mon Dec  8 23:58:04 1997
@@ -17,6 +17,7 @@
 typedef int                    __kernel_ssize_t;
 typedef long int               __kernel_ptrdiff_t;
 typedef long                   __kernel_time_t;
+typedef long		       __kernel_suseconds_t;
 typedef long                   __kernel_clock_t;
 typedef int                    __kernel_pid_t;
 typedef unsigned short         __kernel_ipc_pid_t;
diff -u --recursive --new-file v2.1.71/linux/include/asm-sparc64/byteorder.h linux/include/asm-sparc64/byteorder.h
--- v2.1.71/linux/include/asm-sparc64/byteorder.h	Thu Dec  4 14:53:57 1997
+++ linux/include/asm-sparc64/byteorder.h	Fri Dec  5 05:42:43 1997
@@ -41,6 +41,6 @@
 
 #define __BYTEORDER_HAS_U64__
 
-#include <linux/byteorder_big_endian.h>
+#include <linux/byteorder/big_endian.h>
 
 #endif /* _SPARC64_BYTEORDER_H */
diff -u --recursive --new-file v2.1.71/linux/include/asm-sparc64/posix_types.h linux/include/asm-sparc64/posix_types.h
--- v2.1.71/linux/include/asm-sparc64/posix_types.h	Wed Apr 23 19:01:28 1997
+++ linux/include/asm-sparc64/posix_types.h	Mon Dec  8 23:58:04 1997
@@ -26,6 +26,9 @@
 typedef long                   __kernel_off_t;
 typedef char *                 __kernel_caddr_t;
 
+/* Note this piece of asymmetry from the v9 ABI.  */
+typedef int		       __kernel_suseconds_t;
+
 #ifdef __GNUC__
 typedef long long              __kernel_loff_t;
 #endif
diff -u --recursive --new-file v2.1.71/linux/include/linux/byteorder/big_endian.h linux/include/linux/byteorder/big_endian.h
--- v2.1.71/linux/include/linux/byteorder/big_endian.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/byteorder/big_endian.h	Fri Dec  5 05:40:24 1997
@@ -0,0 +1,56 @@
+#ifndef _LINUX_BYTEORDER_BIG_ENDIAN_H
+#define _LINUX_BYTEORDER_BIG_ENDIAN_H
+
+#ifndef __BIG_ENDIAN
+#define __BIG_ENDIAN 4321
+#endif
+#ifndef __BIG_ENDIAN_BITFIELD
+#define __BIG_ENDIAN_BITFIELD
+#endif
+
+#include <linux/byteorder/swab.h>
+
+#define __constant_htonl(x) ((__u32)(x))
+#define __constant_ntohl(x) ((__u32)(x))
+#define __constant_htons(x) ((__u16)(x))
+#define __constant_ntohs(x) ((__u16)(x))
+#define __cpu_to_le64(x) __swab64((x))
+#define __le64_to_cpu(x) __swab64((x))
+#define __cpu_to_le32(x) __swab32((x))
+#define __le32_to_cpu(x) __swab32((x))
+#define __cpu_to_le16(x) __swab16((x))
+#define __le16_to_cpu(x) __swab16((x))
+#define __cpu_to_be64(x) ((__u64)(x))
+#define __be64_to_cpu(x) ((__u64)(x))
+#define __cpu_to_be32(x) ((__u32)(x))
+#define __be32_to_cpu(x) ((__u32)(x))
+#define __cpu_to_be16(x) ((__u16)(x))
+#define __be16_to_cpu(x) ((__u16)(x))
+#define __cpu_to_le64p(x) __swab64p((x))
+#define __le64_to_cpup(x) __swab64p((x))
+#define __cpu_to_le32p(x) __swab32p((x))
+#define __le32_to_cpup(x) __swab32p((x))
+#define __cpu_to_le16p(x) __swab16p((x))
+#define __le16_to_cpup(x) __swab16p((x))
+#define __cpu_to_be64p(x) (*(__u64*)(x))
+#define __be64_to_cpup(x) (*(__u64*)(x))
+#define __cpu_to_be32p(x) (*(__u32*)(x))
+#define __be32_to_cpup(x) (*(__u32*)(x))
+#define __cpu_to_be16p(x) (*(__u16*)(x))
+#define __be16_to_cpup(x) (*(__u16*)(x))
+#define __cpu_to_le64s(x) __swab64s((x))
+#define __le64_to_cpus(x) __swab64s((x))
+#define __cpu_to_le32s(x) __swab32s((x))
+#define __le32_to_cpus(x) __swab32s((x))
+#define __cpu_to_le16s(x) __swab16s((x))
+#define __le16_to_cpus(x) __swab16s((x))
+#define __cpu_to_be64s(x) do {} while (0)
+#define __be64_to_cpus(x) do {} while (0)
+#define __cpu_to_be32s(x) do {} while (0)
+#define __be32_to_cpus(x) do {} while (0)
+#define __cpu_to_be16s(x) do {} while (0)
+#define __be16_to_cpus(x) do {} while (0)
+
+#include <linux/byteorder/generic.h>
+
+#endif /* _LINUX_BYTEORDER_BIG_ENDIAN_H */
diff -u --recursive --new-file v2.1.71/linux/include/linux/byteorder/generic.h linux/include/linux/byteorder/generic.h
--- v2.1.71/linux/include/linux/byteorder/generic.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/byteorder/generic.h	Fri Dec  5 11:01:37 1997
@@ -0,0 +1,165 @@
+#ifndef _LINUX_BYTEORDER_GENERIC_H
+#define _LINUX_BYTEORDER_GENERIC_H
+
+/*
+ * linux/byteorder_generic.h
+ * Generic Byte-reordering support
+ *
+ * Francois-Rene Rideau <rideau@ens.fr> 19970707
+ *    gathered all the good ideas from all asm-foo/byteorder.h into one file,
+ *    cleaned them up.
+ *    I hope it is compliant with non-GCC compilers.
+ *    I decided to put __BYTEORDER_HAS_U64__ in byteorder.h,
+ *    because I wasn't sure it would be ok to put it in types.h
+ *    Upgraded it to 2.1.43
+ * Francois-Rene Rideau <rideau@ens.fr> 19971012
+ *    Upgraded it to 2.1.57
+ *    to please Linus T., replaced huge #ifdef's between little/big endian
+ *    by nestedly #include'd files.
+ * Francois-Rene Rideau <rideau@ens.fr> 19971205
+ *    Made it to 2.1.71; now a facelift:
+ *    Put files under include/linux/byteorder/
+ *    Split swab from generic support.
+ *
+ * TODO:
+ *   = Regular kernel maintainers could also replace all these manual
+ *    byteswap macros that remain, disseminated among drivers,
+ *    after some grep or the sources...
+ *   = Linus might want to rename all these macros and files to fit his taste,
+ *    to fit his personal naming scheme.
+ *   = it seems that a few drivers would also appreciate
+ *    nybble swapping support...
+ *   = every architecture could add their byteswap macro in asm/byteorder.h
+ *    see how some architectures already do (i386, alpha, ppc, etc)
+ */
+
+/*
+ * The following macros are to be defined by <asm/byteorder.h>:
+ *
+ * Conversion of long and short int between network and host format
+ *	ntohl(__u32 x)
+ *	ntohs(__u16 x)
+ *	htonl(__u32 x)
+ *	htons(__u16 x)
+ * It seems that some programs (which? where? or perhaps a standard? POSIX?)
+ * might like the above to be functions, not macros (why?).
+ * if that's true, then detect them, and take measures.
+ * Anyway, the measure is: define only ___ntohl as a macro instead,
+ * and in a separate file, have
+ * unsigned long inline ntohl(x){return ___ntohl(x);}
+ *
+ * The same for constant arguments
+ *	__constant_ntohl(__u32 x)
+ *	__constant_ntohs(__u16 x)
+ *	__constant_htonl(__u32 x)
+ *	__constant_htons(__u16 x)
+ *
+ * Conversion of XX-bit integers (16- 32- or 64-)
+ * between native cpu format and little/big endian format
+ * 64-bit stuff only defined for proper architectures
+ *	cpu_to_[bl]eXX(__uXX x)
+ *	[bl]eXX_to_cpu(__uXX x)
+ *
+ * The same, but takes a pointer to the value to convert
+ *	cpu_to_[bl]eXXp(__uXX x)
+ *	[bl]eXX_to_cpup(__uXX x)
+ *
+ * The same, but change in situ
+ *	cpu_to_[bl]eXXs(__uXX x)
+ *	[bl]eXX_to_cpus(__uXX x)
+ *
+ * See asm-foo/byteorder.h for examples of how to provide
+ * architecture-optimized versions
+ *
+ */
+
+
+#if defined(__KERNEL__)
+/*
+ * inside the kernel, we can use nicknames;
+ * outside of it, we must avoid POSIX namespace pollution...
+ */
+#define cpu_to_le64 __cpu_to_le64
+#define le64_to_cpu __le64_to_cpu
+#define cpu_to_le32 __cpu_to_le32
+#define le32_to_cpu __le32_to_cpu
+#define cpu_to_le16 __cpu_to_le16
+#define le16_to_cpu __le16_to_cpu
+#define cpu_to_be64 __cpu_to_be64
+#define be64_to_cpu __be64_to_cpu
+#define cpu_to_be32 __cpu_to_be32
+#define be32_to_cpu __be32_to_cpu
+#define cpu_to_be16 __cpu_to_be16
+#define be16_to_cpu __be16_to_cpu
+#define cpu_to_le64p __cpu_to_le64p
+#define le64_to_cpup __le64_to_cpup
+#define cpu_to_le32p __cpu_to_le32p
+#define le32_to_cpup __le32_to_cpup
+#define cpu_to_le16p __cpu_to_le16p
+#define le16_to_cpup __le16_to_cpup
+#define cpu_to_be64p __cpu_to_be64p
+#define be64_to_cpup __be64_to_cpup
+#define cpu_to_be32p __cpu_to_be32p
+#define be32_to_cpup __be32_to_cpup
+#define cpu_to_be16p __cpu_to_be16p
+#define be16_to_cpup __be16_to_cpup
+#define cpu_to_le64s __cpu_to_le64s
+#define le64_to_cpus __le64_to_cpus
+#define cpu_to_le32s __cpu_to_le32s
+#define le32_to_cpus __le32_to_cpus
+#define cpu_to_le16s __cpu_to_le16s
+#define le16_to_cpus __le16_to_cpus
+#define cpu_to_be64s __cpu_to_be64s
+#define be64_to_cpus __be64_to_cpus
+#define cpu_to_be32s __cpu_to_be32s
+#define be32_to_cpus __be32_to_cpus
+#define cpu_to_be16s __cpu_to_be16s
+#define be16_to_cpus __be16_to_cpus
+#endif
+
+
+/*
+ * Handle ntohl and suches. These have various compatibility
+ * issues - like we want to give the prototype even though we
+ * also have a macro for them in case some strange program
+ * wants to take the address of the thing or something..
+ *
+ * Note that these traditionally return a "long", even though
+ * long is often 64-bit these days.. Thus the casts.
+ *
+ * They have to be macros in order to do the constant folding
+ * correctly - if the argument passed into a inline function
+ * it is no longer constant according to gcc..
+ */
+
+#undef ntohl
+#undef ntohs
+#undef htonl
+#undef htons
+
+/*
+ * Do the prototypes. Somebody might want to take the
+ * address or some such sick thing..
+ */
+extern unsigned long int	ntohl(unsigned long int);
+extern unsigned short int	ntohs(unsigned short int);
+extern unsigned long int	htonl(unsigned long int);
+extern unsigned short int	htons(unsigned short int);
+
+
+#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
+
+#define ___htonl(x) __cpu_to_be32(x)
+#define ___htons(x) __cpu_to_be16(x)
+#define ___ntohl(x) __be32_to_cpu(x)
+#define ___ntohs(x) __be16_to_cpu(x)
+
+#define htonl(x) ((unsigned long)___htonl(x))
+#define htons(x) ___htons(x)
+#define ntohl(x) ((unsigned long)___ntohl(x))
+#define ntohs(x) ___ntohs(x)
+
+#endif /* OPTIMIZE */
+
+
+#endif /* _LINUX_BYTEORDER_GENERIC_H */
diff -u --recursive --new-file v2.1.71/linux/include/linux/byteorder/little_endian.h linux/include/linux/byteorder/little_endian.h
--- v2.1.71/linux/include/linux/byteorder/little_endian.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/byteorder/little_endian.h	Sat Dec  6 11:32:49 1997
@@ -0,0 +1,56 @@
+#ifndef _LINUX_BYTEORDER_LITTLE_ENDIAN_H
+#define _LINUX_BYTEORDER_LITTLE_ENDIAN_H
+
+#ifndef __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN 1234
+#endif
+#ifndef __LITTLE_ENDIAN_BITFIELD
+#define __LITTLE_ENDIAN_BITFIELD
+#endif
+
+#include <linux/byteorder/swab.h>
+
+#define __constant_htonl(x) ___swab32((x))
+#define __constant_ntohl(x) ___swab32((x))
+#define __constant_htons(x) ___swab16((x))
+#define __constant_ntohs(x) ___swab16((x))
+#define __cpu_to_le64(x) ((__u64)(x))
+#define __le64_to_cpu(x) ((__u64)(x))
+#define __cpu_to_le32(x) ((__u32)(x))
+#define __le32_to_cpu(x) ((__u32)(x))
+#define __cpu_to_le16(x) ((__u16)(x))
+#define __le16_to_cpu(x) ((__u16)(x))
+#define __cpu_to_be64(x) __swab64((x))
+#define __be64_to_cpu(x) __swab64((x))
+#define __cpu_to_be32(x) __swab32((x))
+#define __be32_to_cpu(x) __swab32((x))
+#define __cpu_to_be16(x) __swab16((x))
+#define __be16_to_cpu(x) __swab16((x))
+#define __cpu_to_le64p(x) (*(__u64*)(x))
+#define __le64_to_cpup(x) (*(__u64*)(x))
+#define __cpu_to_le32p(x) (*(__u32*)(x))
+#define __le32_to_cpup(x) (*(__u32*)(x))
+#define __cpu_to_le16p(x) (*(__u16*)(x))
+#define __le16_to_cpup(x) (*(__u16*)(x))
+#define __cpu_to_be64p(x) __swab64p((x))
+#define __be64_to_cpup(x) __swab64p((x))
+#define __cpu_to_be32p(x) __swab32p((x))
+#define __be32_to_cpup(x) __swab32p((x))
+#define __cpu_to_be16p(x) __swab16p((x))
+#define __be16_to_cpup(x) __swab16p((x))
+#define __cpu_to_le64s(x) do {} while (0)
+#define __le64_to_cpus(x) do {} while (0)
+#define __cpu_to_le32s(x) do {} while (0)
+#define __le32_to_cpus(x) do {} while (0)
+#define __cpu_to_le16s(x) do {} while (0)
+#define __le16_to_cpus(x) do {} while (0)
+#define __cpu_to_be64s(x) __swab64s((x))
+#define __be64_to_cpus(x) __swab64s((x))
+#define __cpu_to_be32s(x) __swab32s((x))
+#define __be32_to_cpus(x) __swab32s((x))
+#define __cpu_to_be16s(x) __swab16s((x))
+#define __be16_to_cpus(x) __swab16s((x))
+
+#include <linux/byteorder/generic.h>
+
+#endif /* _LINUX_BYTEORDER_LITTLE_ENDIAN_H */
diff -u --recursive --new-file v2.1.71/linux/include/linux/byteorder/swab.h linux/include/linux/byteorder/swab.h
--- v2.1.71/linux/include/linux/byteorder/swab.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/byteorder/swab.h	Fri Dec  5 05:52:57 1997
@@ -0,0 +1,155 @@
+#ifndef _LINUX_BYTEORDER_SWAB_H
+#define _LINUX_BYTEORDER_SWAB_H
+
+/*
+ * linux/byteorder/swab.h
+ * Byteswapping, independently from cpu endianness
+ *	swabXX[ps]?(foo)
+ *
+ * Francois-Rene Rideau <rideau@ens.fr> 19971205
+ *    separated swab functions from cpu_to_XX,
+ *    to clean up support for bizarre-endian architectures.
+ *
+ * See asm-i386/byteorder.h and suches for examples of how to provide
+ * architecture-dependent optimized versions
+ *
+ */
+
+#define ___swab16(x) \
+	((__u16)( \
+		(((__u16)(x) & 0x00ffU) << 8) | \
+		(((__u16)(x) & 0xff00U) >> 8) ))
+#define ___swab32(x) \
+	((__u32)( \
+		(((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
+		(((__u32)(x) & (__u32)0x0000ff00UL) <<  8) | \
+		(((__u32)(x) & (__u32)0x00ff0000UL) >>  8) | \
+		(((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
+#define ___swab64(x) \
+	((__u64)( \
+		(__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \
+		(__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \
+		(__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \
+		(__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) <<  8) | \
+	        (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >>  8) | \
+		(__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
+		(__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \
+		(__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) ))
+
+/*
+ * provide defaults when no architecture-specific optimization is detected
+ */
+#ifndef __arch__swab16
+#  define __arch__swab16(x) ___swab16(x)
+#endif
+#ifndef __arch__swab32
+#  define __arch__swab32(x) ___swab32(x)
+#endif
+#ifndef __arch__swab64
+#  define __arch__swab64(x) ___swab64(x)
+#endif
+
+#ifndef __arch__swab16p
+#  define __arch__swab16p(x) __swab16(*(x))
+#endif
+#ifndef __arch__swab32p
+#  define __arch__swab32p(x) __swab32(*(x))
+#endif
+#ifndef __arch__swab64p
+#  define __arch__swab64p(x) __swab64(*(x))
+#endif
+
+#ifndef __arch__swab16s
+#  define __arch__swab16s(x) do { *(x) = __swab16p((x)); } while (0)
+#endif
+#ifndef __arch__swab32s
+#  define __arch__swab32s(x) do { *(x) = __swab32p((x)); } while (0)
+#endif
+#ifndef __arch__swab64s
+#  define __arch__swab64s(x) do { *(x) = __swab64p((x)); } while (0)
+#endif
+
+
+/*
+ * Allow constant folding
+ */
+#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
+#  define __swab16(x) \
+(__builtin_constant_p((__u16)(x)) ? \
+ ___swab16((x)) : \
+ __fswab16((x)))
+#  define __swab32(x) \
+(__builtin_constant_p((__u32)(x)) ? \
+ ___swab32((x)) : \
+ __fswab32((x)))
+#  define __swab64(x) \
+(__builtin_constant_p((__u64)(x)) ? \
+ ___swab64((x)) : \
+ __fswab64((x)))
+#else
+#  define __swab16(x) __fswab16(x)
+#  define __swab32(x) __fswab32(x)
+#  define __swab64(x) __fswab64(x)
+#endif /* OPTIMIZE */
+
+
+extern __inline__ __const__ __u16 __fswab16(__u16 x)
+{
+	return __arch__swab16(x);
+}
+extern __inline__ __u16 __swab16p(__u16 *x)
+{
+	return __arch__swab16p(x);
+}
+extern __inline__ void __swab16s(__u16 *addr)
+{
+	__arch__swab16s(addr);
+}
+
+extern __inline__ __const__ __u32 __fswab32(__u32 x)
+{
+	return __arch__swab32(x);
+}
+extern __inline__ __u32 __swab32p(__u32 *x)
+{
+	return __arch__swab32p(x);
+}
+extern __inline__ void __swab32s(__u32 *addr)
+{
+	__arch__swab32s(addr);
+}
+
+#ifdef __BYTEORDER_HAS_U64__
+extern __inline__ __const__ __u64 __fswab64(__u64 x)
+{
+#  ifdef __SWAB_64_THRU_32__
+	__u32 h = x >> 32;
+        __u32 l = x & ((1ULL<<32)-1);
+        return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h)));
+#  else
+	return __arch__swab64(x);
+#  endif
+}
+extern __inline__ __u64 __swab64p(__u64 *x)
+{
+	return __arch__swab64p(x);
+}
+extern __inline__ void __swab64s(__u64 *addr)
+{
+	__arch__swab64s(addr);
+}
+#endif /* __BYTEORDER_HAS_U64__ */
+
+#if defined(__KERNEL__)
+#define swab16 __swab16
+#define swab32 __swab32
+#define swab64 __swab64
+#define swab16p __swab16p
+#define swab32p __swab32p
+#define swab64p __swab64p
+#define swab16s __swab16s
+#define swab32s __swab32s
+#define swab64s __swab64s
+#endif
+
+#endif /* _LINUX_BYTEORDER_SWAB_H */
diff -u --recursive --new-file v2.1.71/linux/include/linux/byteorder/swabb.h linux/include/linux/byteorder/swabb.h
--- v2.1.71/linux/include/linux/byteorder/swabb.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/byteorder/swabb.h	Fri Dec  5 05:55:56 1997
@@ -0,0 +1,122 @@
+#ifndef _LINUX_BYTEORDER_SWABB_H
+#define _LINUX_BYTEORDER_SWABB_H
+
+/*
+ * linux/byteorder/swabb.h
+ * SWAp Bytes Bizarrely
+ *	swaHHXX[ps]?(foo)
+ *
+ * Support for obNUXIous vax-endian and other bizarre architectures...
+ *
+ */
+
+/*
+ * Meaning of the names I chose (vaxlinux people feel free to correct them):
+ * swahw32	swap 16-bit half-words in a 32-bit word
+ * swahb32	swap 8-bit halves of each 16-bit half-word in a 32-bit word
+ *
+ * No 64-bit support yet. I don't know VAX conventions for long longs.
+ * I guarantee it will be a mess when it's there, though :->
+ * It will be even worse if there are conflicting 64-bit conventions for vaxen
+ *
+ * Note that if communicating with vax machines becomes useful in some kernel
+ * FS driver, we'd have to move that mess into byteorder/swab.h, and
+ * create cpu_to_ve32 and suches. Ouch.
+ */
+
+
+#define ___swahw32(x) \
+	((__u32)( \
+		(((__u32)(x) & (__u32)0x0000ffffUL) << 16) | \
+		(((__u32)(x) & (__u32)0xffff0000UL) >> 16) ))
+#define ___swahb32(x) \
+	((__u32)( \
+		(((__u32)(x) & (__u32)0x00ff00ffUL) << 16) | \
+		(((__u32)(x) & (__u32)0xff00ff00UL) >> 16) ))
+
+/*
+ * provide defaults when no architecture-specific optimization is detected
+ */
+#ifndef __arch__swahw32
+#  define __arch__swahw32(x) ___swahw32(x)
+#endif
+#ifndef __arch__swahb32
+#  define __arch__swahb32(x) ___swahb32(x)
+#endif
+
+#ifndef __arch__swahw32p
+#  define __arch__swahw32p(x) __swahw32(*(x))
+#endif
+#ifndef __arch__swahb32p
+#  define __arch__swahb32p(x) __swahb32(*(x))
+#endif
+
+#ifndef __arch__swahw32s
+#  define __arch__swahw32s(x) do { *(x) = __swahw32p((x)); } while (0)
+#endif
+#ifndef __arch__swahb32s
+#  define __arch__swahb32s(x) do { *(x) = __swahb32p((x)); } while (0)
+#endif
+
+
+/*
+ * Allow constant folding
+ */
+#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
+#  define __swahw32(x) \
+(__builtin_constant_p((__u32)(x)) ? \
+ ___swahw32((x)) : \
+ __fswahw32((x)))
+#  define __swahb32(x) \
+(__builtin_constant_p((__u32)(x)) ? \
+ ___swahb32((x)) : \
+ __fswahb32((x)))
+#else
+#  define __swahw32(x) __fswahw32(x)
+#  define __swahb32(x) __fswahb32(x)
+#endif /* OPTIMIZE */
+
+
+extern __inline__ __const__ __u32 __fswahw32(__u32 x)
+{
+	return __arch__swahw32(x);
+}
+extern __inline__ __u32 __swahw32p(__u32 *x)
+{
+	return __arch__swahw32p(x);
+}
+extern __inline__ void __swahw32s(__u32 *addr)
+{
+	__arch__swahw32s(addr);
+}
+
+
+extern __inline__ __const__ __u32 __fswahb32(__u32 x)
+{
+	return __arch__swahb32(x);
+}
+extern __inline__ __u32 __swahb32p(__u32 *x)
+{
+	return __arch__swahb32p(x);
+}
+extern __inline__ void __swahb32s(__u32 *addr)
+{
+	__arch__swahb32s(addr);
+}
+
+#ifdef __BYTEORDER_HAS_U64__
+/*
+ * Not supported yet
+ */
+#endif /* __BYTEORDER_HAS_U64__ */
+
+#if defined(__KERNEL__)
+#define swahw32 __swahw32
+#define swahb32 __swahb32
+#define swahw32p __swahw32p
+#define swahb32p __swahb32p
+#define swahw32s __swahw32s
+#define swahb32s __swahb32s
+#endif
+
+#endif /* _LINUX_BYTEORDER_SWABB_H */
diff -u --recursive --new-file v2.1.71/linux/include/linux/byteorder/vax_endian.h linux/include/linux/byteorder/vax_endian.h
--- v2.1.71/linux/include/linux/byteorder/vax_endian.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/byteorder/vax_endian.h	Fri Dec  5 05:41:35 1997
@@ -0,0 +1,69 @@
+#ifndef _LINUX_BYTEORDER_VAX_ENDIAN_H
+#define _LINUX_BYTEORDER_VAX_ENDIAN_H
+
+/*
+ * Could have been named NUXI-endian
+ * This file *should* work, but has not been tested.
+ * It's the beginning of what vaxlinux implementers will have to do.
+ * I just hope we won't have to write standardized cpu_to_ve32() and suches!
+ * little endian is 1234; bigendian is 4321; vaxendian is 3412
+ *
+ * But what does a __u64 look like: is it 34127856 or 78563412 ???
+ * I don't dare imagine! Hence, no 64-bit byteorder support yet.
+ *
+ */
+
+#ifndef __VAX_ENDIAN
+#define __VAX_ENDIAN 3412
+#endif
+#ifndef __VAX_ENDIAN_BITFIELD
+#define __VAX_ENDIAN_BITFIELD
+#endif
+
+#include <linux/byteorder/swab.h>
+#include <linux/byteorder/swabb.h>
+
+#define __constant_htonl(x) ___swahb32((x))
+#define __constant_ntohl(x) ___swahb32((x))
+#define __constant_htons(x) ___swab16((x))
+#define __constant_ntohs(x) ___swab16((x))
+#define __cpu_to_le64(x) I DON'T KNOW
+#define __le64_to_cpu(x) I DON'T KNOW
+#define __cpu_to_le32(x) ___swahw32((x))
+#define __le32_to_cpu(x) ___swahw32((x))
+#define __cpu_to_le16(x) ((__u16)(x)
+#define __le16_to_cpu(x) ((__u16)(x)
+#define __cpu_to_be64(x) I DON'T KNOW
+#define __be64_to_cpu(x) I DON'T KNOW
+#define __cpu_to_be32(x) __swahb32((x))
+#define __be32_to_cpu(x) __swahb32((x))
+#define __cpu_to_be16(x) __swab16((x))
+#define __be16_to_cpu(x) __swab16((x))
+#define __cpu_to_le64p(x) I DON'T KNOW
+#define __le64_to_cpup(x) I DON'T KNOW
+#define __cpu_to_le32p(x) ___swahw32p((x))
+#define __le32_to_cpup(x) ___swahw32p((x))
+#define __cpu_to_le16p(x) (*(__u16*)(x))
+#define __le16_to_cpup(x) (*(__u16*)(x))
+#define __cpu_to_be64p(x) I DON'T KNOW
+#define __be64_to_cpup(x) I DON'T KNOW
+#define __cpu_to_be32p(x) __swahb32p((x))
+#define __be32_to_cpup(x) __swahb32p((x))
+#define __cpu_to_be16p(x) __swab16p((x))
+#define __be16_to_cpup(x) __swab16p((x))
+#define __cpu_to_le64s(x) I DON'T KNOW
+#define __le64_to_cpus(x) I DON'T KNOW
+#define __cpu_to_le32s(x) ___swahw32s((x))
+#define __le32_to_cpus(x) ___swahw32s((x))
+#define __cpu_to_le16s(x) do {} while (0)
+#define __le16_to_cpus(x) do {} while (0)
+#define __cpu_to_be64s(x) I DON'T KNOW
+#define __be64_to_cpus(x) I DON'T KNOW
+#define __cpu_to_be32s(x) __swahb32s((x))
+#define __be32_to_cpus(x) __swahb32s((x))
+#define __cpu_to_be16s(x) __swab16s((x))
+#define __be16_to_cpus(x) __swab16s((x))
+
+#include <linux/byteorder/generic.h>
+
+#endif /* _LINUX_BYTEORDER_VAX_ENDIAN_H */
diff -u --recursive --new-file v2.1.71/linux/include/linux/byteorder_big_endian.h linux/include/linux/byteorder_big_endian.h
--- v2.1.71/linux/include/linux/byteorder_big_endian.h	Thu Dec  4 14:53:57 1997
+++ linux/include/linux/byteorder_big_endian.h	Wed Dec 31 16:00:00 1969
@@ -1,54 +0,0 @@
-#ifndef _LINUX_BYTEORDER_BIG_ENDIAN_H
-#define _LINUX_BYTEORDER_BIG_ENDIAN_H
-
-#ifndef __BIG_ENDIAN
-#define __BIG_ENDIAN 4321
-#endif
-#ifndef __BIG_ENDIAN_BITFIELD
-#define __BIG_ENDIAN_BITFIELD
-#endif
-
-#define __constant_htonl(x) ((__u32)(x))
-#define __constant_ntohl(x) ((__u32)(x))
-#define __constant_htons(x) ((__u16)(x))
-#define __constant_ntohs(x) ((__u16)(x))
-#define __cpu_to_le64(x) __swab64((x))
-#define __le64_to_cpu(x) __swab64((x))
-#define __cpu_to_le32(x) __swab32((x))
-#define __le32_to_cpu(x) __swab32((x))
-#define __cpu_to_le16(x) __swab16((x))
-#define __le16_to_cpu(x) __swab16((x))
-#define __cpu_to_be64(x) ((__u64)(x))
-#define __be64_to_cpu(x) ((__u64)(x))
-#define __cpu_to_be32(x) ((__u32)(x))
-#define __be32_to_cpu(x) ((__u32)(x))
-#define __cpu_to_be16(x) ((__u16)(x))
-#define __be16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_le64p(x) __swab64p((x))
-#define __le64_to_cpup(x) __swab64p((x))
-#define __cpu_to_le32p(x) __swab32p((x))
-#define __le32_to_cpup(x) __swab32p((x))
-#define __cpu_to_le16p(x) __swab16p((x))
-#define __le16_to_cpup(x) __swab16p((x))
-#define __cpu_to_be64p(x) (*(__u64*)(x))
-#define __be64_to_cpup(x) (*(__u64*)(x))
-#define __cpu_to_be32p(x) (*(__u32*)(x))
-#define __be32_to_cpup(x) (*(__u32*)(x))
-#define __cpu_to_be16p(x) (*(__u16*)(x))
-#define __be16_to_cpup(x) (*(__u16*)(x))
-#define __cpu_to_le64s(x) __swab64s((x))
-#define __le64_to_cpus(x) __swab64s((x))
-#define __cpu_to_le32s(x) __swab32s((x))
-#define __le32_to_cpus(x) __swab32s((x))
-#define __cpu_to_le16s(x) __swab16s((x))
-#define __le16_to_cpus(x) __swab16s((x))
-#define __cpu_to_be64s(x) do {} while (0)
-#define __be64_to_cpus(x) do {} while (0)
-#define __cpu_to_be32s(x) do {} while (0)
-#define __be32_to_cpus(x) do {} while (0)
-#define __cpu_to_be16s(x) do {} while (0)
-#define __be16_to_cpus(x) do {} while (0)
-
-#include <linux/byteorder_generic.h>
-
-#endif /* _LINUX_BYTEORDER_BIG_ENDIAN_H */
diff -u --recursive --new-file v2.1.71/linux/include/linux/byteorder_generic.h linux/include/linux/byteorder_generic.h
--- v2.1.71/linux/include/linux/byteorder_generic.h	Thu Dec  4 14:53:57 1997
+++ linux/include/linux/byteorder_generic.h	Wed Dec 31 16:00:00 1969
@@ -1,298 +0,0 @@
-#ifndef _LINUX_BYTEORDER_GENERIC_H
-#define _LINUX_BYTEORDER_GENERIC_H
-
-/*
- * linux/byteorder_generic.h
- * Generic Byteswap support
- *
- * Francois-Rene Rideau <rideau@ens.fr> 19970707
- *    gathered all the good ideas from all asm-foo/byteorder.h into one file,
- *    cleaned them up.
- *    I hope it is compliant with non-GCC compilers.
- *    I decided to put __BYTEORDER_HAS_U64__ in byteorder.h,
- *    because I wasn't sure it would be ok to put it in types.h
- *    Upgraded it to 2.1.43
- * Francois-Rene Rideau <rideau@ens.fr> 19971012
- *    Upgraded it to 2.1.57
- *    to please Linus T., replaced huge #ifdef's between little/big endian
- *    by nestedly #include'd files.
- *
- * TODO:
- *   = Regular kernel maintainers could also replace all these manual
- *    byteswap macros that remain, disseminated among drivers,
- *    after some grep or the sources...
- *   = Linus might want to rename all these macros and files to fit his taste,
- *    to fit his personal naming scheme.
- *   = it seems that many drivers would also appreciate
- *    nybble swapping support...
- *   = every architecture could add their byteswap macro in asm/byteorder.h
- *    see how some architectures already do (i386, alpha, ppc, etc)
- */
-
-/*
- * This file is included by both <linux/byteorder_little_endian.h> and
- * <linux/byteorder_big_endian.h>. People porting from machines with
- * bizarre bytedisorder (like the VAX?) will have to write a different one.
- * Actually, this file mostly does byteswapping, and could be named
- * <byteswap.h> or <swab.h> rather than <linux/byteorder_generic.h>
- *
- */
-
-/*
- * The following macros are to be defined by <asm/byteorder.h>:
- *
- * Conversion of long and short int between network and host format
- *	ntohl(__u32 x)
- *	ntohs(__u16 x)
- *	htonl(__u32 x)
- *	htons(__u16 x)
- * It seems that some programs (which? where? or perhaps a standard? POSIX?)
- * might like the above to be functions, not macros (why?).
- * if that's true, then detect them, and take measures.
- * Anyway, the measure is: define only ___ntohl as a macro instead,
- * and in a separate file, have
- * unsigned long inline ntohl(x){return ___ntohl(x);}
- *
- * The same for constant arguments
- *	__constant_ntohl(__u32 x)
- *	__constant_ntohs(__u16 x)
- *	__constant_htonl(__u32 x)
- *	__constant_htons(__u16 x)
- *
- * Conversion of XX-bit integers (16- 32- or 64-)
- * between native cpu format and little/big endian format
- * 64-bit stuff only defined for proper architectures
- *	cpu_to_[bl]eXX(__uXX x)
- *	[bl]eXX_to_cpu(__uXX x)
- *
- * The same, but takes a pointer to the value to convert
- *	cpu_to_[bl]eXXp(__uXX x)
- *	[bl]eXX_to_cpup(__uXX x)
- *
- * The same, but change in situ
- *	cpu_to_[bl]eXXs(__uXX x)
- *	[bl]eXX_to_cpus(__uXX x)
- *
- * Byteswapping, independently from cpu endianness
- *	swabXX[ps]?(foo)
- *
- *
- * See asm-foo/byteorder.h for examples of how to provide
- * architecture-optimized versions
- *
- */
-
-#include <asm/types.h>
-
-/*
- * Generic byte swapping routines. We fall back on
- * these if we don't have any optimized code, and
- * when we have constants that we want the compiler
- * to byte swap for us..
- */
-#define ___swab16(x) \
-	((__u16)( \
-		(((__u16)(x) & 0x00ffU) << 8) | \
-		(((__u16)(x) & 0xff00U) >> 8) ))
-#define ___swab32(x) \
-	((__u32)( \
-		(((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
-		(((__u32)(x) & (__u32)0x0000ff00UL) <<  8) | \
-		(((__u32)(x) & (__u32)0x00ff0000UL) >>  8) | \
-		(((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
-#define ___swab64(x) \
-	((__u64)( \
-		(__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \
-		(__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \
-		(__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \
-		(__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) <<  8) | \
-	        (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >>  8) | \
-		(__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
-		(__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \
-		(__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) ))
-
-/*
- * These do constant folding - this allows the
- * compiler to do any constants at compile
- * time.  Any architecture inline asm optimizations
- * would be pessimizations.
- */
-#define __swab16(x) \
-	(__builtin_constant_p((__u16)(x)) ? \
-	 ___swab16((x)) : __fswab16((x)))
-#define __swab32(x) \
-	(__builtin_constant_p((__u32)(x)) ? \
-	 ___swab32((x)) : __fswab32((x)))
-#define __swab64(x) \
-	(__builtin_constant_p((__u64)(x)) ? \
-	 ___swab64((x)) : __fswab64((x)))
-
-
-/*
- * provide defaults when no architecture-specific optimization is detected
- */
-#ifndef __arch__swab16
-#  define __arch__swab16(x) ___swab16(x)
-#endif
-#ifndef __arch__swab32
-#  define __arch__swab32(x) ___swab32(x)
-#endif
-#ifndef __arch__swab64
-#  define __arch__swab64(x) ___swab64(x)
-#endif
-
-#ifndef __arch__swab16p
-#  define __arch__swab16p(x) __swab16(*(x))
-#endif
-#ifndef __arch__swab32p
-#  define __arch__swab32p(x) __swab32(*(x))
-#endif
-#ifndef __arch__swab64p
-#  define __arch__swab64p(x) __swab64(*(x))
-#endif
-
-#ifndef __arch__swab16s
-#  define __arch__swab16s(x) *(x) = __swab16p((x))
-#endif
-#ifndef __arch__swab32s
-#  define __arch__swab32s(x) *(x) = __swab32p((x))
-#endif
-#ifndef __arch__swab64s
-#  define __arch__swab64s(x) *(x) = __swab64p((x))
-#endif
-
-
-extern __inline__ __const__ __u16 __fswab16(__u16 x)
-{
-	return __arch__swab16(x);
-}
-extern __inline__ __u16 __swab16p(__u16 *x)
-{
-	return __arch__swab16p(x);
-}
-extern __inline__ void __swab16s(__u16 *addr)
-{
-	__arch__swab16s(addr);
-}
-
-extern __inline__ __const__ __u32 __fswab32(__u32 x)
-{
-	return __arch__swab32(x);
-}
-extern __inline__ __u32 __swab32p(__u32 *x)
-{
-	return __arch__swab32p(x);
-}
-extern __inline__ void __swab32s(__u32 *addr)
-{
-	__arch__swab32s(addr);
-}
-
-#ifdef __BYTEORDER_HAS_U64__
-extern __inline__ __const__ __u64 __fswab64(__u64 x)
-{
-#  ifdef __SWAB_64_THRU_32__
-	__u32 h = x >> 32;
-        __u32 l = x & ((1ULL<<32)-1);
-        return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h)));
-#  else
-	return __arch__swab64(x);
-#  endif
-}
-extern __inline__ __u64 __swab64p(__u64 *x)
-{
-	return __arch__swab64p(x);
-}
-extern __inline__ void __swab64s(__u64 *addr)
-{
-	__arch__swab64s(addr);
-}
-#endif /* __BYTEORDER_HAS_U64__ */
-
-#if defined(__KERNEL__) || defined(__REQUIRE_CPU_TO_XX)
-#define swab16 __swab16
-#define swab32 __swab32
-#define swab64 __swab64
-#define swab16p __swab16p
-#define swab32p __swab32p
-#define swab64p __swab64p
-#define swab16s __swab16s
-#define swab32s __swab32s
-#define swab64s __swab64s
-#define cpu_to_le64 __cpu_to_le64
-#define le64_to_cpu __le64_to_cpu
-#define cpu_to_le32 __cpu_to_le32
-#define le32_to_cpu __le32_to_cpu
-#define cpu_to_le16 __cpu_to_le16
-#define le16_to_cpu __le16_to_cpu
-#define cpu_to_be64 __cpu_to_be64
-#define be64_to_cpu __be64_to_cpu
-#define cpu_to_be32 __cpu_to_be32
-#define be32_to_cpu __be32_to_cpu
-#define cpu_to_be16 __cpu_to_be16
-#define be16_to_cpu __be16_to_cpu
-#define cpu_to_le64p __cpu_to_le64p
-#define le64_to_cpup __le64_to_cpup
-#define cpu_to_le32p __cpu_to_le32p
-#define le32_to_cpup __le32_to_cpup
-#define cpu_to_le16p __cpu_to_le16p
-#define le16_to_cpup __le16_to_cpup
-#define cpu_to_be64p __cpu_to_be64p
-#define be64_to_cpup __be64_to_cpup
-#define cpu_to_be32p __cpu_to_be32p
-#define be32_to_cpup __be32_to_cpup
-#define cpu_to_be16p __cpu_to_be16p
-#define be16_to_cpup __be16_to_cpup
-#define cpu_to_le64s __cpu_to_le64s
-#define le64_to_cpus __le64_to_cpus
-#define cpu_to_le32s __cpu_to_le32s
-#define le32_to_cpus __le32_to_cpus
-#define cpu_to_le16s __cpu_to_le16s
-#define le16_to_cpus __le16_to_cpus
-#define cpu_to_be64s __cpu_to_be64s
-#define be64_to_cpus __be64_to_cpus
-#define cpu_to_be32s __cpu_to_be32s
-#define be32_to_cpus __be32_to_cpus
-#define cpu_to_be16s __cpu_to_be16s
-#define be16_to_cpus __be16_to_cpus
-#endif
-
-/*
- * Handle ntohl and suches. These have various compatibility
- * issues - like we want to give the prototype even though we
- * also have a macro for them in case some strange program
- * wants to take the address of the thing or something..
- *
- * Note that these traditionally return a "long", even though
- * long is often 64-bit these days.. Thus the casts.
- *
- * They have to be macros in order to do the constant folding
- * correctly - if the argument passed into a inline function
- * it is no longer constant according to gcc..
- */
-
-#undef ntohl
-#undef ntohs
-#undef htonl
-#undef htons
-
-/*
- * Do the prototypes. Somebody might want to take the
- * address or some such sick thing..
- */
-extern unsigned long int	ntohl(unsigned long int);
-extern unsigned short int	ntohs(unsigned short int);
-extern unsigned long int	htonl(unsigned long int);
-extern unsigned short int	htons(unsigned short int);
-
-#define ___htonl(x) __cpu_to_be32(x)
-#define ___htons(x) __cpu_to_be16(x)
-#define ___ntohl(x) __be32_to_cpu(x)
-#define ___ntohs(x) __be16_to_cpu(x)
-
-#define htonl(x) ((unsigned long)___htonl(x))
-#define htons(x) ___htons(x)
-#define ntohl(x) ((unsigned long)___ntohl(x))
-#define ntohs(x) ___ntohs(x)
-
-#endif /* _LINUX_BYTEORDER_H */
diff -u --recursive --new-file v2.1.71/linux/include/linux/byteorder_little_endian.h linux/include/linux/byteorder_little_endian.h
--- v2.1.71/linux/include/linux/byteorder_little_endian.h	Thu Dec  4 14:53:57 1997
+++ linux/include/linux/byteorder_little_endian.h	Wed Dec 31 16:00:00 1969
@@ -1,54 +0,0 @@
-#ifndef _LINUX_BYTEORDER_LITTLE_ENDIAN_H
-#define _LINUX_BYTEORDER_LITTLE_ENDIAN_H
-
-#ifndef __LITTLE_ENDIAN
-#define __LITTLE_ENDIAN 1234
-#endif
-#ifndef __LITTLE_ENDIAN_BITFIELD
-#define __LITTLE_ENDIAN_BITFIELD
-#endif
-
-#define __constant_htonl(x) ___swab32((x))
-#define __constant_ntohl(x) ___swab32((x))
-#define __constant_htons(x) ___swab16((x))
-#define __constant_ntohs(x) ___swab16((x))
-#define __cpu_to_le64(x) ((__u64)(x))
-#define __le64_to_cpu(x) ((__u64)(x))
-#define __cpu_to_le32(x) ((__u32)(x))
-#define __le32_to_cpu(x) ((__u32)(x))
-#define __cpu_to_le16(x) ((__u16)(x))
-#define __le16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_be64(x) __swab64((x))
-#define __be64_to_cpu(x) __swab64((x))
-#define __cpu_to_be32(x) __swab32((x))
-#define __be32_to_cpu(x) __swab32((x))
-#define __cpu_to_be16(x) __swab16((x))
-#define __be16_to_cpu(x) __swab16((x))
-#define __cpu_to_le64p(x) (*(__u64*)(x))
-#define __le64_to_cpup(x) (*(__u64*)(x))
-#define __cpu_to_le32p(x) (*(__u32*)(x))
-#define __le32_to_cpup(x) (*(__u32*)(x))
-#define __cpu_to_le16p(x) (*(__u16*)(x))
-#define __le16_to_cpup(x) (*(__u16*)(x))
-#define __cpu_to_be64p(x) __swab64p((x))
-#define __be64_to_cpup(x) __swab64p((x))
-#define __cpu_to_be32p(x) __swab32p((x))
-#define __be32_to_cpup(x) __swab32p((x))
-#define __cpu_to_be16p(x) __swab16p((x))
-#define __be16_to_cpup(x) __swab16p((x))
-#define __cpu_to_le64s(x) do {} while (0)
-#define __le64_to_cpus(x) do {} while (0)
-#define __cpu_to_le32s(x) do {} while (0)
-#define __le32_to_cpus(x) do {} while (0)
-#define __cpu_to_le16s(x) do {} while (0)
-#define __le16_to_cpus(x) do {} while (0)
-#define __cpu_to_be64s(x) __swab64s((x))
-#define __be64_to_cpus(x) __swab64s((x))
-#define __cpu_to_be32s(x) __swab32s((x))
-#define __be32_to_cpus(x) __swab32s((x))
-#define __cpu_to_be16s(x) __swab16s((x))
-#define __be16_to_cpus(x) __swab16s((x))
-
-#include <linux/byteorder_generic.h>
-
-#endif /* _LINUX_BYTEORDER_LITTLE_ENDIAN_H */
diff -u --recursive --new-file v2.1.71/linux/include/linux/byteorder_vaxendian.h linux/include/linux/byteorder_vaxendian.h
--- v2.1.71/linux/include/linux/byteorder_vaxendian.h	Thu Dec  4 14:53:57 1997
+++ linux/include/linux/byteorder_vaxendian.h	Wed Dec 31 16:00:00 1969
@@ -1,94 +0,0 @@
-#ifndef _LINUX_BYTEORDER_VAX_ENDIAN_H
-#define _LINUX_BYTEORDER_VAX_ENDIAN_H
-
-/*
- * Could have been named NUXI-endian
- * This file isn't operational.
- * It's the beginning of what vaxlinux implementers will have to do.
- * I just hope we won't have to write standardized cpu_to_ve32() and suches!
- * little endian is 1234; bigendian is 4321; vaxendian is 3412
- * But what does a __u64 look like: is it 34127856 or 78563412 ???
- * I don't dare imagine!
- */
-
-#ifndef __VAX_ENDIAN
-#define __VAX_ENDIAN 3412
-#endif
-#ifndef __VAX_ENDIAN_BITFIELD
-#define __VAX_ENDIAN_BITFIELD
-#endif
-
-#define ___swahw32(x) \
-	((__u32)( \
-		(((__u32)(x) & (__u32)0x0000ffffUL) << 16) | \
-		(((__u32)(x) & (__u32)0xffff0000UL) >> 16) ))
-#define ___swahb32(x) \
-	((__u32)( \
-		(((__u32)(x) & (__u32)0x00ff00ffUL) << 16) | \
-		(((__u32)(x) & (__u32)0xff00ff00UL) >> 16) ))
-
-
-#ifndef __arch__swahw32
-#  define __arch__swahw32(x) ___swahw32(x)
-#endif
-#ifndef __arch__swahb32
-#  define __arch__swahb32(x) ___swahb32(x)
-#endif
-#ifndef __arch__swahw32p
-#  define __arch__swahw32p(x) __swahw32(*(x))
-#endif
-#ifndef __arch__swahb32p
-#  define __arch__swahb32p(x) __swahb32(*(x))
-#endif
-#ifndef __arch__swahw32s
-#  define __arch__swahw32s(x) *(x) = __swahw32p((x))
-#endif
-#ifndef __arch__swahb32s
-#  define __arch__swahb32s(x) *(x) = __swahb32p((x))
-#endif
-
-
-#define __constant_htonl(x) ___swahb32((x))
-#define __constant_ntohl(x) ___swahb32((x))
-#define __constant_htons(x) ___swab16((x))
-#define __constant_ntohs(x) ___swab16((x))
-#define __cpu_to_le64(x) I DON'T KNOW
-#define __le64_to_cpu(x) I DON'T KNOW
-#define __cpu_to_le32(x) ___swahw32((x))
-#define __le32_to_cpu(x) ___swahw32((x))
-#define __cpu_to_le16(x) ((__u16)(x)
-#define __le16_to_cpu(x) ((__u16)(x)
-#define __cpu_to_be64(x) I DON'T KNOW
-#define __be64_to_cpu(x) I DON'T KNOW
-#define __cpu_to_be32(x) __swahb32((x))
-#define __be32_to_cpu(x) __swahb32((x))
-#define __cpu_to_be16(x) __swab16((x))
-#define __be16_to_cpu(x) __swab16((x))
-#define __cpu_to_le64p(x) I DON'T KNOW
-#define __le64_to_cpup(x) I DON'T KNOW
-#define __cpu_to_le32p(x) ___swahw32p((x))
-#define __le32_to_cpup(x) ___swahw32p((x))
-#define __cpu_to_le16p(x) (*(__u16*)(x))
-#define __le16_to_cpup(x) (*(__u16*)(x))
-#define __cpu_to_be64p(x) I DON'T KNOW
-#define __be64_to_cpup(x) I DON'T KNOW
-#define __cpu_to_be32p(x) __swahb32p((x))
-#define __be32_to_cpup(x) __swahb32p((x))
-#define __cpu_to_be16p(x) __swab16p((x))
-#define __be16_to_cpup(x) __swab16p((x))
-#define __cpu_to_le64s(x) I DON'T KNOW
-#define __le64_to_cpus(x) I DON'T KNOW
-#define __cpu_to_le32s(x) ___swahw32s((x))
-#define __le32_to_cpus(x) ___swahw32s((x))
-#define __cpu_to_le16s(x) do {} while (0)
-#define __le16_to_cpus(x) do {} while (0)
-#define __cpu_to_be64s(x) I DON'T KNOW
-#define __be64_to_cpus(x) I DON'T KNOW
-#define __cpu_to_be32s(x) __swahb32s((x))
-#define __be32_to_cpus(x) __swahb32s((x))
-#define __cpu_to_be16s(x) __swab16s((x))
-#define __be16_to_cpus(x) __swab16s((x))
-
-#include <linux/byteorder_generic.h>
-
-#endif /* _LINUX_BYTEORDER_VAX_ENDIAN_H */
diff -u --recursive --new-file v2.1.71/linux/include/linux/coda.h linux/include/linux/coda.h
--- v2.1.71/linux/include/linux/coda.h	Tue Dec  2 16:45:20 1997
+++ linux/include/linux/coda.h	Sun Dec  7 11:51:01 1997
@@ -1,3 +1,11 @@
+/*
+ * Venus interface for Coda.
+ * Original version: (C) 1996 Peter Braam 
+ * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
+ *
+ * Carnegie Mellon encourages users of this code to contribute improvements
+ * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
+ */
 
 /*
  *
diff -u --recursive --new-file v2.1.71/linux/include/linux/coda_cnode.h linux/include/linux/coda_cnode.h
--- v2.1.71/linux/include/linux/coda_cnode.h	Tue Dec  2 16:45:20 1997
+++ linux/include/linux/coda_cnode.h	Sun Dec  7 11:51:01 1997
@@ -1,3 +1,11 @@
+/*
+ * Cnode definitions for Coda.
+ * Original version: (C) 1996 Peter Braam 
+ * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
+ *
+ * Carnegie Mellon encourages users of this code to contribute improvements
+ * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
+ */
 
 /* revamped cnode.h file: platform dependent, kernel only! */
 
diff -u --recursive --new-file v2.1.71/linux/include/linux/coda_opstats.h linux/include/linux/coda_opstats.h
--- v2.1.71/linux/include/linux/coda_opstats.h	Tue Dec  2 16:45:20 1997
+++ linux/include/linux/coda_opstats.h	Sun Dec  7 11:51:01 1997
@@ -1,36 +1,11 @@
-#ifndef _BLURB_
-#define _BLURB_
 /*
-
-            Coda: an Experimental Distributed File System
-                             Release 3.1
-
-          Copyright (c) 1987-1996 Carnegie Mellon University
-                         All Rights Reserved
-
-Permission  to  use, copy, modify and distribute this software and its
-documentation is hereby granted,  provided  that  both  the  copyright
-notice  and  this  permission  notice  appear  in  all  copies  of the
-software, derivative works or  modified  versions,  and  any  portions
-thereof, and that both notices appear in supporting documentation, and
-that credit is given to Carnegie Mellon University  in  all  documents
-and publicity pertaining to direct or indirect use of this code or its
-derivatives.
-
-CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS  KNOWN  TO  HAVE  BUGS,
-SOME  OF  WHICH MAY HAVE SERIOUS CONSEQUENCES.  CARNEGIE MELLON ALLOWS
-FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.   CARNEGIE  MELLON
-DISCLAIMS  ANY  LIABILITY  OF  ANY  KIND  FOR  ANY  DAMAGES WHATSOEVER
-RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE  OR  OF
-ANY DERIVATIVE WORK.
-
-Carnegie  Mellon  encourages  users  of  this  software  to return any
-improvements or extensions that  they  make,  and  to  grant  Carnegie
-Mellon the rights to redistribute these changes without encumbrance.
-*/
-
-static char *rcsid = "$Header: /afs/cs/project/coda-src/cvs/coda/kernel-src/vfs/linux/cfs_opstats.h,v 4.1 1997/01/08 21:53:19 rvb Exp $";
-#endif /*_BLURB_*/
+ * Operations statistics for Coda.
+ * Original version: (C) 1996 Peter Braam 
+ * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
+ *
+ * Carnegie Mellon encourages users of this code to contribute improvements
+ * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
+ */
 
 
 /*
diff -u --recursive --new-file v2.1.71/linux/include/linux/coda_sysctl.h linux/include/linux/coda_sysctl.h
--- v2.1.71/linux/include/linux/coda_sysctl.h	Tue Dec  2 16:45:20 1997
+++ linux/include/linux/coda_sysctl.h	Sun Dec  7 11:51:01 1997
@@ -1,2 +1,10 @@
+/*
+ * Sysctl operations for Coda.
+ * Original version: (C) 1996 Peter Braam 
+ * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
+ *
+ * Carnegie Mellon encourages users of this code to contribute improvements
+ * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
+ */
 void coda_sysctl_init(void);
 void coda_sysctl_clean(void);
diff -u --recursive --new-file v2.1.71/linux/include/linux/console.h linux/include/linux/console.h
--- v2.1.71/linux/include/linux/console.h	Thu Dec  4 14:53:57 1997
+++ linux/include/linux/console.h	Sun Dec  7 12:06:56 1997
@@ -90,8 +90,8 @@
 	int	(*read)(struct console *, const char *, unsigned);
 	kdev_t	(*device)(struct console *);
 	int	(*wait_key)(struct console *);
-        void	(*unblank)(void);
-	void	(*setup)(struct console *, char *);
+	void	(*unblank)(void);
+	int	(*setup)(struct console *, char *);
 	short	flags;
 	short	index;
 	int	cflag;
diff -u --recursive --new-file v2.1.71/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.1.71/linux/include/linux/fs.h	Wed Nov 26 16:24:03 1997
+++ linux/include/linux/fs.h	Tue Dec  9 12:21:32 1997
@@ -547,7 +547,7 @@
 	ssize_t (*read) (struct file *, char *, size_t, loff_t *);
 	ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
 	int (*readdir) (struct file *, void *, filldir_t);
-	unsigned int (*poll) (struct file *, poll_table *);
+	unsigned int (*poll) (struct file *, struct poll_table_struct *);
 	int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
 	int (*mmap) (struct file *, struct vm_area_struct *);
 	int (*open) (struct inode *, struct file *);
diff -u --recursive --new-file v2.1.71/linux/include/linux/pi2.h linux/include/linux/pi2.h
--- v2.1.71/linux/include/linux/pi2.h	Thu Mar 27 14:40:10 1997
+++ linux/include/linux/pi2.h	Tue Dec  9 09:49:59 1997
@@ -1,130 +0,0 @@
-
-#define DMA_BUFF_SIZE 2200
-
-#define ON 1
-#define OFF 0
-
-
-/* Register offset info, specific to the PI
- * E.g., to read the data port on channel A, use
- *  inportb(pichan[dev].base + CHANA + DATA)
- */
-#define CHANB   0   /* Base of channel B regs */
-#define CHANA   2   /* Base of channel A regs */
-
-/* 8530 ports on each channel */
-#define CTL 0
-#define DATA    1
-
-#define DMAEN   0x4 /* Offset off DMA Enable register */
-
-/* Timer chip offsets */
-#define TMR0    0x8 /* Offset of timer 0 register */
-#define TMR1    0x9 /* Offset of timer 1 register */
-#define TMR2    0xA /* Offset of timer 2 register */
-#define TMRCMD  0xB /* Offset of timer command register */
-
-/* Timer chip equates */
-#define SC0 0x00 /* Select counter 0 */
-#define SC1 0x40 /* Select counter 1 */
-#define SC2 0x80 /* Select counter 2 */
-#define CLATCH  0x00 /* Counter latching operation */
-#define MSB 0x20 /* Read/load MSB only */
-#define LSB 0x10 /* Read/load LSB only */
-#define LSB_MSB 0x30 /* Read/load LSB, then MSB */
-#define MODE0   0x00 /* Interrupt on terminal count */
-#define MODE1   0x02 /* Programmable one shot */
-#define MODE2   0x04 /* Rate generator */
-#define MODE3   0x06 /* Square wave rate generator */
-#define MODE4   0x08 /* Software triggered strobe */
-#define MODE5   0x0a /* Hardware triggered strobe */
-#define BCD 0x01 /* BCD counter */
-
-/* DMA controller registers */
-#define DMA_STAT    8   /* DMA controller status register */
-#define DMA_CMD     8   /* DMA controller command register */
-#define DMA_MASK        10  /* DMA controller mask register */
-#define DMA_MODE        11  /* DMA controller mode register */
-#define DMA_RESETFF 12  /* DMA controller first/last flip flop  */
-/* DMA data */
-#define DMA_DISABLE (0x04)  /* Disable channel n */
-#define DMA_ENABLE  (0x00)  /* Enable channel n */
-/* Single transfers, incr. address, auto init, writes, ch. n */
-#define DMA_RX_MODE (0x54)
-/* Single transfers, incr. address, no auto init, reads, ch. n */
-#define DMA_TX_MODE (0x48)
-
-#define SINGLE 3686400
-#define DOUBLE 7372800
-
-#define SIOCGPIPARAM		0x5000	/* get PI parameters */
-#define SIOCSPIPARAM		0x5001	/* set */
-#define SIOCGPIBAUD		0x5002	/* get only baud rate */
-#define SIOCSPIBAUD		0x5003	
-#define SIOCGPIDMA		0x5004	/* get only DMA */
-#define SIOCSPIDMA		0x5005	
-#define SIOCGPIIRQ		0x5006	/* get only IRQ */
-#define SIOCSPIIRQ		0x5007	
-
-struct pi_req  {
-    int cmd;
-    int speed;
-    int clockmode;
-    int txdelay;
-    unsigned char persist;
-    int slotime; 
-    int squeldelay;
-    int dmachan;    
-    int irq;    
-};
-
-#ifdef __KERNEL__
-
-/* Information that needs to be kept for each channel. */
-struct pi_local {
-    struct net_device_stats stats; 
-    long open_time;             /* Useless example local info. */
-    unsigned long xtal; 
-
-    struct mbuf *rcvbuf;/* Buffer for current rx packet */
-    struct mbuf *rxdmabuf1; /* DMA rx buffer */
-    struct mbuf *rxdmabuf2; /* DMA rx buffer */
-
-    int bufsiz;         /* Size of rcvbuf */
-    char *rcp;          /* Pointer into rcvbuf */
-
-    struct sk_buff_head sndq;  /* Packets awaiting transmission */
-    int sndcnt;         /* Number of packets on sndq */
-    struct sk_buff *sndbuf;	/* Current buffer being transmitted */
-    char *txdmabuf;     /* Transmit DMA buffer */
-	char *txptr;		/* Used by B port tx */
-	int txcnt;			
-    char tstate;        /* Transmitter state */
-#define IDLE    0       /* Transmitter off, no data pending */
-#define ACTIVE  1       /* Transmitter on, sending data */
-#define UNDERRUN 2      /* Transmitter on, flushing CRC */
-#define FLAGOUT 3       /* CRC sent - attempt to start next frame */
-#define DEFER 4         /* Receive Active - DEFER Transmit */
-#define ST_TXDELAY 5    /* Sending leading flags */
-#define CRCOUT 6
-    char rstate;        /* Set when !DCD goes to 0 (TRUE) */
-/* Normal state is ACTIVE if Receive enabled */
-#define RXERROR 2       /* Error -- Aborting current Frame */
-#define RXABORT 3       /* ABORT sequence detected */
-#define TOOBIG 4        /* too large a frame to store */
-    int dev;            /* Device number */
-    int base;       /* Base of I/O registers */
-    int cardbase;     /* Base address of card */
-    int stata;        /* address of Channel A status regs */
-    int statb;        /* address of Channel B status regs */
-    int speed;        /* Line speed, bps */
-    int clockmode;    /* tapr 9600 modem clocking option */
-    int txdelay;      /* Transmit Delay 10 ms/cnt */
-    unsigned char persist;       /* Persistence (0-255) as a % */
-    int slotime;      /* Delay to wait on persistence hit */
-    int squeldelay;   /* Delay after XMTR OFF for squelch tail */
-    struct iface *iface;    /* Associated interface */
-    int dmachan;           /* DMA channel for this port */
-};
-
-#endif
diff -u --recursive --new-file v2.1.71/linux/include/linux/poll.h linux/include/linux/poll.h
--- v2.1.71/linux/include/linux/poll.h	Sat Jan 25 13:46:14 1997
+++ linux/include/linux/poll.h	Tue Dec  9 12:21:55 1997
@@ -1 +1,106 @@
+#ifndef _LINUX_POLL_H
+
 #include <asm/poll.h>
+
+#ifdef __KERNEL__
+
+#include <linux/wait.h>
+#include <linux/string.h>
+#include <asm/uaccess.h>
+
+
+struct poll_table_entry {
+	struct wait_queue wait;
+	struct wait_queue ** wait_address;
+};
+
+typedef struct poll_table_struct {
+	unsigned int nr;
+	struct poll_table_entry * entry;
+} poll_table;
+
+#define __MAX_POLL_TABLE_ENTRIES (PAGE_SIZE / sizeof (struct poll_table_entry))
+
+extern inline void poll_wait(struct wait_queue ** wait_address, poll_table *p)
+{
+	struct poll_table_entry * entry;
+
+	if (!p || !wait_address)
+		return;
+	if (p->nr >= __MAX_POLL_TABLE_ENTRIES)
+		return;
+ 	entry = p->entry + p->nr;
+	entry->wait_address = wait_address;
+	entry->wait.task = current;
+	entry->wait.next = NULL;
+	add_wait_queue(wait_address,&entry->wait);
+	p->nr++;
+}
+
+
+/*
+ * For the kernel fd_set we use a fixed set-size for allocation purposes.
+ * This set-size doesn't necessarily bear any relation to the size the user
+ * uses, but should preferably obviously be larger than any possible user
+ * size (NR_OPEN bits).
+ *
+ * We need 6 bitmaps (in/out/ex for both incoming and outgoing), and we
+ * allocate one page for all the bitmaps. Thus we have 8*PAGE_SIZE bits,
+ * to be divided by 6. And we'd better make sure we round to a full
+ * long-word (in fact, we'll round to 64 bytes).
+ */
+
+
+#define KFDS_64BLOCK ((PAGE_SIZE/(6*64))*64)
+#define KFDS_NR (KFDS_64BLOCK*8 > NR_OPEN ? NR_OPEN : KFDS_64BLOCK*8)
+typedef unsigned long kernel_fd_set[KFDS_NR/__NFDBITS];
+
+typedef struct {
+	kernel_fd_set in, out, ex;
+	kernel_fd_set res_in, res_out, res_ex;
+} fd_set_buffer;
+
+
+/*
+ * We do a VERIFY_WRITE here even though we are only reading this time:
+ * we'll write to it eventually..
+ *
+ * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned.
+ */
+static inline
+int get_fd_set(unsigned long nr, void *ufdset, unsigned long *fdset)
+{
+	/* round up nr to nearest "unsigned long" */
+	nr = (nr + 8*sizeof(long) - 1) / (8*sizeof(long)) * sizeof(long);
+	if (ufdset) {
+		int error;
+		error = verify_area(VERIFY_WRITE, ufdset, nr);
+		if (!error)
+			error = __copy_from_user(fdset, ufdset, nr);
+		return error;
+	}
+	memset(fdset, 0, nr);
+	return 0;
+}
+
+static inline
+void set_fd_set(unsigned long nr, void *ufdset, unsigned long *fdset)
+{
+	if (ufdset) {
+		nr = (nr + 8*sizeof(long) - 1) / (8*sizeof(long))*sizeof(long);
+		__copy_to_user(ufdset, fdset, nr);
+	}
+}
+
+static inline
+void zero_fd_set(unsigned long nr, unsigned long *fdset)
+{
+	nr = (nr + 8*sizeof(long) - 1) / (8*sizeof(long)) * sizeof(long);
+	memset(fdset, 0, nr);
+}
+
+extern int do_select(int n, fd_set_buffer *fds, unsigned long timeout);
+
+#endif /* KERNEL */
+
+#endif /* _LINUX_POLL_H */
diff -u --recursive --new-file v2.1.71/linux/include/linux/pt.h linux/include/linux/pt.h
--- v2.1.71/linux/include/linux/pt.h	Thu Mar 27 14:40:10 1997
+++ linux/include/linux/pt.h	Tue Dec  9 09:49:59 1997
@@ -1,174 +0,0 @@
-/*
- * pt.h: Linux device driver for the Gracilis PackeTwin
- * Copyright (C) 1995 Craig Small VK2XLZ (vk2xlz@vk2xlz.ampr.org.)
- *
- * Please read the notice appearing at the top of the file pt.c
- */
-#define DMA_BUFF_SIZE 2200
-
-#define ON 1
-#define OFF 0
-
-
-/* Register offset info, specific to the PT
- * E.g., to read the data port on channel A, use
- *  inportb(pichan[dev].base + CHANA + DATA)
- */
-#define CHANB   0   /* Base of channel B regs */
-#define CHANA   2   /* Base of channel A regs */
-
-/* 8530 ports on each channel */
-#define CTL 0
-#define DATA    1
-
-#define DMAEN   0x8 /* Offset off DMA Enable register */
-
-/* Timer chip offsets */
-#define TMR0    0x4 /* Offset of timer 0 register */
-#define TMR1    0x5 /* Offset of timer 1 register */
-#define TMR2    0x6 /* Offset of timer 2 register */
-#define TMRCMD  0x7 /* Offset of timer command register */
-#define INT_REG	0x8
-#define TMR1CLR 0x9
-#define TMR2CLR 0xa
-
-/* Interrupt register equates */
-#define PT_SCC_MSK	0x1
-#define PT_TMR1_MSK	0x2
-#define PT_TMR2_MSK	0x4
-
-/* Serial/interrupt register equates */
-#define PT_DTRA_ON	0x1
-#define PT_DTRB_ON	0x2
-#define PT_EXTCLKA	0x4
-#define PT_EXTCLKB	0x8
-#define PT_LOOPA_ON	0x10
-#define PT_LOOPB_ON	0x20
-#define PT_EI		0x80
-
-/* Timer chip equates */
-#define SC0 0x00 /* Select counter 0 */
-#define SC1 0x40 /* Select counter 1 */
-#define SC2 0x80 /* Select counter 2 */
-#define CLATCH  0x00 /* Counter latching operation */
-#define MSB 0x20 /* Read/load MSB only */
-#define LSB 0x10 /* Read/load LSB only */
-#define LSB_MSB 0x30 /* Read/load LSB, then MSB */
-#define MODE0   0x00 /* Interrupt on terminal count */
-#define MODE1   0x02 /* Programmable one shot */
-#define MODE2   0x04 /* Rate generator */
-#define MODE3   0x06 /* Square wave rate generator */
-#define MODE4   0x08 /* Software triggered strobe */
-#define MODE5   0x0a /* Hardware triggered strobe */
-#define BCD 0x01 /* BCD counter */
-
-/* DMA controller registers */
-#define DMA_STAT    8   /* DMA controller status register */
-#define DMA_CMD     8   /* DMA controller command register */
-#define DMA_MASK        10  /* DMA controller mask register */
-#define DMA_MODE        11  /* DMA controller mode register */
-#define DMA_RESETFF 12  /* DMA controller first/last flip flop  */
-/* DMA data */
-#define DMA_DISABLE (0x04)  /* Disable channel n */
-#define DMA_ENABLE  (0x00)  /* Enable channel n */
-/* Single transfers, incr. address, auto init, writes, ch. n */
-#define DMA_RX_MODE (0x54)
-/* Single transfers, incr. address, no auto init, reads, ch. n */
-#define DMA_TX_MODE (0x48)
-
-/* Write registers */
-#define DMA_CFG		0x08
-#define SERIAL_CFG	0x09
-#define INT_CFG		0x09	/* shares with serial config */
-#define DMA_CLR_FF	0x0a
-
-#define SINGLE 3686400
-#define DOUBLE 7372800
-#define XTAL   ((long) 6144000L)
-
-#define SIOCGPIPARAM		0x5000	/* get PI parameters */
-#define SIOCSPIPARAM		0x5001	/* set */
-#define SIOCGPIBAUD		0x5002	/* get only baud rate */
-#define SIOCSPIBAUD		0x5003	
-#define SIOCGPIDMA		0x5004	/* get only DMA */
-#define SIOCSPIDMA		0x5005	
-#define SIOCGPIIRQ		0x5006	/* get only IRQ */
-#define SIOCSPIIRQ		0x5007	
-
-struct pt_req
-{
-	int cmd;
-	int speed;
-	int clockmode;
-	int txdelay;
-	unsigned char persist;
-	int slotime; 
-	int squeldelay;
-	int dmachan;    
-	int irq;    
-};
-
-/* SCC Interrupt vectors, if we have set 'status low' */
-#define CHBTxIV		0x00
-#define CHBEXTIV	0x02
-#define CHBRxIV		0x04
-#define CHBSRCIV	0x06
-#define CHATxIV		0x08
-#define CHAEXTIV	0x0a
-#define CHARxIV		0x0c
-#define CHASRCIV	0x0e
-
-
-#ifdef __KERNEL__
-
-/* Information that needs to be kept for each channel. */
-struct pt_local
-{
-	struct net_device_stats stats; /* %%%dp*/
-	long open_time;             /* Useless example local info. */
-	unsigned long xtal; 
-
-	struct mbuf *rcvbuf;/* Buffer for current rx packet */
-	struct mbuf *rxdmabuf1; /* DMA rx buffer */
-	struct mbuf *rxdmabuf2; /* DMA rx buffer */
-
-	int bufsiz;			/* Size of rcvbuf 			*/
-	char *rcp;			/* Pointer into rcvbuf 			*/
-	struct sk_buff_head sndq;	/* Packets awaiting transmission 	*/
-	int sndcnt;			/* Number of packets on sndq 		*/
-	struct sk_buff *sndbuf;		/* Current buffer being transmitted	*/
-	char *txdmabuf; 		/* Transmit DMA buffer 			*/
-	char *txptr;			/* Used by B port tx 			*/
-	int txcnt;			
-	char tstate;			/* Transmitter state 			*/
-#define IDLE    0       /* Transmitter off, no data pending 		*/
-#define ACTIVE  1       /* Transmitter on, sending data 		*/
-#define UNDERRUN 2      /* Transmitter on, flushing CRC			*/
-#define FLAGOUT 3       /* CRC sent - attempt to start next frame	*/
-#define DEFER 4         /* Receive Active - DEFER Transmit		*/
-#define ST_TXDELAY 5    /* Sending leading flags			*/
-#define CRCOUT 6
-	char rstate;        /* Set when !DCD goes to 0 (TRUE)		*/
-/* Normal state is ACTIVE if Receive enabled */
-#define RXERROR 2       /* Error -- Aborting current Frame		*/
-#define RXABORT 3       /* ABORT sequence detected			*/
-#define TOOBIG 4        /* too large a frame to store			*/
-	
-	int dev;		/* Device number */
-	int base;		/* Base of I/O registers */
-	int cardbase;		/* Base address of card */
-	int stata;		/* address of Channel A status regs */
-	int statb;		/* address of Channel B status regs */
-	int speed;        	/* Line speed, bps */
-	int clockmode;    	/* tapr 9600 modem clocking option */
-	int txdelay;      	/* Transmit Delay 10 ms/cnt */
-	unsigned char persist;  /* Persistence (0-255) as a % */
-	int slotime;		/* Delay to wait on persistence hit */
-	int squeldelay; 	/* Delay after XMTR OFF for squelch tail */
-	struct iface *iface;    /* Associated interface */
-	int dmachan;		/* DMA channel for this port */
-	char saved_RR0;		/* The saved version of RR) that we compare with */
-	int nrzi;		/* Do we use NRZI (or NRZ) */
-};
-
-#endif
diff -u --recursive --new-file v2.1.71/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.1.71/linux/include/linux/sched.h	Tue Dec  2 16:45:20 1997
+++ linux/include/linux/sched.h	Tue Dec  9 12:21:32 1997
@@ -601,22 +601,6 @@
 	write_unlock_irqrestore(&waitqueue_lock, flags); 
 }
 
-extern inline void poll_wait(struct wait_queue ** wait_address, poll_table * p)
-{
-	struct poll_table_entry * entry;
-
-	if (!p || !wait_address)
-		return;
-	if (p->nr >= __MAX_POLL_TABLE_ENTRIES)
-		return;
- 	entry = p->entry + p->nr;
-	entry->wait_address = wait_address;
-	entry->wait.task = current;
-	entry->wait.next = NULL;
-	add_wait_queue(wait_address,&entry->wait);
-	p->nr++;
-}
-
 #define REMOVE_LINKS(p) do { unsigned long flags; \
 	write_lock_irqsave(&tasklist_lock, flags); \
 	(p)->next_task->prev_task = (p)->prev_task; \
diff -u --recursive --new-file v2.1.71/linux/include/linux/soundcard.h linux/include/linux/soundcard.h
--- v2.1.71/linux/include/linux/soundcard.h	Wed Nov 12 13:34:28 1997
+++ linux/include/linux/soundcard.h	Tue Dec  9 09:49:59 1997
@@ -599,6 +599,7 @@
 #define SNDCTL_DSP_MAPOUTBUF		_SIOR ('P', 20, buffmem_desc)
 #define SNDCTL_DSP_SETSYNCRO		_SIO  ('P', 21)
 #define SNDCTL_DSP_SETDUPLEX		_SIO  ('P', 22)
+#define SNDCTL_DSP_GETODELAY		_SIOR ('P', 23, int)
 
 /*
  * Application's profile defines the way how playback underrun situations should be handled.
diff -u --recursive --new-file v2.1.71/linux/include/linux/sysv_fs.h linux/include/linux/sysv_fs.h
--- v2.1.71/linux/include/linux/sysv_fs.h	Sat Oct 25 02:44:18 1997
+++ linux/include/linux/sysv_fs.h	Tue Dec  9 12:23:24 1997
@@ -361,17 +361,14 @@
  * Function prototypes
  */
 
-extern int sysv_lookup(struct inode * dir,const char * name, int len,
-	               struct inode ** result);
-extern int sysv_create(struct inode * dir,const char * name, int len, int mode,
-	struct inode ** result);
-extern int sysv_mkdir(struct inode * dir, const char * name, int len, int mode);
-extern int sysv_rmdir(struct inode * dir, const char * name, int len);
-extern int sysv_unlink(struct inode * dir, const char * name, int len);
-extern int sysv_symlink(struct inode * inode, const char * name, int len,
-	const char * symname);
-extern int sysv_link(struct inode * oldinode, struct inode * dir, const char * name, int len);
-extern int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
+extern int sysv_lookup(struct inode * dir, struct dentry * dentry);
+extern int sysv_create(struct inode * dir, struct dentry * dentry, int mode);
+extern int sysv_mkdir(struct inode * dir, struct dentry * dentry, int mode);
+extern int sysv_rmdir(struct inode * dir, struct dentry * dentry);
+extern int sysv_unlink(struct inode * dir, struct dentry * dentry);
+extern int sysv_symlink(struct inode * inode, struct dentry * dentry, const char * symname);
+extern int sysv_link(struct inode * oldinode, struct inode * dir, struct dentry * dentry);
+extern int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev);
 extern int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
 		       struct inode * new_dir, struct dentry * new_dentry);
 extern struct inode * sysv_new_inode(const struct inode * dir);
diff -u --recursive --new-file v2.1.71/linux/include/linux/time.h linux/include/linux/time.h
--- v2.1.71/linux/include/linux/time.h	Thu Dec  4 14:53:57 1997
+++ linux/include/linux/time.h	Tue Dec  9 00:07:19 1997
@@ -2,11 +2,12 @@
 #define _LINUX_TIME_H
 
 #include <asm/param.h>
+#include <linux/types.h>
 
 #ifndef _STRUCT_TIMESPEC
 #define _STRUCT_TIMESPEC
 struct timespec {
-	long	tv_sec;		/* seconds */
+	time_t	tv_sec;		/* seconds */
 	long	tv_nsec;	/* nanoseconds */
 };
 #endif /* _STRUCT_TIMESPEC */
@@ -36,8 +37,8 @@
 }
  
 struct timeval {
-	int	tv_sec;		/* seconds */
-	int	tv_usec;	/* microseconds */
+	time_t		tv_sec;		/* seconds */
+	suseconds_t	tv_usec;	/* microseconds */
 };
 
 struct timezone {
diff -u --recursive --new-file v2.1.71/linux/include/linux/tty_ldisc.h linux/include/linux/tty_ldisc.h
--- v2.1.71/linux/include/linux/tty_ldisc.h	Sat Oct 25 02:44:18 1997
+++ linux/include/linux/tty_ldisc.h	Tue Dec  9 12:21:32 1997
@@ -119,7 +119,8 @@
 	int	(*ioctl)(struct tty_struct * tty, struct file * file,
 			 unsigned int cmd, unsigned long arg);
 	void	(*set_termios)(struct tty_struct *tty, struct termios * old);
-	unsigned int (*poll)(struct tty_struct *, struct file *, poll_table *);
+	unsigned int (*poll)(struct tty_struct *, struct file *,
+			     struct poll_table_struct *);
 	
 	/*
 	 * The following routines are called from below.
diff -u --recursive --new-file v2.1.71/linux/include/linux/types.h linux/include/linux/types.h
--- v2.1.71/linux/include/linux/types.h	Thu Feb  6 02:53:33 1997
+++ linux/include/linux/types.h	Tue Dec  9 00:07:19 1997
@@ -17,6 +17,7 @@
 typedef __kernel_gid_t		gid_t;
 typedef __kernel_daddr_t	daddr_t;
 typedef __kernel_key_t		key_t;
+typedef __kernel_suseconds_t	suseconds_t;
 
 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
 typedef __kernel_loff_t		loff_t;
diff -u --recursive --new-file v2.1.71/linux/include/linux/wait.h linux/include/linux/wait.h
--- v2.1.71/linux/include/linux/wait.h	Sat Jan 25 13:46:14 1997
+++ linux/include/linux/wait.h	Mon Dec  8 23:58:04 1997
@@ -28,18 +28,6 @@
 	return head && head != WAIT_QUEUE_HEAD(q);
 }
 
-struct poll_table_entry {
-	struct wait_queue wait;
-	struct wait_queue ** wait_address;
-};
-
-typedef struct poll_table_struct {
-	unsigned int nr;
-	struct poll_table_entry * entry;
-} poll_table;
-
-#define __MAX_POLL_TABLE_ENTRIES (PAGE_SIZE / sizeof (struct poll_table_entry))
-
 #endif /* __KERNEL__ */
 
 #endif
diff -u --recursive --new-file v2.1.71/linux/init/main.c linux/init/main.c
--- v2.1.71/linux/init/main.c	Thu Dec  4 14:53:57 1997
+++ linux/init/main.c	Tue Dec  9 09:49:59 1997
@@ -225,6 +225,9 @@
 #ifdef CONFIG_SPECIALIX
 extern void specialix_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_DMASCC
+extern void dmascc_setup(char *str, int *ints);
+#endif
 #ifdef CONFIG_BAYCOM_PAR
 extern void baycom_par_setup(char *str, int *ints);
 #endif
@@ -552,6 +555,9 @@
 #endif
 #ifdef CONFIG_RISCOM8
 	{ "riscom8=", riscom8_setup },
+#endif
+#ifdef CONFIG_DMASCC
+	{ "dmascc=", dmascc_setup },
 #endif
 #ifdef CONFIG_SPECIALIX
 	{ "specialix=", specialix_setup },
diff -u --recursive --new-file v2.1.71/linux/ipc/msg.c linux/ipc/msg.c
--- v2.1.71/linux/ipc/msg.c	Wed Sep 24 20:05:48 1997
+++ linux/ipc/msg.c	Tue Dec  9 09:49:59 1997
@@ -669,8 +669,8 @@
 		goto out;
 	case IPC_SET:
 		err = -EPERM;
-		if (!suser() && current->euid != ipcp->cuid && 
-		    current->euid != ipcp->uid)
+		if (current->euid != ipcp->cuid && 
+		    current->euid != ipcp->uid && !suser())
 			goto out;
 		if (tbuf.msg_qbytes > MSGMNB && !suser())
 			goto out;
@@ -684,8 +684,8 @@
 		goto out;
 	case IPC_RMID:
 		err = -EPERM;
-		if (!suser() && current->euid != ipcp->cuid && 
-		    current->euid != ipcp->uid)
+		if (current->euid != ipcp->cuid && 
+		    current->euid != ipcp->uid && !suser())
 			goto out;
 		/*
 		 * There is only one kerneld message queue,
diff -u --recursive --new-file v2.1.71/linux/ipc/sem.c linux/ipc/sem.c
--- v2.1.71/linux/ipc/sem.c	Tue May 13 22:41:19 1997
+++ linux/ipc/sem.c	Tue Dec  9 09:49:59 1997
@@ -487,7 +487,7 @@
 			goto out;
 		break;
 	case IPC_RMID:
-		if (suser() || current->euid == ipcp->cuid || current->euid == ipcp->uid) {
+		if (current->euid == ipcp->cuid || current->euid == ipcp->uid || suser()) {
 			freeary (id);
 			err = 0;
 			goto out;
@@ -545,7 +545,7 @@
 		update_queue(sma);
 		break;
 	case IPC_SET:
-		if (suser() || current->euid == ipcp->cuid || current->euid == ipcp->uid) {
+		if (current->euid == ipcp->cuid || current->euid == ipcp->uid || suser()) {
 			ipcp->uid = tbuf.sem_perm.uid;
 			ipcp->gid = tbuf.sem_perm.gid;
 			ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
diff -u --recursive --new-file v2.1.71/linux/ipc/shm.c linux/ipc/shm.c
--- v2.1.71/linux/ipc/shm.c	Sun Sep  7 13:10:43 1997
+++ linux/ipc/shm.c	Tue Dec  9 09:49:59 1997
@@ -346,8 +346,8 @@
 		copy_to_user (buf, &tbuf, sizeof(*buf));
 		break;
 	case IPC_SET:
-		if (suser() || current->euid == shp->shm_perm.uid ||
-		    current->euid == shp->shm_perm.cuid) {
+		if (current->euid == shp->shm_perm.uid ||
+		    current->euid == shp->shm_perm.cuid || suser()) {
 			ipcp->uid = tbuf.shm_perm.uid;
 			ipcp->gid = tbuf.shm_perm.gid;
 			ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
@@ -358,8 +358,8 @@
 		err = -EPERM;
 		goto out;
 	case IPC_RMID:
-		if (suser() || current->euid == shp->shm_perm.uid ||
-		    current->euid == shp->shm_perm.cuid) {
+		if (current->euid == shp->shm_perm.uid ||
+		    current->euid == shp->shm_perm.cuid || suser()) {
 			shp->shm_perm.mode |= SHM_DEST;
 			if (shp->shm_nattch <= 0)
 				killseg (id);
diff -u --recursive --new-file v2.1.71/linux/ipc/util.c linux/ipc/util.c
--- v2.1.71/linux/ipc/util.c	Tue May 13 22:41:19 1997
+++ linux/ipc/util.c	Tue Dec  9 09:49:59 1997
@@ -1,6 +1,11 @@
 /*
  * linux/ipc/util.c
  * Copyright (C) 1992 Krishna Balasubramanian
+ *
+ * Sep 1997 - Call suser() last after "normal" permission checks so we
+ *            get BSD style process accounting right.
+ *            Occurs in several places in the IPC code.
+ *            Chris Evans, <chris@ferret.lmh.ox.ac.uk>
  */
 
 #include <linux/config.h>
@@ -35,8 +40,6 @@
 {	/* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
 	int requested_mode, granted_mode;
 
-	if (suser())
-		return 0;
 	requested_mode = (flag >> 6) | (flag >> 3) | flag;
 	granted_mode = ipcp->mode;
 	if (current->euid == ipcp->cuid || current->euid == ipcp->uid)
@@ -44,7 +47,7 @@
 	else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))
 		granted_mode >>= 3;
 	/* is there some bit set in requested_mode but not in granted_mode? */
-	if (requested_mode & ~granted_mode & 0007)
+	if ((requested_mode & ~granted_mode & 0007) && !suser())
 		return -1;
 	return 0;
 }
diff -u --recursive --new-file v2.1.71/linux/kernel/itimer.c linux/kernel/itimer.c
--- v2.1.71/linux/kernel/itimer.c	Wed Apr 23 19:01:29 1997
+++ linux/kernel/itimer.c	Mon Dec  8 23:58:05 1997
@@ -45,7 +45,7 @@
 	value->tv_sec = jiffies / HZ;
 }
 
-static int _getitimer(int which, struct itimerval *value)
+int do_getitimer(int which, struct itimerval *value)
 {
 	register unsigned long val, interval;
 
@@ -86,10 +86,10 @@
 	struct itimerval get_buffer;
 
 	if (value) {
-		error = _getitimer(which, &get_buffer);
-		if (!error)
-			error =	copy_to_user(value, &get_buffer, sizeof(get_buffer))
-				? -EFAULT : 0;
+		error = do_getitimer(which, &get_buffer);
+		if (!error &&
+		    copy_to_user(value, &get_buffer, sizeof(get_buffer)))
+			error = -EFAULT;
 	}
 	return error;
 }
@@ -111,14 +111,14 @@
 	}
 }
 
-int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
+int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
 {
 	register unsigned long i, j;
 	int k;
 
 	i = tvtojiffies(&value->it_interval);
 	j = tvtojiffies(&value->it_value);
-	if (ovalue && (k = _getitimer(which, ovalue)) < 0)
+	if (ovalue && (k = do_getitimer(which, ovalue)) < 0)
 		return k;
 	switch (which) {
 		case ITIMER_REAL:
@@ -155,7 +155,8 @@
 /* SMP: Again, only we play with our itimers, and signals are SMP safe
  *      now so that is not an issue at all anymore.
  */
-asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
+asmlinkage int sys_setitimer(int which, struct itimerval *value,
+			     struct itimerval *ovalue)
 {
 	struct itimerval set_buffer, get_buffer;
 	int error;
@@ -168,7 +169,7 @@
 	} else
 		memset((char *) &set_buffer, 0, sizeof(set_buffer));
 
-	error = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
+	error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
 	if (error || !ovalue)
 		return error;
 
diff -u --recursive --new-file v2.1.71/linux/kernel/printk.c linux/kernel/printk.c
--- v2.1.71/linux/kernel/printk.c	Thu Dec  4 14:53:57 1997
+++ linux/kernel/printk.c	Sun Dec  7 12:06:56 1997
@@ -80,9 +80,9 @@
 	if ((c->options = strchr(str, ',')) != NULL)
 		*(c->options++) = 0;
 #ifdef __sparc__
-	if (strcmp(str, "ttya"))
+	if (!strcmp(str, "ttya"))
 		strcpy(c->name, "ttyS0");
-	if (strcmp(str, "ttyb"))
+	if (!strcmp(str, "ttyb"))
 		strcpy(c->name, "ttyS1");
 #endif
 
@@ -317,11 +317,13 @@
 	 *	that registers here.
 	 */
 	if (selected_console == 0) {
-		console->flags |= CON_ENABLED | CON_FIRST;
-		selected_console = 1;
-		if (console->setup)
-			console->setup(console, NULL);
+		if (console->setup == NULL ||
+		    console->setup(console, NULL) == 0) {
+			console->flags |= CON_ENABLED | CON_FIRST;
+			selected_console = 1;
+		}
 	}
+
 	/*
 	 *	See if this console matches one we selected on
 	 *	the command line.
@@ -332,14 +334,19 @@
 		if (console->index >= 0 &&
 		    console->index != console_cmdline[i].index)
 			continue;
+		if (console->index < 0) console->index = 0;
+		if (console->setup &&
+		    console->setup(console, console_cmdline[i].options) != 0)
+			break;
 		console->flags |= CON_ENABLED;
 		console->index = console_cmdline[i].index;
 		if (i == 0)
 			console->flags |= CON_FIRST;
-		if (console->setup)
-			console->setup(console, console_cmdline[i].options);
 		break;
 	}
+
+	if (!(console->flags & CON_ENABLED))
+		return;
 
 	/*
 	 *	Put this console in the list - keep the
diff -u --recursive --new-file v2.1.71/linux/kernel/sched.c linux/kernel/sched.c
--- v2.1.71/linux/kernel/sched.c	Mon Dec  1 12:04:15 1997
+++ linux/kernel/sched.c	Tue Dec  9 09:31:19 1997
@@ -50,8 +50,12 @@
 int securelevel = 0;			/* system security level */
 
 long tick = (1000000 + HZ/2) / HZ;	/* timer interrupt period */
-volatile struct timeval xtime __attribute__ ((aligned (8)));	/* The current time */
-int tickadj = 500/HZ;			/* microsecs */
+
+/* The current time */
+volatile struct timeval xtime __attribute__ ((aligned (16)));
+
+/* Don't completely fail for HZ > 500.  */
+int tickadj = 500/HZ ? : 1;		/* microsecs */
 
 DECLARE_TASK_QUEUE(tq_timer);
 DECLARE_TASK_QUEUE(tq_immediate);
@@ -80,7 +84,7 @@
 int need_resched = 0;
 unsigned long event = 0;
 
-extern int _setitimer(int, struct itimerval *, struct itimerval *);
+extern int do_setitimer(int, struct itimerval *, struct itimerval *);
 unsigned int * prof_buffer = NULL;
 unsigned long prof_len = 0;
 unsigned long prof_shift = 0;
@@ -1114,7 +1118,7 @@
 	it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
 	it_new.it_value.tv_sec = seconds;
 	it_new.it_value.tv_usec = 0;
-	_setitimer(ITIMER_REAL, &it_new, &it_old);
+	do_setitimer(ITIMER_REAL, &it_new, &it_old);
 	oldalarm = it_old.it_value.tv_sec;
 	/* ehhh.. We can't return 0 if we have an alarm pending.. */
 	/* And we'd better return too much than too little anyway */
@@ -1508,7 +1512,7 @@
 
 		render_sigset_t(&p->signal, s);
 		render_sigset_t(&p->blocked, b);
-		printk("\tsig: %d %s %s :", signal_pending(p), s, b);
+		printk("   sig: %d %s %s :", signal_pending(p), s, b);
 		for (q = p->sigqueue; q ; q = q->next)
 			printk(" %d", q->info.si_signo);
 		printk(" X\n");
diff -u --recursive --new-file v2.1.71/linux/kernel/time.c linux/kernel/time.c
--- v2.1.71/linux/kernel/time.c	Sun Sep  7 13:10:43 1997
+++ linux/kernel/time.c	Mon Dec  8 23:58:05 1997
@@ -151,25 +151,17 @@
  * as soon as possible, so that the clock can be set right. Otherwise,
  * various programs will get confused when the clock gets warped.
  */
-asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
+
+int do_sys_settimeofday(struct timeval *tv, struct timezone *tz)
 {
-	static int	firsttime = 1;
-	struct timeval	new_tv;
-	struct timezone new_tz;
+	static int firsttime = 1;
 
 	if (!suser())
 		return -EPERM;
 		
-	if (tv) {
-		if (copy_from_user(&new_tv, tv, sizeof(*tv)))
-			return -EFAULT;
-	}
 	if (tz) {
-		if (copy_from_user(&new_tz, tz, sizeof(*tz)))
-			return -EFAULT;
-
 		/* SMP safe, global irq locking makes it work. */
-		sys_tz = new_tz;
+		sys_tz = *tz;
 		if (firsttime) {
 			firsttime = 0;
 			if (!tv)
@@ -181,9 +173,26 @@
 		/* SMP safe, again the code in arch/foo/time.c should
 		 * globally block out interrupts when it runs.
 		 */
-		do_settimeofday(&new_tv);
+		do_settimeofday(tv);
 	}
 	return 0;
+}
+
+asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
+{
+	struct timeval	new_tv;
+	struct timezone new_tz;
+
+	if (tv) {
+		if (copy_from_user(&new_tv, tv, sizeof(*tv)))
+			return -EFAULT;
+	}
+	if (tz) {
+		if (copy_from_user(&new_tz, tz, sizeof(*tz)))
+			return -EFAULT;
+	}
+
+	return do_sys_settimeofday(tv ? &new_tv : NULL, tz ? &new_tz : NULL);
 }
 
 long pps_offset = 0;		/* pps time offset (us) */
diff -u --recursive --new-file v2.1.71/linux/linux/include/linux/dmascc.h linux/linux/include/linux/dmascc.h
--- v2.1.71/linux/linux/include/linux/dmascc.h	Wed Dec 31 16:00:00 1969
+++ linux/linux/include/linux/dmascc.h	Tue Dec  9 09:49:59 1997
@@ -0,0 +1,43 @@
+/*
+ * $Id: dmascc.h,v 1.1 1997/12/01 10:44:55 oe1kib Exp $
+ *
+ * Driver for high-speed SCC boards (those with DMA support)
+ * Copyright (C) 1997 Klaus Kudielka
+ *
+ * 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.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Ioctls */
+#define SIOCGSCCPARAM SIOCDEVPRIVATE
+#define SIOCSSCCPARAM (SIOCDEVPRIVATE+1)
+
+/* Frequency of timer 0 */
+#define TMR_0_HZ      25600
+
+/* Configurable parameters */
+struct scc_param {
+  int pclk_hz;  /* frequency of BRG input (read-only - don't change) */
+  int brg_tc;   /* baud rate generator terminal count - BRG disabled if < 0 */
+  int nrzi;     /* 0 (nrz), 1 (nrzi) */
+  int clocks;   /* see documentation */
+  int txdelay;  /* [1/TMR_0_HZ] */
+  int txtime;   /* [1/HZ] */
+  int sqdelay;  /* [1/TMR_0_HZ] */
+  int waittime; /* [1/TMR_0_HZ] */
+  int slottime; /* [1/TMR_0_HZ] */
+  int persist;  /* 0 ... 255 */
+  int dma;      /* 1, 3 */
+};
+
diff -u --recursive --new-file v2.1.71/linux/net/Config.in linux/net/Config.in
--- v2.1.71/linux/net/Config.in	Thu Dec  4 14:53:57 1997
+++ linux/net/Config.in	Tue Dec  9 09:49:59 1997
@@ -48,6 +48,7 @@
 #  fi
   tristate 'WAN router' CONFIG_WAN_ROUTER
   bool 'CPU is too slow to handle full bandwidth' CONFIG_CPU_IS_SLOW
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   bool 'QoS and/or fair queueing' CONFIG_NET_SCHED
   if [ "$CONFIG_NET_SCHED" = "y" ]; then
     tristate 'CBQ packet scheduler' CONFIG_NET_SCH_CBQ
@@ -58,6 +59,7 @@
     tristate 'auxiliary TBF queue' CONFIG_NET_SCH_TBF
     tristate 'auxiliary FIFO queue' CONFIG_NET_SCH_PFIFO
     tristate 'auxiliary PRIO queue' CONFIG_NET_SCH_PRIO
+  fi
   fi
 fi
 endmenu
diff -u --recursive --new-file v2.1.71/linux/net/core/dev.c linux/net/core/dev.c
--- v2.1.71/linux/net/core/dev.c	Thu Dec  4 14:53:57 1997
+++ linux/net/core/dev.c	Tue Dec  9 09:49:59 1997
@@ -1573,12 +1573,11 @@
  *
  */
 extern int lance_init(void);
-extern int pi_init(void);
 extern int bpq_init(void);
 extern int scc_init(void);
 extern void sdla_setup(void);
 extern void dlci_setup(void);
-extern int pt_init(void);
+extern int dmascc_init(void);
 extern int sm_init(void);
 extern int baycom_ser_fdx_init(void);
 extern int baycom_ser_hdx_init(void);
@@ -1635,15 +1634,12 @@
 #if defined(CONFIG_LANCE)
 	lance_init();
 #endif
-#if defined(CONFIG_PI)
-	pi_init();
-#endif	
 #if defined(CONFIG_SCC)
 	scc_init();
 #endif
-#if defined(CONFIG_PT)
-	pt_init();
-#endif
+#if defined(CONFIG_DMASCC)
+	dmascc_init();
+#endif	
 #if defined(CONFIG_BPQETHER)
 	bpq_init();
 #endif
diff -u --recursive --new-file v2.1.71/linux/net/core/sock.c linux/net/core/sock.c
--- v2.1.71/linux/net/core/sock.c	Mon Dec  1 12:04:16 1997
+++ linux/net/core/sock.c	Tue Dec  9 09:49:59 1997
@@ -75,6 +75,7 @@
  *                                      protocol private data.
  *              Steve Whitehouse:       Added various other default routines
  *                                      common to several socket families.
+ *              Chris Evans     :       Call suser() check last on F_SETOWN
  *
  * To Fix:
  *
@@ -938,8 +939,9 @@
 			 * way to make sure that you can't send a sigurg to
 			 * another process.
 			 */
-			if (!suser() && current->pgrp != -arg &&
-				current->pid != arg) return(-EPERM);
+			if (current->pgrp != -arg &&
+				current->pid != arg &&
+				!suser()) return(-EPERM);
 			sk->proc = arg;
 			return(0);
 		case F_GETOWN:
diff -u --recursive --new-file v2.1.71/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.1.71/linux/net/ipv4/tcp_ipv4.c	Mon Dec  1 12:04:16 1997
+++ linux/net/ipv4/tcp_ipv4.c	Sun Dec  7 18:26:17 1997
@@ -60,8 +60,13 @@
 extern int sysctl_tcp_window_scaling;
 extern int sysctl_tcp_syncookies;
 
-/* Define this to check TCP sequence numbers in ICMP packets. */
-#define ICMP_PARANOIA 1
+/* Check TCP sequence numbers in ICMP packets. */
+#define ICMP_PARANOIA 1 
+#ifndef ICMP_PARANOIA
+#define ICMP_MIN_LENGTH 4
+#else
+#define ICMP_MIN_LENGTH 8
+#endif
 
 static void tcp_v4_send_reset(struct sk_buff *skb);
 
@@ -772,9 +777,7 @@
 /* 
  * This routine does path mtu discovery as defined in RFC1197.
  */
-static inline void do_pmtu_discovery(struct sock *sk,
-				    struct iphdr *ip,
-				    struct tcphdr *th)
+static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *ip)
 {
 	int new_mtu; 
 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
@@ -825,11 +828,13 @@
 	int type = skb->h.icmph->type;
 	int code = skb->h.icmph->code;
 	struct sock *sk;
-	__u32 seq; 
 	int opening;
+#ifdef ICMP_PARANOIA
+	__u32 seq;
+#endif
 
-	if (len < (iph->ihl << 2)+sizeof(struct tcphdr)) {
-		icmp_statistics.IcmpInErrors++;
+	if (len < (iph->ihl << 2) + ICMP_MIN_LENGTH) { 
+		icmp_statistics.IcmpInErrors++; 
 		return;
 	}
 
@@ -891,7 +896,7 @@
 		break; 
 	case ICMP_DEST_UNREACH:
 		if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
-			do_pmtu_discovery(sk, iph, th); 
+			do_pmtu_discovery(sk, iph); 
 			return; 
 		}
 		break; 
diff -u --recursive --new-file v2.1.71/linux/scripts/Menuconfig linux/scripts/Menuconfig
--- v2.1.71/linux/scripts/Menuconfig	Sun Apr 13 10:18:23 1997
+++ linux/scripts/Menuconfig	Tue Dec  9 09:51:45 1997
@@ -24,6 +24,10 @@
 # 070497 Bernhard Kaindl (bkaindl@netway.at) - get default values for
 # new bool, tristate and dep_tristate parameters from the defconfig file.
 # new configuration parameters are marked with '(NEW)' as in make config.
+# 180697 Bernhard Kaindl (bkaindl@netway.at) - added the needed support
+# for string options. They are handled like the int and hex options.
+# 081297 Pavel Machek (pavel@atrey.karlin.mff.cuni.cz) - better error 
+# handling
 #----------------------------------------------------------------------------
 
 
@@ -179,7 +183,7 @@
 }
 
 #
-# Add a menu item which will call our local int function.
+# Add a menu item which will call our local hex function.
 # 
 function hex () {
 	eval $2=\${$2:-"$3"} x=\${$2##*[x,X]}
@@ -190,6 +194,17 @@
 }
 
 #
+# Add a menu item which will call our local string function.
+# 
+function string () {
+	eval $2=\${$2:-"$3"} x=\$$2
+
+	echo -ne "'$2' '     $1: \"$x\"' " >>MCmenu
+
+	echo -e "function $2 () { l_string '$1' '$2' '$3' '$x' ;}" >>MCradiolists
+}
+
+#
 # Add a menu item which will call our local One-of-Many choice list.
 #
 function choice () {
@@ -482,6 +497,34 @@
 }
 
 #
+# Create a dialog for entering a string into a kernel option.
+#
+function l_string () {
+	while true
+	do
+		if $DIALOG --title "$1" \
+			--backtitle "$backtitle" \
+			--inputbox "$inputbox_instructions_string" \
+			10 75 "$4" 2>MCdialog.out
+		then
+			answer="`cat MCdialog.out`"
+			answer="${answer:-$3}"
+
+			#
+			# Someone may add a nice check for the entered
+			# string here...
+			#
+			eval $2=\"$answer\"
+
+			break
+		fi
+
+		help "$2" "$1"
+	done
+}
+
+
+#
 # Handle a one-of-many choice list.
 #
 function l_choice () {
@@ -540,12 +583,18 @@
 	done
 }
 
+#
+# Call awk, and watch for error codes, etc.
+#
+function callawk () {
+awk "$1" || echo "Awk died with error code $?. Giving up." || exit 1
+}
 
 #
 # A faster awk based recursive parser. (I hope)
 #
 function parser1 () {
-awk '
+callawk '
 BEGIN {
 	menu_no = 0
 	comment_is_option = 0
@@ -598,7 +647,7 @@
 # Secondary parser for single menu mode.
 #
 function parser2 () {
-awk '
+callawk '
 BEGIN {
 	parser("'$CONFIG_IN'","MCmenu0")
 }
@@ -657,9 +706,9 @@
 	#
 	for i in MCmenu*
 	do
+		echo -n "."
 		source ./$i
 	done
-
 	rm -f MCmenu*
 }
 
@@ -681,7 +730,6 @@
 		then
 			clear
 			cat <<EOM
-
 Menuconfig has encountered a possible error in one of the kernel's
 configuration files and is unable to continue.
 
@@ -733,7 +781,6 @@
 			stty sane
 			clear
 			cat <<EOM
-
 There seems to be a problem with the lxdialog companion utility which is
 built prior to running Menuconfig.  Usually this is an indicator that you
 have upgraded/downgraded your ncurses libraries and did not remove the 
@@ -906,8 +953,8 @@
 # Just what it says.
 #
 save_configuration () {
-	${DIALOG} --backtitle "$backtitle" \
-		  --infobox "Saving your kernel configuration..."  3 40
+        echo
+	echo -n "Saving your kernel configuration."
 
 	#
 	# Macro for setting the newval varible. get's default from defconfig
@@ -963,6 +1010,12 @@
 		echo "#define $2 0x${x##*[x,X]}" >>$CONFIG_H
 	}
 
+	function string () {
+		eval x=\${$2:-"$3"}
+		echo "$2=\"$x\"" 			 >>$CONFIG
+		echo "#define $2 \"$x\""	>>$CONFIG_H
+	}
+
 	function define_bool () {
 		eval $1="$2"
 
@@ -1051,6 +1104,8 @@
 		fi
 	}
 
+	echo -n "."
+
 	DEF_CONFIG="${1:-.config}"
 	DEF_CONFIG_H="include/linux/autoconf.h"
 
@@ -1067,7 +1122,8 @@
 	echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H
 
 	MAKE=:	#To prevent sound Makefile from running.
-	
+
+	echo -n "."
 	if . $CONFIG_IN >>.menuconfig.log 2>&1
 	then
 		if [ "$DEF_CONFIG" = ".config" ]
@@ -1080,6 +1136,7 @@
 			     "_$CONFIG_PSS"    != "_y" -a\
 			     "_$CONFIG_SMWAVE" != "_y"   ]
 			then
+				echo -n ", sound..."
 				make -C drivers/sound kernelconfig >>.menuconfig.log 2>&1
 			fi
 
@@ -1164,6 +1221,10 @@
 Please enter a hexadecimal value. \
 Use the <TAB> key to move from the input field to the buttons below it."
 
+inputbox_instructions_string="\
+Please enter a string value. \
+Use the <TAB> key to move from the input field to the buttons below it."
+
 DIALOG="./scripts/lxdialog/lxdialog"
 
 kernel_version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}"
@@ -1188,22 +1249,17 @@
 
 if [ -f $DEFAULTS ]
 then
-  echo "#"
-  echo "# Using defaults found in" $DEFAULTS
-  echo "#"
+  echo "Using defaults found in" $DEFAULTS
   load_config_file $DEFAULTS
 else
-  echo "#"
-  echo "# No defaults found"
-  echo "#"
+  echo "No defaults found"
 fi
 
 
 # Fresh new log.
 >.menuconfig.log
 
-$DIALOG	--backtitle "$backtitle" \
-	--infobox "Preparing configuration scripts..." 3 40
+echo -n "Preparing configuration scripts: version" 
 
 #
 # Check kernel version of previous menuconfig build.
@@ -1222,6 +1278,7 @@
 
 if [ "$rebuildsound" ]
 then
+	echo -n ", sound"
 	# Activate the Linux compatible sound configuration.
 	# This may not work for all sound cards.  (See sound docs)
 	#
@@ -1231,13 +1288,28 @@
 fi
 
 # Load the functions used by the config.in files.
+echo -n ", functions"
 load_functions
 
+if [ ! -e $CONFIG_IN ]
+then
+	echo "Your main config.in file ($CONFIG_IN) does not exist"
+	exit 1
+fi
+
+if [ ! -x $DIALOG ]
+then
+	echo "Your lxdialog utility does not exist"
+	exit 1
+fi
+
 #
 # Read config.in files and parse them into one shell function per menu.
 #
+echo -n ", parsing"
 parse_config_files $CONFIG_IN
 
+echo "done."
 #
 # Start the ball rolling from the top.
 #
@@ -1253,25 +1325,12 @@
 #
 if $DIALOG --backtitle "$backtitle" \
 	   --yesno "Do you wish to save your new kernel configuration?" 5 60
-	   
 then
 	save_configuration
-
-	clear
-	cat <<EOM
-
-
-The linux kernel is now hopefully configured for your setup.
-Check the top-level Makefile for additional configuration,
-and do a 'make dep ; make clean' if you want to be sure all
-the files are correctly re-made.
-
-EOM
+	echo
+	echo The linux kernel is now configured for your setup.
 else
-	clear
-	echo -e "Your kernel configuration changes were NOT saved.\n"
+    	echo 
+	echo Your kernel configuration changes were NOT saved.
 fi
-
-
 exit 0
-
