diff -u --recursive --new-file v2.1.5/linux/CREDITS linux/CREDITS
--- v2.1.5/linux/CREDITS	Thu Oct 10 19:10:54 1996
+++ linux/CREDITS	Tue Oct 29 15:33:37 1996
@@ -927,7 +927,7 @@
 S: USA
 
 N: William (Bill) Metzenthen
-E: billm@jacobi.maths.monash.edu.au
+E: billm@suburbia.net
 D: Author of the FPU emulator.
 D: Minor kernel hacker for other lost causes (Hercules mono, etc).
 S: 22 Parker Street
@@ -1117,6 +1117,12 @@
 S: Rebmannsweg 34h
 S: 79539 Loerrach
 S: Germany
+
+N: Joerg Reuter
+E: jreuter@lykos.oche.de
+E: dl1bke@db0pra.ampr.org
+D: Generic Z8530 driver, AX.25 DAMA slave implementation
+D: Several AX.25 hacks
 
 N: William E. Roadcap
 E: roadcapw@cfw.com
diff -u --recursive --new-file v2.1.5/linux/Documentation/Changes linux/Documentation/Changes
--- v2.1.5/linux/Documentation/Changes	Wed Sep 11 11:45:10 1996
+++ linux/Documentation/Changes	Tue Oct 29 15:15:41 1996
@@ -103,49 +103,67 @@
 this option in their lilo.config file.  Comment it out and re-run lilo
 if you need ramdisks.
 
+Module load errors
+==================
+
+   The 386 Linux kernel versions 2.1.0 and above have moved to address
+0xc0000000.  This means that syscalls that return an address in the
+kernel area will return a value that is a negative 32 bit number.
+Versions of libc prior to libc-5.4.8 will interpret the negative value
+as an error.  In particular, this prevents modules from loading.  You
+need at least libc-5.4.10 to load modules successfully again.
+
+
 The Linux C Library
 ===================
 
-   The latest stable Linux C Library release is 5.2.18.  If you upgrade
-to this from 5.0.9 or earlier, be sure to read the
-`release.libc-5.2.18' file, since GNU make and a few other fairly
-important utils can be broken by the upgrade.
-
-   The current (beta) Linux C Library release is 5.3.12. In this
-release there are some important changes that may cause troubles to
-buggy programs (programs that call free() on a pointer not returned by
-malloc() work with previous libc, but not with this release) so read the
-`release.libc-5.3.12' file carefully!  In the latest libc releases a
-dirent bug, which erroneously defined d->reclen to d->namlen if USE_GNU
-was defined, has been fixed.  Unfortunately, some GNU packages depend
-on this bug.  GNU make 3.xx is one of them.  To fix that you need to
-patch and recompile those programs (a patch for make is included in the
-file `release.libc-.5.3.9', and the address to obtain a precompiled
-binary is at the end of this file).
-
-   Also, the libc-5.3.x line has a known security hole relating to
-rlogin.  Libc-5.3.12 fixes this, so if you're going to run an
-experimental libc, be sure to upgrade to 5.3.12.
+   Before upgrading your C library, be sure to carefully read the
+`release.libc-x.y.z' file. (x.y.z is the version number eg. 5.4.7)
+
+- GNU make, perl, and a few other important utils can be broken by the
+  upgrade.  A dirent bug, which erroneously defined d->reclen to
+  d->namlen if USE_GNU was defined, has been fixed.  Unfortunately,
+  some GNU packages depend on this bug.  GNU make 3.xx is one of them.
+  To fix that you need to patch and recompile those programs (a patch
+  for make is included in the file `release.libc-x.y.z', and the
+  address to obtain a precompiled binary is at the end of this file).
+
+- Upgrading libc can also break xterm support.  If it does, you need
+  to recompile xterm.
+
+- There have been some important changes to libc that may cause
+  trouble with buggy programs.  Programs that call free() on a pointer
+  not returned by malloc() work with older versions of libc, but not
+  with newer versions of libc.
 
-   If you're getting an error message that is something to the effect of
+
+There are good reasons to upgrade your libc though!
+
+- If you use modules, you'll need libc-5.4.10 or later with version
+  2.1.x i386 kernels
+
+- The libc-5.3.x line before libc-5.3.12 have a known security hole
+  relating to rlogin.  Another security fix was done in libc-5.4.7.
+
+- If you're getting an error message that is something like
 
    `fcntl_setlk() called by process 123 with broken flock() emulation'
 
-   then you need to upgrade to at least libc-5.2.18 as well.  A proper
-(in other words, BSD-style ;-) flock system call was added to 2.0.x,
-and older libc's will now give this error.  It doesn't *really* matter,
-so you can just ignore it. If it really annoys you, upgrade libc (and
-recompile any static binaries you might have that are linked against
-the old libc).  If you're feeling lazy, just comment out
-
-   `                printk(KERN_WARNING
-"fcntl_setlk() called by process %d with broken flock()
-  emulation\n",                        current->pid);'
-
-   in linux/fs/locks.c and recompile.  If you're still running a.out,
-there's an unofficial libc-4.7.6 release out to which you can upgrade
-to fix this problem.  Libc is available from
-ftp://sunsite.unc.edu/pub/Linux/GCC/.
+  then you need to upgrade to at least libc-5.2.18.  A proper (in
+  other words, BSD-style ;-) flock system call was added to 2.0.x, and
+  older libc's will now give this error.  It doesn't *really* matter,
+  so you can just ignore it. If it really annoys you, upgrade libc
+  (and recompile any static binaries you might have that are linked
+  against the old libc).  If you're feeling lazy, just comment out
+
+  `printk(KERN_WARNING
+    "fcntl_setlk() called by process %d with broken flock() emulation\n",
+     current->pid);'
+
+  in linux/fs/locks.c and recompile.  If you're still running a.out,
+  there's an unofficial libc-4.7.6 to which you can upgrade to fix
+  this problem.
+
 
 GCC Signal 11 error
 ===================
@@ -416,11 +434,9 @@
    If make no longer works, you need to read the release notes for the
 libc you upgraded to.  The latest libc and release notes can be found at
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC.  This is NOT an error due
-to the kernel, though many people have mistakenly thought it is.  When
-you upgrade to libc-5.3.9, you have to patch make to get it to work.
-All of this is documented in the release notes with libc.  Upgrading
-libc can also break xterm support.  If it does, you need to recompile
-xterm.
+to the kernel, though many people have mistakenly thought it was.  When
+you upgrade to libc-5.3.9 or later, from previous versions, you have
+to patch make to get it to work.
 
 Loop device
 ===========
@@ -605,15 +621,15 @@
 Linux C Library
 ===============
 
-The stable 5.2.18 release:
-ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.2.18.bin.tar.gz
-Installation notes for 5.2.18:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.2.18
-
-The latest 5.3.12 release:
-ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.3.12.bin.tar.gz
-Installation notes for 5.3.12:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.3.12
+The stable 5.4.7 release:
+ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.7.bin.tar.gz
+Installation notes for 5.4.7:
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.7
+
+The latest release:
+ftp://sunsite.unc.edu/pub/Linux/GCC/private/tofu/libc-x.y.z.bin.tar.gz
+Installation notes for x.y.z:
+ftp://sunsite.unc.edu/pub/Linux/GCC/private/tofu/release.libc-x.y.z
 
 Patched make sources:
 ftp://sunsite.unc.edu/pub/Linux/devel/make/make-3.74.patched.tar.gz
@@ -623,12 +639,16 @@
 Linux C++ Library
 =================
 
+ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.2.1.bin.tar.gz
 ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.1.4.bin.tar.gz
 ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.1.3.bin.tar.gz
 Installation notes:
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.2.1
 ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.1.4
 ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.1.3
-Use 2.7.13 with libc 5.2.18 and 2.7.14 with libc 5.3.12.
+Use libg++-2.7.2.1 with libc-5.4.4 and above,
+    libg++-2.7.1.4 with libc-5.3.5 to libc-5.4.3,
+    libg++-2.7.1.3 with libc 5.2.14 to libc-5.3.4
 
 Dynamic Linker
 ==============
@@ -713,4 +733,3 @@
 modified texinfo setup, so you don't need to bother generating a diff
 against the current version before you send the additional information
 to me.
-
diff -u --recursive --new-file v2.1.5/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.5/linux/Documentation/Configure.help	Wed Oct  9 08:55:16 1996
+++ linux/Documentation/Configure.help	Tue Oct 29 15:33:37 1996
@@ -1864,11 +1864,11 @@
   code which can be inserted in and removed from the running kernel
   whenever you want), say M here and read Documentation/modules.txt.
 
-Z8530 SCC kiss emulation driver for AX.25
+Z8530 SCC driver for AX.25
 CONFIG_SCC
   These cards are used to connect your Linux box to an amateur radio
   in order to communicate with other computers.  If you want to use
-  this, read Documentation/networking/z8530drv.txt and the HAM-HOWTO,
+  this, read Documentation/networking/z8530drv.txt and the AX.25-HOWTO,
   available via ftp (user: anonymous) at
   sunsite.unc.edu:/pub/Linux/docs/HOWTO.  If you want to compile this
   as a module ( = code which can be inserted in and removed from the
diff -u --recursive --new-file v2.1.5/linux/Documentation/networking/z8530drv.txt linux/Documentation/networking/z8530drv.txt
--- v2.1.5/linux/Documentation/networking/z8530drv.txt	Fri Apr 12 09:49:29 1996
+++ linux/Documentation/networking/z8530drv.txt	Tue Oct 29 15:33:37 1996
@@ -4,24 +4,22 @@
 Internet:
 =========
 
-ftp.ucsd.edu:/hamradio/packet/tcpip/incoming/z8530drv-2.0.dl1bke.real.tar.gz
+1. db0bm.automation.fh-aachen.de/incoming/dl1bke/z8530drv-utils-3.0.tar.gz
 
-[
-  if you can't find it there, try:
-  .../tcpip/linux/z8530drv-2.0.dl1bke.tar.gz
-
-]
+2. ftp.ucsd.edu:/hamradio/packet/tcpip/incoming/z8530drv-utils-3.0.tar.gz
+   If you can't find it there, try .../tcpip/linux/z8530drv-utils-3.0.tar.gz
 
 and various mirrors (i.e. nic.switch.ch)
 
----------------------------------------------------------------------------
+Please note that the information in this document may be hopelessly outdated.
+-----------------------------------------------------------------------------
 
 
 	 SCC.C - Linux driver for Z8530 based HDLC cards for AX.25      
 
    ********************************************************************
 
-        (c) 1993,1995 by Joerg Reuter DL1BKE
+        (c) 1993,1996 by Joerg Reuter DL1BKE <jreuter@lykos.oche.de>
 
         portions (c) 1993 Guido ten Dolle PE1NNZ
 
@@ -37,7 +35,12 @@
 
      1. if compiled as module: loading the module
      2. Setup of hardware, MODEM and KISS parameters with sccinit
-     3. Attachment of each channel in the packet software
+     3. Attach each channel to the Linux kernel AX.25 with "ifconfig"
+
+Unlike the versions below 2.4 this driver is a real network device
+driver. If you want to run xNOS instead of our fine kernel AX.25
+use a 2.x version (available from above sites) or read the
+AX.25-HOWTO on how to emulate a KISS TNC on network device drivers.
 
 
 1.1 Loading the module
@@ -54,15 +57,14 @@
 
 You should include the insmod in one of the /etc/rc.d/rc.* files,
 and don't forget to insert a call of sccinit after that. It
-will read  your
+will read your /etc/z8530drv.conf.
 
-
-1.2. /etc/z8530drv.rc
-=====================
+1.2. /etc/z8530drv.conf
+=======================
 
 To setup all parameters you must run /sbin/sccinit from one
-of your rc.*-files. This has to be done BEFORE the start of
-NET or axattach. Sccinit reads the file /etc/z8530drv.rc
+of your rc.*-files. This has to be done BEFORE you can
+"ifconfig" an interface. Sccinit reads the file /etc/z8530drv.conf
 and sets the hardware, MODEM and KISS parameters. A sample file is
 delivered with this package. Change it to your needs.
 
@@ -222,7 +224,7 @@
 
 gencfg 2 0x150 4 2 0 1 0x168 9 4915200 
 
-will print a skeleton z8530drv.rc for the OptoSCC to stdout.
+will print a skeleton z8530drv.conf for the OptoSCC to stdout.
 
 gencfg 2 0x300 2 4 5 -4 0 7 4915200 0x10
 
@@ -236,11 +238,11 @@
 The channel definition is divided into three sub sections for each
 channel:
 
-An example for /dev/scc0:
+An example for scc0:
 
 # DEVICE
 
-device /dev/scc0	# the device for the following params
+device scc0	# the device for the following params
 
 # MODEM / BUFFERS
 
@@ -254,10 +256,6 @@
 			#	nrzi = 1k2 MODEM, G3RUH 9k6 MODEM
 			#	nrz  = DF9IC 9k6 MODEM
 			#
-rxbuffers 8		# number of rx buffers allocated
-			# 		(option, default is 4)
-txbuffers 16		# number of tx buffers allocated
-			#		(option, default is 16)
 bufsize	384		# size of buffers. Note that this must include
 			# the AX.25 header, not only the data field!
 			# (optional, defaults to 384)
@@ -283,9 +281,10 @@
 sections IS important. The MODEM parameters are set with the first
 recognized KISS parameter...
 
-Please note that you can initialize the board only once after boot. 
-You can change all parameters but "mode" and "clock" later with the
-Sccparam program or through KISS. Just to avoid security holes... 
+Please note that you can initialize the board only once after boot
+(or insmod). You can change all parameters but "mode" and "clock" 
+later with the Sccparam program or through KISS. Just to avoid 
+security holes... 
 
 (1) this divider is usually mounted on the SCC-PBC (PA0HZP) or not
     present at all (BayCom). It feeds back the output of the DPLL 
@@ -293,71 +292,56 @@
     installed will normally result in keying the transceiver until 
     maxkey expires --- of course without sending anything (useful).
 
-
 2. Attachment of a channel by your AX.25 software
 =================================================
 
-2.1 KA9Q NOS derivates
-======================
+2.1 Kernel AX.25
+================
 
-When the linux has startup, the SCC driver has been initialized,
-you can attach the channels in your packet software. This is done
-by open the scc devices by using the attach asy command.
-The SCC-drivers emulates the scc devices as serial asy ports,
-this means e.g. that the baudrate can be set in the attach command.
+To set up an AX.25 device you can simply type:
 
+	ifconfig scc0 44.128.1.1 hw ax25 dl0tha-7
 
-Example Wampes:
-
-#############################################################################################
-# Wampes device attach
-# NOTE: Interfacename and the device must be the same!!
-# Usage: attach asy 0 0 slip|vjslip|ax25ui|ax25i|nrs|kissui <label> 0 <mtu> <speed> [ip_addr]
-#
-attach asy 0 0 kissi  scc0 256 256 1200   # Attach SCC channel 1 in 1200 baud
-attach asy 0 0 kissi  scc1 256 256 1200   # Attach SCC channel 2 in 1200 baud
-attach asy 0 0 kissui scc2 256 256 38400  # Attach SCC channel 3 in 38400 baud
-attach asy 0 0 kissui scc3 256 256 9600   # Attach SCC channel 4 in 9600 baud
-#              ^^^^
-#              for WAMPES 921229 use here: ax25
-#
+This will create a network interface with the IP number 44.128.20.107 
+and the callsign "dl0tha". If you do not have any IP number (yet) you 
+can use any of the 44.128.0.0 network. Note that you do not need 
+axattach. The purpose of axattach (like slattach) is to create a KISS 
+network device linked to a TTY. Please read the documentation of the 
+ax25-utils and the AX.25-HOWTO to learn how to set the parameters of
+the kernel AX.25.
 
-Example JNOS:
+2.2 NOS, NET and TFKISS
+=======================
 
-############################################
-# JNOS device attach
-#
-attach asy scc0 0 ax25 scc0 256 256 1200
-attach asy scc1 0 ax25 scc1 256 256 1200
-attach asy scc2 0 ax25 scc2 256 256 300
-attach asy scc3 0 ax25 scc3 256 256 4800
-#
-#
+Since the TTY driver (aka KISS TNC emulation) is gone you need
+to emulate the old behaviour. The cost using these programs is
+that you probably need to compile the kernel AX.25, regardless 
+if you actually use it or not. First setup your /etc/ax25/axports,
+for example:
 
+	9k6	dl0tha-9  9600  255 4 9600 baud port (scc3)
+	axlink	dl0tha-15 38400 255 4 Link to NOS
 
-It allows AX.25 communication without a TNC.  Only a MODEM is
-needed. The parameters have the same meaning as in KISS mode.
-In fact, the AX.25 mode is emulating an extended KISS TNC, so
-the same commands can be used to set the parameters of the
-interface (see below).
-
-To be able to run fullduplex using an SCC in AX.25 mode, an 
-external divider must be available, that divides the baudrate 
-generator clock available on the TRxC pin by 32, and puts the 
-resulting signal on the RTxC pint of the same channel of the SCC.  
-Such a divider is not necessary for normal CSMA packet radio 
-operation, but interrupt overhead is slightly reduced if you 
-still install it.  
+Now "ifconfig" the scc device:
 
-2.2 Kernel AX.25
-================
+	ifconfig scc3 44.128.1.1 hw ax25 dl0tha-9
+
+You can now axattach a pseudo-TTY:
+
+	axattach /dev/ptys0 axlink
+
+and start your NOS and attach /dev/ptys0 there. The problem is that
+NOS is reachable only via digipeating through the kernel AX.25
+(disasterous on a DAMA controlled channel). To solve this problem,
+configure "rxecho" to echo the incoming frames from "9k6" to "axlink"
+and outgoing frames from "axlink" to "9k6" and start:
 
-Well, as said before: The driver emulates a KISS TNC, so you
-can simply run
+	rxecho
 
-	axattach -s 1200 /dev/scc0 DL1BKE
+Or simply use "kissbridge" coming with z8530drv-utils:
 
-to establish the link between kernel AX.25 and z8530drv.
+	ifconfig scc3 hw ax25 dl0tha-9
+	kissbridge scc3 /dev/ptys0
 
 
 3. Adjustment and Display of parameters
@@ -369,7 +353,7 @@
 Once a SCC channel has been attached, the parameter settings and 
 some statistic information can be shown using the param program:
 
-dl1bke-u:~$ sccstat /dev/scc0
+dl1bke-u:~$ sccstat scc0
 
 Parameters:
 
@@ -391,43 +375,35 @@
 
 Status:
 
-HDLC                  Z8530           Interrupts         Queues
+HDLC                  Z8530           Interrupts         Buffers
 -----------------------------------------------------------------------
-Sent       :     273  RxOver :     0  RxInts :   125074  RxQueue :    0
-Received   :    1095  TxUnder:     0  TxInts :     4684  TxQueue :    0
-RxErrors   :    1591                  ExInts :    11776  NoSpace :    0
-KissErrors :       0                  SpInts :     1503
+Sent       :     273  RxOver :     0  RxInts :   125074  Size    :  384
+Received   :    1095  TxUnder:     0  TxInts :     4684  NoSpace :    0
+RxErrors   :    1591                  ExInts :    11776
+TxErrors   :       0                  SpInts :     1503
 Tx State   :    idle
 
-Memory allocated:
-
-Buffer size:     384
-rx buffers :       4
-tx buffers :       8
-
 
 The status info shown is:
 
 Sent		- number of frames transmitted
 Received	- number of frames received
 RxErrors	- number of receive errors (CRC, ABORT)
-KissErrors	- number of KISS errors (should be zero...)
+TxErrors	- number of discarded Tx frames (due to various reasons) 
 Tx State	- status of the Tx interrupt handler: idle/busy/active/tail (2)
 RxOver		- number of receiver overruns
-TxUnder		- number of transmitter underruns     
+TxUnder		- number of transmitter underruns
 RxInts		- number of receiver interrupts
 TxInts		- number of transmitter interrupts
 EpInts		- number of receiver special condition interrupts
 SpInts		- number of external/status interrupts
-RxQueue		- number of received packets enqueued for this channel
-TxQueue		- number of packets enqueued for Tx
-NoSpace		- number of times the receiver buffer pool was found empty
-
+Size		- maximum size of an AX.25 frame (*with* AX.25 headers!)
+NoSpace		- number of times a buffer could not get allocated
 
 An overrun is abnormal. If lots of these occur, the product of
 baudrate and number of interfaces is too high for the processing
-power of you computer. If "Space" errors occur, specify a higher
-number of buffers in the "scc.h" file.
+power of you computer. NoSpace errors are unlikely caused by the
+driver or the kernel AX.25.
 
 
 3.2 Setting Parameters
@@ -436,11 +412,8 @@
 
 The setting of parameters of the emulated KISS TNC is done in the 
 same way in the SCC driver. You can change parameters by using
-the command param in NET or NOS
-
-     param <iface> <paramname> <value>
-
-or use the program "sccparam":
+the kissparms program from the ax25-utils package or use the program 
+"sccparam":
 
      sccparam <device> <paramname> <decimal-|hexadecimal value>
 
@@ -621,32 +594,25 @@
      Example: sccparam /dev/scc0 soft on
 
 
-slip:
-     use slip encoding instead of kiss
-
-     Example: sccparam /dev/scc1 slip on
-
-
-
 4. Problems 
 ===========
 
 If you have tx-problems with your BayCom USCC card please check
 the manufacturer of the 8530. SGS chips have a slightly
-different timing. Try Zilog... I have no information if this
-driver works with baudrates higher than 1200 baud. A solution is
-to write to register 8 instead to the data port, but this won't
-work with the ESCC chips *SIGH!*
+different timing. Try Zilog...  A solution is to write to register 8 
+instead to the data port, but this won't work with the ESCC chips. 
+*SIGH!*
+
+A very common problem is that the PTT locks until the maxkeyup timer
+expires, although interrupts and clock source are correct. In most
+cases #define SCC_DELAY solves the problems. For more hints read
+the (pseudo) FAQ and the documentation coming with z8530drv-utils.
 
 I got reports that the driver has problems on some 386-based systems.
 (i.e. Amstrad) Those systems have a bogus AT bus timing which will
 lead to delayed answers on interrupts. You can recognize these
 problems by looking at the output of Sccstat for the suspected
 port. See if it shows under- and overruns you own such a system.
-Perhaps it will help if you simplify the scc_isr() function a bit.
-You'll find a slightly faster version in the files scc_isr_intack
-or scc_isr_novec.
-
 
 Delayed processing of received data: This depends on
 
@@ -654,127 +620,24 @@
 
 - kernel profiling compiled or not
 
-- the rather slow receiver in tty_io.c
-
 - a high interrupt load
 
 - a high load of the machine --- running X, Xmorph, XV and Povray,
   while compiling the kernel... hmm ... even with 32 MB RAM ...  ;-)
+  Or running a named for the whole .ampr.org. domain on an 8 MB
+  box...
 
-- NET's speed itself.
-
+- using information from rxecho or kissbridge.
 
 Kernel panics: please read to /linux/README and find out if it
 really occurred within the scc driver.
 
-If you can't solve a problem, send me
+If you cannot solve a problem, send me
 
 - a description of the problem,
 - information on your hardware (computer system, scc board, modem)
 - your kernel version
-- the output of sccstat /dev/scc# ("#" is the No. of the channel)
-- the settings of "speed", "clock" and "mode" for that channel
-  in /etc/z8530drv.rc
-- your scc_config.h
-
-
-And always remember: 
-The 1.1.* kernel series is for alpha tests -- use at your own risk ;-)
-The 1.2.* series should run reliable. This driver perhaps NOT!
-The 1.3.* kernel series is for alpha tests again... you get the idea!
-
-
-3. DRSI Boards
-==============
-
-I still can't test the DRSI board, but this configuration derived from
-the PE1CHL SCC driver configuration should work:
-
-An example of scc_config.h for 
-
-One DRSI board installed:
-=========================
-
-/* gencfg 1 0x300 0x10 2 0 1 0 7 4915200 */
-
-/* file generated by $Id: gencfg.c,v 1.2 1994/11/29 21:42:24 JReuter Exp JReuter $ */
-
-#include <linux/scc.h>
-
-int     Nchips	     = 1;
-io_port Vector_Latch = 0x0;
-int     Ivec	     = 7;
-long    Clock	     = 4915200;
-char	Board	     = PA0HZP;
-int	Option	     = 0;
-io_port Special_Port = 0x0;
-
-io_port SCC_ctrl[MAXSCC * 2] =
-{0x302, 0x300, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
-
-io_port SCC_data[MAXSCC * 2] =
-{0x303, 0x301, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
-
-/* set to '1' if you have and want ESCC chip (8580/85180/85280) support */
-
-/*					      Chip	*/
-/*				            ========   	*/
-int SCC_Enhanced[MAXSCC] =	{0,	/* ...one...	*/
-				 0,  	/* ...two...	*/
-				 0,  	/* ...three...	*/
-				 0};	/* ...four...	*/
-
-#define VERBOSE_BOOTMSG 1
-#undef  SCC_DELAY		/* perhaps a 486DX2 is a *bit* too fast */
-#undef  SCC_LDELAY		/* slow it even a bit more down */
-#undef  DONT_CHECK		/* don't look if the SCCs you specified are available */
-
-
-
-Two boards installed:
-=====================
-
-/* file generated by $Id: gencfg.c,v 1.2 1994/11/29 21:42:24 JReuter Exp JReuter $ */
-
-#include <linux/scc.h>
-
-int     Nchips	     = 2;
-io_port Vector_Latch = 0x0;
-int     Ivec	     = 7;
-long    Clock	     = 4915200;
-char	Board	     = PA0HZP;
-int	Option	     = 0;
-io_port Special_Port = 0x0;
-
-io_port SCC_ctrl[MAXSCC * 2] =
-{0x302, 0x300, 0x312, 0x310, 0x0, 0x0, 0x0, 0x0};
-
-io_port SCC_data[MAXSCC * 2] =
-{0x303, 0x301, 0x313, 0x311, 0x0, 0x0, 0x0, 0x0};
-
-/* set to '1' if you have and want ESCC chip (8580/85180/85280) support */
-
-/*					      Chip	*/
-/*				            ========   	*/
-int SCC_Enhanced[MAXSCC] =	{0,	/* ...one...	*/
-				 0,  	/* ...two...	*/
-				 0,  	/* ...three...	*/
-				 0};	/* ...four...	*/
-
-#define VERBOSE_BOOTMSG 1
-#undef  SCC_DELAY		/* perhaps a 486DX2 is a *bit* too fast */
-#undef  SCC_LDELAY		/* slow it even a bit more down */
-#undef  DONT_CHECK		/* don't look if the SCCs you specified are available */
-
-
-*****************
-
-You  m u s t  use "clock dpll" in /etc/z8530drv.rc for operation, 
-the on-board baudrate generator is not supported.
-
-*****************
-(mni tnx to Mike Bilow)
-
+- the output of cat /proc/net/z8530
 
 4. Thor RLC100
 ==============
@@ -788,4 +651,4 @@
 
 Joerg Reuter	ampr-net: dl1bke@db0pra.ampr.org
 		AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
-		Internet: jreuter@lykos.tng.oche.de
+		Internet: jreuter@lykos.oche.de
diff -u --recursive --new-file v2.1.5/linux/MAINTAINERS linux/MAINTAINERS
--- v2.1.5/linux/MAINTAINERS	Sun Sep 22 09:41:32 1996
+++ linux/MAINTAINERS	Tue Oct 29 15:33:37 1996
@@ -123,6 +123,18 @@
 L:	linux-hams@vger.rutgers.edu
 S:	Maintained
 
+DAMA SLAVE for AX.25
+P: Joerg Reuter
+M: jreuter@lykos.oche.de
+L: linux-hams@vger.rutgers.edu
+S: Maintained
+
+Z8530 DRIVER FOR AX.25
+P: Joerg Reuter
+M: jreuter@lykos.oche.de
+L: linux-hams@vger.rutgers.edu
+S: Maintained
+
 BUSLOGIC SCSI DRIVER
 P:	Leonard N. Zubkoff
 M:	Leonard N. Zubkoff <lnz@dandelion.com>
@@ -339,6 +351,12 @@
 P:	Eberhard Moenkeberg
 M:	emoenke@gwdg.de
 L:	linux-kernel@vger.rutgers.edu
+S:	Maintained
+
+FPU EMULATOR
+P:	Bill Metzenthen
+M:	billm@suburbia.net
+W:	http://suburbia.net/~billm/floating-point/emulator/
 S:	Maintained
 
 CREDITS FILE
diff -u --recursive --new-file v2.1.5/linux/Makefile linux/Makefile
--- v2.1.5/linux/Makefile	Sat Oct 19 10:07:28 1996
+++ linux/Makefile	Sat Oct 19 10:08:02 1996
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 5
+SUBLEVEL = 6
 
 ARCH = i386
 
diff -u --recursive --new-file v2.1.5/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.1.5/linux/arch/alpha/kernel/osf_sys.c	Wed Oct 16 10:48:06 1996
+++ linux/arch/alpha/kernel/osf_sys.c	Tue Oct 29 14:02:04 1996
@@ -29,7 +29,7 @@
 
 #include <asm/fpu.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
diff -u --recursive --new-file v2.1.5/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.1.5/linux/arch/alpha/kernel/process.c	Thu Oct 10 19:10:54 1996
+++ linux/arch/alpha/kernel/process.c	Tue Oct 29 14:02:04 1996
@@ -27,7 +27,7 @@
 #include <linux/elfcore.h>
 
 #include <asm/reg.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
 
diff -u --recursive --new-file v2.1.5/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c
--- v2.1.5/linux/arch/alpha/kernel/ptrace.c	Mon Sep 23 14:41:33 1996
+++ linux/arch/alpha/kernel/ptrace.c	Tue Oct 29 14:02:04 1996
@@ -13,7 +13,7 @@
 #include <linux/user.h>
 #include <linux/debugreg.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
diff -u --recursive --new-file v2.1.5/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v2.1.5/linux/arch/alpha/kernel/setup.c	Thu Oct 10 19:10:54 1996
+++ linux/arch/alpha/kernel/setup.c	Tue Oct 29 14:02:04 1996
@@ -22,7 +22,7 @@
 #include <linux/delay.h>
 #include <linux/config.h>	/* CONFIG_ALPHA_LCA etc */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/hwrpb.h>
diff -u --recursive --new-file v2.1.5/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c
--- v2.1.5/linux/arch/alpha/kernel/signal.c	Wed Oct 16 10:48:06 1996
+++ linux/arch/alpha/kernel/signal.c	Tue Oct 29 14:02:04 1996
@@ -14,7 +14,7 @@
 #include <linux/mm.h>
 
 #include <asm/bitops.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define _S(nr) (1<<((nr)-1))
 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
diff -u --recursive --new-file v2.1.5/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c
--- v2.1.5/linux/arch/alpha/kernel/time.c	Sun Mar 24 12:09:35 1996
+++ linux/arch/alpha/kernel/time.c	Tue Oct 29 14:02:04 1996
@@ -18,7 +18,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/hwrpb.h>
 
diff -u --recursive --new-file v2.1.5/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v2.1.5/linux/arch/alpha/kernel/traps.c	Sat Oct 19 10:07:28 1996
+++ linux/arch/alpha/kernel/traps.c	Tue Oct 29 14:02:04 1996
@@ -14,7 +14,7 @@
 #include <linux/tty.h>
 
 #include <asm/gentrap.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
 void die_if_kernel(char * str, struct pt_regs * regs, long err)
diff -u --recursive --new-file v2.1.5/linux/arch/alpha/math-emu/fp-emul.c linux/arch/alpha/math-emu/fp-emul.c
--- v2.1.5/linux/arch/alpha/math-emu/fp-emul.c	Wed Oct 16 10:48:06 1996
+++ linux/arch/alpha/math-emu/fp-emul.c	Tue Oct 29 14:02:04 1996
@@ -3,7 +3,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "ieee-math.h"
 
diff -u --recursive --new-file v2.1.5/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c
--- v2.1.5/linux/arch/alpha/mm/fault.c	Wed Oct 16 10:48:06 1996
+++ linux/arch/alpha/mm/fault.c	Tue Oct 29 14:02:04 1996
@@ -16,7 +16,7 @@
 #include <linux/mm.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 
diff -u --recursive --new-file v2.1.5/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c
--- v2.1.5/linux/arch/alpha/mm/init.c	Wed Oct  9 08:55:17 1996
+++ linux/arch/alpha/mm/init.c	Tue Oct 29 14:02:04 1996
@@ -18,7 +18,7 @@
 #include <linux/swap.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/hwrpb.h>
 #include <asm/dma.h>
diff -u --recursive --new-file v2.1.5/linux/arch/i386/kernel/ksyms.c linux/arch/i386/kernel/ksyms.c
--- v2.1.5/linux/arch/i386/kernel/ksyms.c	Wed Oct 16 10:48:06 1996
+++ linux/arch/i386/kernel/ksyms.c	Mon Oct 28 14:41:15 1996
@@ -5,7 +5,7 @@
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
diff -u --recursive --new-file v2.1.5/linux/arch/i386/kernel/ldt.c linux/arch/i386/kernel/ldt.c
--- v2.1.5/linux/arch/i386/kernel/ldt.c	Wed Oct 16 10:48:06 1996
+++ linux/arch/i386/kernel/ldt.c	Mon Oct 28 14:41:15 1996
@@ -10,7 +10,7 @@
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/ldt.h>
 
diff -u --recursive --new-file v2.1.5/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.1.5/linux/arch/i386/kernel/process.c	Wed Oct  9 08:55:17 1996
+++ linux/arch/i386/kernel/process.c	Mon Oct 28 14:41:15 1996
@@ -28,7 +28,7 @@
 #include <linux/delay.h>
 #include <linux/smp.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.1.5/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v2.1.5/linux/arch/i386/kernel/ptrace.c	Wed Oct 16 10:48:06 1996
+++ linux/arch/i386/kernel/ptrace.c	Mon Oct 28 14:41:15 1996
@@ -11,7 +11,7 @@
 #include <linux/user.h>
 #include <linux/debugreg.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
diff -u --recursive --new-file v2.1.5/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.1.5/linux/arch/i386/kernel/setup.c	Mon Sep 30 09:37:53 1996
+++ linux/arch/i386/kernel/setup.c	Mon Oct 28 14:41:15 1996
@@ -28,7 +28,7 @@
 #ifdef CONFIG_BLK_DEV_RAM
 #include <linux/blk.h>
 #endif
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/smp.h>
 
diff -u --recursive --new-file v2.1.5/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- v2.1.5/linux/arch/i386/kernel/signal.c	Wed Oct 16 10:48:06 1996
+++ linux/arch/i386/kernel/signal.c	Mon Oct 28 22:23:05 1996
@@ -15,7 +15,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define _S(nr) (1<<((nr)-1))
 
@@ -181,7 +181,8 @@
 /* set up the "normal" stack seen by the signal handler (iBCS2) */
 #define __CODE ((unsigned long)(frame+24))
 #define CODE(x) ((unsigned long *) ((x)+__CODE))
-	put_user(__CODE,frame);
+	if (put_user(__CODE,frame))
+		do_exit(SIGSEGV);
 	if (current->exec_domain && current->exec_domain->signal_invmap)
 		put_user(current->exec_domain->signal_invmap[signr], frame+1);
 	else
@@ -189,7 +190,7 @@
 	{
 		unsigned int tmp = 0;
 #define PUT_SEG(seg, mem) \
-__asm__("mov %%" #seg",%w0":"=r" (tmp):"0" (tmp)); *(mem) = tmp;
+__asm__("mov %%" #seg",%w0":"=r" (tmp):"0" (tmp)); put_user(tmp,mem);
 		PUT_SEG(gs, frame+2);
 		PUT_SEG(fs, frame+3);
 	}
diff -u --recursive --new-file v2.1.5/linux/arch/i386/kernel/sys_i386.c linux/arch/i386/kernel/sys_i386.c
--- v2.1.5/linux/arch/i386/kernel/sys_i386.c	Wed Oct 16 10:48:06 1996
+++ linux/arch/i386/kernel/sys_i386.c	Mon Oct 28 14:41:15 1996
@@ -16,7 +16,7 @@
 #include <linux/mman.h>
 #include <linux/file.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/ipc.h>
 
 /*
diff -u --recursive --new-file v2.1.5/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v2.1.5/linux/arch/i386/kernel/time.c	Wed Aug 14 19:09:52 1996
+++ linux/arch/i386/kernel/time.c	Mon Oct 28 14:41:15 1996
@@ -21,7 +21,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
diff -u --recursive --new-file v2.1.5/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.1.5/linux/arch/i386/kernel/traps.c	Wed Oct  9 08:55:17 1996
+++ linux/arch/i386/kernel/traps.c	Mon Oct 28 14:41:15 1996
@@ -22,7 +22,7 @@
 #include <linux/mm.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 asmlinkage int system_call(void);
diff -u --recursive --new-file v2.1.5/linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c
--- v2.1.5/linux/arch/i386/kernel/vm86.c	Sat Oct 19 10:07:29 1996
+++ linux/arch/i386/kernel/vm86.c	Mon Oct 28 14:41:15 1996
@@ -11,7 +11,7 @@
 #include <linux/ptrace.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 
diff -u --recursive --new-file v2.1.5/linux/arch/i386/math-emu/README linux/arch/i386/math-emu/README
--- v2.1.5/linux/arch/i386/math-emu/README	Thu Oct  5 15:30:43 1995
+++ linux/arch/i386/math-emu/README	Tue Oct 29 15:16:36 1996
@@ -1,9 +1,9 @@
  +---------------------------------------------------------------------------+
  |  wm-FPU-emu   an FPU emulator for 80386 and 80486SX microprocessors.      |
  |                                                                           |
- | Copyright (C) 1992,1993,1994,1995                                         |
+ | Copyright (C) 1992,1993,1994,1995,1996                                    |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                       Australia.  E-mail billm@suburbia.net               |
  |                                                                           |
  |    This program is free software; you can redistribute it and/or modify   |
  |    it under the terms of the GNU General Public License version 2 as      |
@@ -42,11 +42,11 @@
 some differences.
 
 Please report bugs, etc to me at:
-       billm@jacobi.maths.monash.edu.au
+       billm@suburbia.net
 
 
 --Bill Metzenthen
-  October 1995
+  October 1996
 
 
 ----------------------- Internals of wm-FPU-emu -----------------------
diff -u --recursive --new-file v2.1.5/linux/arch/i386/math-emu/errors.c linux/arch/i386/math-emu/errors.c
--- v2.1.5/linux/arch/i386/math-emu/errors.c	Wed Oct 16 10:48:06 1996
+++ linux/arch/i386/math-emu/errors.c	Mon Oct 28 14:41:15 1996
@@ -19,7 +19,7 @@
 
 #include <linux/signal.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "fpu_system.h"
 #include "exception.h"
diff -u --recursive --new-file v2.1.5/linux/arch/i386/math-emu/fpu_entry.c linux/arch/i386/math-emu/fpu_entry.c
--- v2.1.5/linux/arch/i386/math-emu/fpu_entry.c	Wed Oct 16 10:48:06 1996
+++ linux/arch/i386/math-emu/fpu_entry.c	Mon Oct 28 14:41:15 1996
@@ -26,7 +26,7 @@
 
 #include <linux/signal.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "fpu_system.h"
 #include "fpu_emu.h"
diff -u --recursive --new-file v2.1.5/linux/arch/i386/math-emu/get_address.c linux/arch/i386/math-emu/get_address.c
--- v2.1.5/linux/arch/i386/math-emu/get_address.c	Wed Oct 16 10:48:06 1996
+++ linux/arch/i386/math-emu/get_address.c	Mon Oct 28 14:41:15 1996
@@ -21,7 +21,7 @@
 #include <linux/stddef.h>
 #include <linux/head.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "fpu_system.h"
 #include "exception.h"
diff -u --recursive --new-file v2.1.5/linux/arch/i386/math-emu/load_store.c linux/arch/i386/math-emu/load_store.c
--- v2.1.5/linux/arch/i386/math-emu/load_store.c	Wed Oct 16 10:48:07 1996
+++ linux/arch/i386/math-emu/load_store.c	Mon Oct 28 14:41:15 1996
@@ -18,7 +18,7 @@
  |    other processes using the emulator while swapping is in progress.      |
  +---------------------------------------------------------------------------*/
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "fpu_system.h"
 #include "exception.h"
diff -u --recursive --new-file v2.1.5/linux/arch/i386/math-emu/reg_ld_str.c linux/arch/i386/math-emu/reg_ld_str.c
--- v2.1.5/linux/arch/i386/math-emu/reg_ld_str.c	Wed Oct 16 10:48:07 1996
+++ linux/arch/i386/math-emu/reg_ld_str.c	Mon Oct 28 14:41:15 1996
@@ -17,7 +17,7 @@
  |    other processes using the emulator while swapping is in progress.      |
  +---------------------------------------------------------------------------*/
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "fpu_system.h"
 #include "exception.h"
diff -u --recursive --new-file v2.1.5/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
--- v2.1.5/linux/arch/i386/mm/fault.c	Wed Oct 16 10:48:07 1996
+++ linux/arch/i386/mm/fault.c	Mon Oct 28 14:41:15 1996
@@ -16,7 +16,7 @@
 #include <linux/mm.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 extern void die_if_kernel(const char *,struct pt_regs *,long);
diff -u --recursive --new-file v2.1.5/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.1.5/linux/arch/i386/mm/init.c	Sat Oct 19 10:07:29 1996
+++ linux/arch/i386/mm/init.c	Mon Oct 28 14:41:15 1996
@@ -22,7 +22,7 @@
 #endif
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 
diff -u --recursive --new-file v2.1.5/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.1.5/linux/drivers/block/floppy.c	Sat Oct 19 10:07:29 1996
+++ linux/drivers/block/floppy.c	Mon Oct 28 14:29:19 1996
@@ -161,7 +161,7 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int use_virtual_dma=0; /* virtual DMA for Intel */
 static unsigned short virtual_dma_port=0x3f0;
diff -u --recursive --new-file v2.1.5/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v2.1.5/linux/drivers/block/hd.c	Wed Oct 16 10:48:08 1996
+++ linux/drivers/block/hd.c	Mon Oct 28 14:29:19 1996
@@ -39,7 +39,7 @@
 #define REALLY_SLOW_IO
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define MAJOR_NR HD_MAJOR
 #include <linux/blk.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v2.1.5/linux/drivers/block/ide-cd.c	Wed Oct 16 10:48:08 1996
+++ linux/drivers/block/ide-cd.c	Mon Oct 28 14:29:19 1996
@@ -138,7 +138,7 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
 #include "ide.h"
diff -u --recursive --new-file v2.1.5/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
--- v2.1.5/linux/drivers/block/ide-tape.c	Wed Oct 16 10:48:08 1996
+++ linux/drivers/block/ide-tape.c	Mon Oct 28 14:29:19 1996
@@ -326,7 +326,7 @@
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 /*
diff -u --recursive --new-file v2.1.5/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.1.5/linux/drivers/block/ide.c	Wed Oct 16 10:48:08 1996
+++ linux/drivers/block/ide.c	Tue Oct 29 00:31:24 1996
@@ -288,7 +288,7 @@
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 #ifdef CONFIG_PCI
@@ -2272,11 +2272,13 @@
 	unsigned long capacity, check;
 
 	id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_KERNEL);
-	ide_input_data(drive, id, SECTOR_WORDS);	/* read 512 bytes of id info */
+	ide_input_data(drive, id, SECTOR_WORDS);/* read 512 bytes of id info */
 	sti();
 
+#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO)
 	/*
-	 * EATA SCSI controllers do a hardware ATA emulation:  ignore them
+	 * EATA SCSI controllers do a hardware ATA emulation:  
+	 * Ignore them if there is a driver for them available.
 	 */
 	if ((id->model[0] == 'P' && id->model[1] == 'M')
 	 || (id->model[0] == 'S' && id->model[1] == 'K')) {
@@ -2284,6 +2286,7 @@
 		drive->present = 0;
 		return;
 	}
+#endif
 
 	/*
 	 *  WIN_IDENTIFY returns little-endian info,
diff -u --recursive --new-file v2.1.5/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.1.5/linux/drivers/block/loop.c	Sat Oct 19 10:07:29 1996
+++ linux/drivers/block/loop.c	Mon Oct 28 14:29:19 1996
@@ -22,7 +22,7 @@
 #include <linux/errno.h>
 #include <linux/major.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #ifdef CONFIG_BLK_DEV_LOOP_DES
 #include <linux/des.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.1.5/linux/drivers/block/rd.c	Wed Oct 16 10:48:08 1996
+++ linux/drivers/block/rd.c	Mon Oct 28 14:29:19 1996
@@ -52,7 +52,7 @@
 #include <linux/module.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 extern void wait_for_keypress(void);
 
diff -u --recursive --new-file v2.1.5/linux/drivers/block/umc8672.c linux/drivers/block/umc8672.c
--- v2.1.5/linux/drivers/block/umc8672.c	Mon Aug  5 08:26:00 1996
+++ linux/drivers/block/umc8672.c	Tue Oct 29 15:28:40 1996
@@ -28,7 +28,7 @@
  * Germany
  *
  * To enable UMC8672 support there must a lilo line like
- * append="hd=umc8672"...
+ * append="ide0=umc8672"...
  * To set the speed according to the abilities of the hardware there must be a
  * line like
  * #define UMC_DRIVE0 11
diff -u --recursive --new-file v2.1.5/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.1.5/linux/drivers/block/xd.c	Sat Sep 28 11:46:40 1996
+++ linux/drivers/block/xd.c	Mon Oct 28 14:29:19 1996
@@ -32,7 +32,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/dma.h>
 
 #define MAJOR_NR XT_DISK_MAJOR
diff -u --recursive --new-file v2.1.5/linux/drivers/cdrom/aztcd.c linux/drivers/cdrom/aztcd.c
--- v2.1.5/linux/drivers/cdrom/aztcd.c	Wed Oct 16 10:48:08 1996
+++ linux/drivers/cdrom/aztcd.c	Mon Oct 28 14:29:19 1996
@@ -169,7 +169,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define MAJOR_NR AZTECH_CDROM_MAJOR 
 
diff -u --recursive --new-file v2.1.5/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c
--- v2.1.5/linux/drivers/cdrom/cdu31a.c	Sat Oct 19 10:07:30 1996
+++ linux/drivers/cdrom/cdu31a.c	Mon Oct 28 22:17:40 1996
@@ -191,7 +191,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/dma.h>
 
 #include <linux/cdrom.h>
@@ -1915,7 +1915,9 @@
    int num_tracks;
 
 
-   num_tracks = sony_toc.last_track_num - sony_toc.first_track_num + 1;
+   num_tracks = (  bcd_to_int(sony_toc.last_track_num)
+                 - bcd_to_int(sony_toc.first_track_num)
+		 + 1);
    for (i = 0; i < num_tracks; i++)
    {
       if (sony_toc.tracks[i].track == track)
@@ -2486,8 +2488,8 @@
          i=verify_area(VERIFY_WRITE, hdr, sizeof(*hdr));
          if(i<0)
          	return i;
-         loc_hdr.cdth_trk0 = sony_toc.first_track_num;
-         loc_hdr.cdth_trk1 = sony_toc.last_track_num;
+         loc_hdr.cdth_trk0 = bcd_to_int(sony_toc.first_track_num);
+         loc_hdr.cdth_trk1 = bcd_to_int(sony_toc.last_track_num);
          copy_to_user(hdr, &loc_hdr, sizeof(*hdr));
       }
       return 0;
@@ -2567,8 +2569,8 @@
          	return i;
          
          copy_from_user(&ti, (char *) arg, sizeof(ti));
-         if (   (ti.cdti_trk0 < sony_toc.first_track_num)
-             || (ti.cdti_trk0 > sony_toc.last_track_num)
+         if (   (ti.cdti_trk0 < bcd_to_int(sony_toc.first_track_num))
+             || (ti.cdti_trk0 > bcd_to_int(sony_toc.last_track_num))
              || (ti.cdti_trk1 < ti.cdti_trk0))
          {
             return -EINVAL;
@@ -2587,7 +2589,7 @@
           * If we want to stop after the last track, use the lead-out
           * MSF to do that.
           */
-         if (ti.cdti_trk1 >= sony_toc.last_track_num)
+         if (ti.cdti_trk1 >= bcd_to_int(sony_toc.last_track_num))
          {
             log_to_msf(msf_to_log(sony_toc.lead_out_start_msf)-1,
                        &(params[4]));
diff -u --recursive --new-file v2.1.5/linux/drivers/cdrom/gscd.c linux/drivers/cdrom/gscd.c
--- v2.1.5/linux/drivers/cdrom/gscd.c	Sun May 12 21:13:45 1996
+++ linux/drivers/cdrom/gscd.c	Mon Oct 28 14:29:19 1996
@@ -58,7 +58,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define MAJOR_NR GOLDSTAR_CDROM_MAJOR
 #include <linux/blk.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c
--- v2.1.5/linux/drivers/cdrom/mcd.c	Wed Oct 16 10:48:09 1996
+++ linux/drivers/cdrom/mcd.c	Mon Oct 28 14:29:20 1996
@@ -80,7 +80,7 @@
 /* #define REALLY_SLOW_IO  */
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define MAJOR_NR MITSUMI_CDROM_MAJOR
 #include <linux/blk.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- v2.1.5/linux/drivers/cdrom/sbpcd.c	Wed Oct 16 10:48:10 1996
+++ linux/drivers/cdrom/sbpcd.c	Mon Oct 28 14:29:20 1996
@@ -331,7 +331,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <stdarg.h>
 #include <linux/sbpcd.h>
 #include <linux/config.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c
--- v2.1.5/linux/drivers/cdrom/sjcd.c	Wed Oct 16 10:48:10 1996
+++ linux/drivers/cdrom/sjcd.c	Mon Oct 28 14:29:20 1996
@@ -68,7 +68,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define MAJOR_NR SANYO_CDROM_MAJOR
 #include <linux/blk.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- v2.1.5/linux/drivers/cdrom/sonycd535.c	Wed Oct 16 10:48:11 1996
+++ linux/drivers/cdrom/sonycd535.c	Mon Oct 28 14:29:20 1996
@@ -124,7 +124,7 @@
 #define REALLY_SLOW_IO
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/cdrom.h>
 
diff -u --recursive --new-file v2.1.5/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.1.5/linux/drivers/char/Makefile	Thu Aug 22 18:45:56 1996
+++ linux/drivers/char/Makefile	Tue Oct 29 15:33:37 1996
@@ -196,14 +196,6 @@
   endif
 endif
   
-ifeq ($(CONFIG_SCC),y)
-L_OBJS += scc.o
-else
-  ifeq ($(CONFIG_SCC),m)
-  M_OBJS += scc.o
-  endif
-endif  
-
 ifeq ($(CONFIG_BAYCOM),y)
 L_OBJS += baycom.o
 else
diff -u --recursive --new-file v2.1.5/linux/drivers/char/README.scc linux/drivers/char/README.scc
--- v2.1.5/linux/drivers/char/README.scc	Tue Dec 19 07:09:00 1995
+++ linux/drivers/char/README.scc	Tue Oct 29 15:33:37 1996
@@ -1,24 +1,5 @@
+The z8530drv is now a network device driver, you can find it in
+	../net/scc.c
 
-You will find subset of the documentation in
-
-                 linux/Documentation/networking/z8530drv.txt
-
-
-To use this driver you MUST have the full package from
-
-ftp.ucsd.edu:/hamradio/packet/tcpip/incoming/z8530drv-2.01.dl1bke.real.tar.gz
-
-[
-  if you can't find it there, try:
-  .../tcpip/linux/z8530drv-2.01.dl1bke.tar.gz
-
-]
-
-and various mirrors (i.e. nic.switch.ch)
-
-The package includes the utilities necessary to initialize and
-control the driver.
-
-Joerg Reuter	ampr-net: dl1bke@db0pra.ampr.org
-		AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
-		Internet: jreuter@lykos.tng.oche.de
+A subset of the documentation is in
+	../../Documentation/networking/z8530drv.txt
diff -u --recursive --new-file v2.1.5/linux/drivers/char/amigamouse.c linux/drivers/char/amigamouse.c
--- v2.1.5/linux/drivers/char/amigamouse.c	Mon May 20 07:54:27 1996
+++ linux/drivers/char/amigamouse.c	Mon Oct 28 14:29:20 1996
@@ -40,7 +40,7 @@
 #include <linux/random.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/irq.h>
 #include <asm/amigamouse.h>
 #include <asm/amigahw.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c
--- v2.1.5/linux/drivers/char/apm_bios.c	Wed Oct 16 10:48:11 1996
+++ linux/drivers/char/apm_bios.c	Mon Oct 28 14:29:20 1996
@@ -58,7 +58,7 @@
 #include <linux/module.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/types.h>
 #include <linux/stddef.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/char/atarimouse.c linux/drivers/char/atarimouse.c
--- v2.1.5/linux/drivers/char/atarimouse.c	Thu Apr 18 02:08:04 1996
+++ linux/drivers/char/atarimouse.c	Mon Oct 28 14:29:20 1996
@@ -22,7 +22,7 @@
 
 #include <asm/atarikb.h>
 #include <asm/atari_mouse.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 
 static struct mouse_status mouse;
diff -u --recursive --new-file v2.1.5/linux/drivers/char/atixlmouse.c linux/drivers/char/atixlmouse.c
--- v2.1.5/linux/drivers/char/atixlmouse.c	Mon Sep 30 10:50:59 1996
+++ linux/drivers/char/atixlmouse.c	Mon Oct 28 14:29:20 1996
@@ -20,7 +20,7 @@
 #include <linux/random.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 
diff -u --recursive --new-file v2.1.5/linux/drivers/char/baycom.c linux/drivers/char/baycom.c
--- v2.1.5/linux/drivers/char/baycom.c	Wed Oct 16 10:48:12 1996
+++ linux/drivers/char/baycom.c	Mon Oct 28 14:29:20 1996
@@ -82,7 +82,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/major.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- v2.1.5/linux/drivers/char/busmouse.c	Mon Sep 30 10:51:46 1996
+++ linux/drivers/char/busmouse.c	Mon Oct 28 14:29:20 1996
@@ -47,7 +47,7 @@
 #include <linux/ioport.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 
diff -u --recursive --new-file v2.1.5/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.1.5/linux/drivers/char/console.c	Wed Oct 16 10:48:12 1996
+++ linux/drivers/char/console.c	Mon Oct 28 14:29:20 1996
@@ -105,7 +105,7 @@
 
 #include <asm/io.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #include "kbd_kern.h"
diff -u --recursive --new-file v2.1.5/linux/drivers/char/consolemap.c linux/drivers/char/consolemap.c
--- v2.1.5/linux/drivers/char/consolemap.c	Wed Oct 16 10:48:12 1996
+++ linux/drivers/char/consolemap.c	Mon Oct 28 14:29:20 1996
@@ -11,7 +11,7 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include "consolemap.h"
 
 static unsigned short translations[][256] = {
diff -u --recursive --new-file v2.1.5/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.1.5/linux/drivers/char/cyclades.c	Wed Oct 16 10:48:12 1996
+++ linux/drivers/char/cyclades.c	Mon Oct 28 14:29:20 1996
@@ -280,7 +280,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #include <linux/config.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/char/fbmem.c linux/drivers/char/fbmem.c
--- v2.1.5/linux/drivers/char/fbmem.c	Wed Oct 16 10:48:12 1996
+++ linux/drivers/char/fbmem.c	Mon Oct 28 14:29:20 1996
@@ -17,7 +17,7 @@
 #include <linux/mman.h>
 #include <linux/tty.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.1.5/linux/drivers/char/lp.c	Wed Oct 16 10:48:12 1996
+++ linux/drivers/char/lp.c	Mon Oct 28 14:29:20 1996
@@ -23,7 +23,7 @@
 #include <linux/delay.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 /* the BIOS manuals say there can be up to 4 lpt devices
diff -u --recursive --new-file v2.1.5/linux/drivers/char/lp_m68k.c linux/drivers/char/lp_m68k.c
--- v2.1.5/linux/drivers/char/lp_m68k.c	Wed Oct 16 10:48:12 1996
+++ linux/drivers/char/lp_m68k.c	Mon Oct 28 14:29:20 1996
@@ -57,7 +57,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 
diff -u --recursive --new-file v2.1.5/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.1.5/linux/drivers/char/mem.c	Wed Oct 16 10:48:12 1996
+++ linux/drivers/char/mem.c	Mon Oct 28 14:29:20 1996
@@ -20,7 +20,7 @@
 #include <linux/mm.h>
 #include <linux/random.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.5/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c
--- v2.1.5/linux/drivers/char/msbusmouse.c	Mon Sep 30 10:53:25 1996
+++ linux/drivers/char/msbusmouse.c	Mon Oct 28 14:29:20 1996
@@ -42,7 +42,7 @@
 #include <linux/random.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 
diff -u --recursive --new-file v2.1.5/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- v2.1.5/linux/drivers/char/n_tty.c	Wed Oct 16 10:48:12 1996
+++ linux/drivers/char/n_tty.c	Mon Oct 28 14:29:21 1996
@@ -34,7 +34,7 @@
 #include <linux/string.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 
diff -u --recursive --new-file v2.1.5/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c
--- v2.1.5/linux/drivers/char/pcxx.c	Wed Oct 16 10:48:12 1996
+++ linux/drivers/char/pcxx.c	Mon Oct 28 14:29:21 1996
@@ -78,7 +78,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #define VERSION 	"1.5.7"
diff -u --recursive --new-file v2.1.5/linux/drivers/char/psaux.c linux/drivers/char/psaux.c
--- v2.1.5/linux/drivers/char/psaux.c	Wed Oct 16 10:48:13 1996
+++ linux/drivers/char/psaux.c	Mon Oct 28 14:29:21 1996
@@ -47,7 +47,7 @@
 #include <linux/random.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/config.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/char/pty.c linux/drivers/char/pty.c
--- v2.1.5/linux/drivers/char/pty.c	Wed Oct 16 10:48:13 1996
+++ linux/drivers/char/pty.c	Mon Oct 28 14:29:21 1996
@@ -22,7 +22,7 @@
 #include <linux/major.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 
diff -u --recursive --new-file v2.1.5/linux/drivers/char/random.c linux/drivers/char/random.c
--- v2.1.5/linux/drivers/char/random.c	Wed Oct 16 10:48:13 1996
+++ linux/drivers/char/random.c	Mon Oct 28 14:29:21 1996
@@ -234,7 +234,7 @@
 #include <linux/malloc.h>
 #include <linux/random.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 
diff -u --recursive --new-file v2.1.5/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.1.5/linux/drivers/char/rtc.c	Wed Oct 16 10:48:13 1996
+++ linux/drivers/char/rtc.c	Mon Oct 28 14:29:21 1996
@@ -52,7 +52,7 @@
 #include <linux/mc146818rtc.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 /*
@@ -66,11 +66,11 @@
 
 static struct timer_list rtc_irq_timer;
 
-static int rtc_lseek(struct inode *inode, struct file *file, off_t offset,
-			int origin);
+static long long rtc_llseek(struct inode *inode, struct file *file,
+			    loff_t offset, int origin);
 
-static int rtc_read(struct inode *inode, struct file *file,
-			char *buf, int count);
+static long rtc_read(struct inode *inode, struct file *file,
+			char *buf, unsigned long count);
 
 static int rtc_ioctl(struct inode *inode, struct file *file,
 			unsigned int cmd, unsigned long arg);
@@ -133,13 +133,14 @@
  *	Now all the various file operations that we export.
  */
 
-static int rtc_lseek(struct inode *inode, struct file *file, off_t offset,
-	int origin)
+static long long rtc_llseek(struct inode *inode, struct file *file,
+			    loff_t offset, int origin)
 {
 	return -ESPIPE;
 }
 
-static int rtc_read(struct inode *inode, struct file *file, char *buf, int count)
+static long rtc_read(struct inode *inode, struct file *file, char *buf,
+		     unsigned long count)
 {
 	struct wait_queue wait = { current, NULL };
 	int retval;
@@ -507,7 +508,7 @@
  */
 
 static struct file_operations rtc_fops = {
-	rtc_lseek,
+	rtc_llseek,
 	rtc_read,
 	NULL,		/* No write */
 	NULL,		/* No readdir */
diff -u --recursive --new-file v2.1.5/linux/drivers/char/scc.c linux/drivers/char/scc.c
--- v2.1.5/linux/drivers/char/scc.c	Wed Oct 16 10:48:14 1996
+++ linux/drivers/char/scc.c	Thu Jan  1 02:00:00 1970
@@ -1,2791 +0,0 @@
-#define RCS_ID "$Id: scc.c,v 1.41 1995/12/17 22:36:40 jreuter Exp jreuter $"
-
-#define BANNER "Z8530 SCC driver version 2.01.dl1bke (alpha) by DL1BKE\n"
-
-/*
-
-   ********************************************************************
-   *   SCC.C - Linux driver for Z8530 based HDLC cards for AX.25      *
-   ********************************************************************
-
-
-   ********************************************************************
-
-	Copyright (c) 1993, 1995 Joerg Reuter DL1BKE
-
-	portions (c) 1993 Guido ten Dolle PE1NNZ
-
-   ********************************************************************
-   
-   The driver and the programs in the archive are UNDER CONSTRUCTION.
-   The code is likely to fail, and so your kernel could --- even 
-   a whole network. 
-
-   This driver is intended for Amateur Radio use. If you are running it
-   for commercial purposes, please drop me a note. I am nosy...
-
-   ...BUT:
- 
-   ! You  m u s t  recognize the appropriate legislations of your country !
-   ! before you connect a radio to the SCC board and start to transmit or !
-   ! receive. The GPL allows you to use the  d r i v e r,  NOT the RADIO! !
-
-   For non-Amateur-Radio use please note that you might need a special
-   allowance/licence from the designer of the SCC Board and/or the
-   MODEM. 
-
-   This program is free software; you can redistribute it and/or modify 
-   it under the terms of the (modified) GNU General Public License 
-   delivered with the Linux kernel source.
-   
-   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 find a copy of the GNU General Public License in 
-   /usr/src/linux/COPYING; 
-   
-   ******************************************************************** 
-
-
-   ...If you find any portions of the code that are copyrighted to you,
-   and you don't want to see in here, please send me a private (!) 
-   message to my internet site. I will change it as soon as possible. 
-   Please don't flame to the tcp-group or anywhere else. Thanks!
-
-   Joerg Reuter	ampr-net: dl1bke@db0pra.ampr.org
-		AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
-		Internet: jreuter@lykos.tng.oche.de
-		
-		
-   Incomplete history of z8530drv:
-   -------------------------------
-
-   940913	- started to write the driver, rescued most of my own
-		  code (and Hans Alblas' memory buffer pool concept) from 
-		  an earlier project "sccdrv" which was initiated by 
-		  Guido ten Dolle. Not much of the old driver survived, 
-		  though. The first version I put my hands on was sccdrv1.3
-		  from August 1993. The memory buffer pool concept
-		  appeared in an unauthorized sccdrv version (1.5) from
-		  August 1994.
-
-   950131	- changed copyright notice to GPL without limitations.
-   
-     .
-     .
-     .
-      
-   950922	- using kernel timer chain
-   
-   951002	- splitting timer routine, adding support for throttle/
-   		  unthrottle calls, removed typo in kiss decoder,
-   		  corrected termios settings.
-   		  
-   951011	- at last found one (the?) problem which caused the 
-   		  driver to mess up buffers on heavy load pe1ayx was
-   		  complaining about. Quite simple to reproduce:
-   		  set a 9k6 port into audio loopback, add a route
-   		  to 44.99.99.99 on that route and do a 
-   		  ping -f 44.99.99.99
-   		  
-   951013	- it still does not survive a flood ping...
-   
-   951107	- axattach w/o "-s" option (or setting an invalid 
-   		  baudrate) does not produce "division by zero" faults 
-   		  anymore.
-   		  
-   951114	- rewrote memory management, took first steps to allow
-		  compilation as a module. Well, it looks like a whole
-		  new driver now. BTW: It  d o e s  survive the flood
-		  ping at last...
-		  
-   951116	- scc_config.h is gone -- the driver will be initialized
-   		  through ioctl-commands. Use sccinit.c for this purpose.
-   		  
-   951117	- Well --- what should I say: You can compile it as a
-   		  module now. And I solved the problem with slip.c...
-   		  
-   951120	- most ioctl() routines may be called w/o suser()
-   		  permissions, check if you've set the permissions of
-   		  /dev/scc* right! NOT 0666, you know it's evil ;-)
-   		  
-   951217	- found silly bug in init_channel(), some bugfixes
-   		  for the "standalone" module
-
-
-   Thanks to:
-   ----------
-   
-   PE1CHL Rob	- for a lot of good ideas from his SCC driver for DOS
-   PE1NNZ Guido - for his port of the original driver to Linux
-   KA9Q   Phil  - from whom we stole the mbuf-structure
-   PA3AYX Hans  - for some useful changes
-   DL8MBT Flori - for support
-   DG0FT  Rene  - for the BayCom USCC support
-   PA3AOU Harry - for ESCC testing, information supply and support
-   
-   PE1KOX Rob, DG1RTF Thomas, ON5QK Roland, G4XYW Andy, Linus,
-   EI9GL Paul,
-   
-   and all who sent me bug reports and ideas... 
-   
-   
-   NB -- if you find errors, change something, please let me know
-      	 first before you distribute it... And please don't touch
-   	 the version number. Just replace my callsign in
-   	 "v2.01.dl1bke" with your own. Just to avoid confusion...
-   	 
-   If you want to add your modification to the linux distribution
-   please (!) contact me first.
-   	  
-   Jörg Reuter DL1BKE
-  
-*/
-
-/* ----------------------------------------------------------------------- */
-
-#define DEBUG_BUFFERS	/* keep defined unless it is really stable... */
-
-#undef  SCC_DELAY 	/* perhaps a 486DX2 is a *bit* too fast */
-#undef  SCC_LDELAY 5	/* slow it even a bit more down */
-#undef  DONT_CHECK	/* don't look if the SCCs you specified are available */
-
-#define MAXSCC          4       /* number of max. supported chips */
-#define RXBUFFERS       8       /* default number of RX buffers */
-#define TXBUFFERS       8       /* default number of TX buffers */
-#define BUFSIZE         384     /* must not exceed 4096-sizeof(mbuf) */
-#define TPS             25      /* scc_tx_timer():  Ticks Per Second */
-
-#define DEFAULT_CLOCK	4915200 /* default pclock if nothing is specified */
-
-/* ----------------------------------------------------------------------- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/tqueue.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/termios.h>
-#include <linux/serial.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/malloc.h>
-#include <linux/delay.h>
-#include <linux/scc.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-#include <asm/bitops.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <time.h>
-#include <linux/kernel.h>
-
-#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
-#endif
-
-#ifndef Z8530_MAJOR
-#define Z8530_MAJOR 34
-#endif
-
-int scc_init(void);
-
-static struct mbuf * scc_enqueue_buffer(struct mbuf **queue, struct mbuf * buffer);
-static struct mbuf * scc_dequeue_buffer(struct mbuf **queue);
-static void alloc_buffer_pool(struct scc_channel *scc);
-static void free_buffer_pool(struct scc_channel *scc);
-static struct mbuf * scc_get_buffer(struct scc_channel *scc, char type);
-
-int scc_open(struct tty_struct *tty, struct file *filp);
-static void scc_close(struct tty_struct *tty, struct file *filp);
-int scc_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
-static void scc_put_char(struct tty_struct *tty, unsigned char ch);
-static void scc_flush_chars(struct tty_struct *tty);
-static int scc_write_room(struct tty_struct *tty);
-static int scc_chars_in_buffer(struct tty_struct *tty);
-static void scc_flush_buffer(struct tty_struct *tty);
-static int scc_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static void scc_set_termios(struct tty_struct *tty, struct termios *old_termios);
-static void scc_set_ldisc(struct tty_struct *tty);
-static void scc_throttle(struct tty_struct *tty);
-static void scc_unthrottle(struct tty_struct *tty);
-static void scc_start(struct tty_struct *tty);
-static void scc_stop(struct tty_struct *tty);
-
-static void z8530_init(void);
-
-static void scc_change_speed(struct scc_channel *scc);
-static void kiss_encode(struct scc_channel *scc);
-
-static void init_channel(struct scc_channel *scc);
-static void scc_key_trx (struct scc_channel *scc, char tx);
-static void scc_txint(register struct scc_channel *scc);
-static void scc_exint(register struct scc_channel *scc);
-static void scc_rxint(register struct scc_channel *scc);
-static void scc_spint(register struct scc_channel *scc);
-static void scc_isr(int irq, void *dev_id, struct pt_regs *regs);
-static void scc_tx_timer(unsigned long);
-static void scc_rx_timer(unsigned long);
-static void scc_init_timer(struct scc_channel *scc);
-
-/* from serial.c */
-
-static int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 57600, 115200, 0 };
-
-
-struct tty_driver scc_driver;
-static int scc_refcount;
-static struct tty_struct *scc_table[2*MAXSCC];
-static struct termios scc_termios[2 * MAXSCC];
-static struct termios scc_termios_locked[2 * MAXSCC];
-
-struct irqflags { unsigned char used : 1; } Ivec[16];
-	
-struct scc_channel SCC_Info[2 * MAXSCC];         /* information per channel */
-io_port SCC_ctrl[2 * MAXSCC];			 /* Control ports */
-
-unsigned char Random = 0;		/* random number for p-persist */
-unsigned char Driver_Initialized = 0;
-int Nchips = 0;
-io_port Vector_Latch = 0;
-
-struct semaphore scc_sem = MUTEX;
-unsigned char scc_wbuf[BUFSIZE];
-
-static struct termios scc_std_termios;
-
-/* ******************************************************************** */
-/* *			Port Access Functions			      * */
-/* ******************************************************************** */
-
-static inline unsigned char
-InReg(register io_port port, register unsigned char reg)
-{
-#ifdef SCC_LDELAY
-	register unsigned char r;
-	Outb(port, reg);
-	udelay(SCC_LDELAY);
-	r=Inb(port);
-	udelay(SCC_LDELAY);
-	return r;
-#else
-	Outb(port, reg);
-	return Inb(port);
-#endif
-}
-
-static inline void
-OutReg(register io_port port, register unsigned char reg, register unsigned char val)
-{
-#ifdef SCC_LDELAY
-	Outb(port, reg); udelay(SCC_LDELAY);
-	Outb(port, val); udelay(SCC_LDELAY);
-#else
-	Outb(port, reg);
-	Outb(port, val);
-#endif
-}
-
-static inline void
-wr(register struct scc_channel *scc, register unsigned char reg, register unsigned char val)
-{
-	OutReg(scc->ctrl, reg, (scc->wreg[reg] = val));
-}
-
-static inline void
-or(register struct scc_channel *scc, register unsigned char reg, register unsigned char val)
-{
-	OutReg(scc->ctrl, reg, (scc->wreg[reg] |= val));
-}
-
-static inline void
-cl(register struct scc_channel *scc, register unsigned char reg, register unsigned char val)
-{
-	OutReg(scc->ctrl, reg, (scc->wreg[reg] &= ~val));
-}
-
-/* ******************************************************************** */
-/* * 			Memory Buffer Management			*/
-/* ******************************************************************** */
-
-/*
- * The new buffer scheme uses a ring chain of buffers. This has the
- * advantage to access both, first and last element of the list, very
- * fast. It has the disadvantage to mess things up double if something
- * is wrong.
- *
- * Every scc channel has its own buffer pool now with an adjustable
- * number of buffers for transmit and receive buffers. The buffer
- * size remains the same for each AX.25 frame, but is (as a semi-
- * undocumented feature) adjustable within a range of 512 and 4096
- * to benefit experiments with higher frame lengths. If you need
- * larger frames... Well, you'd better choose a whole new concept
- * for that, like a DMA capable I/O card and a block device driver...
- *
- */
-
-/* ------ Management of buffer queues ------ */
-
-
-/* Insert a buffer at the "end" of the chain */
-
-static struct mbuf * 
-scc_enqueue_buffer(struct mbuf **queue, struct mbuf * buffer)
-{
-	unsigned long flags;
-	struct mbuf * anchor;
-	
-	save_flags(flags); cli();		/* do not disturb! */
-
-#ifdef DEBUG_BUFFERS			
-	if (queue == NULLBUFP)			/* called with illegal parameters, notify the user */
-
-	{
-		printk("z8530drv: Pointer to queue anchor is NULL pointer [enq]\n");
-		restore_flags(flags);
-		return NULLBUF;
-	}
-	
-	if (buffer == NULLBUF)
-	{
-		printk("z8530drv: can't enqueue a NULL pointer\n");
-		restore_flags(flags);
-		return NULLBUF;
-	}
-#endif
-
-	anchor = *queue;			/* the anchor is the "start" of the chain */
-
-	if (anchor == NULLBUF)			/* found an empty list */
-	{
-		*queue = buffer;		/* new anchor */
-		buffer->next = buffer->prev = NULLBUF;
-	} else	
-	if (anchor->prev == NULLBUF)		/* list has one member only */
-	{
-#ifdef DEBUG_BUFFERS
-		if (anchor->prev != NULLBUF)	/* oops?! */
-			printk("weird --- anchor->prev is NULL but not anchor->next [enq]\n");
-#endif			
-		anchor->next = anchor->prev = buffer;
-		buffer->next = buffer->prev = anchor;
-	} else
-#ifdef DEBUG_BUFFERS	
-	if (anchor->next == NULLBUF)		/* this has to be an error. Okay, make the best out of it */
-	{
-		printk("z8530drv: weird --- anchor->next is NULL but not anchor->prev [enq]\n");
-		anchor->next = anchor->prev = buffer;
-		buffer->next = buffer->prev = anchor;
-	} else
-#endif
-	{					/* every other case */
-		buffer->prev = anchor->prev;	/* self explaining, isn't it? */
-		buffer->next = anchor;
-		anchor->prev->next = buffer;
-		anchor->prev = buffer;
-	}
-	
-	restore_flags(flags);
-	return *queue;				/* return "start" of chain */
-}
-
-
-
-/* Remove a buffer from the "start" of the chain an return it */
-
-static struct mbuf * 
-scc_dequeue_buffer(struct mbuf **queue)
-{
-	unsigned long flags;
-	struct mbuf *buffer;
-	
-	save_flags(flags); cli();
-
-#ifdef DEBUG_BUFFERS			
-	if (queue == NULLBUFP)			/* called with illegal parameter */
-
-	{
-		printk("z8530drv: Pointer to queue anchor is NULL pointer [deq]\n");
-		restore_flags(flags);
-		return NULLBUF;
-	}
-#endif
-
-	buffer = *queue;			/* head of the chain */
-	
-	if (buffer != NULLBUF)			/* not an empty list? */
-	{
-		if (buffer->prev != NULLBUF)	/* not last buffer? */
-		{
-#ifdef DEBUG_BUFFERS
-			if (buffer->next == NULLBUF)
-			{			/* what?! */
-				printk("z8530drv: weird --- buffer->next is NULL but not buffer->prev [deq]\n");
-			} else
-#endif
-			if (buffer->prev->next == buffer->prev->prev)
-			{			/* only one buffer remaining... */
-				buffer->next->prev = NULLBUF;
-				buffer->next->next = NULLBUF;
-			} else {		/* the one remaining situation... */
-				buffer->next->prev = buffer->prev;
-				buffer->prev->next = buffer->next;
-			}
-		} 
-#ifdef DEBUG_BUFFERS
-		else if (buffer->next != NULLBUF)
-			printk("z8530drv: weird --- buffer->prev is NULL but not buffer->next [deq]\n");
-#endif
-		*queue = buffer->next;		/* new head of chain */
-		
-		buffer->next = NULLBUF;		/* for security only... */
-		buffer->prev = NULLBUF;
-		buffer->rw_ptr = buffer->data;
-	} 
-	
-	restore_flags(flags);
-	return buffer;				/* give it away... */
-}
-
-/* ------ buffer pool management ------ */
-
-
-/* allocate buffer pool	for a channel */
-
-static void 
-alloc_buffer_pool(struct scc_channel *scc)
-{
-	int k;
-	struct mbuf * bptr;
-	int  buflen;
-	
-	buflen = sizeof(struct mbuf) + scc->stat.bufsize;
-	
-	if (scc->stat.bufsize <  336) scc->stat.bufsize = 336;
-	if (buflen > 4096)
-	{
-		scc->stat.bufsize = 4096-sizeof(struct mbuf);
-		buflen = 4096;
-	}
-	
-	if (scc->stat.rxbuffers < 4)  scc->stat.rxbuffers = 4;
-	if (scc->stat.txbuffers < 4)  scc->stat.txbuffers = 4;
-	
-
-	
-	/* allocate receive buffers for this channel */
-	
-	for (k = 0; k < scc->stat.rxbuffers ; k++)
-	{
-		/* allocate memory for the struct and the buffer */
-		
-		bptr = (struct mbuf *) kmalloc(buflen, GFP_ATOMIC);
-		
-		/* should not happen, but who knows? */
-		
-		if (bptr == NULLBUF)
-		{
-			printk("z8530drv: %s: can't allocate memory for rx buffer pool", kdevname(scc->tty->device));
-			break;
-		}
-		
-		/* clear memory */
-		
-		memset(bptr, 0, buflen);
-		
-		/* initialize structure */
-		
-		bptr->rw_ptr = bptr->data;
-		
-		/* and append the buffer to the pool */
-		
-		scc_enqueue_buffer(&scc->rx_buffer_pool, bptr);
-	}
-	
-	/* now do the same for the transmit buffers */
-	
-	for (k = 0; k < scc->stat.txbuffers ; k++)
-	{
-		bptr = (struct mbuf *) kmalloc(buflen, GFP_ATOMIC);
-		
-		if (bptr == NULLBUF)
-		{
-			printk("z8530drv: %s: can't allocate memory for tx buffer pool", kdevname(scc->tty->device));
-			break;
-		}
-		
-		memset(bptr, 0, buflen);
-		
-		bptr->rw_ptr = bptr->data;
-		
-		scc_enqueue_buffer(&scc->tx_buffer_pool, bptr);
-	}
-}
-
-
-/* remove buffer pool */
-
-static void 
-free_buffer_pool(struct scc_channel *scc)
-{
-	struct mbuf * bptr;
-	unsigned long flags;
-	int cnt;
-	
-	/* this one is a bit tricky and probably dangerous. */
-		
-	save_flags(flags); cli();
-	
-	/* esp. to free the buffers currently in use by ISR */
-	
-	bptr = scc->rx_bp;
-	if (bptr != NULLBUF)
-	{
-		scc->rx_bp = NULLBUF;
-		scc_enqueue_buffer(&scc->rx_buffer_pool, bptr);
-	}
-
-	bptr = scc->tx_bp;	
-	if (bptr != NULLBUF)
-	{
-		scc->tx_bp = NULLBUF;
-		scc_enqueue_buffer(&scc->tx_buffer_pool, bptr);
-	}
-	
-	bptr = scc->kiss_decode_bp;
-	if (bptr != NULLBUF)
-	{
-		scc->kiss_decode_bp = NULLBUF;
-		scc_enqueue_buffer(&scc->tx_buffer_pool, bptr);
-	}
-	
-	bptr = scc->kiss_encode_bp;
-	if (bptr != NULLBUF)
-	{
-		scc->kiss_encode_bp = NULLBUF;
-		scc_enqueue_buffer(&scc->rx_buffer_pool, bptr);
-	}
-	
-	restore_flags(flags);
-	
-	
-	while (scc->rx_queue != NULLBUF)
-	{
-		bptr = scc_dequeue_buffer(&scc->rx_queue);
-		scc_enqueue_buffer(&scc->rx_buffer_pool, bptr);
-	}
-	
-	while (scc->tx_queue != NULLBUF)
-	{
-		bptr = scc_dequeue_buffer(&scc->tx_queue);
-		scc_enqueue_buffer(&scc->tx_buffer_pool, bptr);
-	}
-	
-	/* you want to know why we move every buffer back to the
-	   buffer pool? Well, good question... ;-) 
-	 */
-	
-	cnt = 0;
-	
-	/* Probably because we just want a central position in the
-	   code were we actually call free()?
-	 */
-	
-	while (scc->rx_buffer_pool != NULLBUF)
-	{
-		bptr = scc_dequeue_buffer(&scc->rx_buffer_pool);
-		
-		if (bptr != NULLBUF)
-		{
-			cnt++;
-			kfree(bptr);
-		}
-	}
-
-	if (cnt < scc->stat.rxbuffers)		/* hmm... hmm... :-( */
-		printk("z8530drv: oops, deallocated only %d of %d rx buffers\n", cnt, scc->stat.rxbuffers);
-	if (cnt > scc->stat.rxbuffers)		/* WHAT?!! */
-		printk("z8530drv: oops, deallocated %d instead of %d rx buffers. Very strange.\n", cnt, scc->stat.rxbuffers);
-		
-	cnt = 0;
-	
-	while (scc->tx_buffer_pool != NULLBUF)
-	{
-		bptr = scc_dequeue_buffer(&scc->tx_buffer_pool);
-		
-		if (bptr != NULLBUF)
-		{
-			cnt++;
-			kfree(bptr);
-		}
-	}
-
-	if (cnt < scc->stat.txbuffers)
-		printk("z8530drv: oops, deallocated only %d of %d tx buffers\n", cnt, scc->stat.txbuffers);
-	if (cnt > scc->stat.txbuffers)
-		printk("z8530drv: oops, deallocated %d instead of %d tx buffers. Very strange.\n", cnt, scc->stat.txbuffers);
-}
-		
-		
-/* ------ rx/tx buffer management ------ */
-
-/* 
-   get a fresh buffer from the pool if possible; if not: get one from
-   the queue. We will remove the oldest frame from the queue and hope
-   it was a good idea... ;-)
-   
- */
-
-static struct mbuf * 
-scc_get_buffer(struct scc_channel *scc, char type)
-{
-	struct mbuf * bptr;
-	
-	if (type == BT_TRANSMIT)
-	{
-		bptr = scc_dequeue_buffer(&scc->tx_buffer_pool);
-		
-		/* no free buffers in the pool anymore? */
-		
-		if (bptr == NULLBUF)
-		{
-			printk("z8530drv: scc_get_buffer(%s): tx buffer pool empty\n", kdevname(scc->tty->device));
-			
-			/* use the oldest from the queue instead */
-			
-			bptr = scc_dequeue_buffer(&scc->tx_queue);
-			
-			/* this should never, ever happen... */
-			
-			if (bptr == NULLBUF)
-				printk("z8530drv: scc_get_buffer(): panic - even no buffer found in tx queue\n");
-		}
-	} else {
-		bptr = scc_dequeue_buffer(&scc->rx_buffer_pool);
-		
-		if (bptr == NULLBUF)
-		{
-			printk("z8530drv: scc_get_buffer(%s): rx buffer pool empty\n", kdevname(scc->tty->device));
-			
-			bptr = scc_dequeue_buffer(&scc->rx_queue);
-			
-			if (bptr == NULLBUF)
-				printk("z8530drv: scc_get_buffer(): panic - even no buffer found in rx queue\n");
-		}	
-	}
-	
-	if (bptr != NULLBUF)
-	{
-		bptr->rw_ptr = bptr->data;
-		bptr->cnt = 0;
-	}
-
-	return bptr;
-}
-
-
-/* ******************************************************************** */
-/* *			Interrupt Service Routines		      * */
-/* ******************************************************************** */
-
-/* ----> interrupt service routine for the 8530 <---- */
-
-/* it's recommended to keep this function "inline" ;-) */
-
-static inline void
-scc_isr_dispatch(register struct scc_channel *scc, register int vector)
-{
-	switch (vector & VECTOR_MASK)
-	{
-		case TXINT: scc_txint(scc); break;
-		case EXINT: scc_exint(scc); break;
-		case RXINT: scc_rxint(scc); break;
-		case SPINT: scc_spint(scc); break;
-		default	  : printk("scc_isr(): unknown interrupt status (addr %4.4x, state %2.2x)\n",scc->ctrl,vector);
-	}
-}
-
-
-
-
-
-/* If the card has a latch for the interrupt vector (like the PA0HZP card)
-   use it to get the number of the chip that generated the int.
-   If not: poll all defined chips.
- */
-
-static void
-scc_isr(int irq, void *dev_id, struct pt_regs *regs)
-{
-	register unsigned char vector;	
-	register struct scc_channel *scc;
-	register io_port q;
-	register io_port *p;
-	register int k;
-
-
-	cli();
-	
-	if (Vector_Latch)
-	{
-	    	while(1)			   /* forever...? */
-    		{ 
-			Outb(Vector_Latch, 0);      /* Generate INTACK */
-        
-			/* Read the vector */
-			if((vector=Inb(Vector_Latch)) >= 16 * Nchips) break; 
-						/* ...not forever! */
-          
-			/* Extract channel number and status from vector. */
-			/* Isolate channel number */
-			/* Call handler */
-	        
-			if (vector & 0x01) break; 
-        	 
-		        scc=&SCC_Info[(((vector>>1)&0x7c)^0x04) >> 2];
-        
-			if (!scc->tty) break;
-
-			scc_isr_dispatch(scc, vector);
-			
-			Outb(scc->ctrl,0x38);              /* Reset Highest IUS" opcode to WR0 */
-		}  
-	    	
-		sti();	
-		return;
-	}
-	
-	
-	/* Find the SCC generating the interrupt by polling all attached SCCs
-	 * reading RR3A (the interrupt pending register)
-	 */
-
-	k = 0;
-	p = SCC_ctrl;
-	
-	while (k++ < Nchips)
-	{
-		if (!(q=*p++)) break;
-		
-		Outb(q,3);
-		
-		if (Inb(q))
-		{
-			if (!(q=*p++)) break;
-			
-			Outb(q,2);
-			vector=Inb(q);                  /* Read the vector */
-        
-		        /* Extract channel number and status from vector. */
-		        /* Isolate channel number */
-		        /* Call handler */
-        
-
-			if (vector & 1) break; 
-        
-		        scc = &SCC_Info[(((vector >> 1) & 0x7c) ^ 0x04) >> 2];
-        
-		        if (!scc->tty) break;
-
-			/* Isolate status info from vector, call handler */
-			
-			scc_isr_dispatch(scc, vector);
-
-			k = 0;
-			p = SCC_ctrl;
-
-	     	} else p++;
-	}    
-	
-	sti();
-}
-
-
-
-/* ----> four different interrupt handlers for Tx, Rx, changing of	*/
-/*       DCD/CTS and Rx/Tx errors					*/
-
-
-/* Transmitter interrupt handler */
-static void
-scc_txint(register struct scc_channel *scc)
-{
-	register struct mbuf *bp;
-
-	scc->stat.txints++;
-
-	bp = scc->tx_bp;
-	
-	if (bp == NULLBUF)
-	{
-		do 
-		{
-			if (bp != NULLBUF)
-				scc_enqueue_buffer(&scc->tx_buffer_pool, bp);
-
-			bp = scc_dequeue_buffer(&scc->tx_queue);
-			
-			if (bp == NULLBUF)
-			{
-				scc->stat.tx_state = TXS_BUSY;
-				scc->t_tail = scc->kiss.tailtime;
-				
-				Outb(scc->ctrl, RES_Tx_P);	/* clear int */
-				return;
-			}
-			
-			if ( scc->kiss.not_slip && (bp->cnt > 0) )
-			{
-				bp->rw_ptr++;
-				bp->cnt--;
-			}
-			
-		} while (bp->cnt < 1);
-		
-		
-		Outb(scc->ctrl, RES_Tx_CRC);	/* reset CRC generator */
-		or(scc,R10,ABUNDER);		/* re-install underrun protection */
-		Outb(scc->data,*bp->rw_ptr);	/* send byte */
-		if (!scc->enhanced)		/* reset EOM latch */
-			Outb(scc->ctrl, RES_EOM_L);
-		
-		scc->tx_bp = bp;
-		scc->stat.tx_state = TXS_ACTIVE; /* next byte... */
-	} else
-	if (bp->cnt <= 0)
-	{
-		if (--scc->stat.tx_queued < 0) scc->stat.tx_queued = 0;
-		
-		Outb(scc->ctrl, RES_Tx_P);	/* reset pending int */
-		cl(scc, R10, ABUNDER);		/* send CRC */
-		scc_enqueue_buffer(&scc->tx_buffer_pool, bp);
-		scc->tx_bp = NULLBUF;
-		scc->stat.tx_state = TXS_NEWFRAME; /* next frame... */
-		return;
-	} else {
-		Outb(scc->data,*bp->rw_ptr);		
-	}
-	
-	bp->rw_ptr++;			/* increment pointer */
-	bp->cnt--;                      /* decrease byte count */
-}
-
-static inline void
-flush_FIFO(register struct scc_channel *scc)
-{
-	register int k;
-	
-	for (k=0; k<3; k++)
-		Inb(scc->data);
-		
-	if(scc->rx_bp != NULLBUF)	/* did we receive something? */
-	{
-		scc->stat.rxerrs++;  /* then count it as an error */
-		scc_enqueue_buffer(&scc->rx_buffer_pool, scc->rx_bp);
-		
-		scc->rx_bp = NULLBUF;
-	}
-}
-
-
-/* External/Status interrupt handler */
-static void
-scc_exint(register struct scc_channel *scc)
-{
-	register unsigned char status,changes,chg_and_stat;
-
-	scc->stat.exints++;
-
-	status = InReg(scc->ctrl,R0);
-	changes = status ^ scc->status;
-	chg_and_stat = changes & status;
-	
-	/* ABORT: generated whenever DCD drops while receiving */
-
-	if (chg_and_stat & BRK_ABRT)		/* Received an ABORT */
-		flush_FIFO(scc);
-			
-		
-	/* DCD: on = start to receive packet, off = ABORT condition */
-	/* (a successfully received packet generates a special condition int) */
-	
-	if(changes & DCD)                       /* DCD input changed state */
-	{
-		if(status & DCD)                /* DCD is now ON */
-		{
-			if (scc->modem.clocksrc != CLK_EXTERNAL)
-				OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
-				
-			or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
-		} else {                        /* DCD is now OFF */
-			cl(scc,R3,ENT_HM|RxENABLE); /* disable the receiver */
-			flush_FIFO(scc);
-		}
-	}
-
-#ifdef notdef
-	/* CTS: use external TxDelay (what's that good for?!) */
-	
-	if (chg_and_stat & CTS)			/* CTS is now ON */
-	{			
-		if (!Running(t_txdel) && scc->kiss.txdelay == 0) /* zero TXDELAY = wait for CTS */
-			scc->t_txdel = 0;	/* kick it! */		
-		
-	}
-#endif
-	
-	if ( (status & TxEOM) && (scc->stat.tx_state == TXS_ACTIVE) )
-	{
-		scc->stat.tx_under++;	  /* oops, an underrun! count 'em */
-		Outb(scc->ctrl, RES_Tx_P);
-		Outb(scc->ctrl, RES_EXT_INT);	/* reset ext/status interrupts */
-		scc->t_maxk = 1;
-		
-		if (scc->tx_bp != NULLBUF)
-		{
-			scc_enqueue_buffer(&scc->tx_buffer_pool, scc->tx_bp);
-			scc->tx_bp = NULLBUF;
-		}
-		
-		if (--scc->stat.tx_queued < 0) scc->stat.tx_queued = 0;
-		or(scc,R10,ABUNDER);
-	}
-		
-	if (status & ZCOUNT)		   /* Oops? */
-	{
-		scc->stat.tx_under = 9999;  /* errr... yes. */
-		Outb(scc->ctrl, RES_Tx_P); /* just to be sure */
-		scc->t_maxk = 1;
-		
-		if (scc->tx_bp != NULLBUF)
-		{
-			scc_enqueue_buffer(&scc->tx_buffer_pool, scc->tx_bp);
-			scc->tx_bp = NULLBUF;
-		}
-
-		if (--scc->stat.tx_queued < 0) scc->stat.tx_queued = 0;
-		scc->kiss.tx_inhibit = 1;	/* don't try it again! */
-	}
-		
-	
-	scc->status = status;
-	Outb(scc->ctrl,RES_EXT_INT);
-}
-
-
-/* Receiver interrupt handler */
-static void
-scc_rxint(register struct scc_channel *scc)
-{
-	register struct mbuf *bp;
-
-	scc->stat.rxints++;
-
-	if( Running(t_maxk) && !(scc->kiss.fulldup))
-	{
-		Inb(scc->data);		/* discard char */
-		or(scc,R3,ENT_HM);	/* enter hunt mode for next flag */
-		return;
-	}
-
-	bp = scc->rx_bp;
-	
-	if (bp == NULLBUF)
-	{
-		bp = scc_get_buffer(scc, BT_RECEIVE);
-		if (bp == NULLBUF)
-		{
-			printk("scc_rxint(): panic --- cannot get a buffer\n");
-			Inb(scc->data);
-			or(scc, R3, ENT_HM);
-			scc->stat.nospace++;
-			return;
-		}
-		
-		scc->rx_bp = bp;
-	}
-	
-	if (bp->cnt > scc->stat.bufsize)
-	{
-#ifdef notdef
-		printk("scc_rxint(): oops, received huge frame...\n");
-#endif
-		scc_enqueue_buffer(&scc->rx_buffer_pool, bp);
-		scc->rx_bp = NULLBUF;
-		Inb(scc->data);
-		or(scc, R3, ENT_HM);
-		return;
-	}
-		
-	/* now, we have a buffer. read character and store it */
-	*bp->rw_ptr = Inb(scc->data);
-	bp->rw_ptr++;
-	bp->cnt++;
-}
-
-/* kick rx_timer (try to send received frame or part of it ASAP) */
-
-/* of course we could define a "bottom half" routine to do the job,
-   but since its structures are saved in an array instead of a linked
-   list we would get in trouble if it clashes with another driver or
-   when we try to modularize the driver. IMHO we are fast enough
-   with a timer routine called on the next timer-INT... Your opinions?
- */
-
-static inline void
-kick_rx_timer(register struct scc_channel *scc)
-{
-	if (scc->rx_t.next)
-		del_timer(&(scc->rx_t));
-		
-	scc->rx_t.expires = jiffies + 1;
-	scc->rx_t.function = scc_rx_timer;
-	scc->rx_t.data = (unsigned long) scc;
-	add_timer(&scc->rx_t);
-}
-
-/* Receive Special Condition interrupt handler */
-static void
-scc_spint(register struct scc_channel *scc)
-{
-	register unsigned char status;
-	register struct mbuf *bp;
-
-	scc->stat.spints++;
-
-	status = InReg(scc->ctrl,R1);		/* read receiver status */
-	
-	Inb(scc->data);				/* throw away Rx byte */
-	bp = scc->rx_bp;
-
-	if(status & Rx_OVR)			/* receiver overrun */
-	{
-		scc->stat.rx_over++;             /* count them */
-		or(scc,R3,ENT_HM);               /* enter hunt mode for next flag */
-		
-		if (bp) scc_enqueue_buffer(&scc->rx_buffer_pool, bp);
-		scc->rx_bp = NULLBUF;
-	}
-	
-	if(status & END_FR && bp != NULLBUF)	/* end of frame */
-	{
-		/* CRC okay, frame ends on 8 bit boundary and received something ? */
-		
-		if (!(status & CRC_ERR) && (status & 0xe) == RES8 && bp->cnt)
-		{
-			/* ignore last received byte (first of the CRC bytes) */
-			bp->cnt--;
-			
-			scc_enqueue_buffer(&scc->rx_queue, bp);
-			scc->rx_bp = NULLBUF;
-			scc->stat.rxframes++;
-			scc->stat.rx_queued++;
-			kick_rx_timer(scc);
-		} else {				/* a bad frame */
-			scc_enqueue_buffer(&scc->rx_buffer_pool, bp);
-			scc->rx_bp = NULLBUF;
-			scc->stat.rxerrs++;
-		}
-	}
-	
-	Outb(scc->ctrl,ERR_RES);
-}
-
-
-/* ******************************************************************** */
-/* *			Init Channel					*/
-/* ******************************************************************** */
-
-
-/* ----> set SCC channel speed <---- */
-
-static inline void set_brg(register struct scc_channel *scc, unsigned int tc)
-{
-	unsigned long flags;
-
- 	save_flags(flags); cli();      	/* 2-step register accesses... */
-
-	cl(scc,R14,BRENABL);		/* disable baudrate generator */
-	wr(scc,R12,tc & 255);		/* brg rate LOW */
-	wr(scc,R13,tc >> 8);   		/* brg rate HIGH */
-	or(scc,R14,BRENABL);		/* enable baudrate generator */
-
-	restore_flags(flags);
-}
-
-static inline void set_speed(register struct scc_channel *scc)
-{
-	if (scc->modem.speed > 0)	/* paranoia... */
-		set_brg(scc, (unsigned) (scc->clock / (scc->modem.speed * 64)) - 2);
-}
-
-
-/* ----> initialize a SCC channel <---- */
-
-static inline void init_brg(register struct scc_channel *scc)
-{
-	wr(scc, R14, BRSRC);				/* BRG source = PCLK */
-	OutReg(scc->ctrl, R14, SSBR|scc->wreg[R14]);	/* DPLL source = BRG */
-	OutReg(scc->ctrl, R14, SNRZI|scc->wreg[R14]);	/* DPLL NRZI mode */
-}
-
-/*
- * Initialization according to the Z8530 manual (SGS-Thomson's version):
- *
- * 1. Modes and constants
- *
- * WR9	11000000	chip reset
- * WR4	XXXXXXXX	Tx/Rx control, async or sync mode
- * WR1	0XX00X00	select W/REQ (optional)
- * WR2	XXXXXXXX	program interrupt vector
- * WR3	XXXXXXX0	select Rx control
- * WR5	XXXX0XXX	select Tx control
- * WR6	XXXXXXXX	sync character
- * WR7	XXXXXXXX	sync character
- * WR9	000X0XXX	select interrupt control
- * WR10	XXXXXXXX	miscellaneous control (optional)
- * WR11	XXXXXXXX	clock control
- * WR12	XXXXXXXX	time constant lower byte (optional)
- * WR13	XXXXXXXX	time constant upper byte (optional)
- * WR14	XXXXXXX0	miscellaneous control
- * WR14	XXXSSSSS	commands (optional)
- *
- * 2. Enables
- *
- * WR14	000SSSS1	baud rate enable
- * WR3	SSSSSSS1	Rx enable
- * WR5	SSSS1SSS	Tx enable
- * WR0	10000000	reset Tx CRG (optional)
- * WR1	XSS00S00	DMA enable (optional)
- *
- * 3. Interrupt status
- *
- * WR15	XXXXXXXX	enable external/status
- * WR0	00010000	reset external status
- * WR0	00010000	reset external status twice
- * WR1	SSSXXSXX	enable Rx, Tx and Ext/status
- * WR9	000SXSSS	enable master interrupt enable
- *
- * 1 = set to one, 0 = reset to zero
- * X = user defined, S = same as previous init
- *
- *
- * Note that the implementation differs in some points from above scheme.
- *
- */
- 
-static void
-init_channel(register struct scc_channel *scc)
-{
-	unsigned long flags;
-	
-	if (scc->rx_t.next) del_timer(&(scc->rx_t));
-	if (scc->tx_t.next) del_timer(&(scc->tx_t));
-
-	save_flags(flags); cli();
-
-	wr(scc,R4,X1CLK|SDLC);		/* *1 clock, SDLC mode */
-	wr(scc,R1,0);			/* no W/REQ operation */
-	wr(scc,R3,Rx8|RxCRC_ENAB);	/* RX 8 bits/char, CRC, disabled */	
-	wr(scc,R5,Tx8|DTR|TxCRC_ENAB);	/* TX 8 bits/char, disabled, DTR */
-	wr(scc,R6,0);			/* SDLC address zero (not used) */
-	wr(scc,R7,FLAG);		/* SDLC flag value */
-	wr(scc,R9,VIS);			/* vector includes status */
-	wr(scc,R10,(scc->modem.nrz? NRZ : NRZI)|CRCPS|ABUNDER); /* abort on underrun, preset CRC generator, NRZ(I) */
-	wr(scc,R14, 0);
-
-
-/* set clock sources:
-
-   CLK_DPLL: normal halfduplex operation
-   
-		RxClk: use DPLL
-		TxClk: use DPLL
-		TRxC mode DPLL output
-		
-   CLK_EXTERNAL: external clocking (G3RUH or DF9IC modem)
-   
-  	        BayCom: 		others:
-  	        
-  	        TxClk = pin RTxC	TxClk = pin TRxC
-  	        RxClk = pin TRxC 	RxClk = pin RTxC
-  	     
-
-   CLK_DIVIDER:
-   		RxClk = use DPLL
-   		TxClk = pin RTxC
-   		
-   		BayCom:			others:
-   		pin TRxC = DPLL		pin TRxC = BRG
-   		(RxClk * 1)		(RxClk * 32)
-*/  
-
-   		
-	switch(scc->modem.clocksrc)
-	{
-		case CLK_DPLL:
-			wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
-			init_brg(scc);
-			break;
-
-		case CLK_DIVIDER:
-			wr(scc, R11, ((scc->brand & BAYCOM)? TRxCDP : TRxCBR) | RCDPLL|TCRTxCP|TRxCOI);
-			init_brg(scc);
-			break;
-
-		case CLK_EXTERNAL:
-			wr(scc, R11, (scc->brand & BAYCOM)? RCTRxCP|TCRTxCP : RCRTxCP|TCTRxCP);
-			OutReg(scc->ctrl, R14, DISDPLL);
-			break;
-
-	}
-	
-	set_speed(scc);			/* set baudrate */
-	
-	if(scc->enhanced)
-	{
-		or(scc,R15,SHDLCE|FIFOE);	/* enable FIFO, SDLC/HDLC Enhancements (From now R7 is R7') */
-		wr(scc,R7,AUTOEOM);
-	}
-
-	if((InReg(scc->ctrl,R0)) & DCD)		/* DCD is now ON */
-	{
-		if (scc->modem.clocksrc != CLK_EXTERNAL)
-			or(scc,R14, SEARCH);
-			
-		or(scc,R3,ENT_HM|RxENABLE);	/* enable the receiver, hunt mode */
-	}
-	
-	/* enable CTS (not for Baycom), ABORT & DCD interrupts */
-	wr(scc,R15,((scc->brand & BAYCOM) ? 0 : CTSIE)|BRKIE|DCDIE|TxUIE);
-	
-	Outb(scc->ctrl,RES_EXT_INT);	/* reset ext/status interrupts */
-	Outb(scc->ctrl,RES_EXT_INT);	/* must be done twice */
-
-	or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
-	
-	scc->status = InReg(scc->ctrl,R0);	/* read initial status */
-	
-	or(scc,R9,MIE);			/* master interrupt enable */
-	
-	scc_init_timer(scc);
-			
-	restore_flags(flags);
-}
-
-
-
-
-/* ******************************************************************** */
-/* *			SCC timer functions			      * */
-/* ******************************************************************** */
-
-
-/* ----> scc_key_trx sets the time constant for the baudrate 
-         generator and keys the transmitter		     <---- */
-
-static void
-scc_key_trx(struct scc_channel *scc, char tx)
-{
-	unsigned int time_const;
-
-	if (scc->modem.speed < baud_table[1]) 
-		scc->modem.speed = 1200;
-		
-	if (scc->brand & PRIMUS)
-		Outb(scc->ctrl + 4, scc->option | (tx? 0x80 : 0));
-	
-	time_const = (unsigned) (scc->clock / (scc->modem.speed * (tx? 2:64))) - 2;
-	
-	if (scc->modem.clocksrc == CLK_DPLL)
-	{				/* simplex operation */
-		if (tx)
-		{
-			cl(scc,R3,RxENABLE|ENT_HM);	/* then switch off receiver */
-			
-			set_brg(scc, time_const);	/* reprogram baudrate generator */
-
-			/* DPLL -> Rx clk, BRG -> Tx CLK, TRxC mode output, TRxC = BRG */
-			wr(scc, R11, RCDPLL|TCBR|TRxCOI|TRxCBR);
-			
-			or(scc,R5,RTS|TxENAB);		/* set the RTS line and enable TX */
-		} else {
-			cl(scc,R5,RTS|TxENAB);
-			
-			set_brg(scc, time_const);	/* reprogram baudrate generator */
-			
-			/* DPLL -> Rx clk, DPLL -> Tx CLK, TRxC mode output, TRxC = DPLL */
-			wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
-			
-			or(scc,R3,RxENABLE|ENT_HM);
-		}
-	} else {
-		if (tx)
-			or(scc,R5,RTS|TxENAB);		/* enable tx */
-		else
-			cl(scc,R5,RTS|TxENAB);		/* disable tx */
-	}
-}
-
-
-/* ----> SCC timer interrupt handler and friends. Will be called every 1/TPS s <---- */
-
-static unsigned char Rand = 17;
-
-static inline int is_grouped(register struct scc_channel *scc)
-{
-	int k;
-	struct scc_channel *scc2;
-	unsigned char grp1, grp2;
-
-	grp1 = scc->kiss.group;
-	
-	for (k = 0; k < (Nchips * 2); k++)
-	{
-		scc2 = &SCC_Info[k];
-		grp2 = scc2->kiss.group;
-		
-		if (scc2 == scc || !(scc2->tty && grp2)) 
-			return 0;
-		
-		if ((grp1 & 0x3f) == (grp2 & 0x3f))
-		{
-			if ( (grp1 & TXGROUP) && (scc2->wreg[R5] & RTS) )
-				return 1;
-			
-			if ( (grp1 & RXGROUP) && (scc2->status & DCD) )
-				return 1;
-		}
-	}
-	return 0;
-}
-		
-
-static inline void dw_slot_timeout(register struct scc_channel *scc)
-{
-	scc->t_dwait = TIMER_STOPPED;
-	scc->t_slot = TIMER_STOPPED;
-	
-	if (!scc->kiss.fulldup)
-	{
-		Rand = Rand * 17 + 31;
-		
-		if ( (scc->kiss.softdcd? !(scc->status & SYNC_HUNT):(scc->status & DCD))  || (scc->kiss.persist) < Rand || (scc->kiss.group && is_grouped(scc)) )
-		{
-			if (scc->t_mbusy == TIMER_STOPPED)
-				scc->t_mbusy = TPS * scc->kiss.maxdefer;
-				
-			scc->t_slot = scc->kiss.slottime;
-			return ;
-			
-		}
-	}
-	
-	if ( !(scc->wreg[R5] & RTS) )
-	{
-		scc->t_txdel = scc->kiss.txdelay;
-		scc_key_trx(scc, TX_ON);
-	} else {
-		scc->t_txdel = 0;
-	}
-}
-
-
-
-
-static inline void txdel_timeout(register struct scc_channel *scc)
-{
-	scc->t_txdel = TIMER_STOPPED;
-	
-	scc->t_maxk = TPS * scc->kiss.maxkeyup;
-	
-	if (scc->tx_bp == NULLBUF)
-		scc_txint(scc);	
-}
-	
-
-
-static inline void tail_timeout(register struct scc_channel *scc)
-{
-	scc->t_tail = TIMER_STOPPED;
-	
-	/* when fulldup is 0 or 1, switch off the transmitter.
-	 * when frames are still queued (because of transmit time limit),
-	 * restart the procedure to get the channel after MINTIME.
-	 * when fulldup is 2, the transmitter remains keyed and we
-	 * continue sending after waiting for waittime. IDLETIME is an 
-	 * idle timeout in this case.
-	 */ 
-	 
-	 if (scc->kiss.fulldup < 2)
-	 {
-	 	if (scc->tx_bp)		/* we had a timeout? */
-	 	{
-	 		scc->stat.tx_state = TXS_BUSY;
-	 		scc->t_dwait = TPS * scc->kiss.mintime; /* try again */
-	 	}
-	 	
-	 	scc->stat.tx_state = TXS_IDLE;
-		scc->t_maxk = TIMER_STOPPED;
-	 	scc_key_trx(scc, TX_OFF);
-	 	return;
-	 }
-	 
-	 if (scc->tx_bp)			/* maxkeyup expired */ /* ?! */
-	 {
-	 	scc->stat.tx_state = TXS_BUSY;
-	 	scc->t_txdel = TPS * scc->kiss.waittime;
-	 }
-	 else
-	 
-	 	scc->t_idle = TPS * scc->kiss.idletime;
-}
-
-
-static inline void busy_timeout(register struct scc_channel *scc)
-{
-#ifdef	THROW_AWAY_AFTER_BUSY_TIMEOUT
-	register struct mbuf *bp;		/* not tested */
-
-	while (bp = scc_dequeue_buffer(&scc->tx_queue))
-		scc_enqueue_buffer(&scc->tx_buffer_pool, bp);
-		
-	scc->tx_queue = NULLBUF;
-	scc->stat.tx_state = TXS_IDLE;
-	
-#else
-	scc->t_txdel = scc->kiss.txdelay;	/* brute force ... */
-#endif
-	scc->t_mbusy = TIMER_STOPPED;
-	
-}
-
-
-static inline void maxk_idle_timeout(register struct scc_channel *scc)
-{
-	scc->t_maxk = TIMER_STOPPED;
-	scc->t_idle = TIMER_STOPPED;
-	
-	scc->stat.tx_state = TXS_BUSY;
-	scc->t_tail = scc->kiss.tailtime;
-}
-
-static void
-scc_tx_timer(unsigned long channel)
-{
-	register struct scc_channel *scc;
-	unsigned long flags;
-		
-
-	scc = (struct scc_channel *) channel;
-		
-	if (scc->tty && scc->init)
-	{		
-		save_flags(flags); cli();
-		
-		/* KISS-TNC emulation */
-		
-		if (Expired(t_dwait)) dw_slot_timeout(scc)	; else
-		if (Expired(t_slot))  dw_slot_timeout(scc)	; else
-		if (Expired(t_txdel)) txdel_timeout(scc)   	; else
-		if (Expired(t_tail))  tail_timeout(scc)	   	;
-			
-		/* watchdogs */
-		
-		if (Expired(t_mbusy)) busy_timeout(scc);
-		if (Expired(t_maxk))  maxk_idle_timeout(scc);
-		if (Expired(t_idle))  maxk_idle_timeout(scc);
-			
-		restore_flags(flags);
-	}
-	
-	scc->tx_t.expires = jiffies + HZ/TPS;
-	add_timer(&scc->tx_t);
-}
-			
-
-static void
-scc_rx_timer(unsigned long channel)
-{
-	register struct scc_channel *scc;
-	
-	scc = (struct scc_channel *) channel;
-	
-	if (scc->rx_queue && scc->throttled)
-	{
-		scc->rx_t.expires = jiffies + HZ/TPS;
-		add_timer(&scc->rx_t);
-		return;
-	}
-	
-	kiss_encode(scc);
-	
-	if (scc->rx_queue && !scc->throttled)
-	{
-
-		printk("z8530drv: warning: %s should be throttled\n", 
-		       kdevname(scc->tty->device));
-			       
-		scc->rx_t.expires = jiffies + HZ/TPS;
-		add_timer(&scc->rx_t);
-	}
-}
-
-static void
-scc_init_timer(struct scc_channel *scc)
-{
-	unsigned long flags;
-	
-	save_flags(flags); cli();
-	
-	Stop_Timer(t_dwait);
-	Stop_Timer(t_slot);
-	Stop_Timer(t_txdel);
-	Stop_Timer(t_tail);
-	Stop_Timer(t_mbusy);
-	Stop_Timer(t_maxk);
-	Stop_Timer(t_idle);
-	
-	scc->stat.tx_state = TXS_IDLE;
-	
-	if (scc->tx_t.next) 
-		del_timer(&scc->tx_t);
-	
-	scc->tx_t.data = (unsigned long) scc;
-	scc->tx_t.function = scc_tx_timer;
-	scc->tx_t.expires = jiffies + HZ/TPS;
-	add_timer(&scc->tx_t);
-	
-	scc->rx_t.data = (unsigned long) scc;
-	scc->rx_t.function = scc_rx_timer;
-	
-	restore_flags(flags);
-}
-
-
-/* ******************************************************************** */
-/* *			KISS interpreter			      * */
-/* ******************************************************************** */
-
-
-/*
- * this will set the "kiss" parameters through kiss itself
- */
- 
-static void
-kiss_set_param(struct scc_channel *scc,char cmd, unsigned int val)
-{
-
-#define  VAL val=val*TPS/100
-#define SVAL val? val:TIMER_STOPPED
-
-	switch(cmd){
-	case PARAM_TXDELAY:
-		scc->kiss.txdelay = VAL; break;
-	case PARAM_PERSIST:
-		scc->kiss.persist = val; break;
-	case PARAM_SLOTTIME:
-		scc->kiss.slottime = VAL; break;
-	case PARAM_TXTAIL:
-		scc->kiss.tailtime = VAL; break;
-	case PARAM_FULLDUP:
-		scc->kiss.fulldup = val; break;
-	case PARAM_WAIT:
-		scc->kiss.waittime = VAL; break;
-	case PARAM_MAXKEY:
-		scc->kiss.maxkeyup = SVAL; break;
-	case PARAM_MIN:
-		scc->kiss.mintime = SVAL; break;
-	case PARAM_IDLE:
-		scc->kiss.idletime = val; break;
-	case PARAM_MAXDEFER:
-		scc->kiss.maxdefer = SVAL; break;
-	case PARAM_GROUP:
-		scc->kiss.group = val;  break;
-	case PARAM_TX:
-		scc->kiss.tx_inhibit = val;
-	case PARAM_SOFTDCD:
-		scc->kiss.softdcd = val;
-	}
-	return;
-
-#undef  VAL
-#undef SVAL
-}
-
-
-/* interpret frame: strip CRC and decode KISS */
-
-static void kiss_interpret_frame(struct scc_channel * scc)
-{
-	unsigned char kisscmd;
-	unsigned long flags;
-	struct mbuf *bp;
-
-	bp = scc->kiss_decode_bp;
-	bp->rw_ptr = bp->data;
-	
-#ifdef DEBUG_BUFFERS
-	if (bp == NULLBUF)
-	{
-		printk("kiss_interpret_frame(): weird --- nothing to do.\n");
-		return;
-	}
-#endif
-	
-	if (bp->cnt < 2)
-	{
-		scc_enqueue_buffer(&scc->tx_buffer_pool, bp);
-		scc->kiss_decode_bp = NULLBUF;
-		return;
-	}
-	
-	
-	
-	if (scc->kiss.not_slip)
-	{
-		kisscmd = *bp->rw_ptr;
-		bp->rw_ptr++;
-	} else {
-		kisscmd = 0;
-	}
-
-	if (kisscmd & 0xa0)
-	{
-		if (bp->cnt > 3) 
-			bp->cnt -= 2;
-		else
-		{
-			scc_enqueue_buffer(&scc->tx_buffer_pool, bp);
-			scc->kiss_decode_bp = NULLBUF;
-			return;
-		}
-	}
-	
-	
-	kisscmd &= 0x1f;
-	
-		
-	if (kisscmd)
-	{
-		kiss_set_param(scc, kisscmd, *bp->rw_ptr);
-		scc_enqueue_buffer(&scc->tx_buffer_pool, bp);
-		scc->kiss_decode_bp = NULLBUF;
-		return;
-	}
-
-	scc_enqueue_buffer(&scc->tx_queue, bp);	/* enqueue frame */
-	
-	scc->stat.txframes++;
-	scc->stat.tx_queued++;
-	scc->kiss_decode_bp = NULLBUF;
-
-	save_flags(flags); cli();
-
-	if(scc->stat.tx_state == TXS_IDLE)
-	{      				/* when transmitter is idle */
-		scc->stat.tx_state = TXS_BUSY;
-		scc->t_dwait = (scc->kiss.fulldup? 0:scc->kiss.waittime);
-	}
-	
-	restore_flags(flags);
-}
-
-static inline void kiss_store_byte(struct scc_channel *scc, unsigned char ch)
-{
-	register struct mbuf *bp = scc->kiss_decode_bp;
-	
-	if (bp != NULLBUF)
-	{
-		if (bp->cnt > scc->stat.bufsize)
-			printk("kiss_decode(): frame too long\n");
-		else
-		{
-			*bp->rw_ptr = ch;
-			bp->rw_ptr++;
-			bp->cnt++;
-		}
-	}
-}
-
-static inline int kiss_decode(struct scc_channel *scc, unsigned char ch)
-{
-	switch (scc->stat.tx_kiss_state) 
-	{
-		case KISS_IDLE:
-			if (ch == FEND)
-			{
-				scc->kiss_decode_bp = scc_get_buffer(scc, BT_TRANSMIT);
-				if (scc->kiss_decode_bp == NULLBUF)
-					return 1;
-
-				scc->stat.tx_kiss_state = KISS_DATA;
-			} else scc->stat.txerrs++;
-			break;
-					
-		case KISS_DATA:
-			if (ch == FESC)
-				scc->stat.tx_kiss_state = KISS_ESCAPE;
-			else if (ch == FEND)
-			{
-				kiss_interpret_frame(scc);
-				scc->stat.tx_kiss_state = KISS_IDLE;
-			}
-			else kiss_store_byte(scc, ch);
-			break;
-					
-		case KISS_ESCAPE:
-			if (ch == TFEND)
-			{
-				kiss_store_byte(scc, FEND);
-				scc->stat.tx_kiss_state = KISS_DATA;
-			}
-			else if (ch == TFESC)
-			{
-				kiss_store_byte(scc, FESC);
-				scc->stat.tx_kiss_state = KISS_DATA;
-			}
-			else
-			{
-				scc_enqueue_buffer(&scc->tx_buffer_pool, scc->kiss_decode_bp);
-				scc->kiss_decode_bp = NULLBUF;
-				scc->stat.txerrs++;
-				scc->stat.tx_kiss_state = KISS_IDLE;
-			}
-			break;
-	} /* switch */
-	
-	return 0;
-	
-}
-
-/* ----> Encode received data and write it to the flip-buffer  <---- */
-
-static void
-kiss_encode(register struct scc_channel *scc)
-{
-	struct mbuf *bp;
-	struct tty_struct * tty = scc->tty;
-	unsigned char ch;
-
-	bp = scc->kiss_encode_bp;
-	
-	/* worst case: FEND 0 FESC TFEND -> 4 bytes */
-	
-	while(tty->flip.count < TTY_FLIPBUF_SIZE-4)
-	{
-		if (bp == NULLBUF)
-		{
-			bp = scc_dequeue_buffer(&scc->rx_queue);
-			scc->kiss_encode_bp = bp;
-			
-			if (bp == NULLBUF)
-			{
-				scc->stat.rx_kiss_state = KISS_IDLE;
-				break;
-			}
-		}
-		
-
-		if (bp->cnt <= 0)
-		{
-			if (--scc->stat.rx_queued < 0)
-				scc->stat.rx_queued = 0;
-					
-			if (scc->stat.rx_kiss_state == KISS_RXFRAME)	/* new packet? */
-			{
-				tty_insert_flip_char(tty, FEND, 0);  /* send FEND for old frame */
-				scc->stat.rx_kiss_state = KISS_IDLE; /* generate FEND for new frame */
-			}
-			
-			scc_enqueue_buffer(&scc->rx_buffer_pool, bp);
-			
-			bp = scc->kiss_encode_bp = NULLBUF;
-			continue;
-		}
-		
-
-		if (scc->stat.rx_kiss_state == KISS_IDLE)
-		{
-			tty_insert_flip_char(tty, FEND, 0);
-			
-			if (scc->kiss.not_slip)
-				tty_insert_flip_char(tty, 0, 0);
-					
-			scc->stat.rx_kiss_state = KISS_RXFRAME;
-		}
-				
-		switch(ch = *bp->rw_ptr)
-		{
-			case FEND:
-				tty_insert_flip_char(tty, FESC, 0);
-				tty_insert_flip_char(tty, TFEND, 0);
-				break;
-			case FESC:
-				tty_insert_flip_char(tty, FESC, 0);
-				tty_insert_flip_char(tty, TFESC, 0);
-				break;
-			default:
-				tty_insert_flip_char(tty, ch, 0);
-		}
-			
-		bp->rw_ptr++;
-		bp->cnt--;
-	}
-		
- 	queue_task(&tty->flip.tqueue, &tq_timer); /* kick it... */
-}
-
-
-/* ******************************************************************* */
-/* *		Init channel structures, special HW, etc...	     * */
-/* ******************************************************************* */
-
-
-static void
-z8530_init(void)
-{
-	struct scc_channel *scc;
-	int chip, k;
-	unsigned long flags;
-	char *flag;
-
-
-	printk("Init Z8530 driver: %u channels, IRQ", Nchips*2);
-	
-	flag=" ";
-	for (k = 0; k < 16; k++)
-		if (Ivec[k].used) 
-		{
-			printk("%s%d", flag, k);
-			flag=",";
-		}
-	printk("\n");
-	
-
-	/* reset and pre-init all chips in the system */
-	for (chip = 0; chip < Nchips; chip++)
-	{
-		scc=&SCC_Info[2*chip];
-		if (!scc->ctrl) continue;
-			
-		save_flags(flags); cli();	/* because of 2-step accesses */
-		
-		/* Special SCC cards */
-
-		if(scc->brand & EAGLE)			/* this is an EAGLE card */
-			Outb(scc->special,0x08);	/* enable interrupt on the board */
-			
-		if(scc->brand & (PC100 | PRIMUS))	/* this is a PC100/EAGLE card */
-			Outb(scc->special,scc->option);	/* set the MODEM mode (0x22) */
-
-			
-		/* Init SCC */
-
-		/* some general init we can do now */
-		
-		Outb(scc->ctrl, 0);
-		OutReg(scc->ctrl,R9,FHWRES);		/* force hardware reset */
-		udelay(100);				/* give it 'a bit' more time than required */
-		wr(scc, R2, chip*16);			/* interrupt vector */
-		wr(scc, R9, VIS);			/* vector includes status */
-
-        	restore_flags(flags);
-        }
-
- 
-	Driver_Initialized = 1;
-}
-
-
-/* ******************************************************************** */
-/* * 	Filesystem Routines: open, close, ioctl, settermios, etc      * */
-/* ******************************************************************** */
-
-
-
-/* scc_paranoia_check(): warn user if something went wrong		*/
-
-static inline int scc_paranoia_check(struct scc_channel *scc, kdev_t device,
-				     const char *routine)
-{
-#ifdef SCC_PARANOIA_CHECK
-
-static const char *badmagic = 
-	"Warning: bad magic number for Z8530 SCC struct (%s) in %s\n"; 
-static const char *badinfo =  
-	"Warning: Z8530 not found for (%s) in %s\n";
-       
-	if (!scc->init) 
-	{
-       		printk(badinfo, kdevname(device), routine);
-		return 1;
-	}
-	
-	if (scc->magic != SCC_MAGIC)
-	{
-		printk(badmagic, kdevname(device), routine);
-		return 1;
-	}
-#endif
-
-	return 0;
-}
-
-
-/* ----> this one is called whenever you open the device <---- */
-
-int scc_open(struct tty_struct *tty, struct file * filp)
-{
-	struct scc_channel *scc;
-	int chan;
-	
-	chan = MINOR(tty->device) - tty->driver.minor_start;
-	
-	if (Driver_Initialized)
-	{
-		if ( (chan < 0) || (chan >= (Nchips * 2)) )
-                	return -ENODEV;
-        } else {
-        	tty->driver_data = &SCC_Info[0];
-        	MOD_INC_USE_COUNT;
-        	return 0;
-        }
- 
- 	scc = &SCC_Info[chan];
- 	
-	tty->driver_data = scc;
- 	tty->termios->c_cflag &= ~CBAUD;
- 	
-	if (scc->magic != SCC_MAGIC)
-	{
-		printk("ERROR: scc_open(): bad magic number for device (%s)",
-		       kdevname(tty->device));
-		return -ENODEV;
-	}		
-	
-	MOD_INC_USE_COUNT;
-	
-	if(scc->tty != NULL)
-	{
-		scc->tty_opened++;
-		return 0;
-	}
-
-  	scc->tty = tty;
-	alloc_buffer_pool(scc);
-	
- 	if(!scc->init) return 0;
- 	
-	scc->throttled = 0;
-
-	scc->stat.tx_kiss_state = KISS_IDLE;	/* don't change this... */
-	scc->stat.rx_kiss_state = KISS_IDLE;	/* ...or this */
- 
-	init_channel(scc);
-	return 0;
-}
-
-
-/* ----> and this whenever you close the device <---- */
-
-static void
-scc_close(struct tty_struct *tty, struct file * filp)
-{
-	struct scc_channel *scc = tty->driver_data;
-	unsigned long flags;
-
-        if (!scc || (scc->magic != SCC_MAGIC))
-                return;
-                
-        MOD_DEC_USE_COUNT;
-	
-	if(scc->tty_opened)
-	{
-		scc->tty_opened--;
-		return;
-	}
-	
-	tty->driver_data = NULLBUF;
-	
-	if (!Driver_Initialized)
-		return;
-	
-	save_flags(flags); cli();
-	
-	Outb(scc->ctrl,0);		/* Make sure pointer is written */
-	wr(scc,R1,0);			/* disable interrupts */
-	wr(scc,R3,0);
-	
-	scc->tty = NULL;
-	
-	del_timer(&scc->tx_t);
-	del_timer(&scc->rx_t);
-
-	free_buffer_pool(scc);
-	
-	restore_flags(flags);
-	
-	scc->throttled = 0;
-	tty->stopped = 0;
-}
-
-
-/*
- * change scc_speed
- */
- 
-static void
-scc_change_speed(struct scc_channel * scc)
-{
-	long speed;
-	
-	if (scc->tty == NULL)
-		return;
-		
-
-	speed = baud_table[scc->tty->termios->c_cflag & CBAUD];
-	
-	if (speed > 0) scc->modem.speed = speed;
-	
-	if (scc->stat.tx_state == 0)	/* only switch baudrate on rx... ;-) */
-		set_speed(scc);
-}
-
-
-/* ----> ioctl-routine of the driver <---- */
-
-/* perform ioctl on SCC (sdlc) channel
- * this is used for AX.25 mode, and will set the "kiss" parameters
- */
- 
-/* TIOCMGET 	- get modem status	arg: (unsigned long *) arg
- * TIOCMBIS 	- set PTT		arg: ---
- * TIOCMBIC 	- reset PTT		arg: ---
- * TIOCMBIC 	- set PTT		arg: ---
- * TIOCSCCINI	- initialize driver	arg: ---
- * TIOCCHANINI	- initialize channel	arg: (struct scc_modem *) arg
- * TIOCGKISS	- get level 1 parameter	arg: (struct ioctl_command *) arg
- * TIOCSKISS	- set level 1 parameter arg: (struct ioctl_command *) arg
- * TIOCSCCSTAT  - get driver status	arg: (struct scc_stat *) arg
- */
- 
-
-static int
-scc_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
-{
-	struct scc_channel * scc = tty->driver_data;
-	unsigned long flags, r;
-	unsigned int result;
-	unsigned int value;
-	struct ioctl_command kiss_cmd;
-	struct scc_mem_config memcfg;
-	struct scc_hw_config hwcfg;
-	int error, chan;
-
-        if (scc->magic != SCC_MAGIC) 
-        {
-		printk("ERROR: scc_ioctl(): bad magic number for device %s",
-			kdevname(tty->device));
-			
-                return -ENODEV;
-        }
-	                                                 
-	r = NO_SUCH_PARAM;
-	
-	if (!Driver_Initialized)
-	{
-		if (cmd == TIOCSCCCFG)
-		{
-			int found = 1;
-			
-			if (!suser()) return -EPERM;
-			if (!arg) return -EFAULT;
-			
-			if (Nchips >= MAXSCC) 
-				return -EINVAL;
-			
-			copy_from_user(&hwcfg, (void *) arg, sizeof(hwcfg));
-			
-			if (hwcfg.irq == 2) hwcfg.irq = 9;
-			
-			if (!Ivec[hwcfg.irq].used && hwcfg.irq)
-			{
-				if (request_irq(hwcfg.irq, scc_isr, SA_INTERRUPT, "AX.25 SCC", NULL))
-					printk("z8530drv: Warning --- could not get IRQ %d\n", hwcfg.irq);
-				else
-					Ivec[hwcfg.irq].used = 1;
-			}
-			
-			if (hwcfg.vector_latch) 
-				Vector_Latch = hwcfg.vector_latch;
-				
-			if (hwcfg.clock == 0)
-				hwcfg.clock = DEFAULT_CLOCK;
-
-#ifndef DONT_CHECK
-			save_flags(flags); cli();
-			
-			check_region(scc->ctrl, 1);
-			Outb(hwcfg.ctrl_a, 0);
-			udelay(5);
-			OutReg(hwcfg.ctrl_a,R13,0x55);		/* is this chip really there? */
-			udelay(5);
-			
-			if (InReg(hwcfg.ctrl_a,R13) != 0x55 )
-				found = 0;
-				
-			restore_flags(flags);
-#endif
-
-			if (found)
-			{
-				SCC_Info[2*Nchips  ].ctrl = hwcfg.ctrl_a;
-				SCC_Info[2*Nchips  ].data = hwcfg.data_a;
-				SCC_Info[2*Nchips+1].ctrl = hwcfg.ctrl_b;
-				SCC_Info[2*Nchips+1].data = hwcfg.data_b;
-			
-				SCC_ctrl[2*Nchips  ] = hwcfg.ctrl_a;
-				SCC_ctrl[2*Nchips+1] = hwcfg.ctrl_b;
-			}
-		
-			for (chan = 0; chan < 2; chan++)
-			{
-				SCC_Info[2*Nchips+chan].special = hwcfg.special;
-				SCC_Info[2*Nchips+chan].clock = hwcfg.clock;
-				SCC_Info[2*Nchips+chan].brand = hwcfg.brand;
-				SCC_Info[2*Nchips+chan].option = hwcfg.option;
-				SCC_Info[2*Nchips+chan].enhanced = hwcfg.escc;
-			
-#ifdef DONT_CHECK
-				printk("%s%i: data port = 0x%3.3x  control port = 0x%3.3x\n",
-					scc_driver.name, 2*Nchips+chan, 
-					SCC_Info[2*Nchips+chan].data, 
-					SCC_Info[2*Nchips+chan].ctrl);
-
-#else
-				printk("%s%i: data port = 0x%3.3x  control port = 0x%3.3x -- %s\n",
-					scc_driver.name, 2*Nchips+chan, 
-					chan? hwcfg.data_b : hwcfg.data_a, 
-					chan? hwcfg.ctrl_b : hwcfg.ctrl_a,
-					found? "found" : "missing");
-#endif
-				
-				if (found)
-				{
-					request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl");
-					request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data");
-				}
-			}
-			
-			if (found) Nchips++;
-			
-			return 0;
-		}
-		
-		if (cmd == TIOCSCCINI)
-		{
-			if (!suser())
-				return -EPERM;
-				
-			if (Nchips == 0)
-				return -EINVAL;
-			
-			z8530_init();
-			
-			scc->tty=tty;
-			alloc_buffer_pool(scc);
-			return 0;
-		}
-		
-		return -EINVAL;	/* confuse the user */
-	}
-	
-	if (!scc->init)
-	{
-		if (cmd == TIOCCHANINI)
-		{
-			if (!arg)
-				return -EFAULT;
-				
-			if (!suser())
-				return -EPERM;
-			
-			copy_from_user(&scc->modem, (void *) arg, sizeof(struct scc_modem));
-			
-			/* default KISS Params */
-		
-			if (scc->modem.speed < 4800)
-			{
-				scc->kiss.txdelay = 36*TPS/100;    /* 360 ms */
-				scc->kiss.persist = 42;            /* 25% persistence */			/* was 25 */
-				scc->kiss.slottime = 16*TPS/100;   /* 160 ms */
-				scc->kiss.tailtime = 4;            /* minimal reasonable value */
-				scc->kiss.fulldup = 0;             /* CSMA */
-				scc->kiss.waittime = 50*TPS/100;   /* 500 ms */
-				scc->kiss.maxkeyup = 10;           /* 10 s */
-				scc->kiss.mintime = 3;             /* 3 s */
-				scc->kiss.idletime = 30;           /* 30 s */
-				scc->kiss.maxdefer = 120;	   /* 2 min */
-				scc->kiss.not_slip = 1;		   /* KISS mode */
-				scc->kiss.softdcd = 0;		   /* hardware dcd */
-			} else {
-				scc->kiss.txdelay = 10*TPS/100;    /* 100 ms */
-				scc->kiss.persist = 64;            /* 25% persistence */			/* was 25 */
-				scc->kiss.slottime = 8*TPS/100;    /* 160 ms */
-				scc->kiss.tailtime = 1;            /* minimal reasonable value */
-				scc->kiss.fulldup = 0;             /* CSMA */
-				scc->kiss.waittime = 50*TPS/100;   /* 500 ms */
-				scc->kiss.maxkeyup = 7;            /* 7 s */
-				scc->kiss.mintime = 3;             /* 3 s */
-				scc->kiss.idletime = 30;           /* 30 s */
-				scc->kiss.maxdefer = 120;	   /* 2 min */
-				scc->kiss.not_slip = 1;		   /* KISS mode */
-				scc->kiss.softdcd = 0;		   /* hardware dcd */
-			}
-			
-			scc->init = 1;			
-			
-			return 0;
-		}
-		
-		return -EINVAL;
-	}
-
-	switch(cmd){
-	case TCSBRK:
-		return 0;
-	case TIOCMGET:
-		error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(unsigned int *));
-		if (error)
-			return error;
-
-		save_flags(flags); cli();
-		
-		result =  ((scc->wreg[R5] & RTS) ? TIOCM_RTS : 0)
-			| ((scc->wreg[R5] & DTR) ? TIOCM_DTR : 0)
-			| ((InReg(scc->ctrl,R0) & DCD)  ? TIOCM_CAR : 0)
-			| ((InReg(scc->ctrl,R0) & CTS)  ? TIOCM_CTS : 0);
-		
-		restore_flags(flags);
-			
-		put_user(result,(unsigned int *) arg);
-		return 0;
-	case TIOCMBIS:
-	case TIOCMBIC:
-	case TIOCMSET:
-		switch (cmd) {
-		case TIOCMBIS:
-			scc->wreg[R5] |= DTR;
-			scc->wreg[R5] |= RTS;
-			break;
-		case TIOCMBIC:
-			scc->wreg[R5] &= ~DTR;
-			scc->wreg[R5] &= ~RTS;
-			break;
-		case TIOCMSET:
-			value = get_user((unsigned int *) arg);
-			
-			if(value & TIOCM_DTR)
-				scc->wreg[R5] |= DTR;
-			else
-				scc->wreg[R5] &= ~DTR;
-			if(value & TIOCM_RTS)
-				scc->wreg[R5] |= RTS;
-			else
-				scc->wreg[R5] &= ~RTS;
-			break;
-		}
-		
-		save_flags(flags); cli();
-		
-		if(scc->stat.tx_state == TXS_IDLE && !Running(t_idle))
-			maxk_idle_timeout(scc);
-			
-		restore_flags(flags);
-		
-		return 0;
-		
-	case TCGETS:
-		error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct termios));
-		if (error)
-			return error;
-		if (!arg) 
-			return -EFAULT;
-			
-		copy_to_user((void *) arg, scc->tty->termios, sizeof(struct termios));
-		return 0;
-		
-	case TCSETS:
-	case TCSETSF:		/* should flush first, but... */
-	case TCSETSW:		/* should wait 'till flush, but... */
-		if (!arg)
-			return -EFAULT;
-		
-		copy_from_user(scc->tty->termios, (void *) arg, sizeof(struct termios));
-		scc_change_speed(scc);
-		return 0;
-		
-	case TIOCCHANMEM:
-		if (!arg)
-			return -EFAULT;
-			
-		copy_from_user(&memcfg, (void *) arg, sizeof(struct scc_mem_config));
-		
-		save_flags(flags); cli();
-		
-		free_buffer_pool(scc);
-		scc->stat.rxbuffers = memcfg.rxbuffers;
-		scc->stat.txbuffers = memcfg.txbuffers;
-		scc->stat.bufsize   = memcfg.bufsize;
-		alloc_buffer_pool(scc);
-		
-		restore_flags(flags);
-		return 0;
-		
-		
-	case TIOCSCCSTAT:
-		error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(struct scc_stat));
-		if (error)
-			return error;
-		
-		if (!arg)
-			return -EFAULT;
-			
-		copy_to_user((void *) arg, &scc->stat, sizeof(struct scc_stat));
-		return 0;
-		
-#define TICKS (100/TPS)
-#define CAST(x) (unsigned long)(x)
-#define  Val	kiss_cmd.param
-#define  VAL	kiss_cmd.param*TPS/100
-#define SVAL	kiss_cmd.param? kiss_cmd.param:TIMER_STOPPED
-
-	case TIOCGKISS:
-		error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(struct ioctl_command));
-		if (error)
-			return error;
-			
-		if (!arg)
-			return -EFAULT;
-			
-		copy_from_user(&kiss_cmd, (void *) arg, sizeof(struct ioctl_command));
-
-		switch (kiss_cmd.command)
-		{
-			case PARAM_TXDELAY:	r = CAST(scc->kiss.txdelay*TICKS);	break;
-			case PARAM_PERSIST:	r = CAST(scc->kiss.persist); 		break;
-			case PARAM_SLOTTIME:	r = CAST(scc->kiss.slottime*TICKS);	break;
-			case PARAM_TXTAIL:	r = CAST(scc->kiss.tailtime*TICKS);	break;
-			case PARAM_FULLDUP:	r = CAST(scc->kiss.fulldup); 		break;
-			case PARAM_SOFTDCD:	r = CAST(scc->kiss.softdcd);		break;
-			case PARAM_DTR:		r = CAST((scc->wreg[R5] & DTR)? 1:0); break;
-			case PARAM_RTS:		r = CAST((scc->wreg[R5] & RTS)? 1:0); break;
-			case PARAM_SPEED:	r = CAST(scc->modem.speed);	break;
-			case PARAM_GROUP:	r = CAST(scc->kiss.group); 		break;
-			case PARAM_IDLE:	r = CAST(scc->kiss.idletime);		break;
-			case PARAM_MIN:		r = CAST(scc->kiss.mintime);		break;
-			case PARAM_MAXKEY:	r = CAST(scc->kiss.maxkeyup);		break;
-			case PARAM_WAIT:	r = CAST(scc->kiss.waittime);		break;
-			case PARAM_MAXDEFER:	r = CAST(scc->kiss.maxdefer);		break;
-			case PARAM_TX:		r = CAST(scc->kiss.tx_inhibit);	break;
-			case PARAM_SLIP:	r = CAST(!scc->kiss.not_slip);		break;
-			default:		r = NO_SUCH_PARAM;
-		}
-		
-		kiss_cmd.param = r;
-		
-		copy_to_user((void *) arg, &kiss_cmd, sizeof(struct ioctl_command));
-		return 0;
-		break;
-		
-	case TIOCSKISS:
-		if (!arg)
-			return -EFAULT;
-
-		copy_from_user(&kiss_cmd, (void *) arg, sizeof(struct ioctl_command));
-		
-		switch (kiss_cmd.command)
-		{
-			case PARAM_TXDELAY:	scc->kiss.txdelay=VAL;		break;
-			case PARAM_PERSIST:	scc->kiss.persist=Val;		break;
-			case PARAM_SLOTTIME:	scc->kiss.slottime=VAL;		break;
-			case PARAM_TXTAIL:	scc->kiss.tailtime=VAL;		break;
-			case PARAM_FULLDUP:	scc->kiss.fulldup=Val;		break;
-			case PARAM_SOFTDCD:	scc->kiss.softdcd=Val;		break;
-			case PARAM_DTR:		break; /* does someone need this? */
-			case PARAM_RTS:		break; /* or this? */
-			case PARAM_SPEED:	scc->modem.speed=Val;		break;
-			case PARAM_GROUP:	scc->kiss.group=Val;		break;
-			case PARAM_IDLE:	scc->kiss.idletime=Val;		break;
-			case PARAM_MIN:		scc->kiss.mintime=SVAL;		break;
-			case PARAM_MAXKEY:	scc->kiss.maxkeyup=SVAL;	break;
-			case PARAM_WAIT:	scc->kiss.waittime=Val;		break;
-			case PARAM_MAXDEFER:	scc->kiss.maxdefer=SVAL;	break;
-			case PARAM_TX:		scc->kiss.tx_inhibit=Val;	break;
-			case PARAM_SLIP:	scc->kiss.not_slip=!Val;	break;
-			default:		return -ENOIOCTLCMD;
-		}
-		
-		return 0;
-		break;
-#undef TICKS
-#undef CAST
-#undef VAL
-#undef SVAL
-#undef Val
-		
-	default:
-		return -ENOIOCTLCMD;
-    }
-}
-
-
-/* ----> tx routine: decode KISS data and scc_enqueue it <---- */
-
-/* send raw frame to SCC. used for AX.25 */
-int scc_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
-{
-	struct scc_channel * scc = tty->driver_data;
-	unsigned char *p;
-	unsigned long flags;
-	int cnt, cnt2;
-	
-	if (!tty) return count;
-	
-	if (scc_paranoia_check(scc, tty->device, "scc_write"))
-		return 0;
-
-	if (scc->kiss.tx_inhibit) return count;
-	
-	save_flags(flags); cli();
-	
-	cnt2 = count;
-	
-	while (cnt2)
-	{
-		cnt   = cnt2 > BUFSIZE? BUFSIZE:cnt2;
-		cnt2 -= cnt;
-		
-		if (from_user)
-		{
-			down(&scc_sem);
-			copy_from_user(scc_wbuf, buf, cnt);
-			up(&scc_sem);
-		}
-		else
-			memcpy(scc_wbuf, buf, cnt);
-		
-		/* Strange thing. The timeout of the slip driver is */
-		/* very small, thus we'll wake him up now. 	    */
-
-		if (cnt2 == 0)
-		{
-			wake_up_interruptible(&tty->write_wait);
-		
-			if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-			    tty->ldisc.write_wakeup)
-				(tty->ldisc.write_wakeup)(tty);
-		} else 
-			buf += cnt;
-			
-		p=scc_wbuf;
-		
-		while(cnt--) 
-		  if (kiss_decode(scc, *p++))
-		  {
-		  	scc->stat.nospace++;
-		  	restore_flags(flags);
-		  	return 0;
-		  }		  	
-	} /* while cnt2 */
-
-	restore_flags(flags);
-		
-	return count;
-}
-				
-
-/* put a single char into the buffer */
-
-static void scc_put_char(struct tty_struct * tty, unsigned char ch)
-{
-	struct scc_channel *scc = tty->driver_data;
-	unsigned char ch2;
-	
-	if (scc_paranoia_check(scc, tty->device, "scc_put_char"))
-		return;
-		
-	ch2 = ch;
-	scc_write(tty, 0, &ch2, 1);	/* that's all */
-}
-
-static void scc_flush_chars(struct tty_struct * tty)
-{
-	struct scc_channel *scc = tty->driver_data;
-	
-	scc_paranoia_check(scc, tty->device, "scc_flush_chars"); /* just to annoy the user... */
-	
-	return;	/* no flush needed */
-}
-
-
-static int scc_write_room(struct tty_struct *tty)
-{
-	struct scc_channel *scc = tty->driver_data;
-	
-	if (scc_paranoia_check(scc, tty->device, "scc_write_room"))
-		return 0;
-	
-	return BUFSIZE;
-}
-
-static int scc_chars_in_buffer(struct tty_struct *tty)
-{
-	struct scc_channel *scc = tty->driver_data;
-	
-	if (scc && scc->kiss_decode_bp)
-		return scc->kiss_decode_bp->cnt;
-	else
-		return 0;
-}
-
-static void scc_flush_buffer(struct tty_struct *tty)
-{
-	struct scc_channel *scc = tty->driver_data;
-
-	if (scc_paranoia_check(scc, tty->device, "scc_flush_buffer"))
-		return;
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-}
-
-static void scc_throttle(struct tty_struct *tty)
-{
-	struct scc_channel *scc = tty->driver_data;
-	
-	if (scc_paranoia_check(scc, tty->device, "scc_throttle"))
-		return;
-
-#ifdef DEBUG		
-	printk("scc: scc_throttle() called for device %d\n", MINOR(tty->device));
-#endif
-	scc->throttled = 1;
-	
-	del_timer(&(scc->rx_t));
-	scc->rx_t.expires = jiffies + HZ/TPS;
-	add_timer(&scc->rx_t);
-}
-
-static void scc_unthrottle(struct tty_struct *tty)
-{
-	struct scc_channel *scc = tty->driver_data;
-	
-	if (scc_paranoia_check(scc, tty->device, "scc_unthrottle"))
-		return;
-		
-#ifdef DEBUG
-	printk("scc: scc_unthrottle() called for device %d\n", MINOR(tty->device));
-#endif		
-	scc->throttled = 0;
-	del_timer(&(scc->rx_t));
-	scc_tx_timer(scc->rx_t.data);
-}
-
-/* experimental, the easiest way to stop output is a fake scc_throttle */
-
-static void scc_start(struct tty_struct *tty)
-{
-	struct scc_channel *scc = tty->driver_data;
-	
-	if (scc_paranoia_check(scc, tty->device, "scc_start"))
-		return;
-		
-	scc_unthrottle(tty);
-}
-
-static void scc_stop(struct tty_struct *tty)
-{
-	struct scc_channel *scc = tty->driver_data;
-	
-	if (scc_paranoia_check(scc, tty->device, "scc_stop"))
-		return;
-		
-	scc_throttle(tty);
-}
-
-static void
-scc_set_termios(struct tty_struct * tty, struct termios * old_termios)
-{
-	struct scc_channel *scc = tty->driver_data;
-	
-	if (scc_paranoia_check(scc, tty->device, "scc_set_termios"))
-		return;
-		
-	if (old_termios && (tty->termios->c_cflag == old_termios->c_cflag)) 
-		return;
-		
-	scc_change_speed(scc);
-}
-
-static void
-scc_set_ldisc(struct tty_struct * tty)
-{
-	struct scc_channel *scc = tty->driver_data;
-
-	if (scc_paranoia_check(scc, tty->device, "scc_set_ldisc"))
-		return;
-		
-	scc_change_speed(scc);
-}
-
-
-/* ******************************************************************** */
-/* * 			Init SCC driver 			      * */
-/* ******************************************************************** */
-
-int  scc_init (void)
-{
-	int chip, chan, k;
-	
-	memset(&scc_std_termios, 0, sizeof(struct termios));
-        memset(&scc_driver, 0, sizeof(struct tty_driver));
-        scc_driver.magic = TTY_DRIVER_MAGIC;
-        scc_driver.name = "scc";
-        scc_driver.major = Z8530_MAJOR;
-        scc_driver.minor_start = 0;
-        scc_driver.num = MAXSCC*2;
-        scc_driver.type = TTY_DRIVER_TYPE_SERIAL;
-        scc_driver.subtype = 1;			/* not needed */
-        scc_driver.init_termios = scc_std_termios;
-        scc_driver.init_termios.c_cflag = B9600  | CREAD | CS8 | HUPCL | CLOCAL;
-        scc_driver.init_termios.c_iflag = IGNBRK | IGNPAR;
-        scc_driver.flags = TTY_DRIVER_REAL_RAW;
-        scc_driver.refcount = &scc_refcount;
-        scc_driver.table = scc_table;
-        scc_driver.termios = (struct termios **) scc_termios;
-        scc_driver.termios_locked = (struct termios **) scc_termios_locked;
-        scc_driver.open = scc_open;
-        scc_driver.close = scc_close;
-        scc_driver.write = scc_write;
-        scc_driver.start = scc_start;
-        scc_driver.stop = scc_stop;
-        
-        scc_driver.put_char = scc_put_char;
-        scc_driver.flush_chars = scc_flush_chars;        
-	scc_driver.write_room = scc_write_room;
-	scc_driver.chars_in_buffer = scc_chars_in_buffer;
-	scc_driver.flush_buffer = scc_flush_buffer;
-	
-	scc_driver.throttle = scc_throttle;
-	scc_driver.unthrottle = scc_unthrottle;
-        
-        scc_driver.ioctl = scc_ioctl;
-        scc_driver.set_termios = scc_set_termios;
-        scc_driver.set_ldisc = scc_set_ldisc;
-
-	printk(BANNER);
-        
-        if (tty_register_driver(&scc_driver))
-        {
-		printk("Failed to register Z8530 SCC driver\n");
-		return -EIO;
-	}
-	
-	/* pre-init channel information */
-	
-	for (chip = 0; chip < MAXSCC; chip++)
-	{
-		memset((char *) &SCC_Info[2*chip  ], 0, sizeof(struct scc_channel));
-		memset((char *) &SCC_Info[2*chip+1], 0, sizeof(struct scc_channel));
-		
-		for (chan = 0; chan < 2; chan++)
-		{
-			SCC_Info[2*chip+chan].magic    = SCC_MAGIC;
-			SCC_Info[2*chip+chan].stat.rxbuffers = RXBUFFERS;
-			SCC_Info[2*chip+chan].stat.txbuffers = TXBUFFERS;
-			SCC_Info[2*chip+chan].stat.bufsize   = BUFSIZE;
-		}
-	}
-	
-	for (k = 0; k < 16; k++) Ivec[k].used = 0;
-
-	return 0;
-}
-
-/* ******************************************************************** */
-/* *			    Module support 			      * */
-/* ******************************************************************** */
-
-
-#ifdef MODULE
-int init_module(void)
-{
-	int result = 0;
-	
-	result = scc_init();
-	
-	if (result == 0)
-		printk("Copyright 1993,1995 Joerg Reuter DL1BKE (jreuter@lykos.tng.oche.de)\n");
-		
-	return result;
-}
-
-void cleanup_module(void)
-{
-	long flags;
-	io_port ctrl;
-	int k, errno;
-	struct scc_channel *scc;
-	
-	save_flags(flags); cli();
-	if ( (errno = tty_unregister_driver(&scc_driver)) )
-	{
-		printk("Failed to unregister Z8530 SCC driver (%d)", -errno);
-		restore_flags(flags);
-		return;
-	}
-	
-	for (k = 0; k < Nchips; k++)
-		if ( (ctrl = SCC_ctrl[k*2]) )
-		{
-			Outb(ctrl, 0);
-			OutReg(ctrl,R9,FHWRES);	/* force hardware reset */
-			udelay(50);
-		}
-		
-	for (k = 0; k < Nchips*2; k++)
-	{
-		scc = &SCC_Info[k];
-		if (scc)
-		{
-			release_region(scc->ctrl, 1);
-			release_region(scc->data, 1);
-		}
-	}
-	
-	for (k=0; k < 16 ; k++)
-		if (Ivec[k].used) free_irq(k, NULL);
-		
-	restore_flags(flags);
-}
-#endif
diff -u --recursive --new-file v2.1.5/linux/drivers/char/selection.c linux/drivers/char/selection.c
--- v2.1.5/linux/drivers/char/selection.c	Wed Oct 16 10:48:14 1996
+++ linux/drivers/char/selection.c	Mon Oct 28 23:49:41 1996
@@ -17,7 +17,7 @@
 #include <linux/malloc.h>
 #include <linux/types.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "vt_kern.h"
 #include "consolemap.h"
@@ -290,9 +290,9 @@
 	if (!bp || !c)
 		return 0;
 	do_unblank_screen();
-	current->state = TASK_INTERRUPTIBLE;
 	add_wait_queue(&vt->paste_wait, &wait);
-	while (c) {
+	do {
+		current->state = TASK_INTERRUPTIBLE;
 		if (test_bit(TTY_THROTTLED, &tty->flags)) {
 			schedule();
 			continue;
@@ -301,7 +301,8 @@
 		tty->ldisc.receive_buf(tty, bp, 0, l);
 		c -= l;
 		bp += l;
-	}
+	} while (c);
+	remove_wait_queue(&vt->paste_wait, &wait);
 	current->state = TASK_RUNNING;
 	return 0;
 }
diff -u --recursive --new-file v2.1.5/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.1.5/linux/drivers/char/serial.c	Wed Oct 16 10:48:14 1996
+++ linux/drivers/char/serial.c	Mon Oct 28 14:29:21 1996
@@ -45,7 +45,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 static char *serial_name = "Serial driver";
diff -u --recursive --new-file v2.1.5/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v2.1.5/linux/drivers/char/stallion.c	Wed Oct 16 10:48:14 1996
+++ linux/drivers/char/stallion.c	Mon Oct 28 14:29:21 1996
@@ -45,7 +45,7 @@
 #include <linux/config.h>	/* for CONFIG_PCI */
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/char/tga.c linux/drivers/char/tga.c
--- v2.1.5/linux/drivers/char/tga.c	Wed Oct 16 10:48:14 1996
+++ linux/drivers/char/tga.c	Mon Oct 28 14:29:22 1996
@@ -28,7 +28,7 @@
 
 #include <asm/io.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #include "kbd_kern.h"
diff -u --recursive --new-file v2.1.5/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c
--- v2.1.5/linux/drivers/char/tpqic02.c	Sat Oct 19 10:07:31 1996
+++ linux/drivers/char/tpqic02.c	Mon Oct 28 14:29:23 1996
@@ -216,7 +216,7 @@
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /* We really shouldn't be using this define.. */
 #define IOCCMD_MASK 0x0000ffff
diff -u --recursive --new-file v2.1.5/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.1.5/linux/drivers/char/tty_io.c	Wed Oct 16 10:48:15 1996
+++ linux/drivers/char/tty_io.c	Tue Oct 29 15:33:38 1996
@@ -63,12 +63,10 @@
 #include <linux/string.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 
-#include <linux/scc.h>
-
 #include "kbd_kern.h"
 #include "vt_kern.h"
 #include "selection.h"
@@ -1714,7 +1712,7 @@
 		if (((*p)->tty == tty) ||
 		    ((session > 0) && ((*p)->session == session)))
 			send_sig(SIGKILL, *p, 1);
-		else {
+		else if ((*p)->files) {
 			for (i=0; i < NR_OPEN; i++) {
 				filp = (*p)->files->fd[i];
 				if (filp && (filp->f_op == &tty_fops) &&
@@ -1927,9 +1925,6 @@
 	kbd_init();
 #ifdef CONFIG_SERIAL
 	rs_init();
-#endif
-#ifdef CONFIG_SCC
-	scc_init();
 #endif
 #ifdef CONFIG_CYCLADES
 	cy_init();
diff -u --recursive --new-file v2.1.5/linux/drivers/char/tty_ioctl.c linux/drivers/char/tty_ioctl.c
--- v2.1.5/linux/drivers/char/tty_ioctl.c	Wed Oct 16 10:48:15 1996
+++ linux/drivers/char/tty_ioctl.c	Mon Oct 28 14:29:23 1996
@@ -21,7 +21,7 @@
 
 #include <asm/io.h>
 #include <asm/bitops.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #undef TTY_DEBUG_WAIT_UNTIL_SENT
diff -u --recursive --new-file v2.1.5/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c
--- v2.1.5/linux/drivers/char/vc_screen.c	Sat Oct 19 10:07:31 1996
+++ linux/drivers/char/vc_screen.c	Mon Oct 28 14:29:23 1996
@@ -22,7 +22,7 @@
 #include <linux/tty.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include "vt_kern.h"
 #include "selection.h"
 
diff -u --recursive --new-file v2.1.5/linux/drivers/char/vesa_blank.c linux/drivers/char/vesa_blank.c
--- v2.1.5/linux/drivers/char/vesa_blank.c	Wed Oct 16 10:48:15 1996
+++ linux/drivers/char/vesa_blank.c	Mon Oct 28 14:29:23 1996
@@ -43,7 +43,7 @@
 
 #include <asm/io.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/mm.h>
 
 extern unsigned short video_port_reg, video_port_val;
diff -u --recursive --new-file v2.1.5/linux/drivers/char/vga.c linux/drivers/char/vga.c
--- v2.1.5/linux/drivers/char/vga.c	Wed Oct 16 10:48:15 1996
+++ linux/drivers/char/vga.c	Mon Oct 28 14:29:23 1996
@@ -52,7 +52,7 @@
 
 #include <asm/io.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #include "kbd_kern.h"
diff -u --recursive --new-file v2.1.5/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v2.1.5/linux/drivers/char/vt.c	Wed Oct 16 10:48:15 1996
+++ linux/drivers/char/vt.c	Mon Oct 28 14:29:23 1996
@@ -22,7 +22,7 @@
 #include <linux/fs.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "kbd_kern.h"
 #include "vt_kern.h"
diff -u --recursive --new-file v2.1.5/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
--- v2.1.5/linux/drivers/char/wdt.c	Wed Oct 16 10:48:15 1996
+++ linux/drivers/char/wdt.c	Mon Oct 28 14:29:23 1996
@@ -33,7 +33,7 @@
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 static int wdt_is_open=0;
diff -u --recursive --new-file v2.1.5/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.1.5/linux/drivers/isdn/isdn_common.c	Wed Oct 16 10:48:16 1996
+++ linux/drivers/isdn/isdn_common.c	Mon Oct 28 20:57:44 1996
@@ -726,6 +726,8 @@
 /*
  * isdn_readbchan() tries to get data from the read-queue.
  * It MUST be called with interrupts off.
+ *  
+ * I hope I got the EFAULT error path right -AK.
  */
 int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user)
 {
@@ -736,6 +738,7 @@
 	int dflag;
         struct sk_buff *skb;
 	u_char *cp;
+	int ret = 0; 
 
 	if (!dev->drv[di])
 		return 0;
@@ -749,6 +752,7 @@
 	cp = buf;
 	count = 0;
 	while (left) {
+		        ret = 0; 
                 if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
                         break;
                 if (skb->lock)
@@ -765,15 +769,19 @@
                         count_pull = count_put = 0;
                         while ((count_pull < skb->len) && (left-- > 0)) {
                                 if (dev->drv[di]->DLEflag & DLEmask) {
-                                        if (user)
-                                                put_fs_byte(DLE,cp++);
-                                        else
+									    if (user) {
+                                                ret = put_user(DLE,cp);
+												cp++; 
+												if (ret) break; 
+                                        } else
                                                 *cp++ = DLE;
                                         dev->drv[di]->DLEflag &= ~DLEmask;
                                 } else {
-                                        if (user)
-                                                put_fs_byte(*p,cp++);
-                                        else
+									    if (user) {
+                                                ret = put_user(*p,cp);
+												if (ret) break;
+												cp++; 
+                                        } else
                                                 *cp++ = *p;
                                         if (*p == DLE) {
                                                 dev->drv[di]->DLEflag |= DLEmask;
@@ -794,10 +802,12 @@
                                 dflag = 0;
                         }
                         count_put = count_pull;
+						ret = 0; 
                         if (user)
-                                copy_to_user(cp, skb->data, count_put);
+                                ret = copy_to_user(cp, skb->data, count_put);
                         else
                                 memcpy(cp, skb->data, count_put);
+						count_put -= ret; 
                         cp += count_put;
                         left -= count_put;
                 }
@@ -821,11 +831,11 @@
                          * but we pull off the data we got until now.
                          */
 			skb_pull(skb,count_pull);
-                        skb->lock = 0;
+                        skb->lock = 0; 
                 }
 		dev->drv[di]->rcvcount[channel] -= count_put;
 	}
-	return count;
+	return ret ? -EFAULT : count;
 }
 
 static __inline int isdn_minor2drv(int minor)
@@ -923,9 +933,10 @@
 		p = isdn_statstr();
 		file->private_data = 0;
 		if ((len = strlen(p)) <= count) {
-			copy_to_user(buf, p, len);
+			if (copy_to_user(buf, p, len))
+				return -EFAULT;
 			file->f_pos += len;
-			return len;
+			return len; 
 		}
 		return 0;
 	}
@@ -1072,35 +1083,25 @@
 		return ret;
 	save_flags(flags);
 	cli();
-	if ((ret = verify_area(VERIFY_READ, (void *) src, sizeof(int)))) {
-		restore_flags(flags);
-		return ret;
-	}
-	copy_from_user((char *) &i, src, sizeof(int));
-        src += sizeof(int);
+	ret = get_user(i, src); 
+	if (ret) 
+		goto out; 
+    src += sizeof(int);
 	while (i) {
 		char *c;
 		char *c2;
 
-		if ((ret = verify_area(VERIFY_READ, (void *) src, sizeof(cfg)))) {
-			restore_flags(flags);
-			return ret;
-		}
-		copy_from_user((char *) &cfg, src, sizeof(cfg));
+		if(copy_from_user((char *) &cfg, src, sizeof(cfg)))
+			goto fault; 
 		src += sizeof(cfg);
 		if (!isdn_net_new(cfg.name, NULL)) {
 			restore_flags(flags);
 			return -EIO;
 		}
-		if ((ret = isdn_net_setcfg(&cfg))) {
-			restore_flags(flags);
-			return ret;
-		}
-		if ((ret = verify_area(VERIFY_READ, (void *) src, sizeof(buf)))) {
-			restore_flags(flags);
-			return ret;
-		}
-		copy_from_user(buf, src, sizeof(buf));
+		if ((ret = isdn_net_setcfg(&cfg))) 
+			goto out; 
+		if(copy_from_user(buf, src, sizeof(buf)))
+			goto fault; 
 		src += sizeof(buf);
 		c = buf;
 		while (*c) {
@@ -1109,20 +1110,15 @@
 			strcpy(phone.phone, c);
 			strcpy(phone.name, cfg.name);
 			phone.outgoing = 0;
-			if ((ret = isdn_net_addphone(&phone))) {
-				restore_flags(flags);
-				return ret;
-			}
+			if ((ret = isdn_net_addphone(&phone))) 
+				goto fault; 
 			if (c2)
 				c = c2;
 			else
 				c += strlen(c);
 		}
-		if ((ret = verify_area(VERIFY_READ, (void *) src, sizeof(buf)))) {
-			restore_flags(flags);
-			return ret;
-		}
-		copy_from_user(buf, src, sizeof(buf));
+   		if(copy_from_user(buf, src, sizeof(buf)))
+			goto fault; 
 		src += sizeof(buf);
 		c = buf;
 		while (*c) {
@@ -1131,10 +1127,8 @@
 			strcpy(phone.phone, c);
 			strcpy(phone.name, cfg.name);
 			phone.outgoing = 1;
-			if ((ret = isdn_net_addphone(&phone))) {
-				restore_flags(flags);
-				return ret;
-			}
+			if ((ret = isdn_net_addphone(&phone))) 
+				goto out; 
 			if (c2)
 				c = c2;
 			else
@@ -1142,8 +1136,12 @@
 		}
 		i--;
 	}
+out:
 	restore_flags(flags);
-	return 0;
+	return ret;
+fault:
+	restore_flags(flags);
+	return -EFAULT;
 }
 
 static int isdn_get_allcfg(char *dest)
@@ -1152,17 +1150,13 @@
 	isdn_net_ioctl_phone phone;
 	isdn_net_dev *p;
 	ulong flags;
-	int ret;
+	int ret = 0;
 
 	/* Walk through netdev-chain */
 	save_flags(flags);
 	cli();
 	p = dev->netdev;
 	while (p) {
-		if ((ret = verify_area(VERIFY_WRITE, (void *) dest, sizeof(cfg) + 10))) {
-			restore_flags(flags);
-			return ret;
-		}
 		strcpy(cfg.eaz, p->local.msn);
 		cfg.exclusive = p->local.exclusive;
 		if (p->local.pre_device >= 0) {
@@ -1179,28 +1173,29 @@
 		cfg.callback = (p->local.flags & ISDN_NET_CALLBACK) ? 1 : 0;
 		cfg.chargehup = (p->local.hupflags & 4) ? 1 : 0;
 		cfg.ihup = (p->local.hupflags & 8) ? 1 : 0;
-		copy_to_user(dest, p->local.name, 10);
+		ret = 0; 
+		ret += copy_to_user(dest, p->local.name, 10);
 		dest += 10;
-		copy_to_user(dest, (char *) &cfg, sizeof(cfg));
+		ret += copy_to_user(dest, (char *) &cfg, sizeof(cfg));
 		dest += sizeof(cfg);
 		strcpy(phone.name, p->local.name);
 		phone.outgoing = 0;
-		if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
-			restore_flags(flags);
-			return ret;
-		} else
+		if (ret)
+			break; 
+		if ((ret = isdn_net_getphones(&phone, dest)) < 0) 
+			break; 
+		else
 			dest += ret;
 		strcpy(phone.name, p->local.name);
 		phone.outgoing = 1;
-		if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
-			restore_flags(flags);
-			return ret;
-		} else
+		if ((ret = isdn_net_getphones(&phone, dest)) < 0) 
+			break; 
+		else
 			dest += ret;
 		p = p->next;
 	}
 	restore_flags(flags);
-	return 0;
+	return ret;
 }
 
 static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
@@ -1209,7 +1204,7 @@
 	isdn_ctrl c;
 	int drvidx;
 	int chidx;
-	int ret;
+	int ret = 0;
 	char *s;
 	char name[10];
 	char bname[21];
@@ -1227,14 +1222,15 @@
                                 if (arg) {
                                         ulong *p = (ulong *)arg;
                                         int i;
-                                        if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
-                                                               sizeof(ulong)*ISDN_MAX_CHANNELS*2)))
-                                                return ret;
                                         for (i = 0;i<ISDN_MAX_CHANNELS;i++) {
-                                                put_fs_long(dev->ibytes[i],p++);
-                                                put_fs_long(dev->obytes[i],p++);
+                                                ret = put_user(dev->ibytes[i],p);
+	                                            if (ret) break; 
+												p++; 
+												ret = put_user(dev->obytes[i],p);
+												p++; 
+												if (ret) break; 
                                         }
-                                        return 0;
+                                        return ret;
                                 } else
                                         return -EINVAL;
                                 break;
@@ -1259,62 +1255,48 @@
                         case IIOCNETAIF:
                                 /* Add a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
-                                                return ret;
-                                        copy_from_user(name, (char *) arg, sizeof(name));
+                                        if(copy_from_user(name, (char *) arg, sizeof(name)))
+											return -EFAULT; 
                                         s = name;
                                 } else
                                         s = NULL;
                                 if ((s = isdn_net_new(s, NULL))) {
-                                        if ((ret = verify_area(VERIFY_WRITE, (void *) arg, strlen(s) + 1)))
-                                                return ret;
-                                        copy_to_user((char *) arg, s, strlen(s) + 1);
-                                        return 0;
+									    return copy_to_user((char *) arg, s, strlen(s) + 1) ? -EFAULT : ret; 
                                 } else
                                         return -ENODEV;
                         case IIOCNETASL:
                                 /* Add a slave to a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(bname))))
-                                                return ret;
-                                        copy_from_user(bname, (char *) arg, sizeof(bname));
+                                        if(copy_from_user(bname, (char *) arg, sizeof(bname)))
+											return -EFAULT; 
                                 } else
                                         return -EINVAL;
                                 if ((s = isdn_net_newslave(bname))) {
-                                        if ((ret = verify_area(VERIFY_WRITE, (void *) arg, strlen(s) + 1)))
-                                                return ret;
-                                        copy_to_user((char *) arg, s, strlen(s) + 1);
-                                        return 0;
+                                        return copy_to_user((char *) arg, s, strlen(s) + 1) ? -EFAULT : 0;
                                 } else
                                         return -ENODEV;
                         case IIOCNETDIF:
                                 /* Delete a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
-                                                return ret;
-                                        copy_from_user(name, (char *) arg, sizeof(name));
-                                        return isdn_net_rm(name);
+                                        ret = copy_from_user(name, (char *) arg, sizeof(name));
+                                        return ret ? -EFAULT : isdn_net_rm(name);
                                 } else
                                         return -EINVAL;
                         case IIOCNETSCF:
                                 /* Set configurable parameters of a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(cfg))))
-                                                return ret;
-                                        copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
-                                        return isdn_net_setcfg(&cfg);
+                                        ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
+                                        return ret ? -EFAULT : isdn_net_setcfg(&cfg);
                                 } else
                                         return -EINVAL;
                         case IIOCNETGCF:
                                 /* Get configurable parameters of a network-interface */
-                                if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(cfg))))
-                                                return ret;
-                                        copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
+                                if (arg) {				  
+                                        if(copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+											return -EFAULT; 
                                         if (!(ret = isdn_net_getcfg(&cfg))) {
-                                                if ((ret = verify_area(VERIFY_WRITE, (void *) arg, sizeof(cfg))))
-                                                        return ret;
-                                                copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg));
+                                                if(copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))
+													return -EFAULT; 
                                         }
                                         return ret;
                                 } else
@@ -1322,68 +1304,51 @@
                         case IIOCNETANM:
                                 /* Add a phone-number to a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
-                                                return ret;
-                                        copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
-                                        return isdn_net_addphone(&phone);
+                                        ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
+                                        return ret ? -EFAULT : isdn_net_addphone(&phone);
                                 } else
                                         return -EINVAL;
                         case IIOCNETGNM:
                                 /* Get list of phone-numbers of a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
-                                                return ret;
-                                        copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
-                                        return isdn_net_getphones(&phone, (char *) arg);
+                                        ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
+                                        return ret ? -EFAULT : isdn_net_getphones(&phone, (char *) arg);
                                 } else
                                         return -EINVAL;
                         case IIOCNETDNM:
                                 /* Delete a phone-number of a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
-                                                return ret;
-                                        copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
-                                        return isdn_net_delphone(&phone);
+                                        ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
+                                        return ret ? -EFAULT : isdn_net_delphone(&phone);
                                 } else
                                         return -EINVAL;
                         case IIOCNETDIL:
                                 /* Force dialing of a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
-                                                return ret;
-                                        copy_from_user(name, (char *) arg, sizeof(name));
-                                        return isdn_net_force_dial(name);
+                                        ret = copy_from_user(name, (char *) arg, sizeof(name));
+                                        return ret ? -EFAULT : isdn_net_force_dial(name);
                                 } else
                                         return -EINVAL;
 #ifdef CONFIG_ISDN_PPP
                         case IIOCNETALN:
-                                if(arg) {
-                                        if ((ret = verify_area(VERIFY_READ,
-                                                               (void*)arg,
-                                                               sizeof(name))))
-                                                return ret;
-                                } else
-                                        return -EINVAL;
-                                copy_from_user(name,(char*)arg,sizeof(name));
-                                return isdn_ppp_dial_slave(name);
+								if (arg) 
+                                        ret = copy_from_user(name,(char*)arg,sizeof(name));
+								else
+									    return -EINVAL; 
+                                return ret ? -EFAULT : isdn_ppp_dial_slave(name);
                         case IIOCNETDLN:
+							    
                                 if(arg) {
-                                        if ((ret = verify_area(VERIFY_READ,
-                                                               (void*)arg,
-                                                               sizeof(name))))
-                                                return ret;
+									    ret = copy_from_user(name,(char*)arg,sizeof(name));
                                 } else
                                         return -EINVAL;
-                                copy_from_user(name,(char*)arg,sizeof(name));
-                                return isdn_ppp_hangup_slave(name);
+                                return ret ? -EFAULT : isdn_ppp_hangup_slave(name);
 #endif
                         case IIOCNETHUP:
                                 /* Force hangup of a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
-                                                return ret;
-                                        copy_from_user(name, (char *) arg, sizeof(name));
-                                        return isdn_net_force_hangup(name);
+                                        ret = copy_from_user(name, (char *) arg, sizeof(name));
+								        return ret ? -EFAULT : isdn_net_force_hangup(name);
                                 } else
                                         return -EINVAL;
                                 break;
@@ -1405,12 +1370,10 @@
                                 if (arg) {
                                         int i;
                                         char *p;
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg,
-                                                               sizeof(isdn_ioctl_struct))))
-                                                return ret;
-                                        copy_from_user((char *) &iocts, (char *) arg,
-                                                      sizeof(isdn_ioctl_struct));
-                                        if (strlen(iocts.drvid)) {
+                                        if(copy_from_user((char *) &iocts, (char *) arg,
+                                                      sizeof(isdn_ioctl_struct)))
+											return -EFAULT; 
+										if (strlen(iocts.drvid)) {
                                                 if ((p = strchr(iocts.drvid, ',')))
                                                         *p = 0;
                                                 drvidx = -1;
@@ -1450,17 +1413,14 @@
                                 if (arg) {
                                         char *p = (char *) arg;
                                         int i;
-                                        
-                                        if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
-                                                               (ISDN_MODEM_ANZREG + ISDN_MSNLEN)
-                                                               * ISDN_MAX_CHANNELS)))
-                                                return ret;
-                                        
+                                                                   
                                         for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                                                copy_to_user(p, dev->mdm.info[i].emu.profile,
-                                                            ISDN_MODEM_ANZREG);
+                                                if(copy_to_user(p, dev->mdm.info[i].emu.profile,
+                                                            ISDN_MODEM_ANZREG))
+													return -EFAULT;
                                                 p += ISDN_MODEM_ANZREG;
-                                                copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN);
+                                                if(copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
+													return -EFAULT; 
                                                 p += ISDN_MSNLEN;
                                         }
                                         return (ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS;
@@ -1473,17 +1433,14 @@
                                         char *p = (char *) arg;
                                         int i;
                                         
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg,
-                                                               (ISDN_MODEM_ANZREG + ISDN_MSNLEN)
-                                                               * ISDN_MAX_CHANNELS)))
-                                                return ret;
-                                        
                                         for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                                                copy_from_user(dev->mdm.info[i].emu.profile, p,
-                                                              ISDN_MODEM_ANZREG);
-                                                p += ISDN_MODEM_ANZREG;
-                                                copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN);
-                                                p += ISDN_MSNLEN;
+                                                if(copy_from_user(dev->mdm.info[i].emu.profile, p,
+                                                              ISDN_MODEM_ANZREG))
+													return -EFAULT; 
+												p += ISDN_MODEM_ANZREG;
+                                                if(copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
+													return -EFAULT; 
+												p += ISDN_MSNLEN;
                                         }
                                         return 0;
                                 } else
@@ -1497,11 +1454,10 @@
                                         char *p;
                                         char nstring[255];
                                         
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg,
-                                                               sizeof(isdn_ioctl_struct))))
-                                                return ret;
-                                        copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
-                                        if (strlen(iocts.drvid)) {
+                                        ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+                      
+										if (ret) return -EFAULT;
+										if (strlen(iocts.drvid)) {
                                                 drvidx = -1;
                                                 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
                                                         if (!(strcmp(dev->drvid[i], iocts.drvid))) {
@@ -1513,9 +1469,8 @@
                                         if (drvidx == -1)
                                                 return -ENODEV;
                                         if (cmd == IIOCSETMAP) {
-                                                if ((ret = verify_area(VERIFY_READ, (void *) iocts.arg, 255)))
-                                                        return ret;
-                                                copy_from_user(nstring, (char *) iocts.arg, 255);
+                                                ret = copy_from_user(nstring, (char *) iocts.arg, 255);
+												if (ret) return -EFAULT; 
                                                 memset(dev->drv[drvidx]->msn2eaz, 0,
                                                        sizeof(dev->drv[drvidx]->msn2eaz));
                                                 p = strtok(nstring, ",");
@@ -1531,21 +1486,16 @@
                                                                      strlen(dev->drv[drvidx]->msn2eaz[i]) ?
                                                                      dev->drv[drvidx]->msn2eaz[i] : "-",
                                                                      (i < 9) ? "," : "\0");
-                                                if ((ret = verify_area(VERIFY_WRITE, (void *) iocts.arg,
-                                                                       strlen(nstring) + 1)))
-                                                        return ret;
-                                                copy_to_user((char *) iocts.arg, nstring, strlen(nstring) + 1);
-                                        }
+												if(copy_to_user((char *) iocts.arg, nstring, strlen(nstring) + 1))
+													return -EFAULT; 
+										}
                                         return 0;
                                 } else
                                         return -EINVAL;
                         case IIOCDBGVAR:
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_WRITE, (void *) arg, sizeof(ulong))))
-                                                return ret;
-                                        copy_to_user((char *) arg, (char *) &dev, sizeof(ulong));
-                                        return 0;
-                                } else
+                                        return copy_to_user((char *) arg, (char *) &dev, sizeof(ulong)) ? -EFAULT : 0;
+								} else
                                         return -EINVAL;
                                 break;
                         default:
@@ -1556,10 +1506,10 @@
                                 if (arg) {
                                         int i;
                                         char *p;
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg,
-                                                               sizeof(isdn_ioctl_struct))))
-                                                return ret;
-                                        copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+
+                                        ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+										if (ret)
+											    return -EFAULT; 
                                         if (strlen(iocts.drvid)) {
                                                 if ((p = strchr(iocts.drvid, ',')))
                                                         *p = 0;
@@ -1573,17 +1523,13 @@
                                                 drvidx = 0;
                                         if (drvidx == -1)
                                                 return -ENODEV;
-                                        if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
-                                                               sizeof(isdn_ioctl_struct))))
-                                                return ret;
                                         c.driver = drvidx;
                                         c.command = ISDN_CMD_IOCTL;
                                         c.arg = cmd;
                                         memcpy(c.num, (char *) &iocts.arg, sizeof(ulong));
                                         ret = dev->drv[drvidx]->interface->command(&c);
                                         memcpy((char *) &iocts.arg, c.num, sizeof(ulong));
-                                        copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct));
-                                        return ret;
+                                        return copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct)) ? -EFAULT : 0;
                                 } else
                                         return -EINVAL;
 		}
@@ -1890,9 +1836,12 @@
                 skb_reserve(skb, dev->drv[drvidx]->interface->hl_hdrlen);
                 skb->free = 1;
 
-                if (user)
-                        copy_from_user(skb_put(skb, len), buf, len);
-                else
+                if (user) {
+					    if(copy_from_user(skb_put(skb, len), buf, len)) {
+						        kfree_skb(skb,FREE_WRITE);
+						        return -EFAULT; 
+						}
+                } else
                         memcpy(skb_put(skb, len), buf, len);
 
                 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx,
diff -u --recursive --new-file v2.1.5/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- v2.1.5/linux/drivers/isdn/isdn_net.c	Wed Oct 16 10:48:16 1996
+++ linux/drivers/isdn/isdn_net.c	Mon Oct 28 20:57:44 1996
@@ -170,14 +170,14 @@
 			p->start = 1;
 			p = (((isdn_net_local *) p->priv)->slave);
 		}
-	}
+ 	}
 
-	isdn_MOD_INC_USE_COUNT();
-	return 0;
-}
+	isdn_MOD_INC_USE_COUNT(); 
+ 	return 0; 
+} 
 
-/*
- * Assign an ISDN-channel to a net-interface
+/* 
+ Assign an ISDN-channel to a net-interface 
  */
 static void
 isdn_net_bind_channel(isdn_net_local * lp, int idx)
@@ -2179,7 +2179,7 @@
 	int count = 0;
 	isdn_net_phone *n;
 	int flags;
-	int ret;
+	int ret = 0;
 
 	if (!p)
 		return -ENODEV;
@@ -2188,22 +2188,22 @@
 	inout &= 1;
         for (n = p->local.phone[inout]; n; n = n->next) {
 		if (more) {
-			put_fs_byte(' ', phones++);
+			ret = put_user(((char)' '), phones);
+			phones++; 
 			count++;
 		}
-		if ((ret = verify_area(VERIFY_WRITE, (void *) phones, strlen(n->num) + 1))) {
+		if (ret || copy_to_user(phones, n->num, strlen(n->num) + 1)) {
 			restore_flags(flags);
-			return ret;
+			return -EFAULT;
 		}
-		copy_to_user(phones, n->num, strlen(n->num) + 1);
 		phones += strlen(n->num);
 		count += strlen(n->num);
 		more = 1;
 	}
-        put_fs_byte(0,phones);
-        count++;
+    ret = put_user(((char)0),phones);  
+    count++;
 	restore_flags(flags);
-	return count;
+	return ret ? -EFAULT : count;
 }
 
 /*
diff -u --recursive --new-file v2.1.5/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.1.5/linux/drivers/isdn/isdn_ppp.c	Wed Oct 16 10:48:16 1996
+++ linux/drivers/isdn/isdn_ppp.c	Mon Oct 28 20:57:45 1996
@@ -345,15 +345,15 @@
 	is->state = 0;
 }
 
+#if 0 /* get_user() / put_user() in 2.1 replace them 1:1 */
 /*
  * get_arg .. ioctl helper
  */
 static int get_arg(void *b, unsigned long *val)
 {
 	int r;
-	if ((r = verify_area(VERIFY_READ, (void *) b, sizeof(unsigned long))))
-		 return r;
-	copy_from_user((void *) val, b, sizeof(unsigned long));
+	if (copy_from_user((void *) val, b, sizeof(unsigned long))) 
+		return -EFAULT; 
 	return 0;
 }
 
@@ -368,6 +368,7 @@
 	copy_to_user(b, (void *) &val, sizeof(unsigned long));
 	return 0;
 }
+#endif
 
 /*
  * ippp device ioctl 
@@ -377,6 +378,7 @@
 	unsigned long val;
 	int r;
 	struct ippp_struct *is;
+	unsigned long *argp = (unsigned long*)arg; 
 
 	is = file->private_data;
 
@@ -389,7 +391,7 @@
 	switch (cmd) {
 	case PPPIOCBUNDLE:
 #ifdef CONFIG_ISDN_MPP
-		if ((r = get_arg((void *) arg, &val)))
+		if ((r = get_user(val, arg)))
 			return r;
 		printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
                         (int) min, (int) is->unit, (int) val);
@@ -399,24 +401,24 @@
 #endif
 		break;
 	case PPPIOCGUNIT:	/* get ppp/isdn unit number */
-		if ((r = set_arg((void *) arg, is->unit)))
+		if ((r = put_user(is->unit, argp)))
 			return r;
 		break;
 	case PPPIOCGMPFLAGS:	/* get configuration flags */
-		if ((r = set_arg((void *) arg, is->mpppcfg)))
+		if ((r = put_user(is->mpppcfg, argp)))
 			return r;
 		break;
 	case PPPIOCSMPFLAGS:	/* set configuration flags */
-		if ((r = get_arg((void *) arg, &val)))
+		if ((r = get_user(val, argp)))
 			return r;
 		is->mpppcfg = val;
 		break;
 	case PPPIOCGFLAGS:	/* get configuration flags */
-		if ((r = set_arg((void *) arg, is->pppcfg)))
+		if ((r = put_user(is->pppcfg ,argp)))
 			return r;
 		break;
 	case PPPIOCSFLAGS:	/* set configuration flags */
-		if ((r = get_arg((void *) arg, &val))) {
+		if ((r = get_user(val, argp))) {
 			return r;
 		}
 		if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP)) {
@@ -433,7 +435,7 @@
 		break;
 #endif
 	case PPPIOCSMRU:	/* set receive unit size for PPP */
-		if ((r = get_arg((void *) arg, &val)))
+		if ((r = get_user(val, argp)))
 			return r;
 		is->mru = val;
 		break;
@@ -442,7 +444,7 @@
 	case PPPIOCSMPMTU:
 		break;
 	case PPPIOCSMAXCID:	/* set the maximum compression slot id */
-		if ((r = get_arg((void *) arg, &val)))
+		if ((r = get_user(val, argp)))
 			return r;
 		val++;
 		if(is->maxcid != val) {
@@ -465,11 +467,11 @@
 		}
 		break;
 	case PPPIOCGDEBUG:
-		if ((r = set_arg((void *) arg, is->debug)))
+		if ((r = put_user(is->debug, argp)))
 			return r;
 		break;
 	case PPPIOCSDEBUG:
-		if ((r = get_arg((void *) arg, &val)))
+		if ((r = get_user(val, argp)))
 			return r;
 		is->debug = val;
 		break;
@@ -594,9 +596,6 @@
 	if (!(is->state & IPPP_OPEN))
 		return 0;
 
-	if ((r = verify_area(VERIFY_WRITE, (void *) buf, count)))
-		return r;
-
 	save_flags(flags);
 	cli();
 
@@ -607,7 +606,8 @@
 	}
 	if (b->len < count)
 		count = b->len;
-	copy_to_user(buf, b->buf, count);
+	if (copy_to_user(buf, b->buf, count)) 
+		count = -EFAULT; /* ugly */
 	kfree(b->buf);
 	b->buf = NULL;
 	is->first = b;
@@ -1447,11 +1447,7 @@
 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
 	int err;
 
-        res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
-        err = verify_area (VERIFY_WRITE, res,sizeof(struct ppp_stats));
-
-	if(err)
-		return err;
+	res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
 
 	/* build a temporary stat struct and copy it to user space */
 
@@ -1475,9 +1471,7 @@
 		}
 #endif
 	}
-	copy_to_user (res, &t, sizeof (struct ppp_stats));
-	return 0;
-
+	return copy_to_user (res, &t, sizeof (struct ppp_stats)) ? -EFAULT : 0;
 }
 
 int isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
@@ -1498,9 +1492,8 @@
 		case SIOCGPPPVER:
 			r = (char *) ifr->ifr_ifru.ifru_data;
 			len = strlen(PPP_VERSION) + 1;
-			error = verify_area(VERIFY_WRITE, r, len);
-			if (!error)
-				copy_to_user(r, PPP_VERSION, len);
+			if (copy_to_user(r, PPP_VERSION, len))
+				error = -EFAULT; 
 			break;
 		case SIOCGPPPSTATS:
 			error = isdn_ppp_dev_ioctl_stats (lp->ppp_slot, ifr, dev);
diff -u --recursive --new-file v2.1.5/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- v2.1.5/linux/drivers/isdn/isdn_tty.c	Wed Oct 16 10:48:16 1996
+++ linux/drivers/isdn/isdn_tty.c	Mon Oct 28 20:57:45 1996
@@ -1013,8 +1013,7 @@
 	status = info->lsr;
 	restore_flags(flags);
 	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-	put_user(result, (ulong *) value);
-	return 0;
+	return put_user(result, (ulong *) value);
 }
 
 
@@ -1035,14 +1034,18 @@
 	    | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
 	    | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
 	    | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-	put_user(result, (ulong *) value);
-	return 0;
+	return put_user(result, (ulong *) value);
 }
 
 static int isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value)
 {
-	uint arg = get_user((uint *) value);
-        int pre_dtr;
+	uint arg;
+    int pre_dtr;
+	int error;
+
+	error = get_user(arg, ((uint *) value));
+	if (error)
+	        return error;
 
 	switch (cmd) {
                 case TIOCMBIS:
@@ -1140,19 +1143,17 @@
 #ifdef ISDN_DEBUG_MODEM_IOCTL
                         printk(KERN_DEBUG "ttyI%d ioctl TIOCGSOFTCAR\n", info->line);
 #endif
-                        error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
-                        if (error)
-                                return error;
-                        put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg);
+                        error = put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg);
+						if (error)
+							    return error;
                         return 0;
                 case TIOCSSOFTCAR:
 #ifdef ISDN_DEBUG_MODEM_IOCTL
                         printk(KERN_DEBUG "ttyI%d ioctl TIOCSSOFTCAR\n", info->line);
 #endif
-                        error = verify_area(VERIFY_READ, (void *) arg, sizeof(long));
-                        if (error)
-                                return error;
-                        arg = get_user((ulong *) arg);
+                        error = get_user(arg ,((ulong *) arg));
+						if (error)
+							    return error;
                         tty->termios->c_cflag =
                                 ((tty->termios->c_cflag & ~CLOCAL) |
                                  (arg ? CLOCAL : 0));
@@ -1161,26 +1162,16 @@
 #ifdef ISDN_DEBUG_MODEM_IOCTL
                         printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
 #endif
-                        error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
-                        if (error)
-                                return error;
                         return isdn_tty_get_modem_info(info, (uint *) arg);
                 case TIOCMBIS:
                 case TIOCMBIC:
                 case TIOCMSET:
-                        error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint));
-                        if (error)
-                                return error;
                         return isdn_tty_set_modem_info(info, cmd, (uint *) arg);
                 case TIOCSERGETLSR:	/* Get line status register */
 #ifdef ISDN_DEBUG_MODEM_IOCTL
                         printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
 #endif
-                        error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
-                        if (error)
-                                return error;
-                        else
-                                return isdn_tty_get_lsr_info(info, (uint *) arg);
+                        return isdn_tty_get_lsr_info(info, (uint *) arg);
                         
                 default:
 #ifdef ISDN_DEBUG_MODEM_IOCTL
@@ -2670,7 +2661,7 @@
 
 	for (cnt = count; cnt > 0; p++, cnt--) {
 		if (user)
-			c = get_user(p);
+		    get_user(c, p);
 		else
 			c = *p;
 		total++;
diff -u --recursive --new-file v2.1.5/linux/drivers/isdn/teles/callc.c linux/drivers/isdn/teles/callc.c
--- v2.1.5/linux/drivers/isdn/teles/callc.c	Sat Jun 29 20:36:23 1996
+++ linux/drivers/isdn/teles/callc.c	Mon Oct 28 20:57:45 1996
@@ -1450,9 +1450,10 @@
 
         ptr += i;
 
-        if (user)
-                memcpy_fromfs(ptr, buf, count);
-        else
+        if (user) {
+                if (copy_from_user(ptr, buf, count))
+					return -EFAULT;
+		} else
                 memcpy(ptr, buf, count);
         ibh->datasize = count + i;
 
diff -u --recursive --new-file v2.1.5/linux/drivers/isdn/teles/card.c linux/drivers/isdn/teles/card.c
--- v2.1.5/linux/drivers/isdn/teles/card.c	Sat Aug 31 19:01:49 1996
+++ linux/drivers/isdn/teles/card.c	Mon Oct 28 21:43:22 1996
@@ -64,6 +64,8 @@
 #include <linux/tqueue.h>
 #include <linux/interrupt.h>
 
+#include <asm/io.h>
+
 #undef DCHAN_VERBOSE
 
 extern void     tei_handler(struct PStack *st, byte pr,
@@ -75,9 +77,9 @@
 #define bytein(addr) inb_p(addr)
 
 static inline   byte
-readisac_0(byte * cardm, byte offset)
+readisac_0(unsigned int cardm, byte offset)
 {
-	return *(byte *) (cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset);
+	return readb(cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset);
 }
 
 static inline   byte
@@ -90,9 +92,9 @@
         ((mbase)?readisac_0(mbase,ofs):readisac_3(ibase,ofs))
 
 static inline void
-writeisac_0(byte * cardm, byte offset, byte value)
+writeisac_0(unsigned int cardm, byte offset, byte value)
 {
-	*(byte *) (cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset) = value;
+	writeb(value, cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset);
 }
 
 static inline void
@@ -117,9 +119,9 @@
 }
 
 static inline   byte
-readhscx_0(byte * base, byte hscx, byte offset)
+readhscx_0(unsigned int base, byte hscx, byte offset)
 {
-	return *(byte *) (base + 0x180 + ((offset & 1) ? 0x1FF : 0) +
+	return readb(base + 0x180 + ((offset & 1) ? 0x1FF : 0) +
 			  ((hscx & 1) ? 0x40 : 0) + offset);
 }
 
@@ -133,10 +135,10 @@
         ((mbase)?readhscx_0(mbase,hscx,ofs):readhscx_3(ibase,hscx,ofs))
 
 static inline void
-writehscx_0(byte * base, byte hscx, byte offset, byte data)
+writehscx_0(unsigned int base, byte hscx, byte offset, byte data)
 {
-	*(byte *) (base + 0x180 + ((offset & 1) ? 0x1FF : 0) +
-		   ((hscx & 1) ? 0x40 : 0) + offset) = data;
+	writeb(data, base + 0x180 + ((offset & 1) ? 0x1FF : 0) +
+		   ((hscx & 1) ? 0x40 : 0) + offset);
 }
 
 static inline void
@@ -199,7 +201,7 @@
 #define HSCX_MASK 0x20
 
 static inline void
-waitforCEC_0(byte * base, byte hscx)
+waitforCEC_0(unsigned int base, byte hscx)
 {
 	long            to = 10;
 
@@ -225,7 +227,7 @@
 }
 
 static inline void
-waitforXFW_0(byte * base, byte hscx)
+waitforXFW_0(unsigned int base, byte hscx)
 {
 	long            to = 20;
 
@@ -251,7 +253,7 @@
 }
 
 static inline void
-writehscxCMDR_0(byte * base, byte hscx, byte data)
+writehscxCMDR_0(unsigned int base, byte hscx, byte data)
 {
 	long            flags;
 
@@ -1059,7 +1061,7 @@
 }
 
 static void
-initisac(byte * cardmem, int iobase)
+initisac(unsigned int cardmem, int iobase)
 {
         if (cardmem) {
                 writeisac_0(cardmem, ISAC_MASK, 0xff);
@@ -1093,17 +1095,17 @@
 	struct IsdnCard *card = cards + cardnr;
 
         if (card->membase)
-                if ((unsigned long)card->membase < 0x10000) {
-                        (unsigned long)card->membase <<= 4;
+                if (card->membase < 0x10000) {
+                        card->membase <<= 4;
                         printk(KERN_INFO
-                               "Teles membase configured DOSish, assuming 0x%lx\n",
-                               (unsigned long)card->membase);
+                               "Teles membase configured DOSish, assuming 0x%x\n",
+                               card->membase);
                 }
         if (!card->iobase) {
                 if (card->membase) {
                         printk(KERN_NOTICE
-                               "Teles 8 assumed, mem: %lx irq: %d proto: %s\n",
-                               (long) card->membase, card->interrupt,
+                               "Teles 8 assumed, mem: %x irq: %d proto: %s\n",
+                               card->membase, card->interrupt,
                                (card->protocol == ISDN_PTYPE_1TR6) ?
                                "1TR6" : "EDSS1");
                         printk(KERN_INFO "HSCX version A:%x B:%x\n",
@@ -1186,7 +1188,7 @@
                         break;
                 }
                 if (card->membase) {
-                        cfval |= (((unsigned int) card->membase >> 9) & 0xF0);
+                        cfval |= (card->membase >> 9) & 0xF0;
                 }   
                 if (bytein(card->iobase + 0) != 0x51) {
                         printk(KERN_INFO "XXX Byte at %x is %x\n",
@@ -1232,8 +1234,8 @@
                 
                 if (card->membase)
                         printk(KERN_NOTICE
-                               "Teles 16.0 found, io: %x mem: %lx irq: %d proto: %s\n",
-                               card->iobase, (long) card->membase,
+                               "Teles 16.0 found, io: %x mem: %x irq: %d proto: %s\n",
+                               card->iobase, card->membase,
                                card->interrupt,
                                (card->protocol == ISDN_PTYPE_1TR6) ?
                                "1TR6" : "EDSS1");
@@ -1253,12 +1255,12 @@
         if (card->membase) {
                 cli();
                 timout = jiffies + (HZ / 5) + 1;
-                *(byte *) (card->membase + 0x80) = 0;
+                writeb(0, card->membase + 0x80);
                 sti();
                 while (jiffies <= timout);
                 
                 cli();
-                *(byte *) (card->membase + 0x80) = 1;
+                writeb(1, card->membase + 0x80);
                 timout = jiffies + (HZ / 5) + 1;
                 sti();
                 while (jiffies <= timout);
diff -u --recursive --new-file v2.1.5/linux/drivers/isdn/teles/config.c linux/drivers/isdn/teles/config.c
--- v2.1.5/linux/drivers/isdn/teles/config.c	Sun Apr 21 11:56:15 1996
+++ linux/drivers/isdn/teles/config.c	Mon Oct 28 21:46:22 1996
@@ -29,20 +29,20 @@
 
 struct IsdnCard cards[] =
 {
-	{(byte *) 0xd0000, 15, 0xd80, ISDN_PTYPE_EURO, NULL},	/* example */
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
-	{NULL, 0, 0, 0, NULL},
+	{0xd0000, 15, 0xd80, ISDN_PTYPE_EURO, NULL},	/* example */
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
+	{0, 0, 0, 0, NULL},
 };
diff -u --recursive --new-file v2.1.5/linux/drivers/isdn/teles/llglue.c linux/drivers/isdn/teles/llglue.c
--- v2.1.5/linux/drivers/isdn/teles/llglue.c	Fri Jun  7 16:02:42 1996
+++ linux/drivers/isdn/teles/llglue.c	Mon Oct 28 20:57:46 1996
@@ -46,9 +46,10 @@
 	byte           *p;
 
 	for (p = buf, count = 0; count < len; p++, count++) {
-		if (user)
-			put_fs_byte(*teles_status_read++, p);
-		else
+		if (user) {
+			put_user(*teles_status_read, p);
+			teles_status_read++; 
+		} else
 			*p++ = *teles_status_read++;
 		if (teles_status_read > teles_status_end)
 			teles_status_read = teles_status_buf;
diff -u --recursive --new-file v2.1.5/linux/drivers/isdn/teles/mod.c linux/drivers/isdn/teles/mod.c
--- v2.1.5/linux/drivers/isdn/teles/mod.c	Sun Apr 21 11:56:15 1996
+++ linux/drivers/isdn/teles/mod.c	Mon Oct 28 21:44:46 1996
@@ -14,7 +14,7 @@
 int             nrcards;
 
 typedef struct {
-	byte           *membase;
+	unsigned int	membase;
 	int             interrupt;
 	unsigned int    iobase;
 	unsigned int    protocol;
@@ -73,7 +73,7 @@
                         j++; argc--;
                 }
                 if (argc) {
-                        io[i].membase   = (byte *)ints[j];
+                        io[i].membase   = ints[j];
                         j++; argc--;
                 }
                 if (argc) {
diff -u --recursive --new-file v2.1.5/linux/drivers/isdn/teles/teles.h linux/drivers/isdn/teles/teles.h
--- v2.1.5/linux/drivers/isdn/teles/teles.h	Sun May 19 15:29:31 1996
+++ linux/drivers/isdn/teles/teles.h	Mon Oct 28 21:48:39 1996
@@ -14,8 +14,6 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/major.h>
-#include <asm/segment.h>
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
@@ -28,6 +26,9 @@
 #include <linux/isdnif.h>
 #include <linux/tty.h>
 
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
 #define PH_ACTIVATE   1
 #define PH_DATA       2
 #define PH_DEACTIVATE 3
@@ -306,7 +307,7 @@
 };
 
 struct HscxState {
-	byte           *membase;
+	unsigned int	membase;
 	int             iobase;
 	int             inuse, init, active;
 	struct BufPool  sbufpool, rbufpool, smallpool;
@@ -329,7 +330,7 @@
 #ifdef DEBUG_MAGIC
 	int             magic;
 #endif
-	byte           *membase;
+	unsigned int	membase;
 	int             iobase;
 	struct BufPool  sbufpool, rbufpool, smallpool;
 	struct PStack  *stlist;
@@ -351,7 +352,7 @@
 };
 
 struct IsdnCard {
-	byte           *membase;
+	unsigned int	membase;
 	int             interrupt;
 	unsigned int    iobase;
 	int             protocol;	/* EDSS1 or 1TR6 */
diff -u --recursive --new-file v2.1.5/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.1.5/linux/drivers/net/3c59x.c	Thu Jul 18 10:08:45 1996
+++ linux/drivers/net/3c59x.c	Tue Oct 29 16:25:06 1996
@@ -315,7 +315,7 @@
 
 	root_vortex_dev = NULL;
 	cards_found = vortex_scan(0);
-	return cards_found < 0 ? cards_found : 0;
+	return cards_found ? 0 : -ENODEV;
 }
 
 #else
diff -u --recursive --new-file v2.1.5/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.1.5/linux/drivers/net/8390.c	Sat May 18 11:15:09 1996
+++ linux/drivers/net/8390.c	Mon Oct 28 14:29:23 1996
@@ -48,7 +48,7 @@
 #include <linux/ptrace.h>
 #include <linux/string.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.1.5/linux/drivers/net/Makefile	Thu Oct 10 19:10:55 1996
+++ linux/drivers/net/Makefile	Tue Oct 29 15:33:38 1996
@@ -416,6 +416,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_SCC),y)
+L_OBJS += scc.o
+else
+  ifeq ($(CONFIG_SCC),m)
+  M_OBJS += scc.o
+  endif
+endif
+
 ifeq ($(CONFIG_PI),y)
 L_OBJS += pi2.o
 endif
diff -u --recursive --new-file v2.1.5/linux/drivers/net/README.scc linux/drivers/net/README.scc
--- v2.1.5/linux/drivers/net/README.scc	Thu Jan  1 02:00:00 1970
+++ linux/drivers/net/README.scc	Tue Oct 29 15:33:38 1996
@@ -0,0 +1,23 @@
+
+You will find subset of the documentation in
+
+                 linux/Documentation/networking/z8530drv.txt
+
+To use this driver you MUST have the full package from:
+
+Internet:
+=========
+
+1. db0bm.automation.fh-aachen.de/incoming/dl1bke/z8530drv-utils-3.0.tar.gz
+
+2. ftp.ucsd.edu:/hamradio/packet/tcpip/incoming/z8530drv-utils-3.0.tar.gz
+   If you can't find it there, try .../tcpip/linux/z8530drv-utils-3.0.tar.gz
+
+and various mirrors (i.e. nic.switch.ch)
+
+The package includes the utilities necessary to initialize and
+control the driver.
+
+Joerg Reuter	ampr-net: dl1bke@db0pra.ampr.org
+		AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
+		Internet: jreuter@lykos.oche.de
diff -u --recursive --new-file v2.1.5/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
--- v2.1.5/linux/drivers/net/arcnet.c	Tue Aug  6 12:58:35 1996
+++ linux/drivers/net/arcnet.c	Sat Oct 19 10:36:38 1996
@@ -17,6 +17,14 @@
          
 	**********************
 	
+	v2.56 (96/10/18)
+	  - Turned arc0e/arc0s startup messages back on by default, as most
+	    people will probably not notice the additional devices
+	    otherwise, and experience more protocol confusion than
+	    necessary.
+	  - Fixed a tiny but noticeable bug in the packet debugging routines
+	    (thanks Tomasz)
+
 	v2.55 (96/08/05)
 	  - A couple more messages moved to D_EXTRA.
 	  - SLOW_XMIT_COPY off by default.
@@ -202,7 +210,7 @@
 */
 
 static const char *version =
- "arcnet.c: v2.55 96/08/05 Avery Pennarun <apenwarr@foxnet.net>\n";
+ "arcnet.c: v2.56 96/10/18 Avery Pennarun <apenwarr@foxnet.net>\n";
 
  
 
@@ -708,8 +716,7 @@
         {
 		if (i%16==0)
 			printk("\n" KERN_DEBUG "[%04X] ",i);
-		else
-                       	printk("%02X ",((u_char *)skb->data)[i]);
+               	printk("%02X ",((u_char *)skb->data)[i]);
 	}
         printk("\n");
         restore_flags(flags);
@@ -731,8 +738,7 @@
 	{
 		if (i%16==0)
 			printk("\n" KERN_DEBUG "[%04X] ",i);
-		else
-			printk("%02X ",buffer[i]);
+		printk("%02X ",buffer[i]);
 	}
 	printk("\n");
 	restore_flags(flags);
@@ -754,6 +760,8 @@
  * NOTE: the list of possible ports/shmems is static, so it is retained
  * across calls to arcnet_probe.  So, if more than one ARCnet probe is made,
  * values that were discarded once will not even be tried again.
+ *
+ * FIXME: grab all devices in one shot and eliminate the big static array.
  */
 int arcnet_probe(struct device *dev)
 {
@@ -775,9 +783,8 @@
 			ports[(count-0x200)/16] = count;
 		for (count=0xA0000; count<=0xFF800; count+=2048)
 			shmems[(count-0xA0000)/2048] = count;
-	}
-	else
 		init_once=1;
+	}
 
 	BUGLVL(D_NORMAL) printk(version);
 
@@ -1370,7 +1377,7 @@
 	
 	/* The RFC1201 driver is the default - just store */
 	lp->adev=dev;
-	BUGMSG(D_EXTRA,"ARCnet RFC1201 protocol initialized.\n");
+	BUGMSG(D_NORMAL,"ARCnet RFC1201 protocol initialized.\n");
 
 #ifdef CONFIG_ARCNET_ETH	
 	/* Initialize the ethernet-encap protocol driver */
@@ -1388,7 +1395,7 @@
 	lp->edev->init=arcnetE_init;
 	register_netdev(lp->edev);
 #else
-	BUGMSG(D_EXTRA,"Ethernet-Encap protocol not available (disabled).\n");
+	BUGMSG(D_NORMAL,"Ethernet-Encap protocol not available (disabled).\n");
 #endif
 
 #ifdef CONFIG_ARCNET_1051
@@ -1400,7 +1407,7 @@
 	lp->sdev->init=arcnetS_init;
 	register_netdev(lp->sdev);
 #else
-	BUGMSG(D_EXTRA,"RFC1051 protocol not available (disabled).\n");
+	BUGMSG(D_NORMAL,"RFC1051 protocol not available (disabled).\n");
 #endif
 
 	/* we're started */
@@ -2781,7 +2788,7 @@
 	dev->stop=arcnetE_open_close;
 	dev->hard_start_xmit=arcnetE_send_packet;
 
-	BUGMSG(D_EXTRA,"ARCnet Ethernet-Encap protocol initialized.\n");
+	BUGMSG(D_NORMAL,"ARCnet Ethernet-Encap protocol initialized.\n");
 			
 	return 0;
 }
@@ -2961,7 +2968,7 @@
 	dev->hard_start_xmit=arcnetS_send_packet;
 	dev->hard_header=arcnetS_header;
 	dev->rebuild_header=arcnetS_rebuild_header;
-	BUGMSG(D_EXTRA,"ARCnet RFC1051 (NetBSD, AmiTCP) protocol initialized.\n");
+	BUGMSG(D_NORMAL,"ARCnet RFC1051 (NetBSD, AmiTCP) protocol initialized.\n");
 
 	return 0;
 }
@@ -3241,10 +3248,10 @@
 	
 	
 static int io=0x0;	/* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
-static int irqnum=0;	/* or use the insmod io= irqnum= shmem= options */
+static int irqnum=0;	/* or use the insmod io= irq= shmem= options */
 static int irq=0;
 static int shmem=0;
-static char *device = NULL;
+static char *device = NULL;	/* use eg. device="arc1" to change name */
 
 int
 init_module(void)
@@ -3304,15 +3311,3 @@
 }
 
 #endif /* MODULE */
-
-
-
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c arcnet.c"
- *  version-control: t
- *  kept-new-versions: 5
- *  tab-width: 8
- * End:
- */
-
diff -u --recursive --new-file v2.1.5/linux/drivers/net/bsd_comp.c linux/drivers/net/bsd_comp.c
--- v2.1.5/linux/drivers/net/bsd_comp.c	Sat Sep 28 10:55:22 1996
+++ linux/drivers/net/bsd_comp.c	Mon Oct 28 14:29:23 1996
@@ -76,7 +76,7 @@
 
 #include <asm/system.h>
 #include <asm/bitops.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
 #include <linux/if.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- v2.1.5/linux/drivers/net/de4x5.c	Wed Oct 16 10:48:17 1996
+++ linux/drivers/net/de4x5.c	Mon Oct 28 14:29:23 1996
@@ -234,7 +234,7 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/net/depca.c linux/drivers/net/depca.c
--- v2.1.5/linux/drivers/net/depca.c	Wed Oct 16 10:48:17 1996
+++ linux/drivers/net/depca.c	Mon Oct 28 14:29:23 1996
@@ -221,7 +221,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c
--- v2.1.5/linux/drivers/net/ewrk3.c	Wed Oct 16 10:48:18 1996
+++ linux/drivers/net/ewrk3.c	Mon Oct 28 14:29:23 1996
@@ -154,7 +154,7 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/net/loopback.c linux/drivers/net/loopback.c
--- v2.1.5/linux/drivers/net/loopback.c	Mon May 27 13:12:19 1996
+++ linux/drivers/net/loopback.c	Mon Oct 28 14:29:23 1996
@@ -39,7 +39,7 @@
 #include <linux/in.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 #include <linux/inet.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/net/pi2.c linux/drivers/net/pi2.c
--- v2.1.5/linux/drivers/net/pi2.c	Wed Oct 16 10:48:18 1996
+++ linux/drivers/net/pi2.c	Mon Oct 28 14:29:23 1996
@@ -109,7 +109,7 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.1.5/linux/drivers/net/ppp.c	Sat Oct 19 10:07:31 1996
+++ linux/drivers/net/ppp.c	Mon Oct 28 14:29:23 1996
@@ -76,7 +76,7 @@
 #include <linux/signal.h>	/* used in new tty drivers */
 #include <asm/system.h>
 #include <asm/bitops.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/net/pt.c linux/drivers/net/pt.c
--- v2.1.5/linux/drivers/net/pt.c	Wed Oct 16 10:48:18 1996
+++ linux/drivers/net/pt.c	Mon Oct 28 14:29:23 1996
@@ -79,7 +79,7 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/net/scc.c linux/drivers/net/scc.c
--- v2.1.5/linux/drivers/net/scc.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/net/scc.c	Tue Oct 29 16:35:48 1996
@@ -0,0 +1,2287 @@
+#define RCS_ID "$Id: scc.c,v 1.63 1996/10/09 16:45:47 jreuter Exp jreuter $"
+
+#define VERSION "3.0"
+#define BANNER  "Z8530 SCC driver version "VERSION".dl1bke (experimental) by DL1BKE\n"
+
+/*
+ * Please use z8530drv-utils-3.0 with this version.
+ *            ------------------
+ */
+
+/*
+   ********************************************************************
+   *   SCC.C - Linux driver for Z8530 based HDLC cards for AX.25      *
+   ********************************************************************
+
+
+   ********************************************************************
+
+	Copyright (c) 1993, 1996 Joerg Reuter DL1BKE
+
+	portions (c) 1993 Guido ten Dolle PE1NNZ
+
+   ********************************************************************
+   
+   The driver and the programs in the archive are UNDER CONSTRUCTION.
+   The code is likely to fail, and so your kernel could --- even 
+   a whole network. 
+
+   This driver is intended for Amateur Radio use. If you are running it
+   for commercial purposes, please drop me a note. I am nosy...
+
+   ...BUT:
+ 
+   ! You  m u s t  recognize the appropriate legislations of your country !
+   ! before you connect a radio to the SCC board and start to transmit or !
+   ! receive. The GPL allows you to use the  d r i v e r,  NOT the RADIO! !
+
+   For non-Amateur-Radio use please note that you might need a special
+   allowance/licence from the designer of the SCC Board and/or the
+   MODEM. 
+
+   This program is free software; you can redistribute it and/or modify 
+   it under the terms of the (modified) GNU General Public License 
+   delivered with the Linux kernel source.
+   
+   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 find a copy of the GNU General Public License in 
+   /usr/src/linux/COPYING; 
+   
+   ******************************************************************** 
+
+		
+   Incomplete history of z8530drv:
+   -------------------------------
+
+   940913	- started to write the driver, rescued most of my own
+		  code (and Hans Alblas' memory buffer pool concept) from 
+		  an earlier project "sccdrv" which was initiated by 
+		  Guido ten Dolle. Not much of the old driver survived, 
+		  though. The first version I put my hands on was sccdrv1.3
+		  from August 1993. The memory buffer pool concept
+		  appeared in an unauthorized sccdrv version (1.5) from
+		  August 1994.
+
+   950131	- changed copyright notice to GPL without limitations.
+   
+     .
+     .	<SNIP>
+     .
+   		  
+   961005	- New semester, new driver... 
+
+   		  * KISS TNC emulator removed (TTY driver)
+   		  * Source moved to drivers/net/
+   		  * Includes Z8530 defines from drivers/net/z8530.h
+   		  * Uses sk_buffer memory management
+   		  * Doesn't have own queues anymore
+   		  * Reduced overhead of /proc/net/z8530drv output
+   		  * Streamlined quite a lot things
+   		  * Invents brand new bugs... ;-)
+
+   		  The move to version number 3.0 reflects theses changes.
+   		  You can use version 2.4 if you need a KISS TNC emulator.
+
+   Thanks to all who contributed to this driver with ideas and bug
+   reports!
+   
+   NB -- if you find errors, change something, please let me know
+      	 first before you distribute it... And please don't touch
+   	 the version number. Just replace my callsign in
+   	 "v3.0.dl1bke" with your own. Just to avoid confusion...
+
+   If you want to add your modification to the linux distribution
+   please (!) contact me first.
+   
+   New versions of the driver will be announced on the linux-hams
+   mailing list on vger.rutgers.edu. To subscribe send an e-mail
+   to majordomo@vger.rutgers.edu with the following line in
+   the body of the mail:
+   
+	   subscribe linux-hams
+	   
+   The content of the "Subject" field will be ignored.
+
+   vy 73,
+   Joerg Reuter	ampr-net: dl1bke@db0pra.ampr.org
+		AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
+		Internet: jreuter@lykos.oche.de  
+*/
+
+/* ----------------------------------------------------------------------- */
+
+#undef  SCC_DELAY 	/* perhaps your ISA bus is a *bit* too fast? */
+#undef  SCC_LDELAY 1	/* slow it even a bit more down */
+#undef  DONT_CHECK	/* don't look if the SCCs you specified are available */
+
+#define MAXSCC          4       /* number of max. supported chips */
+#define BUFSIZE         384     /* must not exceed 4096 */
+#undef  DISABLE_ALL_INTS	/* use cli()/sti() in ISR instead of */
+				/* enable_irq()/disable_irq()        */
+#undef	SCC_DEBUG
+
+#define DEFAULT_CLOCK	4915200 /* default pclock if nothing is specified */
+
+/* ----------------------------------------------------------------------- */
+
+#include <linux/module.h>
+#include <linux/config.h>
+
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/in.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <linux/socket.h>
+
+#include <linux/scc.h>
+#include "z8530.h"
+
+#include <net/ax25.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+
+#ifdef MODULE
+int init_module(void);
+void cleanup_module(void);
+#endif
+
+int scc_init(void);
+
+static void t_dwait(unsigned long);
+static void t_txdelay(unsigned long);
+static void t_tail(unsigned long);
+static void t_busy(unsigned long);
+static void t_maxkeyup(unsigned long);
+static void t_idle(unsigned long);
+static void scc_tx_done(struct scc_channel *);
+static void scc_start_tx_timer(struct scc_channel *, void (*)(unsigned long), unsigned long);
+static void scc_start_maxkeyup(struct scc_channel *);
+static void scc_start_defer(struct scc_channel *);
+
+static void z8530_init(void);
+
+static void init_channel(struct scc_channel *scc);
+static void scc_key_trx (struct scc_channel *scc, char tx);
+static void scc_isr(int irq, void *dev_id, struct pt_regs *regs);
+static void scc_init_timer(struct scc_channel *scc);
+
+static int scc_net_setup(struct scc_channel *scc, unsigned char *name);
+static int scc_net_init(struct device *dev);
+static int scc_net_open(struct device *dev);
+static int scc_net_close(struct device *dev);
+static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb);
+static int scc_net_tx(struct sk_buff *skb, struct device *dev);
+static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
+static int scc_net_set_mac_address(struct device *dev, void *addr);
+static int scc_net_rebuild_header(void *buff, struct device *dev, unsigned long raddr, struct sk_buff *skb);
+static int scc_net_header(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len);
+static struct enet_statistics * scc_net_get_stats(struct device *dev);
+
+static unsigned char *SCC_DriverName = "scc";
+
+static struct irqflags { unsigned char used : 1; } Ivec[16];
+	
+static struct scc_channel SCC_Info[2 * MAXSCC];	/* information per channel */
+
+static struct scc_ctrl {
+	io_port chan_A;
+	io_port chan_B;
+	int irq;
+} SCC_ctrl[MAXSCC+1];
+
+static unsigned char Driver_Initialized = 0;
+static int Nchips = 0;
+static io_port Vector_Latch = 0;
+
+
+/* ******************************************************************** */
+/* *			Port Access Functions			      * */
+/* ******************************************************************** */
+
+/* These provide interrupt save 2-step access to the Z8530 registers */
+
+static __inline__ unsigned char
+InReg(io_port port, unsigned char reg)
+{
+	unsigned long flags;
+	unsigned char r;
+	
+	save_flags(flags);
+	cli();
+#ifdef SCC_LDELAY
+	Outb(port, reg);
+	udelay(SCC_LDELAY);
+	r=Inb(port);
+	udelay(SCC_LDELAY);
+#else
+	Outb(port, reg);
+	r=Inb(port);
+#endif
+	restore_flags(flags);
+	return r;
+}
+
+static __inline__ void
+OutReg(io_port port, unsigned char reg, unsigned char val)
+{
+	unsigned long flags;
+	
+	save_flags(flags);
+	cli();
+#ifdef SCC_LDELAY
+	Outb(port, reg); udelay(SCC_LDELAY);
+	Outb(port, val); udelay(SCC_LDELAY);
+#else
+	Outb(port, reg);
+	Outb(port, val);
+#endif
+	restore_flags(flags);
+}
+
+static __inline__ void
+wr(struct scc_channel *scc, unsigned char reg, unsigned char val)
+{
+	OutReg(scc->ctrl, reg, (scc->wreg[reg] = val));
+}
+
+static __inline__ void
+or(struct scc_channel *scc, unsigned char reg, unsigned char val)
+{
+	OutReg(scc->ctrl, reg, (scc->wreg[reg] |= val));
+}
+
+static __inline__ void
+cl(struct scc_channel *scc, unsigned char reg, unsigned char val)
+{
+	OutReg(scc->ctrl, reg, (scc->wreg[reg] &= ~val));
+}
+
+#ifdef DISABLE_ALL_INTS
+static __inline__ void scc_cli(int irq)
+{ cli(); }
+static __inline__ void scc_sti(int irq)
+{ sti(); }
+#else
+static __inline__ void scc_cli(int irq)
+{ disable_irq(irq); }
+static __inline__ void scc_sti(int irq)
+{ enable_irq(irq); }
+#endif
+
+/* ******************************************************************** */
+/* *			Some useful macros			      * */
+/* ******************************************************************** */
+
+
+static __inline__ void
+scc_lock_dev(struct scc_channel *scc)
+{
+	scc->dev->tbusy = 1;
+}
+
+static __inline__ void
+scc_unlock_dev(struct scc_channel *scc)
+{
+	scc->tx_next_buff = NULL;
+	scc->dev->tbusy = 0;
+}
+
+static __inline__ void
+scc_discard_buffers(struct scc_channel *scc)
+{
+	unsigned long flags;
+	
+	save_flags(flags);
+	cli();
+	
+	if (scc->tx_buff != NULL)
+	{
+		dev_kfree_skb(scc->tx_buff, FREE_WRITE);
+		scc->tx_buff = NULL;
+	}
+	
+	if (scc->tx_next_buff != NULL)
+	{
+		dev_kfree_skb(scc->tx_next_buff, FREE_WRITE);
+		scc->tx_next_buff = NULL;
+	}
+	
+	restore_flags(flags);
+}
+
+
+
+/* ******************************************************************** */
+/* *			Interrupt Service Routines		      * */
+/* ******************************************************************** */
+
+
+/* ----> subroutines for the interrupt handlers <---- */
+
+static __inline__ void
+scc_notify(struct scc_channel *scc, int event)
+{
+	struct sk_buff *skb;
+	char *bp;
+	
+        if (scc->kiss.fulldup != KISS_DUPLEX_OPTIMA)
+		return;
+
+	skb = dev_alloc_skb(2);
+	if (skb != NULL)
+	{
+		skb->free = 1;
+		bp = skb_put(skb, 2);
+		*bp++ = PARAM_HWEVENT;
+		*bp++ = event;
+		scc_net_rx(scc, skb);
+	} else
+		scc->stat.nospace++;
+}
+
+static __inline__ void
+flush_rx_FIFO(struct scc_channel *scc)
+{
+	int k;
+	
+	for (k=0; k<3; k++)
+		Inb(scc->data);
+		
+	if(scc->rx_buff != NULL)		/* did we receive something? */
+	{
+		scc->stat.rxerrs++;  /* then count it as an error */
+		kfree_skb(scc->rx_buff, FREE_READ);
+		scc->rx_buff = NULL;
+	}
+}
+
+
+/* ----> four different interrupt handlers for Tx, Rx, changing of	*/
+/*       DCD/CTS and Rx/Tx errors					*/
+
+/* Transmitter interrupt handler */
+static __inline__ void
+scc_txint(struct scc_channel *scc)
+{
+	struct sk_buff *skb;
+
+	scc->stat.txints++;
+	skb = scc->tx_buff;
+	
+	/* send first octet */
+	
+	if (skb == NULL)
+	{
+		skb = scc->tx_next_buff;
+		scc->tx_buff = skb;
+
+		if (skb == NULL)
+		{
+			scc_tx_done(scc);
+			Outb(scc->ctrl, RES_Tx_P);
+			return;
+		}
+		
+		if (skb->len == 0)		/* Paranoia... */
+		{
+			dev_kfree_skb(skb, FREE_WRITE);
+			scc->tx_buff = NULL;
+			scc_tx_done(scc);
+			Outb(scc->ctrl, RES_Tx_P);
+			return;
+		}
+		
+		scc_unlock_dev(scc);
+
+		scc->stat.tx_state = TXS_ACTIVE;
+
+		OutReg(scc->ctrl, R0, RES_Tx_CRC);
+						/* reset CRC generator */
+		or(scc,R10,ABUNDER);		/* re-install underrun protection */
+		Outb(scc->data,*skb->data);	/* send byte */
+		skb_pull(skb, 1);
+
+		if (!scc->enhanced)		/* reset EOM latch */
+			Outb(scc->ctrl,RES_EOM_L);
+		return;
+	}
+	
+	/* End Of Frame... */
+	
+	if (skb->len == 0)
+	{
+		Outb(scc->ctrl, RES_Tx_P);	/* reset pending int */
+		cl(scc, R10, ABUNDER);		/* send CRC */
+		dev_kfree_skb(skb, FREE_WRITE);
+		scc->tx_buff = NULL;
+		scc->stat.tx_state = TXS_NEWFRAME; /* next frame... */
+		return;
+	} 
+	
+	/* send octet */
+	
+	Outb(scc->data,*skb->data);		
+	skb_pull(skb, 1);
+}
+
+
+/* External/Status interrupt handler */
+static __inline__ void
+scc_exint(struct scc_channel *scc)
+{
+	unsigned char status,changes,chg_and_stat;
+
+	scc->stat.exints++;
+
+	status = InReg(scc->ctrl,R0);
+	changes = status ^ scc->status;
+	chg_and_stat = changes & status;
+	
+	/* ABORT: generated whenever DCD drops while receiving */
+
+	if (chg_and_stat & BRK_ABRT)		/* Received an ABORT */
+		flush_rx_FIFO(scc);
+
+
+	/* DCD: on = start to receive packet, off = ABORT condition */
+	/* (a successfully received packet generates a special condition int) */
+	
+	if(changes & DCD)                       /* DCD input changed state */
+	{
+		if(status & DCD)                /* DCD is now ON */
+		{
+			if (scc->modem.clocksrc != CLK_EXTERNAL)
+				OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
+				
+			or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
+		} else {                        /* DCD is now OFF */
+			cl(scc,R3,ENT_HM|RxENABLE); /* disable the receiver */
+			flush_rx_FIFO(scc);
+		}
+		
+		if (!scc->kiss.softdcd)
+			scc_notify(scc, (status & DCD)? HWEV_DCD_ON:HWEV_DCD_OFF);
+	}
+	
+	/* HUNT: software DCD; on = waiting for SYNC, off = receiving frame */
+	
+	if (changes & SYNC_HUNT)
+	{
+		if (scc->kiss.softdcd)
+			scc_notify(scc, (status & SYNC_HUNT)? HWEV_DCD_OFF:HWEV_DCD_ON);
+		else
+			cl(scc,R15,SYNCIE);	/* oops, we were too lazy to disable this? */
+	}
+
+#ifdef notdef
+	/* CTS: use external TxDelay (what's that good for?!)
+	 * Anyway: If we _could_ use it (BayCom USCC uses CTS for
+	 * own purposes) we _should_ use the "autoenable" feature
+	 * of the Z8530 and not this interrupt...
+	 */
+	 
+	if (chg_and_stat & CTS)			/* CTS is now ON */
+	{
+		if (scc->kiss.txdelay == 0)	/* zero TXDELAY = wait for CTS */
+			scc_start_tx_timer(scc, t_txdelay, 0);
+	}
+#endif
+	
+	if (scc->stat.tx_state == TXS_ACTIVE && (status & TxEOM))
+	{
+		scc->stat.tx_under++;	  /* oops, an underrun! count 'em */
+		Outb(scc->ctrl, RES_EXT_INT);	/* reset ext/status interrupts */
+
+		if (scc->tx_buff != NULL)
+		{
+			dev_kfree_skb(scc->tx_buff, FREE_WRITE);
+			scc->tx_buff = NULL;
+		}
+		
+		or(scc,R10,ABUNDER);
+		scc_start_tx_timer(scc, t_txdelay, 1);	/* restart transmission */
+	}
+		
+	scc->status = status;
+	Outb(scc->ctrl,RES_EXT_INT);
+}
+
+
+/* Receiver interrupt handler */
+static __inline__ void
+scc_rxint(struct scc_channel *scc)
+{
+	struct sk_buff *skb;
+
+	scc->stat.rxints++;
+
+	if((scc->wreg[5] & RTS) && scc->kiss.fulldup == KISS_DUPLEX_HALF)
+	{
+		Inb(scc->data);		/* discard char */
+		or(scc,R3,ENT_HM);	/* enter hunt mode for next flag */
+		return;
+	}
+
+	skb = scc->rx_buff;
+	
+	if (skb == NULL)
+	{
+		skb = dev_alloc_skb(scc->stat.bufsize);
+		if (skb == NULL)
+		{
+			scc->dev_stat.rx_dropped++;
+			scc->stat.nospace++;
+			Inb(scc->data);
+			or(scc, R3, ENT_HM);
+			return;
+		}
+		
+		skb->free = 1;
+		scc->rx_buff = skb;
+		
+		*(skb_put(skb, 1)) = 0;	/* KISS data */
+	}
+	
+	if (skb->len >= scc->stat.bufsize)
+	{
+#ifdef notdef
+		printk(KERN_DEBUG "z8530drv: oops, scc_rxint() received huge frame...\n");
+#endif
+		kfree_skb(skb, FREE_READ);
+		scc->rx_buff = NULL;
+		Inb(scc->data);
+		or(scc, R3, ENT_HM);
+		return;
+	}
+
+	*(skb_put(skb, 1)) = Inb(scc->data);
+}
+
+
+/* Receive Special Condition interrupt handler */
+static __inline__ void
+scc_spint(struct scc_channel *scc)
+{
+	unsigned char status;
+	struct sk_buff *skb;
+
+	scc->stat.spints++;
+
+	status = InReg(scc->ctrl,R1);		/* read receiver status */
+	
+	Inb(scc->data);				/* throw away Rx byte */
+	skb = scc->rx_buff;
+
+	if(status & Rx_OVR)			/* receiver overrun */
+	{
+		scc->stat.rx_over++;             /* count them */
+		or(scc,R3,ENT_HM);               /* enter hunt mode for next flag */
+		
+		if (skb != NULL) 
+			kfree_skb(skb, FREE_READ);
+		scc->rx_buff = NULL;
+	}
+
+	if(status & END_FR && skb != NULL)	/* end of frame */
+	{
+		/* CRC okay, frame ends on 8 bit boundary and received something ? */
+		
+		if (!(status & CRC_ERR) && (status & 0xe) == RES8 && skb->len > 0)
+		{
+			/* ignore last received byte (first of the CRC bytes) */
+			skb_trim(skb, skb->len-1);
+			scc_net_rx(scc, skb);
+			scc->rx_buff = NULL;
+			scc->stat.rxframes++;
+		} else {				/* a bad frame */
+			kfree_skb(skb, FREE_READ);
+			scc->rx_buff = NULL;
+			scc->stat.rxerrs++;
+		}
+	} 
+
+	Outb(scc->ctrl,ERR_RES);
+}
+
+
+/* ----> interrupt service routine for the Z8530 <---- */
+
+static void
+scc_isr_dispatch(struct scc_channel *scc, int vector)
+{
+	switch (vector & VECTOR_MASK)
+	{
+		case TXINT: scc_txint(scc); break;
+		case EXINT: scc_exint(scc); break;
+		case RXINT: scc_rxint(scc); break;
+		case SPINT: scc_spint(scc); break;
+	}
+}
+
+/* If the card has a latch for the interrupt vector (like the PA0HZP card)
+   use it to get the number of the chip that generated the int.
+   If not: poll all defined chips.
+ */
+
+#define SCC_IRQTIMEOUT 30000
+
+static void
+scc_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned char vector;	
+	struct scc_channel *scc;
+	struct scc_ctrl *ctrl;
+	int k;
+	
+	scc_cli(irq);
+
+	if (Vector_Latch)
+	{
+	    	for(k=0; k < SCC_IRQTIMEOUT; k++)
+    		{
+			Outb(Vector_Latch, 0);      /* Generate INTACK */
+        
+			/* Read the vector */
+			if((vector=Inb(Vector_Latch)) >= 16 * Nchips) break; 
+			if (vector & 0x01) break;
+        	 
+		        scc=&SCC_Info[vector >> 3 ^ 0x01];
+			if (!scc->dev) break;
+
+			scc_isr_dispatch(scc, vector);
+
+			OutReg(scc->ctrl,R0,RES_H_IUS);              /* Reset Highest IUS */
+		}  
+		scc_sti(irq);
+
+		if (k == SCC_IRQTIMEOUT)
+			printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?\n");
+
+		return;
+	}
+
+	/* Find the SCC generating the interrupt by polling all attached SCCs
+	 * reading RR3A (the interrupt pending register)
+	 */
+
+	ctrl = SCC_ctrl;
+	while (ctrl->chan_A)
+	{
+		if (ctrl->irq != irq)
+		{
+			ctrl++;
+			continue;
+		}
+
+		scc = NULL;
+		for (k = 0; InReg(ctrl->chan_A,R3) && k < SCC_IRQTIMEOUT; k++)
+		{
+			vector=InReg(ctrl->chan_B,R2);	/* Read the vector */
+			if (vector & 0x01) break; 
+
+			scc = &SCC_Info[vector >> 3 ^ 0x01];
+		        if (!scc->dev) break;
+
+			scc_isr_dispatch(scc, vector);
+		}
+
+		if (k == SCC_IRQTIMEOUT)
+		{
+			printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?!\n");
+			break;
+		}
+
+		/* This looks wierd and it is. At least the BayCom USCC doesn't
+		 * use the Interrupt Daisy Chain, thus we'll have to start
+		 * all over again to be sure not to miss an interrupt from 
+		 * (any of) the other chip(s)...
+		 * Honestly, the situation *is* braindamaged...
+		 */
+
+		if (scc != NULL)
+		{
+			OutReg(scc->ctrl,R0,RES_H_IUS);
+			ctrl = SCC_ctrl; 
+		} else
+			ctrl++;
+	}
+	
+	scc_sti(irq);
+}
+
+
+
+/* ******************************************************************** */
+/* *			Init Channel					*/
+/* ******************************************************************** */
+
+
+/* ----> set SCC channel speed <---- */
+
+static __inline__ void 
+set_brg(struct scc_channel *scc, unsigned int tc)
+{
+	cl(scc,R14,BRENABL);		/* disable baudrate generator */
+	wr(scc,R12,tc & 255);		/* brg rate LOW */
+	wr(scc,R13,tc >> 8);   		/* brg rate HIGH */
+	or(scc,R14,BRENABL);		/* enable baudrate generator */
+}
+
+static __inline__ void 
+set_speed(struct scc_channel *scc)
+{
+	disable_irq(scc->irq);
+
+	if (scc->modem.speed > 0)	/* paranoia... */
+		set_brg(scc, (unsigned) (scc->clock / (scc->modem.speed * 64)) - 2);
+
+	enable_irq(scc->irq);
+}
+
+
+/* ----> initialize a SCC channel <---- */
+
+static __inline__ void 
+init_brg(struct scc_channel *scc)
+{
+	wr(scc, R14, BRSRC);				/* BRG source = PCLK */
+	OutReg(scc->ctrl, R14, SSBR|scc->wreg[R14]);	/* DPLL source = BRG */
+	OutReg(scc->ctrl, R14, SNRZI|scc->wreg[R14]);	/* DPLL NRZI mode */
+}
+
+/*
+ * Initialization according to the Z8530 manual (SGS-Thomson's version):
+ *
+ * 1. Modes and constants
+ *
+ * WR9	11000000	chip reset
+ * WR4	XXXXXXXX	Tx/Rx control, async or sync mode
+ * WR1	0XX00X00	select W/REQ (optional)
+ * WR2	XXXXXXXX	program interrupt vector
+ * WR3	XXXXXXX0	select Rx control
+ * WR5	XXXX0XXX	select Tx control
+ * WR6	XXXXXXXX	sync character
+ * WR7	XXXXXXXX	sync character
+ * WR9	000X0XXX	select interrupt control
+ * WR10	XXXXXXXX	miscellaneous control (optional)
+ * WR11	XXXXXXXX	clock control
+ * WR12	XXXXXXXX	time constant lower byte (optional)
+ * WR13	XXXXXXXX	time constant upper byte (optional)
+ * WR14	XXXXXXX0	miscellaneous control
+ * WR14	XXXSSSSS	commands (optional)
+ *
+ * 2. Enables
+ *
+ * WR14	000SSSS1	baud rate enable
+ * WR3	SSSSSSS1	Rx enable
+ * WR5	SSSS1SSS	Tx enable
+ * WR0	10000000	reset Tx CRG (optional)
+ * WR1	XSS00S00	DMA enable (optional)
+ *
+ * 3. Interrupt status
+ *
+ * WR15	XXXXXXXX	enable external/status
+ * WR0	00010000	reset external status
+ * WR0	00010000	reset external status twice
+ * WR1	SSSXXSXX	enable Rx, Tx and Ext/status
+ * WR9	000SXSSS	enable master interrupt enable
+ *
+ * 1 = set to one, 0 = reset to zero
+ * X = user defined, S = same as previous init
+ *
+ *
+ * Note that the implementation differs in some points from above scheme.
+ *
+ */
+ 
+static void
+init_channel(struct scc_channel *scc)
+{
+	disable_irq(scc->irq);
+	
+	if (scc->tx_t.next)    del_timer(&scc->tx_t);
+	if (scc->tx_wdog.next) del_timer(&scc->tx_wdog);
+
+	wr(scc,R4,X1CLK|SDLC);		/* *1 clock, SDLC mode */
+	wr(scc,R1,0);			/* no W/REQ operation */
+	wr(scc,R3,Rx8|RxCRC_ENAB);	/* RX 8 bits/char, CRC, disabled */	
+	wr(scc,R5,Tx8|DTR|TxCRC_ENAB);	/* TX 8 bits/char, disabled, DTR */
+	wr(scc,R6,0);			/* SDLC address zero (not used) */
+	wr(scc,R7,FLAG);		/* SDLC flag value */
+	wr(scc,R9,VIS);			/* vector includes status */
+	wr(scc,R10,(scc->modem.nrz? NRZ : NRZI)|CRCPS|ABUNDER); /* abort on underrun, preset CRC generator, NRZ(I) */
+	wr(scc,R14, 0);
+
+
+/* set clock sources:
+
+   CLK_DPLL: normal halfduplex operation
+   
+		RxClk: use DPLL
+		TxClk: use DPLL
+		TRxC mode DPLL output
+		
+   CLK_EXTERNAL: external clocking (G3RUH or DF9IC modem)
+   
+  	        BayCom: 		others:
+  	        
+  	        TxClk = pin RTxC	TxClk = pin TRxC
+  	        RxClk = pin TRxC 	RxClk = pin RTxC
+  	     
+
+   CLK_DIVIDER:
+   		RxClk = use DPLL
+   		TxClk = pin RTxC
+   		
+   		BayCom:			others:
+   		pin TRxC = DPLL		pin TRxC = BRG
+   		(RxClk * 1)		(RxClk * 32)
+*/  
+
+   		
+	switch(scc->modem.clocksrc)
+	{
+		case CLK_DPLL:
+			wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
+			init_brg(scc);
+			break;
+
+		case CLK_DIVIDER:
+			wr(scc, R11, ((scc->brand & BAYCOM)? TRxCDP : TRxCBR) | RCDPLL|TCRTxCP|TRxCOI);
+			init_brg(scc);
+			break;
+
+		case CLK_EXTERNAL:
+			wr(scc, R11, (scc->brand & BAYCOM)? RCTRxCP|TCRTxCP : RCRTxCP|TCTRxCP);
+			OutReg(scc->ctrl, R14, DISDPLL);
+			break;
+
+	}
+	
+	set_speed(scc);			/* set baudrate */
+	
+	if(scc->enhanced)
+	{
+		or(scc,R15,SHDLCE|FIFOE);	/* enable FIFO, SDLC/HDLC Enhancements (From now R7 is R7') */
+		wr(scc,R7,AUTOEOM);
+	}
+
+	if((InReg(scc->ctrl,R0)) & DCD)		/* DCD is now ON */
+	{
+		if (scc->modem.clocksrc != CLK_EXTERNAL)
+			or(scc,R14, SEARCH);
+			
+		or(scc,R3,ENT_HM|RxENABLE);	/* enable the receiver, hunt mode */
+	}
+	
+	/* enable ABORT, DCD & SYNC/HUNT interrupts */
+
+	wr(scc,R15, BRKIE|TxUIE|DCDIE);
+	if (scc->kiss.softdcd)
+		or(scc,R15, SYNCIE);
+
+	Outb(scc->ctrl,RES_EXT_INT);	/* reset ext/status interrupts */
+	Outb(scc->ctrl,RES_EXT_INT);	/* must be done twice */
+
+	or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
+	
+	scc->status = InReg(scc->ctrl,R0);	/* read initial status */
+	
+	or(scc,R9,MIE);			/* master interrupt enable */
+	
+	scc_init_timer(scc);
+			
+	enable_irq(scc->irq);
+}
+
+
+
+
+/* ******************************************************************** */
+/* *			SCC timer functions			      * */
+/* ******************************************************************** */
+
+
+/* ----> scc_key_trx sets the time constant for the baudrate 
+         generator and keys the transmitter		     <---- */
+
+static void
+scc_key_trx(struct scc_channel *scc, char tx)
+{
+	unsigned int time_const;
+		
+	if (scc->brand & PRIMUS)
+		Outb(scc->ctrl + 4, scc->option | (tx? 0x80 : 0));
+
+	if (scc->modem.speed < 300) 
+		scc->modem.speed = 1200;
+
+	time_const = (unsigned) (scc->clock / (scc->modem.speed * (tx? 2:64))) - 2;
+
+	disable_irq(scc->irq);
+
+	if (tx)
+	{
+		or(scc, R1, TxINT_ENAB);	/* t_maxkeyup may have reset these */
+		or(scc, R15, TxUIE);
+	}
+
+	if (scc->modem.clocksrc == CLK_DPLL)
+	{				/* force simplex operation */
+		if (tx)
+		{
+			cl(scc, R3, RxENABLE|ENT_HM);	/* switch off receiver */
+			cl(scc, R15, DCDIE);		/* No DCD changes, please */
+			set_brg(scc, time_const);	/* reprogram baudrate generator */
+
+			/* DPLL -> Rx clk, BRG -> Tx CLK, TRxC mode output, TRxC = BRG */
+			wr(scc, R11, RCDPLL|TCBR|TRxCOI|TRxCBR);
+			
+			or(scc,R5,RTS|TxENAB);		/* set the RTS line and enable TX */
+		} else {
+			cl(scc,R5,RTS|TxENAB);
+			
+			set_brg(scc, time_const);	/* reprogram baudrate generator */
+			
+			/* DPLL -> Rx clk, DPLL -> Tx CLK, TRxC mode output, TRxC = DPLL */
+			wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
+			
+			or(scc,R3,RxENABLE|ENT_HM);
+			or(scc,R15, DCDIE);
+		}
+	} else {
+		if (tx)
+		{
+			if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
+			{
+				cl(scc, R3, RxENABLE);
+				cl(scc, R15, DCDIE);
+			}
+				
+				
+			or(scc,R5,RTS|TxENAB);		/* enable tx */
+		} else {
+			cl(scc,R5,RTS|TxENAB);		/* disable tx */
+			
+			if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
+			{
+				or(scc, R3, RxENABLE|ENT_HM);
+				or(scc, R15, DCDIE);
+			}
+		}
+	}
+
+	enable_irq(scc->irq);
+}
+
+
+/* ----> SCC timer interrupt handler and friends. <---- */
+
+static void 
+scc_start_tx_timer(struct scc_channel *scc, void (*handler)(unsigned long), unsigned long when)
+{
+	unsigned long flags;
+	
+	save_flags(flags);
+	cli();
+
+	if (scc->tx_t.next) 
+		del_timer(&scc->tx_t);
+
+	if (when == 0)
+	{
+		handler((unsigned long) scc);
+	} else 
+	if (when != TIMER_OFF)
+	{
+		scc->tx_t.data = (unsigned long) scc;
+		scc->tx_t.function = handler;
+		scc->tx_t.expires = jiffies + (when*HZ)/100;
+		add_timer(&scc->tx_t);
+	}
+	
+	restore_flags(flags);	
+}
+
+static void
+scc_start_defer(struct scc_channel *scc)
+{
+	unsigned long flags;
+	
+	save_flags(flags);
+	cli();
+
+	if (scc->tx_wdog.next)
+		del_timer(&scc->tx_wdog);
+	
+	if (scc->kiss.maxdefer != 0 && scc->kiss.maxdefer != TIMER_OFF)
+	{
+		scc->tx_wdog.data = (unsigned long) scc;
+		scc->tx_wdog.function = t_busy;
+		scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxdefer;
+		add_timer(&scc->tx_wdog);
+	}
+	restore_flags(flags);
+}
+
+static void
+scc_start_maxkeyup(struct scc_channel *scc)
+{
+	unsigned long flags;
+	
+	save_flags(flags);
+	cli();
+
+	if (scc->tx_wdog.next)
+		del_timer(&scc->tx_wdog);
+	
+	if (scc->kiss.maxkeyup != 0 && scc->kiss.maxkeyup != TIMER_OFF)
+	{
+		scc->tx_wdog.data = (unsigned long) scc;
+		scc->tx_wdog.function = t_maxkeyup;
+		scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxkeyup;
+		add_timer(&scc->tx_wdog);
+	}
+	
+	restore_flags(flags);
+}
+
+/* 
+ * This is called from scc_txint() when there are no more frames to send.
+ * Not exactly a timer function, but it is a close friend of the family...
+ */
+
+static void
+scc_tx_done(struct scc_channel *scc)
+{
+	/* 
+	 * trx remains keyed in fulldup mode 2 until t_idle expires.
+	 */
+				 
+	switch (scc->kiss.fulldup)
+	{
+		case KISS_DUPLEX_LINK:
+			scc->stat.tx_state = TXS_IDLE2;
+			if (scc->kiss.idletime != TIMER_OFF)
+			scc_start_tx_timer(scc, t_idle, scc->kiss.idletime*100);
+			break;
+		case KISS_DUPLEX_OPTIMA:
+			scc_notify(scc, HWEV_ALL_SENT);
+			break;
+		default:
+			scc->stat.tx_state = TXS_BUSY;
+			scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
+	}
+
+	scc_unlock_dev(scc);
+}
+
+
+static unsigned char Rand = 17;
+
+static __inline__ int 
+is_grouped(struct scc_channel *scc)
+{
+	int k;
+	struct scc_channel *scc2;
+	unsigned char grp1, grp2;
+
+	grp1 = scc->kiss.group;
+	
+	for (k = 0; k < (Nchips * 2); k++)
+	{
+		scc2 = &SCC_Info[k];
+		grp2 = scc2->kiss.group;
+		
+		if (scc2 == scc || !(scc2->dev && grp2))
+			continue;
+		
+		if ((grp1 & 0x3f) == (grp2 & 0x3f))
+		{
+			if ( (grp1 & TXGROUP) && (scc2->wreg[R5] & RTS) )
+				return 1;
+			
+			if ( (grp1 & RXGROUP) && (scc2->status & DCD) )
+				return 1;
+		}
+	}
+	return 0;
+}
+
+/* DWAIT and SLOTTIME expired
+ *
+ * fulldup == 0:  DCD is active or Rand > P-persistence: start t_busy timer
+ *                else key trx and start txdelay
+ * fulldup == 1:  key trx and start txdelay
+ * fulldup == 2:  mintime expired, reset status or key trx and start txdelay
+ */
+
+static void 
+t_dwait(unsigned long channel)
+{
+	struct scc_channel *scc = (struct scc_channel *) channel;
+	
+	if (scc->stat.tx_state == TXS_WAIT)	/* maxkeyup or idle timeout */
+	{
+		if (scc->tx_next_buff == NULL)	/* nothing to send */
+		{
+			scc->stat.tx_state = TXS_IDLE;
+			scc_unlock_dev(scc);	/* t_maxkeyup locked it. */
+			return;
+		}
+
+		scc->stat.tx_state = TXS_BUSY;
+	}
+
+	if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
+	{
+		Rand = Rand * 17 + 31;
+		
+		if ( (scc->kiss.softdcd? !(scc->status & SYNC_HUNT):(scc->status & DCD))  || (scc->kiss.persist) < Rand || (scc->kiss.group && is_grouped(scc)) )
+		{
+			scc_start_defer(scc);
+			scc_start_tx_timer(scc, t_dwait, scc->kiss.slottime);
+			return ;
+		}
+	}
+
+	if ( !(scc->wreg[R5] & RTS) )
+	{
+		scc_key_trx(scc, TX_ON);
+		scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);
+	} else {
+		scc_start_tx_timer(scc, t_txdelay, 0);
+	}
+}
+
+
+/* TXDELAY expired
+ *
+ * kick transmission by a fake scc_txint(scc), start 'maxkeyup' watchdog.
+ */
+
+static void 
+t_txdelay(unsigned long channel)
+{
+	struct scc_channel *scc = (struct scc_channel *) channel;
+
+	scc_start_maxkeyup(scc);
+
+	if (scc->tx_buff == NULL)
+	{
+		disable_irq(scc->irq);
+		scc_txint(scc);	
+		enable_irq(scc->irq);
+	}
+}
+	
+
+/* TAILTIME expired
+ *
+ * switch off transmitter. If we were stopped by Maxkeyup restart
+ * transmission after 'mintime' seconds
+ */
+
+static void 
+t_tail(unsigned long channel)
+{
+	struct scc_channel *scc = (struct scc_channel *) channel;
+	unsigned long flags;
+	
+ 	save_flags(flags);
+ 	cli();
+ 
+ 	if (scc->tx_wdog.next)
+ 		del_timer(&scc->tx_wdog);
+ 		
+ 	scc_key_trx(scc, TX_OFF);
+
+ 	restore_flags(flags);
+
+ 	if (scc->stat.tx_state == TXS_TIMEOUT)		/* we had a timeout? */
+ 	{
+ 		scc->stat.tx_state = TXS_WAIT;
+
+ 		if (scc->kiss.mintime != TIMER_OFF)	/* try it again */
+ 			scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);
+ 		else
+ 			scc_start_tx_timer(scc, t_dwait, 0);
+ 		return;
+ 	}
+ 	
+ 	scc->stat.tx_state = TXS_IDLE;
+	scc_unlock_dev(scc);
+}
+
+
+/* BUSY timeout
+ *
+ * throw away send buffers if DCD remains active too long.
+ */
+
+static void 
+t_busy(unsigned long channel)
+{
+	struct scc_channel *scc = (struct scc_channel *) channel;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	
+	if (scc->tx_t.next)
+		del_timer(&scc->tx_t);
+
+	restore_flags(flags);
+	
+	scc_lock_dev(scc);
+
+	scc_discard_buffers(scc);
+
+	scc->stat.txerrs++;
+	scc->stat.tx_state = TXS_IDLE;
+	
+	scc_unlock_dev(scc);
+}
+
+/* MAXKEYUP timeout
+ *
+ * this is our watchdog.
+ */
+
+static void 
+t_maxkeyup(unsigned long channel)
+{
+	struct scc_channel *scc = (struct scc_channel *) channel;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+
+	/* 
+	 * let things settle down before we start to
+	 * accept new data.
+	 */
+
+	scc_lock_dev(scc);
+	scc_discard_buffers(scc);
+
+	if (scc->tx_t.next)
+		del_timer(&scc->tx_t);
+
+	cl(scc, R1, TxINT_ENAB);	/* force an ABORT, but don't */
+	cl(scc, R15, TxUIE);		/* count it. */
+	OutReg(scc->ctrl, R0, RES_Tx_P);
+
+	restore_flags(flags);
+
+	scc->stat.txerrs++;
+	scc->stat.tx_state = TXS_TIMEOUT;
+	scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
+}
+
+/* IDLE timeout
+ *
+ * in fulldup mode 2 it keys down the transmitter after 'idle' seconds
+ * of inactivity. We will not restart transmission before 'mintime'
+ * expires.
+ */
+
+static void 
+t_idle(unsigned long channel)
+{
+	struct scc_channel *scc = (struct scc_channel *) channel;
+	unsigned long flags;
+	
+	save_flags(flags);
+	cli();
+	
+	if (scc->tx_wdog.next)
+		del_timer(&scc->tx_wdog);
+
+	restore_flags(flags);
+	
+	scc_key_trx(scc, TX_OFF);
+
+	if (scc->kiss.mintime != TIMER_OFF)
+		scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);
+	scc->stat.tx_state = TXS_WAIT;
+}
+
+static void
+scc_init_timer(struct scc_channel *scc)
+{
+	unsigned long flags;
+	
+	save_flags(flags); 
+	cli();
+	
+	scc->stat.tx_state = TXS_IDLE;
+
+	restore_flags(flags);
+}
+
+
+/* ******************************************************************** */
+/* *			Set/get L1 parameters			      * */
+/* ******************************************************************** */
+
+
+/*
+ * this will set the "hardware" parameters through KISS commands or ioctl()
+ */
+
+#define CAST(x) (unsigned long)(x)
+
+static unsigned int
+scc_set_param(struct scc_channel *scc, unsigned int cmd, unsigned int arg)
+{
+	int dcd;
+
+	switch (cmd)
+	{
+		case PARAM_TXDELAY:	scc->kiss.txdelay=arg;		break;
+		case PARAM_PERSIST:	scc->kiss.persist=arg;		break;
+		case PARAM_SLOTTIME:	scc->kiss.slottime=arg;		break;
+		case PARAM_TXTAIL:	scc->kiss.tailtime=arg;		break;
+		case PARAM_FULLDUP:	scc->kiss.fulldup=arg;		break;
+		case PARAM_DTR:		break; /* does someone need this? */
+		case PARAM_GROUP:	scc->kiss.group=arg;		break;
+		case PARAM_IDLE:	scc->kiss.idletime=arg;		break;
+		case PARAM_MIN:		scc->kiss.mintime=arg;		break;
+		case PARAM_MAXKEY:	scc->kiss.maxkeyup=arg;		break;
+		case PARAM_WAIT:	scc->kiss.waittime=arg;		break;
+		case PARAM_MAXDEFER:	scc->kiss.maxdefer=arg;		break;
+		case PARAM_TX:		scc->kiss.tx_inhibit=arg;	break;
+
+		case PARAM_SOFTDCD:	
+			scc->kiss.softdcd=arg;
+			if (arg)
+				or(scc, R15, SYNCIE);
+			else
+				cl(scc, R15, SYNCIE);
+			break;
+				
+		case PARAM_SPEED:
+			if (arg < 256)
+				scc->modem.speed=arg*100;
+			else
+				scc->modem.speed=arg;
+
+			if (scc->stat.tx_state == 0)	/* only switch baudrate on rx... ;-) */
+				set_speed(scc);
+			break;
+			
+		case PARAM_RTS:	
+			if ( !(scc->wreg[R5] & RTS) )
+			{
+				if (arg != TX_OFF)
+					scc_key_trx(scc, TX_ON);
+					scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);
+			} else {
+				if (arg == TX_OFF)
+				{
+					scc->stat.tx_state = TXS_BUSY;
+					scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
+				}
+			}
+			break;
+			
+		case PARAM_HWEVENT:
+			dcd = (scc->kiss.softdcd? !(scc->status & SYNC_HUNT):(scc->status & DCD));
+			scc_notify(scc, dcd? HWEV_DCD_ON:HWEV_DCD_OFF);
+			break;
+
+		default:		return -EINVAL;
+	}
+	
+	return 0;
+}
+
+
+ 
+static unsigned long
+scc_get_param(struct scc_channel *scc, unsigned int cmd)
+{
+	switch (cmd)
+	{
+		case PARAM_TXDELAY:	return CAST(scc->kiss.txdelay);
+		case PARAM_PERSIST:	return CAST(scc->kiss.persist);
+		case PARAM_SLOTTIME:	return CAST(scc->kiss.slottime);
+		case PARAM_TXTAIL:	return CAST(scc->kiss.tailtime);
+		case PARAM_FULLDUP:	return CAST(scc->kiss.fulldup);
+		case PARAM_SOFTDCD:	return CAST(scc->kiss.softdcd);
+		case PARAM_DTR:		return CAST((scc->wreg[R5] & DTR)? 1:0);
+		case PARAM_RTS:		return CAST((scc->wreg[R5] & RTS)? 1:0);
+		case PARAM_SPEED:	return CAST(scc->modem.speed);
+		case PARAM_GROUP:	return CAST(scc->kiss.group);
+		case PARAM_IDLE:	return CAST(scc->kiss.idletime);
+		case PARAM_MIN:		return CAST(scc->kiss.mintime);
+		case PARAM_MAXKEY:	return CAST(scc->kiss.maxkeyup);
+		case PARAM_WAIT:	return CAST(scc->kiss.waittime);
+		case PARAM_MAXDEFER:	return CAST(scc->kiss.maxdefer);
+		case PARAM_TX:		return CAST(scc->kiss.tx_inhibit);
+		default:		return NO_SUCH_PARAM;
+	}
+
+}
+
+#undef CAST
+#undef SVAL
+
+/* ******************************************************************* */
+/* *		Init channel structures, special HW, etc...	     * */
+/* ******************************************************************* */
+
+/*
+ * Reset the Z8530s and setup special hardware
+ */
+
+static void
+z8530_init(void)
+{
+	struct scc_channel *scc;
+	int chip, k;
+	unsigned long flags;
+	char *flag;
+
+
+	printk(KERN_INFO "Init Z8530 driver: %u channels, IRQ", Nchips*2);
+	
+	flag=" ";
+	for (k = 0; k < 16; k++)
+		if (Ivec[k].used) 
+		{
+			printk("%s%d", flag, k);
+			flag=",";
+		}
+	printk("\n");
+
+
+	/* reset and pre-init all chips in the system */
+	for (chip = 0; chip < Nchips; chip++)
+	{
+		scc=&SCC_Info[2*chip];
+		if (!scc->ctrl) continue;
+
+		/* Special SCC cards */
+
+		if(scc->brand & EAGLE)			/* this is an EAGLE card */
+			Outb(scc->special,0x08);	/* enable interrupt on the board */
+			
+		if(scc->brand & (PC100 | PRIMUS))	/* this is a PC100/PRIMUS card */
+			Outb(scc->special,scc->option);	/* set the MODEM mode (0x22) */
+
+			
+		/* Reset and pre-init Z8530 */
+
+		save_flags(flags);
+		cli();
+		
+		Outb(scc->ctrl, 0);
+		OutReg(scc->ctrl,R9,FHWRES);		/* force hardware reset */
+		udelay(100);				/* give it 'a bit' more time than required */
+		wr(scc, R2, chip*16);			/* interrupt vector */
+		wr(scc, R9, VIS);			/* vector includes status */
+		
+        	restore_flags(flags);
+        }
+
+ 
+	Driver_Initialized = 1;
+}
+
+/*
+ * Allocate device structure, err, instance, and register driver
+ */
+
+static int 
+scc_net_setup(struct scc_channel *scc, unsigned char *name)
+{
+	unsigned char *buf;
+	struct device *dev;
+
+	if (dev_get(name) != NULL)
+	{
+		printk(KERN_INFO "Z8530drv: device %s already exists.\n", name);
+		return -EEXIST;
+	}
+
+	if ((scc->dev = (struct device *) kmalloc(sizeof(struct device), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+
+	dev = scc->dev;
+	memset(dev, 0, sizeof(struct device));
+
+	buf = (unsigned char *) kmalloc(10, GFP_KERNEL);
+	strcpy(buf, name);
+
+	dev->priv = (void *) scc;
+	dev->name = buf;
+	dev->init = scc_net_init;
+
+	if (register_netdev(dev) != 0)
+	{
+		kfree(dev);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+
+
+/* ******************************************************************** */
+/* *			    Network driver methods		      * */
+/* ******************************************************************** */
+
+static unsigned char ax25_bcast[AX25_ADDR_LEN] =
+{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
+static unsigned char ax25_nocall[AX25_ADDR_LEN] =
+{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
+
+/* ----> Initialize device <----- */
+
+static int 
+scc_net_init(struct device *dev)
+{
+	int k;
+
+	for (k=0; k < DEV_NUMBUFFS; k++)
+		skb_queue_head_init(&dev->buffs[k]);
+	dev->tx_queue_len    = 16;	/* should be enough... */
+
+	dev->open            = scc_net_open;
+	dev->stop	     = scc_net_close;
+
+	dev->hard_start_xmit = scc_net_tx;
+	dev->hard_header     = scc_net_header;
+	dev->rebuild_header  = scc_net_rebuild_header;
+	dev->set_mac_address = scc_net_set_mac_address;
+	dev->get_stats       = scc_net_get_stats;
+	dev->do_ioctl        = scc_net_ioctl;
+
+	memcpy(dev->broadcast, ax25_bcast,  AX25_ADDR_LEN);
+	memcpy(dev->dev_addr,  ax25_nocall, AX25_ADDR_LEN);
+ 
+	dev->flags      = 0;
+	dev->family     = AF_INET;
+	dev->pa_addr    = 0;
+	dev->pa_brdaddr = 0;
+	dev->pa_mask    = 0;
+	dev->pa_alen    = 4;
+
+	dev->type = ARPHRD_AX25;
+	dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
+	dev->mtu = AX25_DEF_PACLEN;
+	dev->addr_len = AX25_ADDR_LEN;
+
+	return 0;
+}
+
+/* ----> open network device <---- */
+
+static int 
+scc_net_open(struct device *dev)
+{
+	struct scc_channel *scc = (struct scc_channel *) dev->priv;
+
+	if (scc == NULL || scc->magic != SCC_MAGIC)
+		return -ENODEV;
+
+ 	if (!scc->init)
+		return -EINVAL;
+
+	MOD_INC_USE_COUNT;
+	
+	scc->tx_buff = scc->tx_next_buff = NULL;
+ 
+	init_channel(scc);
+
+	dev->tbusy = 0;
+	dev->start = 1;
+
+	return 0;
+}
+
+/* ----> close network device <---- */
+
+static int 
+scc_net_close(struct device *dev)
+{
+	struct scc_channel *scc = (struct scc_channel *) dev->priv;
+	unsigned long flags;
+
+	if (scc == NULL || scc->magic != SCC_MAGIC)
+		return -ENODEV;
+
+	MOD_DEC_USE_COUNT;
+
+	save_flags(flags); 
+	cli();
+	
+	Outb(scc->ctrl,0);		/* Make sure pointer is written */
+	wr(scc,R1,0);			/* disable interrupts */
+	wr(scc,R3,0);
+
+	del_timer(&scc->tx_t);
+	del_timer(&scc->tx_wdog);
+
+	restore_flags(flags);
+	
+	scc_discard_buffers(scc);
+
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	return 0;
+}
+
+/* ----> receive frame, called from scc_rxint() <---- */
+
+static void 
+scc_net_rx(struct scc_channel *scc, struct sk_buff *skb)
+{
+	if (skb->len == 0)
+	{
+		kfree_skb(skb, FREE_READ);
+		return;
+	}
+		
+	scc->dev_stat.rx_packets++;
+
+	skb->dev      = scc->dev;
+	skb->protocol = htons(ETH_P_AX25);
+	skb->mac.raw  = skb->data;
+	
+	netif_rx(skb);
+	return;
+}
+
+/* ----> transmit frame <---- */
+
+static int 
+scc_net_tx(struct sk_buff *skb, struct device *dev)
+{
+	struct scc_channel *scc = (struct scc_channel *) dev->priv;
+	unsigned long flags;
+	char kisscmd;
+	long ticks;
+	
+	if (dev->tbusy)
+	{
+		ticks = (signed) (jiffies - dev->trans_start);
+
+		if (ticks < scc->kiss.maxdefer*HZ || scc == NULL)
+			return 1;
+
+		/* 
+		 * Throw away transmission queue. 
+		 */
+
+		if (scc->tx_wdog.next)
+			del_timer(&scc->tx_wdog);
+		t_busy((unsigned long) scc);
+                dev->trans_start = jiffies;
+        }
+        
+	if (skb == NULL)
+	{
+		dev_tint(dev);
+		return 0;
+	}
+	
+	if (scc == NULL || scc->magic != SCC_MAGIC)
+	{
+		dev_kfree_skb(skb, FREE_WRITE);
+		return 0;
+	}
+
+	if (skb->len > scc->stat.bufsize || skb->len < 2)
+	{
+		scc->dev_stat.tx_dropped++;	/* bogus frame */
+		dev_kfree_skb(skb, FREE_WRITE);
+		return 0;
+	}
+	
+	scc->dev_stat.tx_packets++;
+	scc->stat.txframes++;
+	
+	kisscmd = *skb->data & 0x1f;
+	skb_pull(skb, 1);
+
+	if (kisscmd)
+	{
+		scc_set_param(scc, kisscmd, *skb->data);
+		dev_kfree_skb(skb, FREE_WRITE);
+		return 0;
+	}
+
+	save_flags(flags);
+	cli();
+	
+	scc_lock_dev(scc);
+	
+	if (scc->tx_next_buff != NULL)
+	{
+		printk(KERN_ERR "z8530drv: race condition, discarding frame\n");
+		dev_kfree_skb(skb, FREE_WRITE);
+		scc_lock_dev(scc);
+		restore_flags(flags);
+		return 0;
+	}
+	
+	dev->trans_start = jiffies;
+	scc->tx_next_buff = skb;
+
+	/*
+	 * Start transmission if the trx state is idle or
+	 * t_idle hasn't expired yet. Use dwait/persistance/slottime
+	 * algorithm for normal halfduplex operation.
+	 */
+
+	if(scc->stat.tx_state == TXS_IDLE || scc->stat.tx_state == TXS_IDLE2)
+	{
+		scc->stat.tx_state = TXS_BUSY;
+		if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
+			scc_start_tx_timer(scc, t_dwait, scc->kiss.waittime);
+		else
+			scc_start_tx_timer(scc, t_dwait, 0);
+	}
+
+	restore_flags(flags);
+
+	return 0;
+}
+
+/* ----> ioctl functions <---- */
+
+/*
+ * SIOCSCCCFG		- configure driver	arg: (struct scc_hw_config *) arg
+ * SIOCSCCINI		- initialize driver	arg: ---
+ * SIOCSCCCHANINI	- initialize channel	arg: (struct scc_modem *) arg
+ * SIOCSCCSMEM		- set memory		arg: (struct scc_mem_config *) arg
+ * SIOCSCCGKISS		- get level 1 parameter	arg: (struct scc_kiss_cmd *) arg
+ * SIOCSCCSKISS		- set level 1 parameter arg: (struct scc_kiss_cmd *) arg
+ * SIOCSCCGSTAT		- get driver status	arg: (struct scc_stat *) arg
+ */
+
+static int
+scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+{
+	struct scc_kiss_cmd kiss_cmd;
+	struct scc_mem_config memcfg;
+	struct scc_hw_config hwcfg;
+	unsigned char device_name[10];
+	struct scc_channel *scc;
+	int chan;
+	void *arg;
+	
+	scc = (struct scc_channel *) dev->priv;
+	if (scc == NULL || scc->magic != SCC_MAGIC)
+		return -EINVAL;
+		
+	arg = (void *) ifr->ifr_data;
+	
+	if (!Driver_Initialized)
+	{
+		if (cmd == SIOCSCCCFG)
+		{
+			int found = 1;
+
+			if (!suser()) return -EPERM;
+			if (!arg) return -EFAULT;
+
+			if (Nchips >= MAXSCC) 
+				return -EINVAL;
+
+			if (copy_from_user(&hwcfg, arg, sizeof(hwcfg)))
+				return -EFAULT;
+
+			if (hwcfg.irq == 2) hwcfg.irq = 9;
+
+			if (!Ivec[hwcfg.irq].used && hwcfg.irq)
+			{
+				if (request_irq(hwcfg.irq, scc_isr, SA_INTERRUPT, "AX.25 SCC", NULL))
+					printk(KERN_WARNING "z8530drv: warning, cannot get IRQ %d\n", hwcfg.irq);
+				else
+					Ivec[hwcfg.irq].used = 1;
+			}
+
+			if (hwcfg.vector_latch) 
+				Vector_Latch = hwcfg.vector_latch;
+
+			if (hwcfg.clock == 0)
+				hwcfg.clock = DEFAULT_CLOCK;
+
+#ifndef DONT_CHECK
+			disable_irq(hwcfg.irq);
+
+			check_region(scc->ctrl, 1);
+			Outb(hwcfg.ctrl_a, 0);
+			udelay(5);
+			OutReg(hwcfg.ctrl_a,R13,0x55);		/* is this chip really there? */
+			udelay(5);
+
+			if (InReg(hwcfg.ctrl_a,R13) != 0x55)
+				found = 0;
+
+			enable_irq(hwcfg.irq);
+#endif
+
+			if (found)
+			{
+				SCC_Info[2*Nchips  ].ctrl = hwcfg.ctrl_a;
+				SCC_Info[2*Nchips  ].data = hwcfg.data_a;
+				SCC_Info[2*Nchips  ].irq  = hwcfg.irq;
+				SCC_Info[2*Nchips+1].ctrl = hwcfg.ctrl_b;
+				SCC_Info[2*Nchips+1].data = hwcfg.data_b;
+				SCC_Info[2*Nchips+1].irq  = hwcfg.irq;
+			
+				SCC_ctrl[Nchips].chan_A = hwcfg.ctrl_a;
+				SCC_ctrl[Nchips].chan_B = hwcfg.ctrl_b;
+				SCC_ctrl[Nchips].irq    = hwcfg.irq;
+			}
+
+
+			for (chan = 0; chan < 2; chan++)
+			{
+				sprintf(device_name, "%s%i", SCC_DriverName, 2*Nchips+chan);
+
+				SCC_Info[2*Nchips+chan].special = hwcfg.special;
+				SCC_Info[2*Nchips+chan].clock = hwcfg.clock;
+				SCC_Info[2*Nchips+chan].brand = hwcfg.brand;
+				SCC_Info[2*Nchips+chan].option = hwcfg.option;
+				SCC_Info[2*Nchips+chan].enhanced = hwcfg.escc;
+
+#ifdef DONT_CHECK
+				printk(KERN_INFO "%s: data port = 0x%3.3x  control port = 0x%3.3x\n",
+					device_name, 
+					SCC_Info[2*Nchips+chan].data, 
+					SCC_Info[2*Nchips+chan].ctrl);
+
+#else
+				printk(KERN_INFO "%s: data port = 0x%3.3lx  control port = 0x%3.3lx -- %s\n",
+					device_name,
+					chan? hwcfg.data_b : hwcfg.data_a, 
+					chan? hwcfg.ctrl_b : hwcfg.ctrl_a,
+					found? "found" : "missing");
+#endif
+
+				if (found)
+				{
+					request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl");
+					request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data");
+					if (Nchips+chan != 0)
+						scc_net_setup(&SCC_Info[2*Nchips+chan], device_name);
+				}
+			}
+			
+			if (found) Nchips++;
+			
+			return 0;
+		}
+		
+		if (cmd == SIOCSCCINI)
+		{
+			if (!suser())
+				return -EPERM;
+				
+			if (Nchips == 0)
+				return -EINVAL;
+
+			z8530_init();
+			return 0;
+		}
+		
+		return -EINVAL;	/* confuse the user */
+	}
+	
+	if (!scc->init)
+	{
+		if (cmd == SIOCSCCCHANINI)
+		{
+			if (!suser()) return -EPERM;
+			if (!arg) return -EINVAL;
+			
+			scc->stat.bufsize   = BUFSIZE;
+
+			if (copy_from_user(&scc->modem, arg, sizeof(struct scc_modem)))
+				return -EINVAL;
+			
+			/* default KISS Params */
+		
+			if (scc->modem.speed < 4800)
+			{
+				scc->kiss.txdelay = 36;		/* 360 ms */
+				scc->kiss.persist = 42;		/* 25% persistence */			/* was 25 */
+				scc->kiss.slottime = 16;	/* 160 ms */
+				scc->kiss.tailtime = 4;		/* minimal reasonable value */
+				scc->kiss.fulldup = 0;		/* CSMA */
+				scc->kiss.waittime = 50;	/* 500 ms */
+				scc->kiss.maxkeyup = 10;	/* 10 s */
+				scc->kiss.mintime = 3;		/* 3 s */
+				scc->kiss.idletime = 30;	/* 30 s */
+				scc->kiss.maxdefer = 120;	/* 2 min */
+				scc->kiss.softdcd = 0;		/* hardware dcd */
+			} else {
+				scc->kiss.txdelay = 10;		/* 100 ms */
+				scc->kiss.persist = 64;		/* 25% persistence */			/* was 25 */
+				scc->kiss.slottime = 8;		/* 160 ms */
+				scc->kiss.tailtime = 1;		/* minimal reasonable value */
+				scc->kiss.fulldup = 0;		/* CSMA */
+				scc->kiss.waittime = 50;	/* 500 ms */
+				scc->kiss.maxkeyup = 7;		/* 7 s */
+				scc->kiss.mintime = 3;		/* 3 s */
+				scc->kiss.idletime = 30;	/* 30 s */
+				scc->kiss.maxdefer = 120;	/* 2 min */
+				scc->kiss.softdcd = 0;		/* hardware dcd */
+			}
+			
+			scc->tx_buff = scc->tx_next_buff = NULL;
+			scc->init = 1;
+			
+			return 0;
+		}
+		
+		return -EINVAL;
+	}
+	
+	switch(cmd)
+	{
+		case SIOCSCCRESERVED:
+			return -ENOIOCTLCMD;
+
+		case SIOCSCCSMEM:
+			if (!suser()) return -EPERM;
+			if (!arg || copy_from_user(&memcfg, arg, sizeof(memcfg)))
+				return -EINVAL;
+			scc->stat.bufsize   = memcfg.bufsize;
+			return 0;
+		
+		case SIOCSCCGSTAT:
+			if (!arg || copy_to_user(arg, &scc->stat, sizeof(scc->stat)))
+				return -EINVAL;
+			return 0;
+		
+		case SIOCSCCGKISS:
+			if (!arg || copy_from_user(&kiss_cmd, arg, sizeof(kiss_cmd)))
+				return -EINVAL;
+			kiss_cmd.param = scc_get_param(scc, kiss_cmd.command);
+			if (copy_to_user(arg, &kiss_cmd, sizeof(kiss_cmd)))
+				return -EINVAL;
+			return 0;
+		
+		case SIOCSCCSKISS:
+			if (!suser()) return -EPERM;
+			if (!arg || copy_from_user(&kiss_cmd, arg, sizeof(kiss_cmd)))
+				return -EINVAL;
+			return scc_set_param(scc, kiss_cmd.command, kiss_cmd.param);
+
+		default:
+			return -ENOIOCTLCMD;
+		
+	}
+	
+	return -EINVAL;
+}
+
+/* ----> set interface callsign <---- */
+
+static int 
+scc_net_set_mac_address(struct device *dev, void *addr)
+{
+	struct sockaddr *sa = (struct sockaddr *) addr;
+	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+	return 0;
+}
+
+/* ----> rebuild header <---- */
+
+static int 
+scc_net_rebuild_header(void *buff, struct device *dev, unsigned long raddr, struct sk_buff *skb)
+{
+    return ax25_rebuild_header(buff, dev, raddr, skb);
+}
+
+/* ----> "hard" header <---- */
+
+static int 
+scc_net_header(struct sk_buff *skb, struct device *dev, unsigned short type, 
+	       void *daddr, void *saddr, unsigned len)
+{
+    return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
+}
+
+/* ----> get statistics <---- */
+
+static struct enet_statistics *
+scc_net_get_stats(struct device *dev)
+{
+	struct scc_channel *scc = (struct scc_channel *) dev->priv;
+	
+	if (scc == NULL || scc->magic != SCC_MAGIC)
+		return NULL;
+		
+	scc->dev_stat.rx_errors = scc->stat.rxerrs + scc->stat.rx_over;
+	scc->dev_stat.tx_errors = scc->stat.txerrs + scc->stat.tx_under;
+	scc->dev_stat.rx_fifo_errors = scc->stat.rx_over;
+	scc->dev_stat.tx_fifo_errors = scc->stat.tx_under;
+
+	return &scc->dev_stat;
+}
+
+/* ******************************************************************** */
+/* *		dump statistics to /proc/net/z8530drv		      * */
+/* ******************************************************************** */
+
+
+static int 
+scc_net_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+	struct scc_channel *scc;
+	struct scc_kiss *kiss;
+	struct scc_stat *stat;
+	int len = 0;
+	off_t pos = 0;
+	off_t begin = 0;
+	int k;
+
+	len += sprintf(buffer, "z8530drv-"VERSION"\n");
+
+	if (!Driver_Initialized)
+	{
+		len += sprintf(buffer+len, "not initialized\n");
+		goto done;
+	}
+
+	if (!Nchips)
+	{
+		len += sprintf(buffer+len, "chips missing\n");
+		goto done;
+	}
+
+	for (k = 0; k < Nchips*2; k++)
+	{
+		scc = &SCC_Info[k];
+		stat = &scc->stat;
+		kiss = &scc->kiss;
+
+		if (!scc->init)
+			continue;
+
+		/* dev	data ctrl irq clock brand enh vector special option 
+		 *	baud nrz clocksrc softdcd bufsize
+		 *	rxints txints exints spints
+		 *	rcvd rxerrs over / xmit txerrs under / nospace bufsize
+		 *	txd pers slot tail ful wait min maxk idl defr txof grp
+		 *	W ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
+		 *	R ## ## XX ## ## ## ## ## XX ## ## ## ## ## ## ##
+		 */
+
+		len += sprintf(buffer+len, "%s\t%3.3lx %3.3lx %d %lu %2.2x %d %3.3lx %3.3lx %d\n",
+				scc->dev->name,
+				scc->data, scc->ctrl, scc->irq, scc->clock, scc->brand,
+				scc->enhanced, Vector_Latch, scc->special,
+				scc->option);
+		len += sprintf(buffer+len, "\t%lu %d %d %d %d\n",
+				scc->modem.speed, scc->modem.nrz,
+				scc->modem.clocksrc, kiss->softdcd,
+				stat->bufsize);
+		len += sprintf(buffer+len, "\t%lu %lu %lu %lu\n",
+				stat->rxints, stat->txints, stat->exints, stat->spints);
+		len += sprintf(buffer+len, "\t%lu %lu %d / %lu %lu %d / %d %d\n",
+				stat->rxframes, stat->rxerrs, stat->rx_over,
+				stat->txframes, stat->txerrs, stat->tx_under,
+				stat->nospace,  stat->tx_state);
+
+#define K(x) kiss->x
+		len += sprintf(buffer+len, "\t%d %d %d %d %d %d %d %d %d %d %d %d\n",
+				K(txdelay), K(persist), K(slottime), K(tailtime),
+				K(fulldup), K(waittime), K(mintime), K(maxkeyup),
+				K(idletime), K(maxdefer), K(tx_inhibit), K(group));
+#undef K
+#ifdef SCC_DEBUG
+		{
+			int reg;
+
+		len += sprintf(buffer+len, "\tW ");
+			for (reg = 0; reg < 16; reg++)
+				len += sprintf(buffer+len, "%2.2x ", scc->wreg[reg]);
+			len += sprintf(buffer+len, "\n");
+			
+		len += sprintf(buffer+len, "\tR %2.2x %2.2x XX ", InReg(scc->ctrl,R0), InReg(scc->ctrl,R1));
+			for (reg = 3; reg < 8; reg++)
+				len += sprintf(buffer+len, "%2.2x ", InReg(scc->ctrl, reg));
+			len += sprintf(buffer+len, "XX ");
+			for (reg = 9; reg < 16; reg++)
+				len += sprintf(buffer+len, "%2.2x ", InReg(scc->ctrl, reg));
+			len += sprintf(buffer+len, "\n");
+		}
+#endif
+		len += sprintf(buffer+len, "\n");
+
+                pos = begin + len;
+
+                if (pos < offset) {
+                        len   = 0;
+                        begin = pos;
+                }
+
+                if (pos > offset + length)
+                        break;
+	}
+
+done:
+
+        *start = buffer + (offset - begin);
+        len   -= (offset - begin);
+
+        if (len > length) len = length;
+
+        return len;
+}
+
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry scc_proc_dir_entry = 
+{ 
+  PROC_NET_Z8530, 8, "z8530drv", S_IFREG | S_IRUGO, 1, 0, 0, 0, 
+  &proc_net_inode_operations, scc_net_get_info 
+};
+
+#define scc_net_procfs_init()   proc_net_register(&scc_proc_dir_entry);
+#define scc_net_procfs_remove() proc_net_unregister(PROC_NET_Z8530);
+#else
+#define scc_net_procfs_init()
+#define scc_net_procfs_remove()
+#endif
+
+  
+/* ******************************************************************** */
+/* * 			Init SCC driver 			      * */
+/* ******************************************************************** */
+
+int scc_init (void)
+{
+	int chip, chan, k, result;
+	char devname[10];
+	
+	printk(KERN_INFO BANNER);
+	
+	memset(&SCC_ctrl, 0, sizeof(SCC_ctrl));
+	
+	/* pre-init channel information */
+	
+	for (chip = 0; chip < MAXSCC; chip++)
+	{
+		memset((char *) &SCC_Info[2*chip  ], 0, sizeof(struct scc_channel));
+		memset((char *) &SCC_Info[2*chip+1], 0, sizeof(struct scc_channel));
+		
+		for (chan = 0; chan < 2; chan++)
+			SCC_Info[2*chip+chan].magic = SCC_MAGIC;
+	}
+
+	for (k = 0; k < 16; k++) Ivec[k].used = 0;
+
+	sprintf(devname,"%s0", SCC_DriverName);
+	
+	result = scc_net_setup(SCC_Info, devname);
+	if (result)
+	{
+		printk(KERN_ERR "z8530drv: cannot initialize module\n");
+		return result;
+	}
+
+	scc_net_procfs_init();
+
+	return 0;
+}
+
+/* ******************************************************************** */
+/* *			    Module support 			      * */
+/* ******************************************************************** */
+
+
+#ifdef MODULE
+int init_module(void)
+{
+	int result = 0;
+	
+	result = scc_init();
+
+	if (result == 0)
+		printk(KERN_INFO "Copyright 1993,1996 Joerg Reuter DL1BKE (jreuter@lykos.tng.oche.de)\n");
+		
+	return result;
+}
+
+void cleanup_module(void)
+{
+	long flags;
+	io_port ctrl;
+	int k;
+	struct scc_channel *scc;
+	
+	save_flags(flags); 
+	cli();
+
+	if (Nchips == 0)
+		unregister_netdev(SCC_Info[0].dev);
+
+	for (k = 0; k < Nchips; k++)
+		if ( (ctrl = SCC_ctrl[k].chan_A) )
+		{
+			Outb(ctrl, 0);
+			OutReg(ctrl,R9,FHWRES);	/* force hardware reset */
+			udelay(50);
+		}
+		
+	for (k = 0; k < Nchips*2; k++)
+	{
+		scc = &SCC_Info[k];
+		if (scc)
+		{
+			release_region(scc->ctrl, 1);
+			release_region(scc->data, 1);
+			if (scc->dev)
+			{
+				unregister_netdev(scc->dev);
+				kfree(scc->dev);
+			}
+		}
+	}
+	
+	for (k=0; k < 16 ; k++)
+		if (Ivec[k].used) free_irq(k, NULL);
+		
+	restore_flags(flags);
+
+	scc_net_procfs_remove();
+}
+#endif
diff -u --recursive --new-file v2.1.5/linux/drivers/net/slhc.c linux/drivers/net/slhc.c
--- v2.1.5/linux/drivers/net/slhc.c	Tue Jun 25 12:03:29 1996
+++ linux/drivers/net/slhc.c	Mon Oct 28 14:29:24 1996
@@ -75,7 +75,7 @@
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/mm.h>
 #include <net/checksum.h>
 #include <net/slhc_vj.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v2.1.5/linux/drivers/net/slip.c	Sat Oct 19 10:07:31 1996
+++ linux/drivers/net/slip.c	Mon Oct 28 14:29:24 1996
@@ -57,7 +57,7 @@
 #include <linux/module.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <linux/string.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/net/strip.c linux/drivers/net/strip.c
--- v2.1.5/linux/drivers/net/strip.c	Wed Oct 16 10:48:19 1996
+++ linux/drivers/net/strip.c	Mon Oct 28 14:29:24 1996
@@ -75,7 +75,7 @@
 
 #include <stdlib.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 /*
diff -u --recursive --new-file v2.1.5/linux/drivers/net/z8530.h linux/drivers/net/z8530.h
--- v2.1.5/linux/drivers/net/z8530.h	Tue Jun  6 11:22:11 1995
+++ linux/drivers/net/z8530.h	Tue Oct 29 15:33:39 1996
@@ -218,3 +218,26 @@
 /* Read Register 13 (upper byte of baud rate generator constant) */
 
 /* Read Register 15 (value of WR 15) */
+
+/* 8580/85180/85280 Enhanced SCC register definitions */
+
+/* Write Register 7' (SDLC/HDLC Programmable Enhancements) */
+#define AUTOTXF	0x01		/* Auto Tx Flag */
+#define AUTOEOM 0x02		/* Auto EOM Latch Reset */
+#define AUTORTS	0x04		/* Auto RTS */
+#define TXDNRZI 0x08		/* TxD Pulled High in SDLC NRZI mode */
+#define FASTDTR 0x10		/* Fast DTR/REQ Mode */
+#define CRCCBCR	0x20		/* CRC Check Bytes Completely Received */
+#define EXTRDEN	0x40		/* Extended Read Enabled */
+
+/* Write Register 15 (external/status interrupt control) */
+#define SHDLCE	1		/* SDLC/HDLC Enhancements Enable */
+#define FIFOE	4		/* FIFO Enable */
+
+/* Read Register 6 (frame status FIFO) */
+#define BCLSB	0xff		/* LSB of 14 bits count */
+
+/* Read Register 7 (frame status FIFO) */
+#define BCMSB	0x3f		/* MSB of 14 bits count */
+#define FDA	0x40		/* FIFO Data Available Status */
+#define FOY	0x80		/* FIFO Overflow Status */
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c
--- v2.1.5/linux/drivers/scsi/BusLogic.c	Wed Jul 17 21:22:13 1996
+++ linux/drivers/scsi/BusLogic.c	Mon Oct 28 13:39:05 1996
@@ -25,7 +25,7 @@
 
 
 #define BusLogic_DriverVersion		"2.0.6"
-#define BusLogic_DriverDate		"17 July 1996"
+#define BusLogic_DriverDate		"19 October 1996"
 
 
 #include <linux/module.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/BusLogic.h linux/drivers/scsi/BusLogic.h
--- v2.1.5/linux/drivers/scsi/BusLogic.h	Wed Jul 17 21:22:13 1996
+++ linux/drivers/scsi/BusLogic.h	Mon Oct 28 13:39:05 1996
@@ -1066,11 +1066,10 @@
 
 static inline void BusLogic_Delay(int Seconds)
 {
-  unsigned long TimeoutJiffies = jiffies + Seconds * HZ;
   unsigned long ProcessorFlags;
   save_flags(ProcessorFlags);
   sti();
-  while (jiffies < TimeoutJiffies) barrier();
+  while (--Seconds >= 0) udelay(1000000);
   restore_flags(ProcessorFlags);
 }
 
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v2.1.5/linux/drivers/scsi/Config.in	Sat Oct  5 16:58:34 1996
+++ linux/drivers/scsi/Config.in	Tue Oct 29 00:31:24 1996
@@ -24,9 +24,9 @@
 dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI
 dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI
 dep_tristate 'DTC3180/3280 SCSI support' CONFIG_SCSI_DTC3280 $CONFIG_SCSI
-dep_tristate 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA $CONFIG_SCSI
 dep_tristate 'EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI
 dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
+dep_tristate 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA $CONFIG_SCSI
 dep_tristate 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
 dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
 if [ "$CONFIG_SCSI_GENERIC_NCR5380" != "n" ]; then
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c
--- v2.1.5/linux/drivers/scsi/NCR5380.c	Wed Oct  9 08:55:21 1996
+++ linux/drivers/scsi/NCR5380.c	Tue Oct 29 16:21:11 1996
@@ -734,7 +734,7 @@
  */
 
 static void NCR5380_print_status (struct Scsi_Host *instance) {
-   char pr_bfr[256];
+   static char pr_bfr[512];
    char *start;
    int len;
 
@@ -767,7 +767,7 @@
 */
 
 #undef SPRINTF
-#define SPRINTF(args...) do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
+#define SPRINTF(args...) do { if(pos < buffer + length-80) pos += sprintf(pos, ## args); } while(0)
 static
 char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
 static
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/README.FlashPoint linux/drivers/scsi/README.FlashPoint
--- v2.1.5/linux/drivers/scsi/README.FlashPoint	Wed Jul 17 21:22:13 1996
+++ linux/drivers/scsi/README.FlashPoint	Tue Oct 29 14:55:15 1996
@@ -1,4 +1,67 @@
+The BusLogic FlashPoint SCSI host adapters are now supported on Linux 2.0.x.
+See http://www.dandelion.com/Linux/ for the beta test BusLogic driver which
+includes FlashPoint support.  The upgrade program described below will remain
+available through the end of 1996.
 
+
+
+	  MYLEX INTRODUCES LINUX OPERATING SYSTEM SUPPORT FOR ITS
+	      BUSLOGIC FLASHPOINT LINE OF SCSI HOST ADAPTERS
+
+
+FREMONT, CA, -- October 8, 1996 -- Mylex Corporation has expanded Linux
+operating system support to its BusLogic brand of FlashPoint Ultra SCSI
+host adapters.  All of BusLogic's other SCSI host adapters, including the
+MultiMaster line, currently support the Linux operating system.  Linux
+drivers and information will be available on October 15th at
+http://www.dandelion.com/Linux/.
+
+"Mylex is committed to supporting the Linux community," says Peter Shambora,
+vice president of marketing for Mylex.  "We have supported Linux driver
+development and provided technical support for our host adapters for several
+years, and are pleased to now make our FlashPoint products available to this
+user base."
+
+The Linux Operating System
+
+Linux is a freely-distributed implementation of UNIX for Intel x86, Sun
+SPARC, SGI MIPS, Motorola 68k, Digital Alpha AXP and Motorola PowerPC
+machines.  It supports a wide range of software, including the X Window
+System, Emacs, and TCP/IP networking.  Further information is available at
+http://www.linux.org and http://www.ssc.com/linux.
+
+FlashPoint Host Adapters
+
+The FlashPoint family of Ultra SCSI host adapters, designed for workstation
+and file server environments, are available in narrow, wide, dual channel,
+and dual channel wide versions.  These adapters feature SeqEngine
+automation technology, which minimizes SCSI command overhead and reduces
+the number of interrupts generated to the CPU.
+
+About Mylex
+
+Mylex Corporation (NASDAQ/NM SYMBOL: MYLX), founded in 1983, is a leading
+producer of RAID technology and network management products.  The company
+produces high performance disk array (RAID) controllers, and complementary
+computer products for network servers, mass storage systems, workstations
+and system boards.  Through its wide range of RAID controllers and its
+BusLogic line of Ultra SCSI host adapter products, Mylex provides enabling
+intelligent I/O technologies that increase network management control,
+enhance CPU utilization, optimize I/O performance, and ensure data security
+and availability.  Products are sold globally through a network of OEMs,
+major distributors, VARs, and system integrators.  Mylex Corporation is
+headquartered at 34551 Ardenwood Blvd., Fremont, CA.
+
+				   ####
+
+Contact:
+
+Peter Shambora
+Vice President of Marketing
+Mylex Corp.
+510/796-6100
+peters@mylex.com
+
 			       ANNOUNCEMENT
 	       BusLogic FlashPoint LT/BT-948 Upgrade Program
 			      1 February 1996
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.1.5/linux/drivers/scsi/aic7xxx.c	Wed Oct 16 10:48:19 1996
+++ linux/drivers/scsi/aic7xxx.c	Tue Oct 29 00:21:09 1996
@@ -1,3 +1,5 @@
+#define EXPERIMENTAL_FLAGS 0
+
 /*+M*************************************************************************
  * Adaptec AIC7xxx device driver for Linux.
  *
@@ -4314,7 +4316,7 @@
   p->flags = config->flags;
   p->chan_num = config->chan_num;
   p->scb_link = &(p->scb_usage);
-#ifdef AIC7XXX_SHARE_SCBS
+#if defined(CONFIG_PCI) && defined(AIC7XXX_SHARE_SCBS)
   if ((p->chan_num == 0) && ((p->type == AIC_7873) | (p->type == AIC_7883)))
   {
     shared_3985_scbs = &(p->scb_usage);
@@ -4410,7 +4412,7 @@
     outb(config->scsi_id_b, SCSIID + base);
     scsi_conf = inb(SCSICONF + base + 1) & (ENSPCHK | STIMESEL);
     outb(scsi_conf | ENSTIMER | ACTNEGEN | STPWEN, SXFRCTL1 + base);
-#if 1
+#if EXPERIMENTAL_FLAGS
     outb(ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1 + base);
 #else
     outb(ENSELTIMO, SIMODE1 + base);
@@ -4432,7 +4434,7 @@
   outb(config->scsi_id, SCSIID + base);
   scsi_conf = inb(SCSICONF + base) & (ENSPCHK | STIMESEL);
   outb(scsi_conf | ENSTIMER | ACTNEGEN | STPWEN, SXFRCTL1 + base);
-#if 1
+#if EXPERIMENTAL_FLAGS
   outb(ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1 + base);
 #else
   outb(ENSELTIMO, SIMODE1 + base);
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c
--- v2.1.5/linux/drivers/scsi/eata_dma.c	Wed Aug 14 10:21:03 1996
+++ linux/drivers/scsi/eata_dma.c	Tue Oct 29 00:31:24 1996
@@ -58,7 +58,7 @@
  * Jagdis who did a lot of testing and found quite a number *
  * of bugs during the development.                          *
  ************************************************************
- *  last change: 96/08/13                 OS: Linux 2.0.12  *
+ *  last change: 96/10/21                 OS: Linux 2.0.23  *
  ************************************************************/
 
 /* Look in eata_dma.h for configuration and revision information */
@@ -295,12 +295,9 @@
            sp->EOC = FALSE; /* Clean out this flag */
 
            if (ccb->status == LOCKED || ccb->status == RESET) {
-               ccb->status = FREE;
-               eata_stat = inb(base + HA_RSTATUS);
-               printk("eata_dma: int_handler, reseted command returned,"
-                      " freeing reseted queueslot\n");
+               printk("eata_dma: int_handler, reseted command pid %ld returned"
+		      "\n", cmd->pid);
 	       DBG(DBG_INTR && DBG_DELAY, DELAY(1));
-	       break;
 	    }
 	    
 	    eata_stat = inb(base + HA_RSTATUS); 
@@ -467,23 +464,33 @@
     struct Scsi_Host *sh;
     struct eata_ccb *ccb;
     struct scatterlist *sl;
+
     
     save_flags(flags);
     cli();
+
+#if 0
+    for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->next) {
+      if(inb((uint)sh->base + HA_RAUXSTAT) & HA_AIRQ) {
+            printk("eata_dma: scsi%d interrupt pending in eata_queue.\n"
+		   "          Calling interrupt handler.\n", sh->host_no);
+            eata_int_handler(sh->irq, 0, 0);
+      }
+    }
+#endif
     
     queue_counter++;
 
     hd = HD(cmd);
     sh = cmd->host;
     
-#if 1
     if (cmd->cmnd[0] == REQUEST_SENSE && cmd->sense_buffer[0] != 0) {
         DBG(DBG_REQSENSE, printk(KERN_DEBUG "Tried to REQUEST SENSE\n"));
 	cmd->result = DID_OK << 16;
 	done(cmd);
+
 	return(0);
     }
-#endif
 
     /* check for free slot */
     for (y = hd->last_ccb + 1, x = 0; x < sh->can_queue; x++, y++) { 
@@ -678,7 +685,6 @@
 			   " reason %x\n", cmd->pid, cmd->target, cmd->lun, 
 			   cmd->abort_reason));
 	
-    /* Some interrupt controllers seem to loose interrupts */
     for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->next) {
         if(inb((uint)sh->base + HA_RAUXSTAT) & HA_AIRQ) {
             printk("eata_dma: scsi%d interrupt pending in eata_reset.\n"
@@ -686,6 +692,7 @@
             eata_int_handler(sh->irq, 0, 0);
       }
     }
+
     if (HD(cmd)->state == RESET) {
 	printk("eata_reset: exit, already in reset.\n");
 	restore_flags(flags);
@@ -766,9 +773,9 @@
     restore_flags(flags);
     
     if (success) {
-	DBG(DBG_ABNORM, printk("eata_reset: exit, success.\n"));
+	DBG(DBG_ABNORM, printk("eata_reset: exit, pending.\n"));
 	DBG(DBG_ABNORM && DBG_DELAY, DELAY(1));
-	return (SCSI_RESET_SUCCESS);
+	return (SCSI_RESET_PENDING);
     } else {
 	DBG(DBG_ABNORM, printk("eata_reset: exit, wakeup.\n"));
 	DBG(DBG_ABNORM && DBG_DELAY, DELAY(1));
@@ -852,8 +859,9 @@
 		    device->queue_depth = (TYPE_OTHER_QUEUE * factor) / 10;
 		    break;
 		}
-	    } else /* ISA forces us to limit the QS because of bounce buffers*/
-	        device->queue_depth = 2; /* I know this is cruel */
+	    } else /* ISA forces us to limit the queue depth because of the 
+		    * bounce buffer memory overhead. I know this is cruel */
+	        device->queue_depth = 2; 
 
 	    /* 
 	     * It showed that we need to set an upper limit of commands 
@@ -863,6 +871,8 @@
 	     */
 	    if(device->queue_depth > UPPER_DEVICE_QUEUE_LIMIT)
 		device->queue_depth = UPPER_DEVICE_QUEUE_LIMIT;
+	    if(device->queue_depth == 0) 
+		device->queue_depth = 1;
 
 	    printk(KERN_INFO "scsi%d: queue depth for target %d on channel %d "
 		   "set to %d\n", host->host_no, device->id, device->channel,
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/eata_dma.h linux/drivers/scsi/eata_dma.h
--- v2.1.5/linux/drivers/scsi/eata_dma.h	Wed Aug 14 10:21:03 1996
+++ linux/drivers/scsi/eata_dma.h	Tue Oct 29 00:31:24 1996
@@ -4,7 +4,7 @@
 *             mike@i-Connect.Net                        *
 *             neuffer@mail.uni-mainz.de                 *
 *********************************************************
-* last change: 96/08/14                                 *
+* last change: 96/10/14                                 *
 ********************************************************/
 
 #ifndef _EATA_DMA_H
@@ -17,7 +17,7 @@
 
 #define VER_MAJOR 2
 #define VER_MINOR 5
-#define VER_SUB   "9a"
+#define VER_SUB   "9b"
 
 
 /************************************************************************
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/eata_generic.h linux/drivers/scsi/eata_generic.h
--- v2.1.5/linux/drivers/scsi/eata_generic.h	Wed Aug 14 10:21:03 1996
+++ linux/drivers/scsi/eata_generic.h	Tue Oct 29 00:31:24 1996
@@ -68,7 +68,7 @@
 #define SG_SIZE		 64 
 #define SG_SIZE_BIG	 252	       /* max. 8096 elements, 64k */
 
-#define UPPER_DEVICE_QUEUE_LIMIT 24    /* The limit we have to set for the 
+#define UPPER_DEVICE_QUEUE_LIMIT 64    /* The limit we have to set for the 
 					* device queue to keep the broken 
 					* midlevel SCSI code from producing
 					* bogus timeouts
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.1.5/linux/drivers/scsi/hosts.c	Wed Aug  7 12:31:21 1996
+++ linux/drivers/scsi/hosts.c	Tue Oct 29 00:31:24 1996
@@ -224,6 +224,12 @@
 #ifdef CONFIG_SCSI_ADVANSYS
 	ADVANSYS,
 #endif
+#ifdef CONFIG_SCSI_EATA_DMA
+    EATA_DMA,
+#endif
+#ifdef CONFIG_SCSI_EATA_PIO
+    EATA_PIO,
+#endif
 /* BusLogic must come before aha1542.c */
 #ifdef CONFIG_SCSI_BUSLOGIC
     BUSLOGIC,
@@ -281,12 +287,6 @@
 #endif
 #ifdef CONFIG_SCSI_NCR53C8XX
     NCR53C8XX,
-#endif
-#ifdef CONFIG_SCSI_EATA_DMA
-    EATA_DMA,
-#endif
-#ifdef CONFIG_SCSI_EATA_PIO
-    EATA_PIO,
 #endif
 #ifdef CONFIG_SCSI_7000FASST
     WD7000,
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.1.5/linux/drivers/scsi/scsi.c	Wed Oct 16 10:48:22 1996
+++ linux/drivers/scsi/scsi.c	Tue Oct 29 00:31:24 1996
@@ -17,8 +17,8 @@
  *  add scatter-gather, multiple outstanding request, and other
  *  enhancements.
  *
- *  Native multichannel and wide scsi support added 
- *  by Michael Neuffer neuffer@goofy.zdv.uni-mainz.de
+ *  Native multichannel, wide scsi, /proc/scsi and hot plugging 
+ *  support added by Michael Neuffer <mike@i-connect.net>
  *
  *  Added request_module("scsi_hostadapter") for kerneld:
  *  (Put an "alias scsi_hostadapter your_hostadapter" in /etc/conf.modules)
@@ -47,6 +47,7 @@
 #include <linux/stat.h>
 #include <linux/blk.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -275,6 +276,7 @@
  */
 {"SONY","CD-ROM CDU-8001","*", BLIST_BORKEN},
 {"TEXEL","CD-ROM","1.06", BLIST_BORKEN},
+{"IOMEGA","Io20S         *F","*", BLIST_KEY},
 {"INSITE","Floptical   F*8I","*", BLIST_KEY},
 {"INSITE","I325VM","*", BLIST_KEY},
 {"NRC","MBR-7","*", BLIST_FORCELUN | BLIST_SINGLELUN},
@@ -1219,17 +1221,19 @@
      */
     timeout = host->last_reset + MIN_RESET_DELAY;
     if (jiffies < timeout) {
-        /*
-         * NOTE: This may be executed from within an interrupt
-         * handler!  This is bad, but for now, it'll do.  The irq
-         * level of the interrupt handler has been masked out by the
-         * platform dependent interrupt handling code already, so the
-         * sti() here will not cause another call to the SCSI host's
-         * interrupt handler (assuming there is one irq-level per
-         * host).
-         */
-        sti();
-        while (jiffies < timeout) barrier();
+	int ticks_remaining = timeout - jiffies;
+	/*
+	 * NOTE: This may be executed from within an interrupt
+	 * handler!  This is bad, but for now, it'll do.  The irq
+	 * level of the interrupt handler has been masked out by the
+	 * platform dependent interrupt handling code already, so the
+	 * sti() here will not cause another call to the SCSI host's
+	 * interrupt handler (assuming there is one irq-level per
+	 * host).
+	 */
+	sti();
+	while (--ticks_remaining >= 0) udelay(1000000/HZ);
+	host->last_reset = jiffies - MIN_RESET_DELAY;
     }
     restore_flags(flags);
     
@@ -3065,7 +3069,11 @@
 	 */
 	
 	for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next)
-	    if(shpnt->hostt == tpnt) scan_scsis(shpnt,0,0,0,0);
+	    if(shpnt->hostt == tpnt) {
+	      scan_scsis(shpnt,0,0,0,0);
+	      if (shpnt->select_queue_depths != NULL)
+		  (shpnt->select_queue_depths)(shpnt, scsi_devices);
+	    }
 	
 	for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
 	    if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)();
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v2.1.5/linux/drivers/scsi/scsi_ioctl.c	Wed Oct 16 10:48:22 1996
+++ linux/drivers/scsi/scsi_ioctl.c	Mon Oct 28 14:29:24 1996
@@ -7,7 +7,7 @@
 #include <linux/module.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.1.5/linux/drivers/scsi/sd.c	Wed Sep 18 11:13:52 1996
+++ linux/drivers/scsi/sd.c	Tue Oct 29 00:31:24 1996
@@ -512,7 +512,7 @@
 
 	if (flag++ == 0)
 	    SCpnt = allocate_device(&CURRENT,
-				    rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device, 0); 
+			   rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device, 0); 
 	else SCpnt = NULL;
 	
 	/*
@@ -537,7 +537,8 @@
 	    cli();
 	    req = CURRENT;
 	    while(req){
-		SCpnt = request_queueable(req, rscsi_disks[DEVICE_NR(req->rq_dev)].device);
+		SCpnt = request_queueable(req, 
+                                   rscsi_disks[DEVICE_NR(req->rq_dev)].device);
 		if(SCpnt) break;
 		req1 = req;
 		req = req->next;
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/sd_ioctl.c linux/drivers/scsi/sd_ioctl.c
--- v2.1.5/linux/drivers/scsi/sd_ioctl.c	Thu May  2 07:48:54 1996
+++ linux/drivers/scsi/sd_ioctl.c	Mon Oct 28 14:29:24 1996
@@ -11,7 +11,7 @@
 #include <linux/hdreg.h>
 #include <linux/errno.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/blk.h>
 #include "scsi.h"
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c
--- v2.1.5/linux/drivers/scsi/seagate.c	Wed Oct 16 10:48:22 1996
+++ linux/drivers/scsi/seagate.c	Mon Oct 28 14:29:24 1996
@@ -1633,7 +1633,7 @@
 	return SCSI_RESET_WAKEUP;
 	}
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include "sd.h"
 #include <scsi/scsi_ioctl.h>
 
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v2.1.5/linux/drivers/scsi/sg.c	Wed Oct 16 10:48:22 1996
+++ linux/drivers/scsi/sg.c	Mon Oct 28 14:29:24 1996
@@ -18,7 +18,7 @@
 #include <linux/ioctl.h>
 #include <linux/fcntl.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/blk.h>
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v2.1.5/linux/drivers/scsi/sr_ioctl.c	Wed Oct 16 10:48:22 1996
+++ linux/drivers/scsi/sr_ioctl.c	Mon Oct 28 14:29:24 1996
@@ -2,7 +2,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 
diff -u --recursive --new-file v2.1.5/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v2.1.5/linux/drivers/scsi/st.c	Wed Oct 16 10:48:22 1996
+++ linux/drivers/scsi/st.c	Tue Oct 29 00:45:09 1996
@@ -11,7 +11,7 @@
   Copyright 1992 - 1996 Kai Makisara
 		 email Kai.Makisara@metla.fi
 
-  Last modified: Tue Oct  1 22:53:51 1996 by makisara@kai.makisara.fi
+  Last modified: Tue Oct 22 20:59:52 1996 by root@kai.makisara.fi
   Some small formal changes - aeb, 950809
 */
 
@@ -26,7 +26,7 @@
 #include <linux/mtio.h>
 #include <linux/ioctl.h>
 #include <linux/fcntl.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/dma.h>
 #include <asm/system.h>
 
@@ -888,10 +888,12 @@
 
 
 /* Write command */
-	static int
-st_write(struct inode * inode, struct file * filp, const char * buf, int count)
+	static long
+st_write(struct inode * inode, struct file * filp, const char * buf,
+	 unsigned long count)
 {
-    int total, do_count, blks, retval, transfer;
+    long total;
+    int do_count, blks, retval, transfer;
     int write_threshold;
     int doing_write = 0;
     static unsigned char cmd[10];
@@ -1166,10 +1168,10 @@
 
 
 /* Read command */
-	static int
-st_read(struct inode * inode, struct file * filp, char * buf, int count)
+	static long
+st_read(struct inode * inode, struct file * filp, char * buf, unsigned long count)
 {
-    int total;
+    long total;
     int transfer, blks, bytes;
     static unsigned char cmd[10];
     Scsi_Cmnd * SCpnt = NULL;
@@ -1310,7 +1312,7 @@
 		  (STp->buffer)->buffer_bytes = (blks - transfer) * STp->block_size;
 #if DEBUG
 		  if (debugging)
-		    printk(ST_DEB_MSG "st%d: ILI but enough data received %d %d.\n",
+		    printk(ST_DEB_MSG "st%d: ILI but enough data received %ld %d.\n",
 			   dev, count - total, (STp->buffer)->buffer_bytes);
 #endif
 		  if (count - total > (STp->buffer)->buffer_bytes)
@@ -1332,7 +1334,7 @@
 #if DEBUG
 		if (debugging)
 		  printk(ST_DEB_MSG
-		    "st%d: EOF detected (%d bytes read, transferred %d bytes).\n",
+		    "st%d: EOF detected (%d bytes read, transferred %ld bytes).\n",
 			 dev, (STp->buffer)->buffer_bytes, total);
 #endif
 	      }
@@ -2314,6 +2316,7 @@
       return (-EBUSY);
 
     STp->drv_block = (STp->mt_status)->mt_fileno = (-1);
+    STp->eof = ST_NOEOF;
     if ((STp->buffer)->last_result_fatal != 0) {
       result = (-EIO);
       if (STp->can_partitions &&
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/.object_files linux/drivers/sound/.object_files
--- v2.1.5/linux/drivers/sound/.object_files	Sun Jun 30 11:50:18 1996
+++ linux/drivers/sound/.object_files	Thu Jan  1 02:00:00 1970
@@ -1,35 +0,0 @@
-audio.o
-dmabuf.o
-opl3.o
-sequencer.o
-midibuf.o
-sb_card.o
-pas2_card.o
-adlib_card.o
-pas2_pcm.o
-pas2_mixer.o
-pas2_midi.o
-gus_card.o
-gus_wave.o
-mpu401.o
-gus_midi.o
-gus_vol.o
-patmgr.o
-sb_mixer.o
-sb_common.o
-midi_synth.o
-uart6850.o
-uart401.o
-sound_timer.o
-sb_midi.o
-sb_audio.o
-sys_timer.o
-ics2101.o
-ad1848.o
-pss.o
-sscape.o
-trix.o
-aedsp16.o
-mad16.o
-cs4232.o
-maui.o
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/.objects linux/drivers/sound/.objects
--- v2.1.5/linux/drivers/sound/.objects	Thu Aug  1 15:43:05 1996
+++ linux/drivers/sound/.objects	Tue Oct 29 09:32:32 1996
@@ -24,7 +24,7 @@
 	OBJS := $(OBJS)  dmabuf.o
 endif
 
-ifdef CONFIG_GUS
+ifdef CONFIG_GUSHW
 	OBJS := $(OBJS)  gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o
 endif
 
@@ -76,7 +76,7 @@
 	OBJS := $(OBJS)  sound_timer.o
 endif
 
-ifdef CONFIG_SSCAPE
+ifdef CONFIG_SSCAPEHW
 	OBJS := $(OBJS)  sscape.o
 endif
 
@@ -95,3 +95,4 @@
 ifdef CONFIG_UART401
 	OBJS := $(OBJS)  uart401.o
 endif
+
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/.version linux/drivers/sound/.version
--- v2.1.5/linux/drivers/sound/.version	Sun Jun 30 11:43:44 1996
+++ linux/drivers/sound/.version	Tue Oct 29 09:31:12 1996
@@ -1,2 +1,2 @@
-3.5.5-beta1
-0x030504
+3.7-beta6
+0x030701
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/CHANGELOG linux/drivers/sound/CHANGELOG
--- v2.1.5/linux/drivers/sound/CHANGELOG	Sat Jul  6 11:31:43 1996
+++ linux/drivers/sound/CHANGELOG	Tue Oct 29 09:31:15 1996
@@ -1,5 +1,9 @@
-Changelog for version 3.5.4
----------------------------
+Changelog for version 3.7-beta5
+-------------------------------
+
+Since 3.5
+- Changes almost everywhere.
+- Support for OPTi 82C924 based soundcards.
 
 Since 3.5.4-beta8
 - Fixed a bug in handling of non-fragment sized writes in 16 bit/stereo mode
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v2.1.5/linux/drivers/sound/Config.in	Tue Aug 20 17:38:55 1996
+++ linux/drivers/sound/Config.in	Tue Oct 29 09:32:01 1996
@@ -14,4 +14,5 @@
 
 if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
    bool 'ACI mixer (miroPCM12)' CONFIG_ACI_MIXER
+   bool 'AWE32 synth' CONFIG_AWE32_SYNTH
 fi
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/Config.std linux/drivers/sound/Config.std
--- v2.1.5/linux/drivers/sound/Config.std	Sat Jul  6 11:31:43 1996
+++ linux/drivers/sound/Config.std	Tue Oct 29 09:32:01 1996
@@ -2,10 +2,10 @@
 # Sound driver configuration
 #
 #--------
-# There is another config script which is compatible with rest of
+# There is another confic script which is compatible with rest of
 # the kernel. It can be activated by running 'make mkscript' in this
 # directory. Please note that this is an _experimental_ feature which
-# doesn't work with all cards (PSS, SM Wave, AudioTrix Pro, Maui).
+# doesn't work with all cards (PSS, SM Wave, AudioTriX Pro, Maui).
 #--------
 #
 $MAKE -C drivers/sound config || exit 1
@@ -14,4 +14,5 @@
 
 if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
    bool 'ACI mixer (miroPCM12)' CONFIG_ACI_MIXER
+   bool 'AWE32 synth' CONFIG_AWE32_SYNTH
 fi
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v2.1.5/linux/drivers/sound/Makefile	Sun Jun 30 11:43:41 1996
+++ linux/drivers/sound/Makefile	Tue Oct 29 09:31:12 1996
@@ -21,8 +21,6 @@
 ifeq (.defines,$(wildcard .defines))
 include .defines
 include .objects
-else
-OBJS   = `cat .object_files`
 endif
 
 ifndef TOPDIR
@@ -72,7 +70,7 @@
 
 clean:
 	rm -f core core.* *.o *.a tmp_make *~ x y z *%
-	rm -f configure sound_stub.c objects/*.o 
+	rm -f configure
 	cd lowlevel;make clean
 
 indent:
@@ -80,7 +78,7 @@
 
 local.h: 
 	$(MAKE) clean
-	$(MAKE) setup-$(TARGET_OS)
+	$(MAKE) setup
 	$(MAKE) oldconfig
 	$(MAKE) dep
 	@echo
@@ -93,7 +91,7 @@
 	@echo
 
 config: configure
-	@$(MAKE) setup-$(TARGET_OS)
+	@$(MAKE) setup
 	@./configure > local.h
 	@echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h
 	@echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h
@@ -101,7 +99,7 @@
 #	@echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null
 	@echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h
 
-oldconfig: setup-$(TARGET_OS) configure
+oldconfig: setup configure
 	@./configure -o > local.h
 	@echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h
 	@echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h
@@ -109,7 +107,7 @@
 #	@echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null
 	@echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h
 
-kernelconfig: setup-$(TARGET_OS)
+kernelconfig: setup
 	rm -f configure
 	$(HOSTCC) -o configure configure.c
 	./configure fixedlocal > local.h
@@ -120,7 +118,7 @@
 #	@echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null
 	@echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h
 
-mkscript: setup-$(TARGET_OS)
+mkscript: setup
 	rm -f configure
 	$(HOSTCC) -o configure configure.c
 	./configure script > Config.in
@@ -136,9 +134,9 @@
 	@cat .blurb
 
 dep:
-	$(CPP) -M *.c > .depend
+	$(CPP) -M $(CFLAGS) -I. *.c > .depend
 
-setup-linux:
+setup:
 	@echo Compiling Sound Driver v $(VERSION) for Linux
 
 sound.o: local.h $(FIXEDOBJS) sound.a
@@ -151,6 +149,9 @@
 
 lowlevel/lowlevel.o: dummy
 		cd lowlevel;make
+
+contrib:
+		cd lowlevel;make clean;make module CFLAGS="$(CFLAGS)"
 
 ifdef USE_DEPEND
 #
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/Readme linux/drivers/sound/Readme
--- v2.1.5/linux/drivers/sound/Readme	Sat Jul  6 11:31:43 1996
+++ linux/drivers/sound/Readme	Tue Oct 29 09:31:13 1996
@@ -1,8 +1,8 @@
-USS Lite version 3.5.4 release notes
-------------------------------------
+OSS Lite version 3.7-beta release notes
+---------------------------------------
 
 Most up to date information about this driver is available from 
-http://www.4front-tech.com/usslite or http://personal.eunet.fi/pp/voxware
+http://www.4front-tech.com/ossfree or http://personal.eunet.fi/pp/voxware
 (European mirror).
 
 
@@ -16,15 +16,12 @@
 check http://www.4front-tech.com/pguide for more info.
 
    ====================================================
--  THIS VERSION ____REQUIRES____ Linux 1.3.70 OR LATER.
+-  THIS VERSION ____REQUIRES____ Linux 2.1.5 OR LATER.
    ====================================================
 
-It's very likely that this driver version is incompatible with
-Linux versions later than 2.0.x.
-
 Packages "snd-util-3.5.tar.gz" and "snd-data-0.1.tar.Z"
 contain useful utilities to be used with this driver.
-See http://www.4front-tech.com/usslite/getting.html for
+See http://www.4front-tech.com/ossfree/getting.html for
 download instructions.
 
 If you are looking for the installation instructions, please
@@ -35,7 +32,7 @@
 
 See Readme.cards.
 
-Please check http://www.4front-tech.com/usslite if you don't find
+Please check http://www.4front-tech.com/ossfree if you don't find
 your soundcard there.
 
 Contributors
@@ -73,6 +70,8 @@
 	Gregor Hoffleit	Mozart support (initial version)
 	Riccardo Facchetti Audio Excel DSP 16 (aedsp16) support
 	James Hightower Spotting a tiny but important bug in CS423x support.
+	Denis Sablic	OPTi 82C924 spesific enhancements (non PnP mode)
+	Tim MacKenzie	Full duplex support for OPTi 82C930.
 	
 	Please look at lowlevel/README for more contributors.
 
@@ -113,7 +112,7 @@
 =========================
 
 Read the sound HOWTO (sunsite.unc.edu:/pub/Linux/docs/...?).
-Also look at the home page (http://www.4front-tech.com/usslite). It may
+Also look at the home page (http://www.4front-tech.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
@@ -168,7 +167,7 @@
 
 Hannu Savolainen
 hannu@voxware.pp.fi, hannu@4front-tech.com	
-(Please check http://www.4front-tech.com/usslite before mailing me).
+(Please check http://www.4front-tech.com/ossfree before mailing me).
 
 Snail mail:	Hannu Savolainen
 		Hiekkalaiturintie 3 A 8
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/Readme.aedsp16 linux/drivers/sound/Readme.aedsp16
--- v2.1.5/linux/drivers/sound/Readme.aedsp16	Mon Jul 15 09:55:11 1996
+++ linux/drivers/sound/Readme.aedsp16	Tue Oct 29 09:31:13 1996
@@ -1,6 +1,6 @@
-Information about Audio Excel DSP 16 can be found in the source
+Informations about Audio Excel DSP 16 can be found in the source
 file aedsp16.c
 Please, read the head of the source before using it. It contain useful
-information.
+informations.
 
     Riccardo
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/Readme.cards linux/drivers/sound/Readme.cards
--- v2.1.5/linux/drivers/sound/Readme.cards	Mon Sep 16 13:05:18 1996
+++ linux/drivers/sound/Readme.cards	Tue Oct 29 09:31:14 1996
@@ -1,9 +1,15 @@
-Configuring version 3.5.4 (for Linux) with some most common soundcards
-======================================================================
+Configuring version 3.7 (for Linux) with some most common soundcards
+====================================================================
+
+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
+not valid for OSS/Linux.
 
 IMPORTANT!	This document covers only cards that were "known" when
 		this driver version was released. Please look at
-		http://www.4front-tech.com/usslite for info about
+		http://www.4front-tech.com/ossfree for info about
 		cards introduced recently.
 
 		The following covers mainly the "old" configuration
@@ -22,45 +28,15 @@
 Cards that are not (fully) supported by this driver
 ---------------------------------------------------
 
-There are many soundcards which don't work with this driver
-version (v3.5). Support for some of them is expected to be
-available during/after summer 1996 (in version 3.6). Please check
-http://www.4front-tech.com/usslite for latest news. Please don't
-mail me and ask about these cards. The unsupported cards are:
-
-	- All PnP soundcards (SB PnP, GUS PnP, Soundscape PnP etc.)
-		Schedule for availability of PnP soundcard support in
-		USS/Lite depends on progress made by kernel PnP team
-		(probably in Linux 2.1.xx versions). With Linux 2.0.x
-		versions there are two ways to get PnP soundcards to work:
-	 	- Use isapnptools, DOS, Win95 or PnP aware BIOS to wake up the
-		card before starting the sound driver. See "Configuring PnP 
-		soundcards" below for some hints.
-		- Support for SB PnP and GUS PnP is present in USS/Linux (the
-		commercial version of this driver).
-	- Mwave soundcards and motherboards
-		(Version 3.6 or 3.7. Depends on how fast I get
-		suitable documents for Mwave).
-	- Emu8k (SB 32/AWE)
-		(Probably not _before_ summer 97. I know the unofficial
-		AWE programmers guide so don't send me more copies of it).
-	- Diamond Edge 3D
-		(ASAP. In practice this may take relatively long time).
-	- Compaq Deskpro
-		(Version 3.5.4-beta6 (already released))
-	- Sound Galaxy Washington/Waverider
-		(Audio features already in USS/Linux (USS/Lite soon). 
-		Can't promise the waverider synth since
-		availability of chip specs is uncertain).
-	- Yamaha OPL4 (on cards having _RAM_ for samples)
-		(Late 96?. Works as OPL3 with current driver versions)
+See http://www.4front-tech.com/ossfree for information about soundcards 
+to be supported in future. 
 
 How to use sound without recompiling kernel and/or sound driver
 ---------------------------------------------------------------
 
 There is commercial sound driver which should be released during Apr 96.
 It comes in precompiled form and doesn't require recompiling of kernel. See
-http://www.4Front-tech.com/uss.html for more info.
+http://www.4Front-tech.com/oss.html for more info.
 
 Configuring PnP cards
 ---------------------
@@ -75,9 +51,9 @@
 available for it (see information about CS4232 later in this document).
 
 PnP soundcards (as well as most other PnP ISA cards) are not supported
-by version 3.5 of this driver (Linux 1.3.xx and Linux 2.0.x). Proper
-support for them should be released during spring 96 
-(see http://www.4front-tech.com/usslite for latest info).
+by this version of the driver . Proper
+support for them should be released during spring 97 once kernel level
+PnP support is available.
 
 There is a method to get most of the PnP cards to work. The basic method
 is the following:
@@ -99,6 +75,7 @@
 Some machines have BIOS utility for setting PnP resources. This is a good
 way to configure some cards. In this case you don't need to boot DOS/Win95
 prior starting Linux.
+
 Another way to initialize PnP cards without DOS/Win95 is a Linux based
 PnP isolation tool. When writing this there is a pre alpha test version
 of such tool available from ftp://ftp.demon.co.uk/pub/unix/linux/utils. The
@@ -106,11 +83,9 @@
 solution which may be incompatible with future kernel versions having proper
 support for PnP cards. There are bugs in setting DMA channels in earlier
 versions of isapnptools so at least version 1.6 is required with soundcards.
-You can find latest version of isapnptools from
-ftp://ftp.demon.co.uk/pub/unix/linux/utils/
 
-These two methods don't work with GUS PnP which requires some additional
-initialization (cards DOS/Win95 driver does it). 
+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.
 
 Read this before trying to configure the driver
 -----------------------------------------------
@@ -138,25 +113,35 @@
 	SB 1.0 to 2.0
 	SB Pro
 	SB 16
-	NOTE!	The ASP chip and the EMU synth of AWE32 are not supported 
-		since their manufacturer doesn't release information about
-		the card. However, both SB16ASP and AWE32 work with
-		the driver just like a SB16. Also see the comment about some
-		unsupported cards at the end of this file.
-		(The OPL3 FM chip of SB32/AWE works but you cannot hear it).
+	SB32/AWE
+		Configure SB32/AWE just like SB16. See lowlevel/README.awe
+		for information about using the wave table synth.
 	SB16 compatible cards by other manufacturers than Creative.
-		You have been fooled since there are no SB16 compatible
+		You have been fooled since there are _no_ SB16 compatible
 		cards on the market (Feb 96). It's likely that your card
 		is compatible just with SB Pro but there is also a non-SB-
 		compatible 16 bit mode. Usually it's MSS/WSS but it could also
-		be a proprietary one like MV Jazz16 or ESS ES688.
+		be a proprietary one like MV Jazz16 or ESS ES688. OPTi
+		MAD16 chips are very common in so called "SB 16 bit cards".
+	"Supposed to be SB compatible" cards.
+		Forget the SB compatibility and check for other alternatives
+		first. The only cards that work with the SB driver in
+		Linux have been made by Creative Technology (there is at least
+		one chip on the card with "CREATIVE" printed on it). The
+		only other SB compatible chips are ESS and Jazz16 chips
+		(maybe ALSxxx chips too but they propably don't work).
+
+		Practically all soundcards have some kind of SB emulation mode
+		in addition to their native (16 bit) mode. In most cases this
+		(8 bit only) SB compatible mode doesn't work with Linux. However
+		in most cases the native 16 bit mode is supported by Linux.
 
 Gravis Ultrasound (GUS)
 	GUS
 	GUS + the 16 bit option
 	GUS MAX
 	GUS ACE (No MIDI port and audio recording)
-	GUS PnP (Partially supported)
+	GUS PnP (in GUS MAX compatible mode)
 
 MPU-401	and compatibles
 	The driver works both with the full (intelligent mode) MPU-401
@@ -230,8 +215,8 @@
 	NOTE! The new PnP SoundScape is not supported yet.
 
 MAD16 and Mozart based cards
-	The Mozart (OAK OTI-601), MAD16 (OPTi 82C928), MAD16 Pro (OPTi 82C929) 
-	and OPTi 82C930 interface
+	The Mozart (OAK OTI-601), MAD16 (OPTi 82C928), MAD16 Pro (OPTi 82C929),
+	OPTi 82C924 (non PnP mode) and OPTi 82C930 interface
 	chips are used in many different soundcards, including some
 	cards by Reveal miro and Turtle Beach (Tropez). The purpose of these
 	chips is to connect other audio components to the PC bus. The
@@ -240,16 +225,14 @@
 
 Audio Excel DSP16 
 	Support for this card was written by Riccardo Faccetti
-	(riccardo@cdc8g5.cdc.polimi.it). See aedsp16.c for more info.
-	(This driver is not functional in version 3.5 of this driver. A
-	patch should be made available during April 96 (sunsite.unc.edu)).
+	(riccardo@cdc8g5.cdc.polimi.it). The AEDSP16 driver included in
+	this source distribution is not fully functional. A patch is
+	available from sunsite.unc.edu/pub/Linux/kernel/sound.
 	
 Crystal CS4232 based cards such as AcerMagic S23, TB Tropez _Plus_ and 
 	many PC motherboards (Compaq, HP, Intel, ...)
 	CS4232 is a PnP multimedia chip which contains a CS3231A codec,
 	SB and MPU401 emulations. There is support for OPL3 too.
-	This is a temporary driver which uses the chip in non PnP mode
-	(The final driver should be included in version 3.6 of the driver).
 	Unfortunately the MPU401 mode doesn't work (I don't know how to
 	initialize it). 
 
@@ -454,7 +437,8 @@
 	- Answer 'y' if you have the AudioTrix Pro.
   "Support for MAD16 and/or Mozart based cards",
 	- Answer y if your card has a Mozart (OAK OTI-601) or MAD16
-	  (OPTi 82C928, 82C929 or 82C930) audio interface chip. These chips are
+	  (OPTi 82C928, 82C929, 82C924 or 82C930) audio interface chip. 
+	  These chips are
 	  currently quite common so it's possible that many no-name cards
 	  have one of them. In addition the MAD16 chip is used in some
 	  cards made by known manufacturers such as Turtle Beach (Tropez),
@@ -463,15 +447,11 @@
 	- This enables TB Maui specific initialization. Works with TB Maui
 	and TB Tropez (may not work with Tropez Plus).
 
-  "Audio Excel DSP 16 initialization support",
-	- Don't know much about this card. Look at aedsp16.c for more info.
 
 Then the configuration program asks some y/n questions about the higher
 level services. It's recommended to answer 'y' to each of these questions.
 Answer 'n' only if you know you will not need the option.
 
-  "/dev/dsp and /dev/audio supports (usually required)",
-	- Answering 'n' disables /dev/dsp and /dev/audio. Answer 'y'.
   "MIDI interface support",
 	- Answering 'n' disables /dev/midi## devices and access to any
 	  MIDI ports using /dev/sequencer and /dev/music. This option
@@ -705,7 +685,10 @@
 Ensoniq SoundScape
 ------------------
 
-NOTE!	The new PnP SoundScape is not supported yet.
+NOTE!	The new PnP SoundScape is not supported yet. Soundscape compatible
+	cards made by Reveal don't work with Linux. They use older revision
+	of the Soundscape chipset which is not fully compatible with
+	newer cards made by Ensoniq.
 
 The SoundScape driver handles initialization of MSS and MPU supports
 itself so you don't need to enable other drivers than SoundScape
@@ -719,7 +702,7 @@
 !!!!!	    purposes. It WAS required to change /dev/dsp (a symlink) to !!!!
 !!!!!	    point to /dev/dsp1.						!!!!
 !!!!!                                                                   !!!!
-!!!!!	    This is not required with USS versions 3.5-beta6 and later	!!!!
+!!!!!	    This is not required with OSS versions 3.5-beta6 and later	!!!!
 !!!!!	    since there is now just one audio device file. Please 	!!!!
 !!!!!	    change /dev/dsp to point back to /dev/dsp0 if you are	!!!!
 !!!!!	    upgrading from an earlier driver version using		!!!!
@@ -757,6 +740,10 @@
 soundscape.co0. New Soundscape revisions such as Elite and PnP use
 code files with higher numbers (.co2, .co3, etc.).
 
+NOTE!	Ensoniq Soundscape VIVO is not compatible with other Soundscape cards.
+	Currently it's possible to use it in Linux only with OSS/Linux
+	drivers.
+
 Check /var/adm/messages after running ssinit. The driver prints
 the board version after downloading the microcode file. That version
 number must match the number in the name of the microcode file (extension).
@@ -801,6 +788,10 @@
 can be enabled by configuring the card to use two DMA channels. Possible
 DMA channel pairs are: 0&1, 1&0 and 3&0.
 
+NOTE! Cards having an OPTi 82C924 chip work with OSS/Free only in
+non-PnP mode (usually jumper selectable). The PnP mode is supported only
+by OSS/Linux.
+
 MV Jazz (ProSonic)
 ------------------
 
@@ -855,10 +846,6 @@
 for all of the settings. Configure driver for MSS, MPU, SB/SB Pro  and OPL3 
 supports with these cards. 
 
-The config program asks if you want support for the mixer of
-SG NX Pro. Answer 'y' to these questions if you have one of the above 8 or
-16 bit Aztech cards.
-
 There are some new Sound Galaxies in the market. I have no experience with
 them so read the card's manual carefully.
 
@@ -992,14 +979,12 @@
 to all low level drivers and be tested too, maybe with multiple
 operating systems). For this reason I have made a decision to not support
 obsolete cards. It's possible that someone else makes a separately 
-distributed driver (diffs) for the card. Version v3.6 will be much more
-modular so making separately distributed drivers will be easier with it.
-(The bad news is that v3.6 will not be available before summer -96).
+distributed driver (diffs) for the card. 
 
 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/usslite). Then please contact
+(http://www.4front-tech.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.
@@ -1015,12 +1000,12 @@
 products to public or at least their require signing a NDA. It's not
 possible to implement a freeware driver for them. However it's possible
 that support for such cards become available in the commercial version
-of this driver (see http://www.4Front-tech.com/uss.html for more info).
+of this driver (see http://www.4Front-tech.com/oss.html for more info).
 
 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/usslite/new_cards.html)
+at the home page (http://www.4front-tech.com/ossfree/new_cards.html)
 for latest info.
 
 Information about unsupported soundcards and chipsets is welcome as well
@@ -1032,9 +1017,9 @@
 hannu@voxware.pp.fi
 
 Personal home page:	   http://personal.eunet.fi/pp/voxware/hannu.html
-www home page of USS/Lite: http://www.4front-tech.com/usslite
+www home page of OSS/Free: http://www.4front-tech.com/ossfree
   European/Finnish mirror: http://personal.eunet.fi/pp/voxware
 
-www home page of commercial
-Open Sound System drivers: http://www.4front-tech.com/uss.html
+www home page of commercial OSS
+(Open Sound System) drivers: http://www.4front-tech.com/oss.html
 
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/Readme.linux linux/drivers/sound/Readme.linux
--- v2.1.5/linux/drivers/sound/Readme.linux	Sat Jul  6 11:31:43 1996
+++ linux/drivers/sound/Readme.linux	Tue Oct 29 09:31:13 1996
@@ -67,7 +67,7 @@
 check for possible boot (insmod) time error messages in /var/adm/messages.
 
 - Other messages or problems
-Please check http://www.4front-tech.com/usslite for more info.
+Please check http://www.4front-tech.com/osslite for more info.
 
 Hannu Savolainen
 hannu@voxware.pp.fi
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
--- v2.1.5/linux/drivers/sound/ad1848.c	Sun Aug 18 10:46:48 1996
+++ linux/drivers/sound/ad1848.c	Tue Oct 29 09:31:24 1996
@@ -17,7 +17,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -36,6 +36,7 @@
   {
     int             base;
     int             irq;
+    int             dma1, dma2;
     int             dual_dma;	/* 1, when two DMA channels allocated */
     unsigned char   MCE_bit;
     unsigned char   saved_regs[16];
@@ -46,6 +47,7 @@
     int             channels;
     int             audio_format;
     unsigned char   format_bits;
+    int             audio_flags;
 
     int             xfer_count;
     int             audio_mode;
@@ -63,14 +65,15 @@
 
     /* Mixer parameters */
     int             recmask;
-    int             supported_devices;
-    int             supported_rec_devices;
-    unsigned short  levels[32];
+    int             supported_devices, orig_devices;
+    int             supported_rec_devices, orig_rec_devices;
+    int            *levels;
+    short           mixer_reroute[32];
     int             dev_no;
     volatile unsigned long timer_ticks;
     int             timer_running;
     int             irq_ok;
-    int            *osp;
+    mixer_ents     *mix_devices;
   }
 
 ad1848_info;
@@ -86,12 +89,12 @@
 {
   0,
   AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW,
-  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM,
-  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM,
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
   AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW,	/* AD1845 */
-  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM,
-  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM,
-  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM
 };
 
 static ad1848_info dev_info[MAX_AUDIO_DEV];
@@ -128,7 +131,7 @@
 
   save_flags (flags);
   cli ();
-  outb ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc));
+  outb (((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr (devc));
   x = inb (io_Indexed_Data (devc));
   /*  printk("(%02x<-%02x) ", reg|devc->MCE_bit, x); */
   restore_flags (flags);
@@ -148,8 +151,8 @@
 
   save_flags (flags);
   cli ();
-  outb ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc));
-  outb ((unsigned char) (data & 0xff), io_Indexed_Data (devc));
+  outb (((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr (devc));
+  outb (((unsigned char) (data & 0xff)), io_Indexed_Data (devc));
   /* printk("(%02x->%02x) ", reg|devc->MCE_bit, data); */
   restore_flags (flags);
 }
@@ -204,6 +207,7 @@
 /*
  * Let's have some delay
  */
+
   for (i = 0; i < 1000; i++)
     inb (devc->base);
 }
@@ -220,7 +224,7 @@
     inb (devc->base);
 
   /*
-     * Restore back old volume registers (unmute)
+   * Restore back old volume registers (unmute)
    */
   for (i = 6; i < 8; i++)
     {
@@ -249,7 +253,7 @@
       return;
     }
 
-  outb (devc->MCE_bit, io_Index_Addr (devc));
+  outb ((devc->MCE_bit), io_Index_Addr (devc));
   restore_flags (flags);
 }
 
@@ -268,7 +272,7 @@
 
   devc->MCE_bit = 0x00;
   prev = inb (io_Index_Addr (devc));
-  outb (0x00, io_Index_Addr (devc));	/* Clear the MCE bit */
+  outb ((0x00), io_Index_Addr (devc));	/* Clear the MCE bit */
 
   if ((prev & 0x40) == 0)	/* Not in MCE mode */
     {
@@ -276,7 +280,7 @@
       return;
     }
 
-  outb (0x00, io_Index_Addr (devc));	/* Clear the MCE bit */
+  outb ((0x00), io_Index_Addr (devc));	/* Clear the MCE bit */
   wait_for_calibration (devc);
   restore_flags (flags);
 }
@@ -290,6 +294,15 @@
 
   mask &= devc->supported_rec_devices;
 
+  /* Rename the mixer bits if necessary */
+  for (i = 0; i < 32; i++)
+    if (devc->mixer_reroute[i] != i)
+      if (mask & (1 << i))
+	{
+	  mask &= ~(1 << i);
+	  mask |= (1 << devc->mixer_reroute[i]);
+	}
+
   n = 0;
   for (i = 0; i < 32; i++)	/* Count selected device bits */
     if (mask & (1 << i))
@@ -339,21 +352,30 @@
   ad_write (devc, 0, (ad_read (devc, 0) & 0x3f) | recdev);
   ad_write (devc, 1, (ad_read (devc, 1) & 0x3f) | recdev);
 
+  /* Rename the mixer bits back if necessary */
+  for (i = 0; i < 32; i++)
+    if (devc->mixer_reroute[i] != i)
+      if (mask & (1 << devc->mixer_reroute[i]))
+	{
+	  mask &= ~(1 << devc->mixer_reroute[i]);
+	  mask |= (1 << i);
+	}
+
   devc->recmask = mask;
   return mask;
 }
 
 static void
-change_bits (unsigned char *regval, int dev, int chn, int newval)
+change_bits (ad1848_info * devc, unsigned char *regval, int dev, int chn, int newval)
 {
   unsigned char   mask;
   int             shift;
 
-  if (mix_devices[dev][chn].polarity == 1)	/* Reverse */
+  if (devc->mix_devices[dev][chn].polarity == 1)	/* Reverse */
     newval = 100 - newval;
 
-  mask = (1 << mix_devices[dev][chn].nbits) - 1;
-  shift = mix_devices[dev][chn].bitpos;
+  mask = (1 << devc->mix_devices[dev][chn].nbits) - 1;
+  shift = devc->mix_devices[dev][chn].bitpos;
   newval = (int) ((newval * mask) + 50) / 100;	/* Scale it */
 
   *regval &= ~(mask << shift);	/* Clear bits */
@@ -364,7 +386,9 @@
 ad1848_mixer_get (ad1848_info * devc, int dev)
 {
   if (!((1 << dev) & devc->supported_devices))
-    return -(EINVAL);
+    return -EINVAL;
+
+  dev = devc->mixer_reroute[dev];
 
   return devc->levels[dev];
 }
@@ -379,12 +403,20 @@
   int             regoffs;
   unsigned char   val;
 
+  if (dev > 31)
+    return -EINVAL;
+
+  if (!(devc->supported_devices & (1 << dev)))
+    return -EINVAL;
+
+  dev = devc->mixer_reroute[dev];
+
   if (left > 100)
     left = 100;
   if (right > 100)
     right = 100;
 
-  if (mix_devices[dev][RIGHT_CHN].nbits == 0)	/* Mono control */
+  if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0)	/* Mono control */
     right = left;
 
   retvol = left | (right << 8);
@@ -397,14 +429,8 @@
   left = mix_cvt[left];
   right = mix_cvt[right];
 
-  if (dev > 31)
-    return -(EINVAL);
-
-  if (!(devc->supported_devices & (1 << dev)))
-    return -(EINVAL);
-
-  if (mix_devices[dev][LEFT_CHN].nbits == 0)
-    return -(EINVAL);
+  if (devc->mix_devices[dev][LEFT_CHN].nbits == 0)
+    return -EINVAL;
 
   devc->levels[dev] = retvol;
 
@@ -412,9 +438,9 @@
      * Set the left channel
    */
 
-  regoffs = mix_devices[dev][LEFT_CHN].regno;
+  regoffs = devc->mix_devices[dev][LEFT_CHN].regno;
   val = ad_read (devc, regoffs);
-  change_bits (&val, dev, LEFT_CHN, left);
+  change_bits (devc, &val, dev, LEFT_CHN, left);
   ad_write (devc, regoffs, val);
   devc->saved_regs[regoffs] = val;
 
@@ -422,12 +448,12 @@
      * Set the right channel
    */
 
-  if (mix_devices[dev][RIGHT_CHN].nbits == 0)
+  if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0)
     return retvol;		/* Was just a mono channel */
 
-  regoffs = mix_devices[dev][RIGHT_CHN].regno;
+  regoffs = devc->mix_devices[dev][RIGHT_CHN].regno;
   val = ad_read (devc, regoffs);
-  change_bits (&val, dev, RIGHT_CHN, right);
+  change_bits (devc, &val, dev, RIGHT_CHN, right);
   ad_write (devc, regoffs, val);
   devc->saved_regs[regoffs] = val;
 
@@ -438,17 +464,33 @@
 ad1848_mixer_reset (ad1848_info * devc)
 {
   int             i;
+  char            name[32];
+
+  devc->mix_devices = &(ad1848_mix_devices[0]);
+
+  sprintf (name, "%s_%d", devc->chip_name, nr_ad1848_devs);
+
+  for (i = 0; i < 32; i++)
+    devc->mixer_reroute[i] = i;
 
   switch (devc->model)
     {
     case MD_4231:
     case MD_4231A:
-    case MD_C930:
-    case MD_IWAVE:
     case MD_1845:
       devc->supported_devices = MODE2_MIXER_DEVICES;
       break;
 
+    case MD_C930:
+      devc->supported_devices = C930_MIXER_DEVICES;
+      devc->mix_devices = &(c930_mix_devices[0]);
+      break;
+
+    case MD_IWAVE:
+      devc->supported_devices = MODE3_MIXER_DEVICES;
+      devc->mix_devices = &(iwave_mix_devices[0]);
+      break;
+
     case MD_4232:
       devc->supported_devices = MODE3_MIXER_DEVICES;
       break;
@@ -458,10 +500,14 @@
     }
 
   devc->supported_rec_devices = MODE1_REC_DEVICES;
+  devc->orig_devices = devc->supported_devices;
+  devc->orig_rec_devices = devc->supported_rec_devices;
+
+  devc->levels = load_mixer_volumes (name, default_mixer_levels, 1);
 
   for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
     if (devc->supported_devices & (1 << i))
-      ad1848_mixer_set (devc, i, default_mixer_levels[i]);
+      ad1848_mixer_set (devc, i, devc->levels[i]);
   ad1848_set_recmask (devc, SOUND_MASK_MIC);
 }
 
@@ -472,16 +518,19 @@
 
   if (((cmd >> 8) & 0xff) == 'M')
     {
+      int             val;
 
       if (_IOC_DIR (cmd) & _IOC_WRITE)
 	switch (cmd & 0xff)
 	  {
 	  case SOUND_MIXER_RECSRC:
-	    return snd_ioctl_return ((int *) arg, ad1848_set_recmask (devc, get_user ((int *) arg)));
+	    get_user (val, (int *) arg);
+	    return ioctl_out (arg, ad1848_set_recmask (devc, val));
 	    break;
 
 	  default:
-	    return snd_ioctl_return ((int *) arg, ad1848_mixer_set (devc, cmd & 0xff, get_user ((int *) arg)));
+	    get_user (val, (int *) arg);
+	    return ioctl_out (arg, ad1848_mixer_set (devc, cmd & 0xff, val));
 	  }
       else
 	switch (cmd & 0xff)	/*
@@ -490,31 +539,34 @@
 	  {
 
 	  case SOUND_MIXER_RECSRC:
-	    return snd_ioctl_return ((int *) arg, devc->recmask);
+	    return ioctl_out (arg, devc->recmask);
 	    break;
 
 	  case SOUND_MIXER_DEVMASK:
-	    return snd_ioctl_return ((int *) arg, devc->supported_devices);
+	    return ioctl_out (arg, devc->supported_devices);
 	    break;
 
 	  case SOUND_MIXER_STEREODEVS:
-	    return snd_ioctl_return ((int *) arg, devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX));
+	    if (devc->model == MD_C930)
+	      return ioctl_out (arg, devc->supported_devices);
+	    else
+	      return ioctl_out (arg, devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX));
 	    break;
 
 	  case SOUND_MIXER_RECMASK:
-	    return snd_ioctl_return ((int *) arg, devc->supported_rec_devices);
+	    return ioctl_out (arg, devc->supported_rec_devices);
 	    break;
 
 	  case SOUND_MIXER_CAPS:
-	    return snd_ioctl_return ((int *) arg, SOUND_CAP_EXCL_INPUT);
+	    return ioctl_out (arg, SOUND_CAP_EXCL_INPUT);
 	    break;
 
 	  default:
-	    return snd_ioctl_return ((int *) arg, ad1848_mixer_get (devc, cmd & 0xff));
+	    return ioctl_out (arg, ad1848_mixer_get (devc, cmd & 0xff));
 	  }
     }
   else
-    return -(EINVAL);
+    return -EINVAL;
 }
 
 static int
@@ -560,7 +612,7 @@
 
   n = sizeof (speed_table) / sizeof (speed_struct);
 
-  if (arg == 0)
+  if (arg <= 0)
     return devc->speed;
 
   if (devc->model == MD_1845)	/* AD1845 has different timer than others */
@@ -730,7 +782,7 @@
   unsigned long   flags;
 
   if (dev < 0 || dev >= num_audiodevs)
-    return -(ENXIO);
+    return -ENXIO;
 
   devc = (ad1848_info *) audio_devs[dev]->devc;
 
@@ -740,7 +792,7 @@
   if (devc->opened)
     {
       restore_flags (flags);
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   devc->dual_dma = 0;
@@ -788,7 +840,7 @@
 static int
 ad1848_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -828,8 +880,7 @@
   save_flags (flags);
   cli ();
 
-  /* ad_write (devc, 9, ad_read (devc, 9) & ~ 0x01); / * Playback disable */
-  ad1848_halt (dev);
+  ad1848_halt_output (dev);
   DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
 
   ad_write (devc, 15, (unsigned char) (cnt & 0xff));
@@ -880,8 +931,7 @@
 
   if (dma_restart)
     {
-      /* ad1848_halt (dev); */
-      ad_write (devc, 9, ad_read (devc, 9) & ~0x02);	/* Capture disable */
+      ad1848_halt_input (dev);
       DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
     }
 
@@ -911,6 +961,25 @@
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
 
   ad_mute (devc);
+  {
+/*
+ * This code fragment ensures that the playback FIFO is empty before
+ * setting the codec for playback. Enabling playback for a moment should
+ * be enough to do that.
+ */
+    int             tmout;
+
+    ad_write (devc, 9, ad_read (devc, 9) | 0x01);	/* Enable playback */
+    disable_dma (audio_devs[dev]->dmachan1);
+    for (tmout = 0; tmout < 1000000; tmout++)
+      if (ad_read (devc, 11) & 0x10)	/* DRQ active */
+	if (tmout > 10000)
+	  break;
+    ad_write (devc, 9, ad_read (devc, 9) & ~0x01);	/* Stop playback */
+
+    enable_dma (audio_devs[dev]->dmachan1);
+    devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
+  }
 
   return ad1848_prepare_for_IO (dev, bsize, bcount);
 }
@@ -943,13 +1012,6 @@
 
   old_fs = ad_read (devc, 8);
 
-  if (devc->model != MD_4232)
-    if (fs == old_fs)		/* No change */
-      {
-	restore_flags (flags);
-	devc->xfer_count = 0;
-	return 0;
-      }
 
   ad_enter_MCE (devc);		/* Enables changes to the format select reg */
 
@@ -963,9 +1025,12 @@
   /*
    * Write to I8 starts resynchronization. Wait until it completes.
    */
-  timeout = 10000;
-  while (timeout > 0 && inb (devc->base) == 0x80)
-    timeout--;
+  timeout = 0;
+  while (timeout < 100 && inb (devc->base) != 0x80)
+    timeout++;
+  timeout = 0;
+  while (timeout < 10000 && inb (devc->base) == 0x80)
+    timeout++;
 
   /*
      * If mode >= 2 (CS4231), set I28 also. It's the capture format register.
@@ -975,12 +1040,15 @@
       ad_write (devc, 28, fs);
 
       /*
-         * Write to I28 starts resynchronization. Wait until it completes.
+       * Write to I28 starts resynchronization. Wait until it completes.
        */
-      timeout = 10000;
-      while (timeout > 0 && inb (devc->base) == 0x80)
-	timeout--;
-
+      timeout = 0;
+      while (timeout < 100 && inb (devc->base) != 0x80)
+	timeout++;
+
+      timeout = 0;
+      while (timeout < 10000 && inb (devc->base) == 0x80)
+	timeout++;
     }
 
   if (devc->model == MD_4232)
@@ -1020,6 +1088,7 @@
 
   if (bits & 0x02)
     ad1848_halt_input (dev);
+  devc->audio_mode = 0;
 }
 
 static void
@@ -1028,31 +1097,31 @@
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
   unsigned long   flags;
 
+  if (!(ad_read (devc, 9) & 0x02))
+    return;			/* Capture not enabled */
+
   save_flags (flags);
   cli ();
 
   ad_mute (devc);
 
-  if (devc->model == MD_4232)	/* Use applied black magic */
-    {
-      int             tmout;
+  {
+    int             tmout;
 
-      disable_dma (audio_devs[dev]->dmachan1);
+    disable_dma (audio_devs[dev]->dmachan1);
 
-      for (tmout = 0; tmout < 100000; tmout++)
-	if (ad_read (devc, 11) & 0x10)
-	  break;
-      ad_write (devc, 9, ad_read (devc, 9) & ~0x01);	/* Stop playback */
+    for (tmout = 0; tmout < 100000; tmout++)
+      if (ad_read (devc, 11) & 0x10)
+	break;
+    ad_write (devc, 9, ad_read (devc, 9) & ~0x02);	/* Stop capture */
 
-      enable_dma (audio_devs[dev]->dmachan1);
-      restore_flags (flags);
-      return;
-    }
-  ad_write (devc, 9, ad_read (devc, 9) & ~0x02);	/* Stop capture */
+    enable_dma (audio_devs[dev]->dmachan1);
+    devc->audio_mode &= ~PCM_ENABLE_INPUT;
+  }
 
 
-  outb (0, io_Status (devc));	/* Clear interrupt status */
-  outb (0, io_Status (devc));	/* Clear interrupt status */
+  outb ((0), io_Status (devc));	/* Clear interrupt status */
+  outb ((0), io_Status (devc));	/* Clear interrupt status */
 
   devc->audio_mode &= ~PCM_ENABLE_INPUT;
 
@@ -1065,30 +1134,30 @@
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
   unsigned long   flags;
 
+  if (!(ad_read (devc, 9) & 0x01))
+    return;			/* Playback not enabled */
+
   save_flags (flags);
   cli ();
 
   ad_mute (devc);
-  if (devc->model == MD_4232)	/* Use applied black magic */
-    {
-      int             tmout;
+  {
+    int             tmout;
 
-      disable_dma (audio_devs[dev]->dmachan1);
+    disable_dma (audio_devs[dev]->dmachan1);
 
-      for (tmout = 0; tmout < 100000; tmout++)
-	if (ad_read (devc, 11) & 0x10)
-	  break;
-      ad_write (devc, 9, ad_read (devc, 9) & ~0x01);	/* Stop playback */
+    for (tmout = 0; tmout < 100000; tmout++)
+      if (ad_read (devc, 11) & 0x10)
+	break;
+    ad_write (devc, 9, ad_read (devc, 9) & ~0x01);	/* Stop playback */
 
-      enable_dma (audio_devs[dev]->dmachan1);
-      restore_flags (flags);
-      return;
-    }
-  ad_write (devc, 9, ad_read (devc, 9) & ~0x01);	/* Stop playback */
+    enable_dma (audio_devs[dev]->dmachan1);
+    devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
+  }
 
 
-  outb (0, io_Status (devc));	/* Clear interrupt status */
-  outb (0, io_Status (devc));	/* Clear interrupt status */
+  outb ((0), io_Status (devc));	/* Clear interrupt status */
+  outb ((0), io_Status (devc));	/* Clear interrupt status */
 
   devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
 
@@ -1112,20 +1181,20 @@
   if (state & PCM_ENABLE_OUTPUT)
     tmp |= 0x01;
 
-  if (!(state & PCM_ENABLE_OUTPUT) && old & 0x01);
   ad_mute (devc);
 
   ad_write (devc, 9, tmp);
 
-  if (state & PCM_ENABLE_OUTPUT && !(old & 0x01));
   ad_unmute (devc);
 
   restore_flags (flags);
 }
 
-int
-ad1848_detect (int io_base, int *ad_flags, int *osp)
+void
+ad1848_init_hw (ad1848_info * devc)
 {
+  int             i;
+
   /*
    * Initial values for the indirect registers of CS4248/AD1848.
    */
@@ -1139,6 +1208,64 @@
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
   };
 
+
+  for (i = 0; i < 16; i++)
+    ad_write (devc, i, init_values[i]);
+
+
+  ad_mute (devc);		/* Initialize some variables */
+  ad_unmute (devc);		/* Leave it unmuted now */
+
+  if (devc->model > MD_1848)
+    {
+      ad_write (devc, 12, ad_read (devc, 12) | 0x40);	/* Mode2 = enabled */
+
+      if (devc->model == MD_IWAVE)
+	ad_write (devc, 12, 0x6c);	/* Select codec mode 3 */
+
+      for (i = 16; i < 32; i++)
+	ad_write (devc, i, init_values[i]);
+
+    }
+
+  if (devc->model > MD_1848)
+    {
+      if (devc->audio_flags & DMA_DUPLEX)
+	ad_write (devc, 9, ad_read (devc, 9) & ~0x04);	/* Dual DMA mode */
+      else
+	ad_write (devc, 9, ad_read (devc, 9) | 0x04);	/* Single DMA mode */
+
+      if (devc->model == MD_1845)
+	ad_write (devc, 27, ad_read (devc, 27) | 0x08);		/* Alternate freq select enabled */
+
+      if (devc->model == MD_IWAVE)
+	{			/* Some magic Interwave specific initialization */
+	  ad_write (devc, 12, 0x6c);	/* Select codec mode 3 */
+	  ad_write (devc, 17, 0xc2);	/* Alternate feature enable */
+	}
+    }
+  else
+    {
+      devc->audio_flags &= ~DMA_DUPLEX;
+      ad_write (devc, 9, ad_read (devc, 9) | 0x04);	/* Single DMA mode */
+    }
+
+  outb ((0), io_Status (devc));	/* Clear pending interrupts */
+
+  /*
+   * Toggle the MCE bit. It completes the initialization phase.
+   */
+
+  ad_enter_MCE (devc);		/* In case the bit was off */
+  ad_leave_MCE (devc);
+
+  ad1848_mixer_reset (devc);
+}
+
+int
+ad1848_detect (int io_base, int *ad_flags, int *osp)
+{
+
   unsigned char   tmp;
   ad1848_info    *devc = &dev_info[nr_ad1848_devs];
   unsigned char   tmp1 = 0xff, tmp2 = 0xff;
@@ -1153,8 +1280,10 @@
   if (ad_flags)
     {
       if (*ad_flags == 0x12345678)
-	interwave = 1;
-      *ad_flags = 0;
+	{
+	  interwave = 1;
+	  *ad_flags = 0;
+	}
     }
 
   if (nr_ad1848_devs >= MAX_AUDIO_DEV)
@@ -1176,7 +1305,7 @@
   devc->opened = 0;
   devc->chip_name = "AD1848";
   devc->model = MD_1848;	/* AD1848 or CS4248 */
-  devc->osp = osp;
+  devc->levels = NULL;
   devc->debug_flag = 0;
 
   /*
@@ -1190,6 +1319,20 @@
    */
 
   DDB (printk ("ad1848_detect() - step A\n"));
+
+/*
+ * Wait for the device to stop initialization
+ */
+  /* outb(( 0x0b),  devc->base); */
+
+  for (i = 0; i < 10000000; i++)
+    {
+      unsigned char   x = inb (devc->base);
+
+      if (x == 0xff || !(x & 0x80))
+	break;
+    }
+
   if ((inb (devc->base) & 0x80) != 0x00)	/* Not a AD1848 */
     {
       DDB (printk ("ad1848 detect error - step A (%02x)\n",
@@ -1284,7 +1427,14 @@
    */
 
   DDB (printk ("ad1848_detect() - step G\n"));
-  ad_write (devc, 12, 0x40);	/* Set mode2, clear 0x80 */
+
+  if (ad_flags && *ad_flags == 400)
+    *ad_flags = 0;
+  else
+    ad_write (devc, 12, 0x40);	/* Set mode2, clear 0x80 */
+
+  if (ad_flags)
+    *ad_flags = 0;
 
   tmp1 = ad_read (devc, 12);
   if (tmp1 & 0x80)
@@ -1419,22 +1569,6 @@
   if (devc->model == MD_1848 && ad1847_flag)
     devc->chip_name = "AD1847";
 
-  for (i = 0; i < 16; i++)
-    ad_write (devc, i, init_values[i]);
-
-  ad_mute (devc);		/* Initialize some variables */
-  ad_unmute (devc);		/* Leave it unmuted now */
-
-  if (devc->model > MD_1848)
-    {
-      ad_write (devc, 12, ad_read (devc, 12) | 0x40);	/* Mode2 = enabled */
-
-      if (devc->model == MD_IWAVE)
-	ad_write (devc, 12, 0x6c);	/* Select codec mode 3 */
-
-      for (i = 16; i < 32; i++)
-	ad_write (devc, i, init_values[i]);
-    }
 
   return 1;
 }
@@ -1454,7 +1588,6 @@
 
   ad1848_info    *devc = &dev_info[nr_ad1848_devs];
 
-  int             audio_flags = DMA_AUTOMODE;
 
 
   request_region (devc->base, 4, devc->chip_name);
@@ -1462,37 +1595,9 @@
   devc->irq = (irq > 0) ? irq : 0;
   devc->opened = 0;
   devc->timer_ticks = 0;
-  devc->osp = osp;
-
-  if (devc->model > MD_1848)
-    {
-      if (dma_capture == dma_playback || dma_capture == -1 || dma_playback == -1)
-	{
-	  ad_write (devc, 9, ad_read (devc, 9) | 0x04);		/* Single DMA mode */
-	  audio_flags &= ~DMA_DUPLEX;
-	}
-      else
-	{
-	  ad_write (devc, 9, ad_read (devc, 9) & ~0x04);	/* Dual DMA mode */
-	  audio_flags |= DMA_DUPLEX;
-	}
-
-      if (devc->model == MD_1845)
-	ad_write (devc, 27, ad_read (devc, 27) | 0x08);		/* Alternate freq select enabled */
-
-      if (devc->model == MD_IWAVE)
-	{			/* Some magic Interwave specific initialization */
-	  ad_write (devc, 12, 0x6c);	/* Select codec mode 3 */
-	  ad_write (devc, 17, 0xc2);	/* Alternate feature enable */
-	}
-    }
-  else
-    {
-      audio_flags &= ~DMA_DUPLEX;
-      ad_write (devc, 9, ad_read (devc, 9) | 0x04);	/* Single DMA mode */
-    }
-
-  outb (0, io_Status (devc));	/* Clear pending interrupts */
+  devc->dma1 = dma_playback;
+  devc->dma2 = dma_capture;
+  devc->audio_flags = DMA_AUTOMODE;
 
   if (name != NULL && name[0] != 0)
     sprintf (dev_name,
@@ -1504,14 +1609,22 @@
   conf_printf2 (dev_name,
 		devc->base, devc->irq, dma_playback, dma_capture);
 
-  if (devc->model == MD_1848)
-    audio_flags |= DMA_HARDSTOP;
+  if (devc->model == MD_1848 || devc->model == MD_C930)
+    devc->audio_flags |= DMA_HARDSTOP;
+
+  if (devc->model > MD_1848)
+    {
+      if (devc->dma1 == devc->dma2 || devc->dma2 == -1 || devc->dma1 == -1)
+	devc->audio_flags &= ~DMA_DUPLEX;
+      else
+	devc->audio_flags |= DMA_DUPLEX;
+    }
 
   if ((my_dev = sound_install_audiodrv (AUDIO_DRIVER_VERSION,
 					dev_name,
 					&ad1848_audio_driver,
 					sizeof (struct audio_driver),
-					audio_flags,
+					devc->audio_flags,
 					ad_format_mask[devc->model],
 					devc,
 					dma_playback,
@@ -1520,17 +1633,21 @@
       return;
     }
 
+  nr_ad1848_devs++;
+
+  ad1848_init_hw (devc);
+
   if (irq > 0)
     {
       irq2dev[irq] = devc->dev_no = my_dev;
       if (snd_set_irq_handler (devc->irq, ad1848_interrupt,
 			       "SoundPort",
-			       devc->osp) < 0)
+			       NULL) < 0)
 	{
 	  printk ("ad1848: IRQ in use\n");
 	}
 
-      if (devc->model != MD_1848)
+      if (devc->model != MD_1848 && devc->model != MD_C930)
 	{
 	  int             x;
 	  unsigned char   tmp = ad_read (devc, 16);
@@ -1547,17 +1664,20 @@
 	  if (devc->timer_ticks == 0)
 	    printk ("ad1848: Interrupt test failed (IRQ%d)\n", devc->irq);
 	  else
-	    devc->irq_ok = 1;
+	    {
+	      DDB (printk ("Interrupt test OK\n"));
+	      devc->irq_ok = 1;
+	    }
 	}
       else
 	devc->irq_ok = 1;	/* Couldn't test. assume it's OK */
     }
   else if (irq < 0)
     irq2dev[-irq] = devc->dev_no = my_dev;
-  nr_ad1848_devs++;
 
 #ifdef CONFIG_SEQUENCER
-  if (devc->model != MD_1848 && devc->model != MD_1845 && devc->irq_ok)
+  if (devc->model != MD_1848 &&
+      devc->model != MD_C930 && devc->irq_ok)
     ad1848_tmr_install (my_dev);
 #endif
 
@@ -1571,14 +1691,6 @@
 	  printk ("ad1848.c: Can't allocate DMA%d\n", dma_capture);
     }
 
-  /*
-     * Toggle the MCE bit. It completes the initialization phase.
-   */
-
-  ad_enter_MCE (devc);		/* In case the bit was off */
-  ad_leave_MCE (devc);
-  ad1848_mixer_reset (devc);
-
   if (sound_install_mixer (MIXER_DRIVER_VERSION,
 			   dev_name,
 			   &ad1848_mixer_operations,
@@ -1590,6 +1702,59 @@
 }
 
 void
+ad1848_control (int cmd, int arg)
+{
+  ad1848_info    *devc;
+
+  if (nr_ad1848_devs < 1)
+    return;
+
+  devc = &dev_info[nr_ad1848_devs - 1];
+
+  switch (cmd)
+    {
+    case AD1848_SET_XTAL:	/* Change clock frequency of AD1845 (only ) */
+      if (devc->model != MD_1845)
+	return;
+      ad_enter_MCE (devc);
+      ad_write (devc, 29, (ad_read (devc, 29) & 0x1f) | (arg << 5));
+      ad_leave_MCE (devc);
+      break;
+
+    case AD1848_MIXER_REROUTE:
+      {
+	int             o = (arg >> 8) & 0xff;
+	int             n = arg & 0xff;
+
+	if (n == SOUND_MIXER_NONE)
+	  {			/* Just hide this control */
+	    ad1848_mixer_set (devc, o, 0);	/* Shut up it */
+	    devc->supported_devices &= ~(1 << o);
+	    devc->supported_rec_devices &= ~(1 << o);
+	    return;
+	  }
+
+	/* Make the mixer control identified by o to appear as n */
+
+	if (o < 0 || o > SOUND_MIXER_NRDEVICES)
+	  return;
+	if (n < 0 || n > SOUND_MIXER_NRDEVICES)
+	  return;
+	if (!(devc->supported_devices & (1 << o)))
+	  return;		/* Not supported */
+
+	devc->mixer_reroute[n] = o;	/* Rename the control */
+	devc->supported_devices &= ~(1 << o);
+	devc->supported_devices |= (1 << n);
+	if (devc->supported_rec_devices & (1 << o))
+	  devc->supported_rec_devices |= (1 << n);
+	devc->supported_rec_devices &= ~(1 << o);
+      }
+      break;
+    }
+}
+
+void
 ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma)
 {
   int             i, dev = 0;
@@ -1629,6 +1794,7 @@
   ad1848_info    *devc;
   int             dev;
   int             alt_stat = 0xff;
+  unsigned char   c930_stat = 0;
 
   if (irq < 0 || irq > 15)
     {
@@ -1655,6 +1821,8 @@
   else
     devc = (ad1848_info *) audio_devs[dev]->devc;
 
+interrupt_again:		/* Jump back here if int status doesn't reset */
+
   status = inb (io_Status (devc));
 
   if (status == 0x80)
@@ -1662,8 +1830,25 @@
 
   if (status & 0x01)
     {
-
-      if (devc->model != MD_1848)
+      if (devc->model == MD_C930)
+	{			/* 82C930 has interrupt status register in MAD16 register MC11 */
+	  unsigned long   flags;
+
+	  save_flags (flags);
+	  cli ();
+
+	  alt_stat = 0;
+
+	  outb ((11), 0xe0e);
+	  c930_stat = inb (0xe0f);
+
+	  if (c930_stat & 0x04)
+	    alt_stat |= 0x10;	/* Playback intr */
+	  if (c930_stat & 0x08)
+	    alt_stat |= 0x20;	/* Playback intr */
+	  restore_flags (flags);
+	}
+      else if (devc->model != MD_1848)
 	alt_stat = ad_read (devc, 24);
 
       if (devc->opened && devc->audio_mode & PCM_ENABLE_INPUT && alt_stat & 0x20)
@@ -1687,10 +1872,30 @@
 	}
     }
 
-  if (devc->model != MD_1848)
+  if (devc->model == MD_C930)
+    {				/* 82C930 has interrupt status register in MAD16 register MC11 */
+      unsigned long   flags;
+
+      save_flags (flags);
+      cli ();
+
+      outb ((11), 0xe0e);
+      outb ((~c930_stat), 0xe0f);
+      restore_flags (flags);
+    }
+  else if (devc->model != MD_1848)
     ad_write (devc, 24, ad_read (devc, 24) & ~alt_stat);	/* Selective ack */
   else
-    outb (0, io_Status (devc));	/* Clear interrupt status */
+    outb ((0), io_Status (devc));	/* Clear interrupt status */
+
+/*
+ * Sometimes playback or capture interrupts occur while a timer interrupt
+ * is being handled. The interrupt will not be retriggered if we don't
+ * handle it now. Check if an interrupt is still pending and restart
+ * the handler in this case.
+ */
+  if (inb (io_Status (devc)) & 0x01)
+    goto interrupt_again;
 }
 
 /*
@@ -1733,7 +1938,7 @@
       return 0;
     }
 
-  outb (tmp | 0x04, 0xc44);	/* Select bank 1 */
+  outb ((tmp | 0x04), 0xc44);	/* Select bank 1 */
   if (inb (0xc44) != 0x04)
     {
       DDB (printk ("init_deskpro: Invalid bank1 signature in port 0xc44\n"));
@@ -1774,9 +1979,9 @@
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc44 (before): ");
-  outb (tmp & ~0x04, 0xc44);
+  outb ((tmp & ~0x04), 0xc44);
   printk ("%02x ", inb (0xc44));
-  outb (tmp | 0x04, 0xc44);
+  outb ((tmp | 0x04), 0xc44);
   printk ("%02x\n", inb (0xc44));
 #endif
 
@@ -1802,14 +2007,14 @@
 		   hw_config->io_base));
       return 0;
     }
-  outb (tmp & ~0x04, 0xc44);	/* Write to bank=0 */
+  outb ((tmp & ~0x04), 0xc44);	/* Write to bank=0 */
 
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc44 (after): ");
-  outb (tmp & ~0x04, 0xc44);	/* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44);	/* Select bank=0 */
   printk ("%02x ", inb (0xc44));
-  outb (tmp | 0x04, 0xc44);	/* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);	/* Select bank=1 */
   printk ("%02x\n", inb (0xc44));
 #endif
 
@@ -1826,23 +2031,23 @@
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc45 (before): ");
-  outb (tmp & ~0x04, 0xc44);	/* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44);	/* Select bank=0 */
   printk ("%02x ", inb (0xc45));
-  outb (tmp | 0x04, 0xc44);	/* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);	/* Select bank=1 */
   printk ("%02x\n", inb (0xc45));
 #endif
 
-  outb (tmp & ~0x04, 0xc44);	/* Select bank=0 */
-  outb (0x88, 0xc45);		/* FM base 7:0 = 0x88 */
-  outb (tmp | 0x04, 0xc44);	/* Select bank=1 */
-  outb (0x10, 0xc45);		/* MSS ID = 0x10 (MSS port returns 0x04) */
+  outb ((tmp & ~0x04), 0xc44);	/* Select bank=0 */
+  outb ((0x88), 0xc45);		/* FM base 7:0 = 0x88 */
+  outb ((tmp | 0x04), 0xc44);	/* Select bank=1 */
+  outb ((0x10), 0xc45);		/* MSS ID = 0x10 (MSS port returns 0x04) */
 
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc45 (after): ");
-  outb (tmp & ~0x04, 0xc44);	/* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44);	/* Select bank=0 */
   printk ("%02x ", inb (0xc45));
-  outb (tmp | 0x04, 0xc44);	/* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);	/* Select bank=1 */
   printk ("%02x\n", inb (0xc45));
 #endif
 
@@ -1857,23 +2062,23 @@
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc46 (before): ");
-  outb (tmp & ~0x04, 0xc44);	/* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44);	/* Select bank=0 */
   printk ("%02x ", inb (0xc46));
-  outb (tmp | 0x04, 0xc44);	/* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);	/* Select bank=1 */
   printk ("%02x\n", inb (0xc46));
 #endif
 
-  outb (tmp & ~0x04, 0xc44);	/* Select bank=0 */
-  outb (0x03, 0xc46);		/* FM base 15:8 = 0x03 */
-  outb (tmp | 0x04, 0xc44);	/* Select bank=1 */
-  outb (0x11, 0xc46);		/* ASIC ID = 0x11 */
+  outb ((tmp & ~0x04), 0xc44);	/* Select bank=0 */
+  outb ((0x03), 0xc46);		/* FM base 15:8 = 0x03 */
+  outb ((tmp | 0x04), 0xc44);	/* Select bank=1 */
+  outb ((0x11), 0xc46);		/* ASIC ID = 0x11 */
 
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc46 (after): ");
-  outb (tmp & ~0x04, 0xc44);	/* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44);	/* Select bank=0 */
   printk ("%02x ", inb (0xc46));
-  outb (tmp | 0x04, 0xc44);	/* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);	/* Select bank=1 */
   printk ("%02x\n", inb (0xc46));
 #endif
 
@@ -1887,23 +2092,23 @@
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc47 (before): ");
-  outb (tmp & ~0x04, 0xc44);	/* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44);	/* Select bank=0 */
   printk ("%02x ", inb (0xc47));
-  outb (tmp | 0x04, 0xc44);	/* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);	/* Select bank=1 */
   printk ("%02x\n", inb (0xc47));
 #endif
 
-  outb (tmp & ~0x04, 0xc44);	/* Select bank=0 */
-  outb (0x7c, 0xc47);		/* FM decode enable bits = 0x7c */
-  outb (tmp | 0x04, 0xc44);	/* Select bank=1 */
-  outb (0x00, 0xc47);		/* Reserved bank1 = 0x00 */
+  outb ((tmp & ~0x04), 0xc44);	/* Select bank=0 */
+  outb ((0x7c), 0xc47);		/* FM decode enable bits = 0x7c */
+  outb ((tmp | 0x04), 0xc44);	/* Select bank=1 */
+  outb ((0x00), 0xc47);		/* Reserved bank1 = 0x00 */
 
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc47 (after): ");
-  outb (tmp & ~0x04, 0xc44);	/* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44);	/* Select bank=0 */
   printk ("%02x ", inb (0xc47));
-  outb (tmp | 0x04, 0xc44);	/* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);	/* Select bank=1 */
   printk ("%02x\n", inb (0xc47));
 #endif
 
@@ -1915,7 +2120,7 @@
   printk ("Port 0xc6f (before) = %02x\n", inb (0xc6f));
 #endif
 
-  outb (0x80, 0xc6f);
+  outb ((0x80), 0xc6f);
 
 #ifdef DEBUGXL
   printk ("Port 0xc6f (after) = %02x\n", inb (0xc6f));
@@ -2034,8 +2239,6 @@
   int             dma = hw_config->dma;
   int             dma2 = hw_config->dma2;
 
-  if (!ad1848_detect (hw_config->io_base + 4, &ad_flags, hw_config->osp))
-    return;
 
   if (hw_config->card_subtype == 1)	/* Has no IRQ/DMA registers */
     {
@@ -2055,9 +2258,9 @@
   if (bits == -1)
     return;
 
-  outb (bits | 0x40, config_port);
+  outb ((bits | 0x40), config_port);
   if ((inb (version_port) & 0x40) == 0)
-    printk ("[IRQ Conflict?]");
+    printk ("[MSS: IRQ Conflict?]");
 
 /*
  * Handle the capture DMA channel
@@ -2090,7 +2293,7 @@
   else
     dma2 = dma;
 
-  outb (bits | dma_bits[dma] | dma2_bit, config_port);	/* Write IRQ+DMA setup */
+  outb ((bits | dma_bits[dma] | dma2_bit), config_port);	/* Write IRQ+DMA setup */
 
   ad1848_init ("MSS audio codec", hw_config->io_base + 4,
 	       hw_config->irq,
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/ad1848_mixer.h linux/drivers/sound/ad1848_mixer.h
--- v2.1.5/linux/drivers/sound/ad1848_mixer.h	Sun Jun 30 11:43:36 1996
+++ linux/drivers/sound/ad1848_mixer.h	Tue Oct 29 09:31:07 1996
@@ -7,7 +7,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -31,13 +31,22 @@
 					 SOUND_MASK_IGAIN | \
 					 SOUND_MASK_PCM | SOUND_MASK_IMIX)
 
-#define MODE2_MIXER_DEVICES		(SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | SOUND_MASK_MIC | \
+#define MODE2_MIXER_DEVICES		(SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | \
+					 SOUND_MASK_MIC | \
 					 SOUND_MASK_LINE3 | SOUND_MASK_SPEAKER | \
 					 SOUND_MASK_IGAIN | \
 					 SOUND_MASK_PCM | SOUND_MASK_IMIX)
 
 #define MODE3_MIXER_DEVICES		(MODE2_MIXER_DEVICES | SOUND_MASK_VOLUME)
 
+/* OPTi 82C930 has no IMIX level control, but it can still be selected as an
+ * input
+ */
+#define C930_MIXER_DEVICES	(SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | \
+				 SOUND_MASK_MIC | SOUND_MASK_VOLUME | \
+				 SOUND_MASK_LINE3 | \
+				 SOUND_MASK_IGAIN | SOUND_MASK_PCM)
+
 struct mixer_def {
 	unsigned int regno: 7;
 	unsigned int polarity:1;	/* 0=normal, 1=reversed */
@@ -55,6 +64,7 @@
 };
 
 typedef struct mixer_def mixer_ent;
+typedef mixer_ent mixer_ents[2];
 
 /*
  * Most of the mixer entries work in backwards. Setting the polarity field
@@ -68,7 +78,7 @@
 #define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r)	\
 	{{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
 
-mixer_ent mix_devices[32][2] = {
+mixer_ents ad1848_mix_devices[32] = {
 MIX_ENT(SOUND_MIXER_VOLUME,	27, 1, 0, 4,	29, 1, 0, 4),
 MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0),
 MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0),
@@ -88,14 +98,59 @@
 MIX_ENT(SOUND_MIXER_LINE3,	18, 1, 0, 5,	19, 1, 0, 5)
 };
 
-static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
+mixer_ents iwave_mix_devices[32] = {
+MIX_ENT(SOUND_MIXER_VOLUME,	25, 1, 0, 5,	27, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH,	 4, 1, 0, 5,	 5, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_PCM,	 6, 1, 0, 6,	 7, 1, 0, 6),
+MIX_ENT(SOUND_MIXER_SPEAKER,	26, 1, 0, 4,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE,	18, 1, 0, 5,	19, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_MIC,	 0, 0, 5, 1,	 1, 0, 5, 1),
+MIX_ENT(SOUND_MIXER_CD,	 	 2, 1, 0, 5,	 3, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_IMIX,	13, 1, 2, 6,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_IGAIN,	 0, 0, 0, 4,	 1, 0, 0, 4),
+MIX_ENT(SOUND_MIXER_OGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 	 2, 1, 0, 5,	 3, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_LINE2,	 4, 1, 0, 5,	 5, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_LINE3,	18, 1, 0, 5,	19, 1, 0, 5)
+};
+
+/* OPTi 82C930 has somewhat different port addresses.
+ * Note: VOLUME == SPEAKER, SYNTH == LINE2, LINE == LINE3, CD == LINE1
+ * VOLUME, SYNTH, LINE, CD are not enabled above.
+ * MIC is level of mic monitoring direct to output. Same for CD, LINE, etc.
+ */
+mixer_ents c930_mix_devices[32] = {
+MIX_ENT(SOUND_MIXER_VOLUME,	22, 1, 0, 5,	23, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH,	 4, 1, 0, 5,	 5, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_PCM,	 6, 1, 0, 6,	 7, 1, 0, 6),
+MIX_ENT(SOUND_MIXER_SPEAKER,	22, 1, 0, 5,	 23, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_LINE,	18, 1, 1, 4,	19, 1, 1, 4),
+MIX_ENT(SOUND_MIXER_MIC,	 20, 1, 0, 4,	 21, 1, 0, 4),
+MIX_ENT(SOUND_MIXER_CD,	 	 2, 1, 1, 4,	 3, 1, 1, 4),
+MIX_ENT(SOUND_MIXER_IMIX,	0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_IGAIN,	 0, 0, 0, 4,	 1, 0, 0, 4),
+MIX_ENT(SOUND_MIXER_OGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 	 2, 1, 1, 4,	 3, 1, 1, 4),
+MIX_ENT(SOUND_MIXER_LINE2,	 4, 1, 1, 4,	 5, 1, 1, 4),
+MIX_ENT(SOUND_MIXER_LINE3,	18, 1, 1, 4,	19, 1, 1, 4)
+};
+
+static int default_mixer_levels[32] =
 {
   0x3232,			/* Master Volume */
   0x3232,			/* Bass */
   0x3232,			/* Treble */
   0x4b4b,			/* FM */
   0x3232,			/* PCM */
-  0x4b4b,			/* PC Speaker */
+  0x1515,			/* PC Speaker */
   0x2020,			/* Ext Line */
   0x1010,			/* Mic */
   0x4b4b,			/* CD */
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/adlib_card.c linux/drivers/sound/adlib_card.c
--- v2.1.5/linux/drivers/sound/adlib_card.c	Sun Jun 30 11:43:48 1996
+++ linux/drivers/sound/adlib_card.c	Tue Oct 29 09:31:24 1996
@@ -7,7 +7,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -32,7 +32,8 @@
 
   if (check_region (hw_config->io_base, 4))
     {
-      printk ("\n\nopl3.c: I/O port %x already in use\n\n", hw_config->io_base);
+      DDB (printk ("opl3.c: I/O port %x already in use\n",
+		   hw_config->io_base));
       return 0;
     }
 
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/aedsp16.c linux/drivers/sound/aedsp16.c
--- v2.1.5/linux/drivers/sound/aedsp16.c	Mon Jul 15 09:55:11 1996
+++ linux/drivers/sound/aedsp16.c	Tue Oct 29 09:31:25 1996
@@ -349,7 +349,7 @@
 };
 
 /*
- * Buffers to store audio card information
+ * Buffers to store audio card informations
  */
 static char     AudioExcelName[CARDNAMELEN + 1];
 static char     AudioExcelVersion[CARDVERLEN + 1];
@@ -403,9 +403,9 @@
   /*
      * Reset DSP
    */
-  outb (1, (port + DSP_RESET));
+  outb ((1), (port + DSP_RESET));
   tenmicrosec ();
-  outb (0, (port + DSP_RESET));
+  outb ((0), (port + DSP_RESET));
   tenmicrosec ();
   tenmicrosec ();
   return CheckDSPOkay (port);
@@ -425,7 +425,7 @@
        */
       if (!(ret & 0x80))
 	{
-	  outb (cmd, port + DSP_COMMAND);
+	  outb ((cmd), port + DSP_COMMAND);
 	  return 0;
 	}
     }
@@ -706,7 +706,7 @@
      * can allow me to release the requested region.
    */
   if (!(ae_init & INIT_MPU401))
-    request_region (hw_config->io_base, 0x0f, "AEDSP16 (SBPro)");
+    request_region (hw_config->io_base, 0x0f, "aedsp16 (sbpro)");
 #endif
 
   ae_init |= INIT_SBPRO;
@@ -774,11 +774,11 @@
      * can allow me to release the requested region. So when unloading
      * and then reloading it, we are going to have some nice Oops!
    */
-  request_region (hw_config->io_base, 0x08, "AEDSP16 (MSS)");
+  request_region (hw_config->io_base, 0x08, "aedsp16 (mss)");
 #endif
 
   if (!(ae_init & INIT_MPU401))
-    request_region (AEDSP16_BASE, 0x0f, "AEDSP16 (SBPro)");
+    request_region (AEDSP16_BASE, 0x0f, "aedsp16 (sbpro)");
 
   ae_init |= INIT_MSS;
   return 0;
@@ -837,11 +837,11 @@
      * request any region because there is not a uninit routine that
      * can allow me to release the requested region.
    */
-  request_region (hw_config->io_base, 0x02, "AEDSP16 (mpu401)");
+  request_region (hw_config->io_base, 0x02, "aedsp16 (mpu401)");
 #endif
 
   if (!(ae_init & (INIT_MSS | INIT_SBPRO)))
-    request_region (AEDSP16_BASE, 0x0f, "AEDSP16 (SBPro)");
+    request_region (AEDSP16_BASE, 0x0f, "aedsp16 (sbpro)");
 
   ae_init |= INIT_MPU401;
   return 0;
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/audio.c linux/drivers/sound/audio.c
--- v2.1.5/linux/drivers/sound/audio.c	Wed Oct 16 10:48:23 1996
+++ linux/drivers/sound/audio.c	Tue Oct 29 09:43:46 1996
@@ -7,7 +7,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -31,11 +31,13 @@
 #define		AM_WRITE	1
 #define 	AM_READ		2
 
+
 static int      audio_format[MAX_AUDIO_DEV];
 static int      local_conversion[MAX_AUDIO_DEV];
 
+#define CNV_MU_LAW	0x00000001
 static int
-set_format (int dev, long fmt)
+set_format (int dev, int fmt)
 {
   if (fmt != AFMT_QUERY)
     {
@@ -46,12 +48,12 @@
 	if (fmt == AFMT_MU_LAW)
 	  {
 	    fmt = AFMT_U8;
-	    local_conversion[dev] = AFMT_MU_LAW;
+	    local_conversion[dev] = CNV_MU_LAW;
 	  }
 	else
 	  fmt = AFMT_U8;	/* This is always supported */
 
-      audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) fmt, 1);
+      audio_format[dev] = audio_devs[dev]->d->set_bits (dev, fmt);
     }
 
   if (local_conversion[dev])	/* This shadows the HW format */
@@ -64,7 +66,7 @@
 audio_open (int dev, struct fileinfo *file)
 {
   int             ret;
-  long            bits;
+  int             bits;
   int             dev_type = dev & 0x0f;
   int             mode = file->mode & O_ACCMODE;
 
@@ -75,6 +77,9 @@
   else
     bits = 8;
 
+  if (dev < 0 || dev >= num_audiodevs)
+    return -ENXIO;
+
   if ((ret = DMAbuf_open (dev, mode)) < 0)
     return ret;
 
@@ -90,11 +95,8 @@
 
   local_conversion[dev] = 0;
 
-  if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) bits, 1) != bits)
+  if (audio_devs[dev]->d->set_bits (dev, bits) != bits)
     {
-      printk ("audio: Can't set number of bits on device %d\n", dev);
-      audio_release (dev, file);
-      return -(ENXIO);
     }
 
   if (dev_type == SND_DEV_AUDIO)
@@ -107,6 +109,7 @@
   audio_mode[dev] = AM_NONE;
   dev_nblock[dev] = 0;
 
+
   return ret;
 }
 
@@ -119,6 +122,13 @@
 
   if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
     {
+      int             i, n = buf_size & 3;
+
+      if (n)			/* Not 4 byte aligned */
+	{
+	  for (i = 0; i < n; i++)
+	    dma_buf[buf_ptr++] = dmap->neutral_byte;
+	}
       DMAbuf_start_output (dev, buf_no, buf_ptr);
     }
 
@@ -130,11 +140,10 @@
 
   for (i = dmap->qlen + 1; i < dmap->nbufs; i++)
     {
+      p = (p + 1) % dmap->nbufs;
       memset (dmap->raw_buf + p * dmap->fragment_size,
 	      dmap->neutral_byte,
 	      dmap->fragment_size);
-
-      p = (p + 1) % dmap->nbufs;
     }
 
   dmap->flags |= DMA_CLEAN;
@@ -225,7 +234,7 @@
 					    dev_nblock[dev])) < 0)
 	    {
 	      /* Handle nonblocking mode */
-	      if (dev_nblock[dev] && buf_no == -(EAGAIN))
+	      if (dev_nblock[dev] && buf_no == -EAGAIN)
 		return p;	/* No more space. Return # of accepted bytes */
 	      return buf_no;
 	    }
@@ -236,17 +245,18 @@
       if (l > (buf_size - buf_ptr))
 	l = (buf_size - buf_ptr);
 
-      if (!audio_devs[dev]->d->copy_from_user)
+
+      if (!audio_devs[dev]->d->copy_user)
 	{			/*
 				 * No device specific copy routine
 				 */
 	  copy_from_user (&dma_buf[buf_ptr], &(buf)[p], l);
 	}
       else
-	audio_devs[dev]->d->copy_from_user (dev,
-					    dma_buf, buf_ptr, buf, p, l);
+	audio_devs[dev]->d->copy_user (dev,
+				       dma_buf, buf_ptr, buf, p, l);
 
-      if (local_conversion[dev] == AFMT_MU_LAW)
+      if (local_conversion[dev] & CNV_MU_LAW)
 	{
 	  /*
 	   * This just allows interrupts while the conversion is running
@@ -303,7 +313,7 @@
 	{
 	  /* Nonblocking mode handling. Return current # of bytes */
 
-	  if (dev_nblock[dev] && buf_no == -(EAGAIN))
+	  if (dev_nblock[dev] && buf_no == -EAGAIN)
 	    return p;
 
 	  return buf_no;
@@ -316,7 +326,7 @@
        * Insert any local processing here.
        */
 
-      if (local_conversion[dev] == AFMT_MU_LAW)
+      if (local_conversion[dev] & CNV_MU_LAW)
 	{
 	  /*
 	   * This just allows interrupts while the conversion is running
@@ -326,7 +336,11 @@
 	  translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
 	}
 
-      copy_to_user (&(buf)[p], dmabuf, l);
+      {
+	char           *fixit = dmabuf;
+
+	copy_to_user (&(buf)[p], fixit, l);
+      };
 
       DMAbuf_rmchars (dev, buf_no, l);
 
@@ -341,6 +355,9 @@
 audio_ioctl (int dev, struct fileinfo *file,
 	     unsigned int cmd, caddr_t arg)
 {
+  int             val;
+
+/* printk("audio_ioctl(%x, %x)\n", cmd, arg); */
 
   dev = dev >> 4;
 
@@ -351,7 +368,7 @@
       else
 	printk ("/dev/dsp%d: No coprocessor for this device\n", dev);
 
-      return -(ENXIO);
+      return -ENXIO;
     }
   else
     switch (cmd)
@@ -361,33 +378,39 @@
 	  return 0;
 
 	sync_output (dev);
-	return DMAbuf_ioctl (dev, cmd, arg, 0);
+	DMAbuf_sync (dev);
+	DMAbuf_reset (dev);
+	return 0;
 	break;
 
       case SNDCTL_DSP_POST:
 	if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 	  return 0;
+	audio_devs[dev]->dmap_out->flags |= DMA_POST;
 	sync_output (dev);
+	DMAbuf_ioctl (dev, SNDCTL_DSP_POST, 0, 1);
 	return 0;
 	break;
 
       case SNDCTL_DSP_RESET:
 	audio_mode[dev] = AM_NONE;
-	return DMAbuf_ioctl (dev, cmd, arg, 0);
+	DMAbuf_reset (dev);
+	return 0;
 	break;
 
       case SNDCTL_DSP_GETFMTS:
-	return snd_ioctl_return ((int *) arg, audio_devs[dev]->format_mask | AFMT_MU_LAW);
+	return ioctl_out (arg, audio_devs[dev]->format_mask);
 	break;
 
       case SNDCTL_DSP_SETFMT:
-	return snd_ioctl_return ((int *) arg, set_format (dev, get_user ((int *) arg)));
+	get_user (val, (int *) arg);
+	return ioctl_out (arg, set_format (dev, val));
 
       case SNDCTL_DSP_GETISPACE:
 	if (!(audio_devs[dev]->open_mode & OPEN_READ))
 	  return 0;
 	if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
-	  return -(EBUSY);
+	  return -EBUSY;
 
 	{
 	  audio_buf_info  info;
@@ -397,7 +420,11 @@
 	  if (err < 0)
 	    return err;
 
-	  copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+	  {
+	    char           *fixit = (char *) &info;
+
+	    copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+	  };
 	  return 0;
 	}
 
@@ -405,7 +432,7 @@
 	if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 	  return -EPERM;
 	if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
-	  return -(EBUSY);
+	  return -EBUSY;
 
 	{
 	  audio_buf_info  info;
@@ -420,7 +447,11 @@
 	  if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
 	    info.bytes -= buf_ptr;
 
-	  copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+	  {
+	    char           *fixit = (char *) &info;
+
+	    copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+	  };
 	  return 0;
 	}
 
@@ -447,18 +478,64 @@
 
 	  info |= DSP_CAP_MMAP;
 
-	  copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+	  {
+	    char           *fixit = (char *) &info;
+
+	    copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+	  };
 	  return 0;
 	}
 	break;
 
+      case SOUND_PCM_WRITE_RATE:
+	get_user (val, (int *) arg);
+	return ioctl_out (arg, audio_devs[dev]->d->set_speed (dev, val));
+
+      case SOUND_PCM_READ_RATE:
+	return ioctl_out (arg, audio_devs[dev]->d->set_speed (dev, 0));
+
+      case SNDCTL_DSP_STEREO:
+	{
+	  int             n;
+
+	  get_user (n, (int *) arg);
+	  if (n > 1)
+	    {
+	      printk ("sound: SNDCTL_DSP_STEREO called with invalid argument %d\n",
+		      n);
+	      return ioctl_out (arg, audio_devs[dev]->d->set_channels (dev, n));
+	    }
+
+	  if (n < 0)
+	    return -EINVAL;
+
+	  return ioctl_out (arg, audio_devs[dev]->d->set_channels (dev, n + 1) - 1);
+	}
+
+      case SOUND_PCM_WRITE_CHANNELS:
+	get_user (val, (int *) arg);
+	return ioctl_out (arg, audio_devs[dev]->d->set_channels (dev, val));
+
+      case SOUND_PCM_READ_CHANNELS:
+	return ioctl_out (arg, audio_devs[dev]->d->set_channels (dev, 0));
+
+      case SOUND_PCM_READ_BITS:
+	return ioctl_out (arg, audio_devs[dev]->d->set_bits (dev, 0));
+
+      case SNDCTL_DSP_SETDUPLEX:
+	if (audio_devs[dev]->flags & DMA_DUPLEX)
+	  return 0;
+	else
+	  return -EIO;
+	break;
+
       default:
 	return DMAbuf_ioctl (dev, cmd, arg, 0);
       }
 }
 
 void
-audio_init (void)
+audio_init_devices (void)
 {
   /*
      * NOTE! This routine could be called several times during boot.
@@ -466,7 +543,7 @@
 }
 
 int
-audio_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
+audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
   char           *dma_buf;
   int             buf_no, buf_ptr, buf_size;
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/configure.c linux/drivers/sound/configure.c
--- v2.1.5/linux/drivers/sound/configure.c	Wed Sep 25 21:35:40 1996
+++ linux/drivers/sound/configure.c	Tue Oct 29 09:31:28 1996
@@ -1,16 +1,16 @@
 /*
  *     PnP soundcard support is not included in this version.
  *
- *       AEDSP16 will not work without significant changes.
+ *     There is a separately distributed patch available for AEDSP16.
  */
-#define DISABLED_OPTIONS 	(B(OPT_SPNP)|B(OPT_AEDSP16)|B(OPT_UNUSED1)|B(OPT_UNUSED2))
+#define DISABLED_OPTIONS 	(B(OPT_SPNP)|B(OPT_AEDSP16)|B(OPT_UNUSED1)|B(OPT_UNUSED2)|B(OPT_UNUSED3)|B(OPT_UNUSED4)|B(OPT_UNUSED5))
 /*
  * sound/configure.c  - Configuration program for the Linux Sound Driver
  */
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -51,34 +51,31 @@
 #define OPT_UNUSED1	16
 #define OPT_UNUSED2	17
 #define OPT_AEDSP16     18
-#define OPT_AUDIO	19
-#define OPT_MIDI_AUTO	20
-#define OPT_MIDI	21
+#define OPT_UNUSED3	19
+#define OPT_UNUSED4	20
+#define OPT_UNUSED5	21
 #define OPT_YM3812_AUTO	22
 #define OPT_YM3812	23
 #define OPT_LAST	23	/* Last defined OPT number */
 
-#define DUMMY_OPTS (B(OPT_MIDI_AUTO)|B(OPT_YM3812_AUTO))
+#define DUMMY_OPTS (B(OPT_YM3812_AUTO))
 
-#define ANY_DEVS (B(OPT_AUDIO)|B(OPT_MIDI)|B(OPT_GUS)| \
+#define ANY_DEVS (B(OPT_SB)|B(OPT_PAS)|B(OPT_GUS)| \
 		  B(OPT_MPU401)|B(OPT_PSS)|B(OPT_GUS16)|B(OPT_GUSMAX)| \
 		  B(OPT_MSS)|B(OPT_SSCAPE)|B(OPT_UART6850)|B(OPT_TRIX)| \
-		  B(OPT_MAD16)|B(OPT_CS4232)|B(OPT_MAUI)|B(OPT_ADLIB))
-#define AUDIO_CARDS (B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_GUS) | \
-		B (OPT_MSS) | B (OPT_GUS16) | B (OPT_GUSMAX) | B (OPT_TRIX) | \
-		B (OPT_SSCAPE)| B(OPT_MAD16) | B(OPT_CS4232))
+		  B(OPT_MAD16)|B(OPT_CS4232)|B(OPT_MAUI)|B(OPT_ADLIB)| \
+		  B(OPT_SPNP))
 #define MPU_DEVS (B(OPT_PSS)|\
 		  B(OPT_CS4232)|B(OPT_SPNP)|B(OPT_MAUI)|B(OPT_SSCAPE))
-#define UART401_DEVS (SBDSP_DEVS|B(OPT_TRIX)|B(OPT_MAD16))
-#define MIDI_CARDS (MPU_DEVS | UART401_DEVS | \
-		    B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_MPU401) | \
-		    B (OPT_GUS) | B (OPT_TRIX) | B (OPT_SSCAPE)|B(OPT_MAD16) | \
-		    B (OPT_CS4232)|B(OPT_MAUI))
+#define UART401_DEVS (SBDSP_DEVS|B(OPT_TRIX)|B(OPT_MAD16)|B(OPT_SPNP))
+#define NON_AUDIO_CARDS (B(OPT_ADLIB)|B(OPT_MPU401)|B(OPT_UART6850)|B(OPT_MAUI))
+#define AUDIO_CARDS (ANY_DEVS & ~NON_AUDIO_CARDS)
+#define MIDI_CARDS (ANY_DEVS & ~(B(OPT_ADLIB)|B(OPT_MSS)))
 #define AD1848_DEVS (B(OPT_GUS16)|B(OPT_MSS)|B(OPT_PSS)|B(OPT_GUSMAX)|\
 		     B(OPT_SSCAPE)|B(OPT_TRIX)|B(OPT_MAD16)|B(OPT_CS4232)|\
 		     B(OPT_SPNP))
 #define SBDSP_DEVS (B(OPT_SB)|B(OPT_SPNP)|B(OPT_MAD16)|B(OPT_TRIX))
-#define SEQUENCER_DEVS (OPT_MIDI|OPT_YM3812|OPT_ADLIB|OPT_GUS|OPT_MAUI|MIDI_CARDS)
+#define SEQUENCER_DEVS (MIDI_CARDS|B(OPT_YM3812)|B(OPT_ADLIB)|B(OPT_GUS)|B(OPT_MAUI))
 /*
  * Options that have been disabled for some reason (incompletely implemented
  * and/or tested). Don't remove from this list before looking at file
@@ -138,9 +135,9 @@
   {B (OPT_SB), B (OPT_PAS), "UNUSED1", 1, 0, 1},
   {B (OPT_SB) | B (OPT_UNUSED1), B (OPT_PAS), "UNUSED2", 1, 0, 1},
   {B (OPT_UNUSED1) | B (OPT_MSS) | B (OPT_MPU401), 0, "AEDSP16", 1, 0, 0},
-  {AUDIO_CARDS, 0, "AUDIO", 1, 0, 1},
-  {B (OPT_MPU401) | B (OPT_MAUI), 0, "MIDI_AUTO", 0, OPT_MIDI, 0},
-  {MIDI_CARDS, 0, "MIDI", 1, 0, 1},
+  {AUDIO_CARDS, 0, "UNUSED3", 1, 0, 1},
+  {B (OPT_MPU401) | B (OPT_MAUI), 0, "UNUSED4", 0, 0, 0},
+  {MIDI_CARDS, 0, "UNUSED5", 1, 0, 1},
   {B (OPT_ADLIB), 0, "YM3812_AUTO", 0, OPT_YM3812, 0},
   {B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_ADLIB) | B (OPT_MSS) | B (OPT_PSS), B (OPT_YM3812_AUTO), "YM3812", 1, 0, 1}
 };
@@ -167,9 +164,9 @@
   "*** Unused option 1 ***",
   "*** Unused option 2 ***",
   "Audio Excel DSP 16 initialization support",
-  "/dev/dsp and /dev/audio support",
-  "This should not be asked",
-  "MIDI interface support",
+  "*** Unused option 3 ***",
+  "*** Unused option 4 ***",
+  "*** Unused option 5 ***",
   "This should not be asked",
   "FM synthesizer (YM3812/OPL-3) support",
   "Is the sky really falling"
@@ -289,10 +286,26 @@
   }
   ,
   {
+    "GUSHW", B (OPT_GUS) | B (OPT_SPNP)
+  }
+  ,
+  {
+    "SSCAPEHW", B (OPT_SSCAPE) | B (OPT_SPNP)
+  }
+  ,
+  {
     "SEQUENCER", SEQUENCER_DEVS
   }
   ,
   {
+    "AUDIO", AUDIO_CARDS
+  }
+  ,
+  {
+    "MIDI", MIDI_CARDS
+  }
+  ,
+  {
     NULL, 0
   }
 };
@@ -410,6 +423,32 @@
 #define FMT_INT 2
 
 void
+show_comment (int mask, char *txt)
+{
+  int             i;
+
+  if (dump_only)
+    {
+
+      for (i = 0; i < OPT_LAST; i++)
+	if (mask == B (i))
+	  {
+	    printf ("\n\nif [ \"$CONFIG_%s\" = \"y\" ]; then\n",
+		    hw_table[i].macro);
+	    printf ("comment '%s'\n", txt);
+	    printf ("fi\n");
+	  }
+    }
+  else
+    {
+      if (!(mask & selected_options))
+	return;
+
+      fprintf (stderr, "%s\n", txt);
+    }
+}
+
+void
 ask_int_choice (int mask, char *macro,
 		char *question,
 		int format,
@@ -682,14 +721,11 @@
   printf ("#define SELECTED_SOUND_OPTIONS\t0x%08x\n", selected_options);
   fprintf (stderr, "Old configuration copied.\n");
 
-#if defined(linux) || defined(Solaris)
   build_defines ();
-#endif
   old_config_used = 1;
   return 1;
 }
 
-#if defined(linux) || defined(Solaris)
 void
 build_defines (void)
 {
@@ -723,7 +759,6 @@
   fprintf (optf, "\n");
   fclose (optf);
 }
-#endif
 
 void
 ask_parameters (void)
@@ -735,13 +770,11 @@
    * IRQ and DMA settings
    */
 
-#if 0	/* Disable this broken question. */
   ask_int_choice (B (OPT_AEDSP16), "AEDSP16_BASE",
 		  "I/O base for Audio Excel DSP 16",
 		  FMT_HEX,
 		  0x220,
 		  "220 or 240");
-#endif
 
   ask_int_choice (B (OPT_SB), "SBC_BASE",
 		  "I/O base for SB",
@@ -762,7 +795,7 @@
 		  "0, 1 or 3");
 
   ask_int_choice (B (OPT_SB), "SB_DMA2",
-		"Sound Blaster 16 bit DMA (_REQUIRED_for SB16, Jazz16, SMW)",
+		  "Sound Blaster 16 bit DMA (SB16, Jazz16, SMW)",
 		  FMT_INT,
 		  5,
 		  "5, 6 or 7 (use 1 for 8 bit cards)");
@@ -770,14 +803,19 @@
   ask_int_choice (B (OPT_SB), "SB_MPU_BASE",
 		  "MPU401 I/O base of SB16, Jazz16 and ES1688",
 		  FMT_HEX,
-		  0,
+		  0x330,
 		  "Check from manual of the card");
 
+  show_comment (B (OPT_SB),
+	   "MPU401 IRQ is only required with Jazz16, SM Wave and ESS1688.");
+  show_comment (B (OPT_SB),
+		"Enter -1 to the following question if you have something else such as SB16/32.");
+
   ask_int_choice (B (OPT_SB), "SB_MPU_IRQ",
 		  "SB MPU401 IRQ (Jazz16, SM Wave and ES1688)",
 		  FMT_INT,
 		  -1,
-		  "Use -1 with SB16");
+		  "Check from manual of the card");
 
   ask_int_choice (B (OPT_PAS), "PAS_IRQ",
 		  "PAS16 IRQ",
@@ -867,6 +905,10 @@
 		  9,
 		  "Check from manual of the card");
 
+  if (dump_only)
+    show_comment (B (OPT_MAUI),
+	"ERROR! You have to use old sound configuration method with Maui.");
+
   ask_int_choice (B (OPT_MAUI), "MAUI_BASE",
 		  "I/O base for Maui",
 		  FMT_HEX,
@@ -891,6 +933,10 @@
 		  -1,
 		  "(Unknown)");
 
+  if (dump_only)
+    show_comment (B (OPT_PSS),
+    "ERROR! You have to use old sound configuration method with PSS cards.");
+
   ask_int_choice (B (OPT_PSS), "PSS_BASE",
 		  "PSS I/O base",
 		  FMT_HEX,
@@ -990,6 +1036,10 @@
 
     }
 
+  if (dump_only)
+    show_comment (B (OPT_MAUI),
+    "ERROR! You have to use old sound configuration method with AudioTrix.");
+
   ask_int_choice (B (OPT_TRIX), "TRIX_BASE",
 		  "AudioTrix audio I/O base",
 		  FMT_HEX,
@@ -1115,11 +1165,6 @@
 		  FMT_INT,
 		  9,
 		  "5, 7, 9 or 10");
-  ask_int_choice (B (OPT_AUDIO), "DSP_BUFFSIZE",
-		  "Audio DMA buffer size",
-		  FMT_INT,
-		  65536,
-		  "4096, 16384, 32768 or 65536");
 }
 
 void
@@ -1367,7 +1412,7 @@
 	{
 
 	  if (think_positively (
-	    "Do you want support for the Audio Excel Sound Blaster Pro mode",
+	   "Do you want support for the Audio Excel Sound Blaster Pro mode",
 				 1,
 				 "Enable this option if you want the Audio Excel sound card to operate\n"
 				 "in Sound Blaster Pro mode.\n"))
@@ -1445,7 +1490,7 @@
 
       if (think_positively ("Do you want to include TRXPRO.HEX in your kernel",
 			    1,
-	"The MediaTrix AudioTrix Pro has an on-board microcontroller which\n"
+       "The MediaTrix AudioTrix Pro has an on-board microcontroller which\n"
 			    "needs to be initialized by downloading the code from the file TRXPRO.HEX\n"
 			    "in the DOS driver directory. If you don't have the TRXPRO.HEX file handy\n"
 			    "you may skip this step. However, the SB and MPU-401 modes of AudioTrix\n"
@@ -1540,10 +1585,6 @@
 
   printf ("#define SELECTED_SOUND_OPTIONS\t0x%08lx\n", selected_options);
   fprintf (stderr, "\nThe sound driver is now configured.\n");
-
-#if defined(SCO) || defined(ISC) || defined(SYSV)
-  fprintf (stderr, "Remember to update the System file\n");
-#endif
 
   if (!old_config_used)
     {
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/cs4232.c linux/drivers/sound/cs4232.c
--- v2.1.5/linux/drivers/sound/cs4232.c	Sat Jul  6 11:31:42 1996
+++ linux/drivers/sound/cs4232.c	Tue Oct 29 09:31:28 1996
@@ -11,7 +11,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -30,7 +30,7 @@
 static void 
 CS_OUT (unsigned char a)
 {
-  outb (a, KEY_PORT);
+  outb ((a), KEY_PORT);
 }
 #define CS_OUT2(a, b)		{CS_OUT(a);CS_OUT(b);}
 #define CS_OUT3(a, b, c)	{CS_OUT(a);CS_OUT(b);CS_OUT(c);}
@@ -71,11 +71,10 @@
   int             base = hw_config->io_base, irq = hw_config->irq;
   int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
 
-  static wait_handle *cs_sleeper = NULL;
+  static struct wait_queue *cs_sleeper = NULL;
   static volatile struct snd_wait cs_sleep_flag =
   {0};
 
-  osp = hw_config->osp;
 
 /*
  * Verify that the I/O port range is free.
@@ -105,7 +104,7 @@
 
   for (n = 0; n < 4; n++)
     {
-      cs_sleep_flag.flags = WK_NONE;
+      cs_sleep_flag.opts = WK_NONE;
 /*
  * Wake up the card by sending a 32 byte Crystal key to the key port.
  */
@@ -117,17 +116,17 @@
 	unsigned long   tlimit;
 
 	if (HZ / 10)
-	  current_set_timeout (tlimit = jiffies + (HZ / 10));
+	  current->timeout = tlimit = jiffies + (HZ / 10);
 	else
 	  tlimit = (unsigned long) -1;
-	cs_sleep_flag.flags = WK_SLEEP;
-	module_interruptible_sleep_on (&cs_sleeper);
-	if (!(cs_sleep_flag.flags & WK_WAKEUP))
+	cs_sleep_flag.opts = WK_SLEEP;
+	interruptible_sleep_on (&cs_sleeper);
+	if (!(cs_sleep_flag.opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      cs_sleep_flag.flags |= WK_TIMEOUT;
+	      cs_sleep_flag.opts |= WK_TIMEOUT;
 	  }
-	cs_sleep_flag.flags &= ~WK_SLEEP;
+	cs_sleep_flag.opts &= ~WK_SLEEP;
       };			/* Delay */
 
 /*
@@ -165,17 +164,17 @@
 	unsigned long   tlimit;
 
 	if (HZ / 10)
-	  current_set_timeout (tlimit = jiffies + (HZ / 10));
+	  current->timeout = tlimit = jiffies + (HZ / 10);
 	else
 	  tlimit = (unsigned long) -1;
-	cs_sleep_flag.flags = WK_SLEEP;
-	module_interruptible_sleep_on (&cs_sleeper);
-	if (!(cs_sleep_flag.flags & WK_WAKEUP))
+	cs_sleep_flag.opts = WK_SLEEP;
+	interruptible_sleep_on (&cs_sleeper);
+	if (!(cs_sleep_flag.opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      cs_sleep_flag.flags |= WK_TIMEOUT;
+	      cs_sleep_flag.opts |= WK_TIMEOUT;
 	  }
-	cs_sleep_flag.flags &= ~WK_SLEEP;
+	cs_sleep_flag.opts &= ~WK_SLEEP;
       };			/* Delay */
 
 /*
@@ -202,17 +201,17 @@
 	unsigned long   tlimit;
 
 	if (HZ / 5)
-	  current_set_timeout (tlimit = jiffies + (HZ / 5));
+	  current->timeout = tlimit = jiffies + (HZ / 5);
 	else
 	  tlimit = (unsigned long) -1;
-	cs_sleep_flag.flags = WK_SLEEP;
-	module_interruptible_sleep_on (&cs_sleeper);
-	if (!(cs_sleep_flag.flags & WK_WAKEUP))
+	cs_sleep_flag.opts = WK_SLEEP;
+	interruptible_sleep_on (&cs_sleeper);
+	if (!(cs_sleep_flag.opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      cs_sleep_flag.flags |= WK_TIMEOUT;
+	      cs_sleep_flag.opts |= WK_TIMEOUT;
 	  }
-	cs_sleep_flag.flags &= ~WK_SLEEP;
+	cs_sleep_flag.opts &= ~WK_SLEEP;
       };			/* Delay */
 
 /*
@@ -227,17 +226,17 @@
 	unsigned long   tlimit;
 
 	if (HZ)
-	  current_set_timeout (tlimit = jiffies + (HZ));
+	  current->timeout = tlimit = jiffies + (HZ);
 	else
 	  tlimit = (unsigned long) -1;
-	cs_sleep_flag.flags = WK_SLEEP;
-	module_interruptible_sleep_on (&cs_sleeper);
-	if (!(cs_sleep_flag.flags & WK_WAKEUP))
+	cs_sleep_flag.opts = WK_SLEEP;
+	interruptible_sleep_on (&cs_sleeper);
+	if (!(cs_sleep_flag.opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      cs_sleep_flag.flags |= WK_TIMEOUT;
+	      cs_sleep_flag.opts |= WK_TIMEOUT;
 	  }
-	cs_sleep_flag.flags &= ~WK_SLEEP;
+	cs_sleep_flag.opts &= ~WK_SLEEP;
       };			/* Longer delay */
     }
 
@@ -249,6 +248,7 @@
 {
   int             base = hw_config->io_base, irq = hw_config->irq;
   int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
+  int             old_num_mixers = num_mixers;
 
   if (dma2 == -1)
     dma2 = dma1;
@@ -260,6 +260,13 @@
 	       0,
 	       hw_config->osp);
 
+  if (num_mixers > old_num_mixers)
+    {				/* Assume the mixer map is as suggested in the CS4232 databook */
+      AD1848_REROUTE (SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
+      AD1848_REROUTE (SOUND_MIXER_LINE2, SOUND_MIXER_CD);
+      AD1848_REROUTE (SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH);	/* FM synth */
+    }
+
 #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   if (mpu_base != 0 && mpu_irq != 0)
     {
@@ -275,7 +282,6 @@
       hw_config2.driver_use_1 = 0;
       hw_config2.driver_use_2 = 0;
       hw_config2.card_subtype = 0;
-      hw_config2.osp = hw_config->osp;
 
       if (probe_mpu401 (&hw_config2))
 	{
@@ -320,7 +326,6 @@
       hw_config2.driver_use_1 = 0;
       hw_config2.driver_use_2 = 0;
       hw_config2.card_subtype = 0;
-      hw_config2.osp = hw_config->osp;
 
       unload_mpu401 (&hw_config2);
     }
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c
--- v2.1.5/linux/drivers/sound/dev_table.c	Mon Sep 30 10:02:06 1996
+++ linux/drivers/sound/dev_table.c	Tue Oct 29 09:31:29 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -44,7 +44,7 @@
   if (num_audiodevs)		/* Audio devices present */
     {
       DMAbuf_init ();
-      audio_init ();
+      audio_init_devices ();
     }
 #endif
 
@@ -70,6 +70,14 @@
   if (trace_init)
     printk ("Sound initialization started\n");
 
+#ifdef CONFIG_LOWLEVEL_SOUND
+  {
+    extern void     sound_preinit_lowlevel_drivers (void);
+
+    sound_preinit_lowlevel_drivers ();
+  }
+#endif
+
 /*
  * Check the number of cards actually defined in the table
  */
@@ -105,6 +113,14 @@
 						 */
       }
 
+#ifdef CONFIG_LOWLEVEL_SOUND
+  {
+    extern void     sound_init_lowlevel_drivers (void);
+
+    sound_init_lowlevel_drivers ();
+  }
+#endif
+
   if (trace_init)
     printk ("Sound initialization complete\n");
 }
@@ -112,7 +128,7 @@
 void
 sndtable_init (void)
 {
-  return start_cards ();
+  start_cards ();
 }
 
 void
@@ -147,7 +163,7 @@
 
   unsigned long   flags;
 
-  DDB (printk ("unload driver %d: ", type));
+  DEB (printk ("unload driver %d: ", type));
 
   for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
     if (snd_installed_cards[i].card_type == type)
@@ -156,7 +172,7 @@
 	  {
 	    if ((drv = snd_find_driver (type)) != -1)
 	      {
-		DDB (printk (" card %d", i));
+		DEB (printk (" card %d", i));
 		if (sound_drivers[drv].unload)
 		  {
 		    sound_drivers[drv].unload (&snd_installed_cards[i].config);
@@ -165,7 +181,7 @@
 	      }
 	  }
       }
-  DDB (printk ("\n"));
+  DEB (printk ("\n"));
 
   save_flags (flags);
   cli ();
@@ -179,12 +195,10 @@
 {
   int             sel = -1;
 
-  DDB (printk ("sndtable_probe(%d)\n", unit));
+  DEB (printk ("sndtable_probe(%d)\n", unit));
 
   if (!unit)
-    return TRUE;
-
-  sound_started = 1;
+    return 1;
 
 
   if (sel == -1 && num_sound_cards < max_sound_cards)
@@ -211,15 +225,14 @@
       snd_installed_cards[sel].config.driver_use_1 = hw_config->driver_use_1;
       snd_installed_cards[sel].config.driver_use_2 = hw_config->driver_use_2;
       snd_installed_cards[sel].config.card_subtype = hw_config->card_subtype;
-      snd_installed_cards[sel].config.osp = hw_config->osp;
 
       if ((drv = snd_find_driver (snd_installed_cards[sel].card_type)) == -1)
 	{
 	  snd_installed_cards[sel].enabled = 0;
-	  DDB (printk ("Failed to find driver\n"));
-	  return FALSE;
+	  DEB (printk ("Failed to find driver\n"));
+	  return 0;
 	}
-      DDB (printk ("Driver name '%s'\n", sound_drivers[drv].name));
+      DEB (printk ("Driver name '%s'\n", sound_drivers[drv].name));
 
       hw_config->card_subtype =
 	snd_installed_cards[sel].config.card_subtype =
@@ -227,99 +240,32 @@
 
       if (sound_drivers[drv].probe (hw_config))
 	{
-	  DDB (printk ("Hardware probed OK\n"));
-	  return TRUE;
+	  DEB (printk ("Hardware probed OK\n"));
+	  return 1;
 	}
 
-      DDB (printk ("Failed to find hardware\n"));
+      DEB (printk ("Failed to find hardware\n"));
       snd_installed_cards[sel].enabled = 0;	/*
 						 * Mark as not detected
 						 */
-      return FALSE;
+      return 0;
     }
 
-  return FALSE;
+  return 0;
 }
 
-int
-sndtable_start_card (int unit, struct address_info *hw_config)
-{
-  int             sel = -1;
-
-  DDB (printk ("sndtable_probe(%d)\n", unit));
-
-  if (!unit)
-    return TRUE;
-
-  sound_started = 1;
-
-  if (sel == -1 && num_sound_cards < max_sound_cards)
-    {
-      int             i;
-
-      i = sel = (num_sound_cards++);
-
-      snd_installed_cards[sel].card_type = unit;
-      snd_installed_cards[sel].enabled = 1;
-    }
-
-  if (sel != -1)
-    {
-      int             drv;
-
-      snd_installed_cards[sel].for_driver_use = NULL;
-      snd_installed_cards[sel].config.io_base = hw_config->io_base;
-      snd_installed_cards[sel].config.irq = hw_config->irq;
-      snd_installed_cards[sel].config.dma = hw_config->dma;
-      snd_installed_cards[sel].config.dma2 = hw_config->dma2;
-      snd_installed_cards[sel].config.name = hw_config->name;
-      snd_installed_cards[sel].config.always_detect = hw_config->always_detect;
-      snd_installed_cards[sel].config.driver_use_1 = hw_config->driver_use_1;
-      snd_installed_cards[sel].config.driver_use_2 = hw_config->driver_use_2;
-      snd_installed_cards[sel].config.card_subtype = hw_config->card_subtype;
-      snd_installed_cards[sel].config.osp = hw_config->osp;
-
-      if ((drv = snd_find_driver (snd_installed_cards[sel].card_type)) == -1)
-	{
-	  snd_installed_cards[sel].enabled = 0;
-	  DDB (printk ("Failed to find driver\n"));
-	  return FALSE;
-	}
-      DDB (printk ("Driver name '%s'\n", sound_drivers[drv].name));
-
-      hw_config->card_subtype =
-	snd_installed_cards[sel].config.card_subtype =
-	sound_drivers[drv].card_subtype;
-
-      if (sound_drivers[drv].probe (hw_config))
-	{
-	  DDB (printk ("Hardware probed OK\n"));
-	  sound_drivers[drv].attach (hw_config);
-	  start_services ();
-	  return TRUE;
-	}
-
-      DDB (printk ("Failed to find hardware\n"));
-      snd_installed_cards[sel].enabled = 0;	/*
-						 * Mark as not detected
-						 */
-      return FALSE;
-    }
-
-  return FALSE;
-}
 
 int
 sndtable_init_card (int unit, struct address_info *hw_config)
 {
   int             i, n = num_sound_cards;
 
-  DDB (printk ("sndtable_init_card(%d) entered\n", unit));
+  DEB (printk ("sndtable_init_card(%d) entered\n", unit));
 
   if (!unit)
     {
       sndtable_init ();
-      return TRUE;
+      return 1;
     }
 
   for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
@@ -336,7 +282,6 @@
 	snd_installed_cards[i].config.driver_use_1 = hw_config->driver_use_1;
 	snd_installed_cards[i].config.driver_use_2 = hw_config->driver_use_2;
 	snd_installed_cards[i].config.card_subtype = hw_config->card_subtype;
-	snd_installed_cards[i].config.osp = hw_config->osp;
 
 	if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1)
 	  snd_installed_cards[i].enabled = 0;	/*
@@ -345,18 +290,18 @@
 	else
 	  {
 
-	    DDB (printk ("Located card - calling attach routine\n"));
+	    DEB (printk ("Located card - calling attach routine\n"));
 	    sound_drivers[drv].attach (hw_config);
 
-	    DDB (printk ("attach routine finished\n"));
+	    DEB (printk ("attach routine finished\n"));
 	  }
 	start_services ();
-	return TRUE;
+	return 1;
       }
 
-  DDB (printk ("sndtable_init_card: No card defined with type=%d, num cards: %d\n",
+  DEB (printk ("sndtable_init_card: No card defined with type=%d, num cards: %d\n",
 	       unit, num_sound_cards));
-  return FALSE;
+  return 0;
 }
 
 int
@@ -449,7 +394,6 @@
 	  snd_installed_cards[ptr].config.driver_use_1 = 0;
 	  snd_installed_cards[ptr].config.driver_use_2 = 0;
 	  snd_installed_cards[ptr].config.card_subtype = 0;
-	  snd_installed_cards[ptr].config.osp = NULL;
 	}
     }
 }
@@ -486,6 +430,7 @@
 			int dma1,
 			int dma2)
 {
+#ifdef CONFIG_AUDIO
   struct audio_driver *d;
   struct audio_operations *op;
   int             l, num;
@@ -493,14 +438,14 @@
   if (num_audiodevs >= MAX_AUDIO_DEV)
     {
       printk ("Sound: Too many audio drivers\n");
-      return -(EIO);
+      return -EIO;
     }
 
   if (vers != AUDIO_DRIVER_VERSION ||
       driver_size > sizeof (struct audio_driver))
     {
       printk ("Sound: Incompatible audio driver for %s\n", name);
-      return -(EIO);
+      return -EIO;
     }
 
 
@@ -516,7 +461,7 @@
   if (d == NULL || op == NULL)
     {
       printk ("Sound: Can't allocate driver for (%s)\n", name);
-      return -(ENOSPC);
+      return -ENOSPC;
     }
 
   memset ((char *) op, 0, sizeof (struct audio_operations));
@@ -546,11 +491,12 @@
   audio_devs[num_audiodevs] = op;
   num = num_audiodevs++;
 
-#ifdef CONFIG_AUDIO
   DMAbuf_init ();
-  audio_init ();
-#endif
+  audio_init_devices ();
   return num;
+#else
+  return -EINVAL;
+#endif
 }
 
 int 
@@ -566,14 +512,14 @@
   if (num_mixers >= MAX_MIXER_DEV)
     {
       printk ("Sound: Too many mixer drivers\n");
-      return -(EIO);
+      return -EIO;
     }
 
   if (vers != MIXER_DRIVER_VERSION ||
       driver_size > sizeof (struct mixer_operations))
     {
       printk ("Sound: Incompatible mixer driver for %s\n", name);
-      return -(EIO);
+      return -EIO;
     }
 
 
@@ -584,7 +530,7 @@
   if (op == NULL)
     {
       printk ("Sound: Can't allocate mixer driver for (%s)\n", name);
-      return -(ENOSPC);
+      return -ENOSPC;
     }
 
   memset ((char *) op, 0, sizeof (struct mixer_operations));
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h
--- v2.1.5/linux/drivers/sound/dev_table.h	Sun Sep 15 13:21:20 1996
+++ linux/drivers/sound/dev_table.h	Tue Oct 29 16:36:14 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -22,6 +22,7 @@
  * Numbers 1000 to N are reserved for driver's internal use.
  */
 #define SNDCARD_DESKPROXL		27	/* Compaq Deskpro XL */
+#define SNDCARD_SBPNP			29
 
 /*
  *	NOTE! 	NOTE!	NOTE!	NOTE!
@@ -50,12 +51,6 @@
 	void *for_driver_use;
 };
 
-typedef struct pnp_sounddev
-{
-	int id;
-	void (*setup)(void *dev);
-	char *driver_name;
-}pnp_sounddev;
 
 /*
  * Device specific parameters (used only by dmabuf.c)
@@ -90,6 +85,7 @@
 #define DMA_ALLOC_DONE	0x00000020
 #define DMA_SYNCING	0x00000040
 #define DMA_CLEAN	0x00000080
+#define DMA_POST	0x00000100
 
 	int      open_mode;
 
@@ -112,6 +108,7 @@
 
 	int	 underrun_count;
 	int	 byte_counter;
+	int	 data_rate; /* Bytes/second */
 
 	int	 mapping_flags;
 #define			DMA_MAP_MAPPED		0x00000001
@@ -126,7 +123,7 @@
  * in the recent soundcards.
  */
 typedef struct coproc_operations {
-		char name[32];
+		char name[64];
 		int (*open) (void *devc, int sub_device);
 		void (*close) (void *devc, int sub_device);
 		int (*ioctl) (void *devc, unsigned int cmd, caddr_t arg, int local);
@@ -148,7 +145,7 @@
 	void (*reset) (int dev);
 	void (*halt_xfer) (int dev);
 	int (*local_qlen)(int dev);
-        void (*copy_from_user)(int dev, char *localbuf, int localoffs,
+        void (*copy_user)(int dev, char *localbuf, int localoffs,
                                const char *userbuf, int useroffs, int len);
 	void (*halt_input) (int dev);
 	void (*halt_output) (int dev);
@@ -159,7 +156,7 @@
 };
 
 struct audio_operations {
-        char name[32];
+        char name[64];
 	int flags;
 #define NOTHING_SPECIAL 	0x00
 #define NEEDS_RESTART		0x01
@@ -167,6 +164,7 @@
 #define DMA_DUPLEX		0x04
 #define DMA_PSEUDO_AUTOMODE	0x08
 #define DMA_HARDSTOP		0x10
+#define DMA_NODMA		0x20
 	int  format_mask;	/* Bitmask for supported audio formats */
 	void *devc;		/* Driver specific info */
 	struct audio_driver *d;
@@ -181,12 +179,15 @@
 	int min_fragment;	/* 0 == unlimited */
 };
 
+int *load_mixer_volumes(char *name, int *levels, int present);
+
 struct mixer_operations {
 	char id[16];
-	char name[32];
+	char name[64];
 	int (*ioctl) (int dev, unsigned int cmd, caddr_t arg);
 	
 	void *devc;
+	int modify_counter;
 };
 
 struct synth_operations {
@@ -242,7 +243,7 @@
 		);
 	void (*close) (int dev);
 	int (*ioctl) (int dev, unsigned int cmd, caddr_t arg);
-	int (*putc) (int dev, unsigned char data);
+	int (*outputc) (int dev, unsigned char data);
 	int (*start_read) (int dev);
 	int (*end_read) (int dev);
 	void (*kick)(int dev);
@@ -273,6 +274,7 @@
 };
 
 #ifdef _DEV_TABLE_C_   
+
 	struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL}; int num_audiodevs = 0;
 	struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL}; int num_mixers = 0;
 	struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0;
@@ -301,8 +303,6 @@
 #endif
 #ifdef CONFIG_MSS
 		{"MSS", 0, SNDCARD_MSS,	"MS Sound System",	attach_ms_sound, probe_ms_sound, unload_ms_sound},
-	/* MSS without IRQ/DMA config registers (for DEC Alphas) */
-		{"PCXBJ", 1, SNDCARD_PSEUDO_MSS,	"MS Sound System (AXP)",	attach_ms_sound, probe_ms_sound, unload_ms_sound},
 	/* Compaq Deskpro XL */
 		{"DESKPROXL", 2, SNDCARD_DESKPROXL,	"Compaq Deskpro XL",	attach_ms_sound, probe_ms_sound, unload_ms_sound},
 #endif
@@ -314,35 +314,48 @@
 		{"CS4232", 0, SNDCARD_CS4232,	"CS4232",		attach_cs4232, probe_cs4232, unload_cs4232},
 		{"CS4232MPU", 0, SNDCARD_CS4232_MPU,	"CS4232 MIDI",		attach_cs4232_mpu, probe_cs4232_mpu, unload_cs4232_mpu},
 #endif
-#ifdef CONFIG_YM3812
+#if defined(CONFIG_YM3812)
 		{"OPL3", 0, SNDCARD_ADLIB,	"OPL-2/OPL-3 FM",		attach_adlib_card, probe_adlib, unload_adlib},
 #endif
 #ifdef CONFIG_PAS
 		{"PAS16", 0, SNDCARD_PAS,	"ProAudioSpectrum",	attach_pas_card, probe_pas, unload_pas},
 #endif
-#if defined(CONFIG_MPU401) && defined(CONFIG_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
 		{"MPU401", 0, SNDCARD_MPU401,"Roland MPU-401",	attach_mpu401, probe_mpu401, unload_mpu401},
 #endif
+#if (defined(CONFIG_UART401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+	{"UART401", 0, SNDCARD_UART401,"MPU-401 (UART)", 
+		attach_uart401, probe_uart401, unload_uart401},
+#endif
 #if defined(CONFIG_MAUI)
 		{"MAUI", 0, SNDCARD_MAUI,"TB Maui",	attach_maui, probe_maui, unload_maui},
 #endif
 #if defined(CONFIG_UART6850) && defined(CONFIG_MIDI)
 		{"MIDI6850", 0, SNDCARD_UART6850,"6860 UART Midi",	attach_uart6850, probe_uart6850, unload_uart6850},
 #endif
-#ifdef CONFIG_SB
+
+
+
+
+#ifdef CONFIG_SBDSP
 		{"SBLAST", 0, SNDCARD_SB,	"Sound Blaster",		attach_sb_card, probe_sb, unload_sb},
-#ifdef CONFIG_MIDI
+		{"SBPNP", 6, SNDCARD_SBPNP,	"Sound Blaster PnP",		attach_sb_card, probe_sb, unload_sb},
+
+#	ifdef CONFIG_MIDI
 		{"SBMPU", 0, SNDCARD_SB16MIDI,"SB MPU-401",	attach_sbmpu, probe_sbmpu, unload_sbmpu},
+#	endif
 #endif
-#endif
+
+
+
 #ifdef CONFIG_GUS16
 		{"GUS16", 0, SNDCARD_GUS16,	"Ultrasound 16-bit opt.",	attach_gus_db16, probe_gus_db16, unload_gus_db16},
 #endif
-#ifdef CONFIG_GUS
+#ifdef CONFIG_GUSHW
 		{"GUS", 0, SNDCARD_GUS,	"Gravis Ultrasound",	attach_gus_card, probe_gus, unload_gus},
 		{"GUSPNP", 1, SNDCARD_GUSPNP,	"GUS PnP",	attach_gus_card, probe_gus, unload_gus},
 #endif
-#ifdef CONFIG_SSCAPE
+#ifdef CONFIG_SSCAPEHW
 		{"SSCAPE", 0, SNDCARD_SSCAPE, "Ensoniq SoundScape",	attach_sscape, probe_sscape, unload_sscape},
 		{"SSCAPEMSS", 0, SNDCARD_SSCAPE_MSS,	"MS Sound System (SoundScape)",	attach_ss_ms_sound, probe_ss_ms_sound, unload_ss_ms_sound},
 #endif
@@ -351,6 +364,7 @@
 		{"TRXPROSB", 0, SNDCARD_TRXPRO_SB, "AudioTrix (SB mode)",	attach_trix_sb, probe_trix_sb, unload_trix_sb},
 		{"TRXPROMPU", 0, SNDCARD_TRXPRO_MPU, "AudioTrix MIDI",	attach_trix_mpu, probe_trix_mpu, unload_trix_mpu},
 #endif
+
 		{NULL, 0, 0,		"*?*",			NULL, NULL, NULL}
 	};
 
@@ -479,11 +493,6 @@
 #ifdef CONFIG_YM3812
 		{SNDCARD_ADLIB, {FM_MONO, 0, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
-/* Define some expansion space */
-		{0, {0}, 0},
-		{0, {0}, 0},
-		{0, {0}, 0},
-		{0, {0}, 0},
 		{0, {0}, 0}
 	};
 
@@ -498,11 +507,12 @@
 	int max_sound_cards = 20;
 #endif
 
-#   ifdef MODULE
+#if defined(MODULE) || (!defined(linux) && !defined(_AIX))
 	int trace_init = 0;
 #   else
 	int trace_init = 1;
 #   endif
+
 #else
 	extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; extern int num_audiodevs;
 	extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixers;
@@ -531,9 +541,8 @@
 void sound_setup (char *str, int *ints);
 
 int sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan);
-void sound_free_dmap (int dev, struct dma_buffparms *dmap);
+void sound_free_dmap (int dev, struct dma_buffparms *dmap, int chn);
 extern int sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info);
-void install_pnp_sounddrv(struct pnp_sounddev *drv);
 int sndtable_probe (int unit, struct address_info *hw_config);
 int sndtable_init_card (int unit, struct address_info *hw_config);
 int sndtable_start_card (int unit, struct address_info *hw_config);
@@ -543,8 +552,8 @@
 			int count, int dma_mode, int autoinit);
 void sound_dma_intr (int dev, struct dma_buffparms *dmap, int chan);
 
-#define AUDIO_DRIVER_VERSION	1
-#define MIXER_DRIVER_VERSION	1
+#define AUDIO_DRIVER_VERSION	2
+#define MIXER_DRIVER_VERSION	2
 int sound_install_audiodrv(int vers,
 			   char *name,
 			   struct audio_driver *driver,
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c
--- v2.1.5/linux/drivers/sound/dmabuf.c	Wed Oct 16 10:48:23 1996
+++ linux/drivers/sound/dmabuf.c	Tue Oct 29 09:31:31 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -15,14 +15,14 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIG_AUDIO) || defined(CONFIG_GUS)
+#if defined(CONFIG_AUDIO) || defined(CONFIG_GUSHW)
 
-static wait_handle *in_sleeper[MAX_AUDIO_DEV] =
+static struct wait_queue *in_sleeper[MAX_AUDIO_DEV] =
 {NULL};
 static volatile struct snd_wait in_sleep_flag[MAX_AUDIO_DEV] =
 {
   {0}};
-static wait_handle *out_sleeper[MAX_AUDIO_DEV] =
+static struct wait_queue *out_sleeper[MAX_AUDIO_DEV] =
 {NULL};
 static volatile struct snd_wait out_sleep_flag[MAX_AUDIO_DEV] =
 {
@@ -57,30 +57,31 @@
   unsigned        i, n;
   unsigned        sr, nc, sz, bsz;
 
-  if (dmap->fragment_size == 0)
-    {				/* Compute the fragment size using the default algorithm */
+  sr = dsp_dev->d->set_speed (dev, 0);
+  nc = dsp_dev->d->set_channels (dev, 0);
+  sz = dsp_dev->d->set_bits (dev, 0);
 
-      sr = dsp_dev->d->set_speed (dev, 0);
-      nc = dsp_dev->d->set_channels (dev, 0);
-      sz = dsp_dev->d->set_bits (dev, 0);
+  if (sz == 8)
+    dmap->neutral_byte = NEUTRAL8;
+  else
+    dmap->neutral_byte = NEUTRAL16;
 
-      if (sz == 8)
-	dmap->neutral_byte = NEUTRAL8;
-      else
-	dmap->neutral_byte = NEUTRAL16;
+  if (sr < 1 || nc < 1 || sz < 1)
+    {
+      printk ("Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n",
+	      dev, sr, nc, sz);
+      sr = DSP_DEFAULT_SPEED;
+      nc = 1;
+      sz = 8;
+    }
 
-      if (sr < 1 || nc < 1 || sz < 1)
-	{
-	  printk ("Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n",
-		  dev, sr, nc, sz);
-	  sr = DSP_DEFAULT_SPEED;
-	  nc = 1;
-	  sz = 8;
-	}
+  sz = sr * nc * sz;
 
-      sz = sr * nc * sz;
+  sz /= 8;			/* #bits -> #bytes */
+  dmap->data_rate = sz;
 
-      sz /= 8;			/* #bits -> #bytes */
+  if (dmap->fragment_size == 0)
+    {				/* Compute the fragment size using the default algorithm */
 
       /*
          * Compute a buffer size for time not exceeding 1 second.
@@ -103,11 +104,12 @@
 
       if (dmap->subdivision == 0)	/* Not already set */
 	{
-	  dmap->subdivision = 1;	/* Init to the default value */
-#ifndef V35A9_COMPATIBLE
-	  if (recording)
-	    dmap->subdivision = 4;	/* Use shorter fragments when recording */
-#endif
+	  dmap->subdivision = 4;	/* Init to the default value */
+
+	  if ((bsz / dmap->subdivision) > 4096)
+	    dmap->subdivision *= 2;
+	  if ((bsz / dmap->subdivision) < 4096)
+	    dmap->subdivision = 1;
 	}
 
       bsz /= dmap->subdivision;
@@ -138,8 +140,16 @@
     n = MAX_SUB_BUFFERS;
   if (n > dmap->max_fragments)
     n = dmap->max_fragments;
+
+  if (n < 2)
+    {
+      n = 2;
+      bsz /= 2;
+    }
+
   dmap->nbufs = n;
   dmap->bytes_in_use = n * bsz;
+  dmap->fragment_size = bsz;
 
   if (dmap->raw_buf)
     memset (dmap->raw_buf,
@@ -159,11 +169,11 @@
 {
   if (dmap == audio_devs[dev]->dmap_out)
     {
-      out_sleep_flag[dev].flags = WK_NONE;
+      out_sleep_flag[dev].opts = WK_NONE;
     }
   else
     {
-      in_sleep_flag[dev].flags = WK_NONE;
+      in_sleep_flag[dev].opts = WK_NONE;
     }
 
   dmap->flags = DMA_BUSY;	/* Other flags off */
@@ -174,6 +184,7 @@
   dmap->dma_mode = DMODE_NONE;
   dmap->mapping_flags = 0;
   dmap->neutral_byte = NEUTRAL8;
+  dmap->data_rate = 8000;
   dmap->cfrag = -1;
   dmap->closing = 0;
 }
@@ -182,7 +193,7 @@
 open_dmap (int dev, int mode, struct dma_buffparms *dmap, int chan)
 {
   if (dmap->flags & DMA_BUSY)
-    return -(EBUSY);
+    return -EBUSY;
 
   {
     int             err;
@@ -192,12 +203,12 @@
   }
 
   if (dmap->raw_buf == NULL)
-    return -(ENOSPC);		/* Memory allocation failed during boot */
+    return -ENOSPC;		/* Memory allocation failed during boot */
 
   if (sound_open_dma (chan, audio_devs[dev]->name))
     {
       printk ("Unable to grab(2) DMA%d for the audio driver\n", chan);
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   dmap->open_mode = mode;
@@ -206,6 +217,7 @@
   dmap->max_fragments = 65536;	/* Just a large value */
   dmap->byte_counter = 0;
 
+
   dma_init_buffers (dev, dmap);
 
   return 0;
@@ -221,19 +233,19 @@
   dmap->flags &= ~DMA_BUSY;
 
   disable_dma (chan);
-  sound_free_dmap (dev, dmap);
+  sound_free_dmap (dev, dmap, chan);
 }
 
 static unsigned int
 default_set_bits (int dev, unsigned int bits)
 {
-  return audio_devs[dev]->d->ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) (long) bits, 1);
+  return audio_devs[dev]->d->ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) bits, 1);
 }
 
 static int
 default_set_speed (int dev, int speed)
 {
-  return audio_devs[dev]->d->ioctl (dev, SNDCTL_DSP_SPEED, (caddr_t) (long) speed, 1);
+  return audio_devs[dev]->d->ioctl (dev, SNDCTL_DSP_SPEED, (caddr_t) speed, 1);
 }
 
 static short
@@ -241,7 +253,7 @@
 {
   int             c = channels;
 
-  return audio_devs[dev]->d->ioctl (dev, SNDCTL_DSP_CHANNELS, (caddr_t) (long) c, 1);
+  return audio_devs[dev]->d->ioctl (dev, SNDCTL_DSP_CHANNELS, (caddr_t) c, 1);
 }
 
 static void
@@ -265,13 +277,13 @@
   if (dev >= num_audiodevs)
     {
       /*  printk ("PCM device %d not installed.\n", dev); */
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   if (!audio_devs[dev])
     {
       /* printk ("PCM device %d not initialized\n", dev); */
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   if (!(audio_devs[dev]->flags & DMA_DUPLEX))
@@ -296,7 +308,8 @@
 
   audio_devs[dev]->enable_bits = mode;
   if (mode & OPEN_READ &&
-      audio_devs[dev]->flags & DMA_DUPLEX && dmap_out != dmap_in)
+      audio_devs[dev]->flags & DMA_DUPLEX &&
+      dmap_out != dmap_in)
     if ((retval = open_dmap (dev, mode, dmap_in, audio_devs[dev]->dmachan2)) < 0)
       {
 	audio_devs[dev]->d->close (dev);
@@ -305,8 +318,8 @@
       }
   audio_devs[dev]->open_mode = mode;
   audio_devs[dev]->go = 1;
-  in_sleep_flag[dev].flags = WK_NONE;
-  out_sleep_flag[dev].flags = WK_NONE;
+  in_sleep_flag[dev].opts = WK_NONE;
+  out_sleep_flag[dev].opts = WK_NONE;
 
   audio_devs[dev]->d->set_bits (dev, 8);
   audio_devs[dev]->d->set_channels (dev, 1);
@@ -315,8 +328,8 @@
   return 0;
 }
 
-static void
-dma_reset (int dev)
+void
+DMAbuf_reset (int dev)
 {
   unsigned long   flags;
 
@@ -336,14 +349,70 @@
 dma_reset_output (int dev)
 {
   unsigned long   flags;
+  int             tmout;
+
+  struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+
+  if (dmap->dma_mode != DMODE_OUTPUT)
+    return;
+
+  if (!(dmap->flags & DMA_STARTED))	/* DMA is not active */
+    return;
 
+/*
+ * First wait until the current fragment has been played completely
+ */
   save_flags (flags);
   cli ();
+
+  tmout =
+    (dmap->fragment_size * HZ) / dmap->data_rate;
+
+  tmout += HZ / 10;		/* Some safety distance */
+
+  if (tmout < (HZ / 2))
+    tmout = HZ / 2;
+  if (tmout > 20 * HZ)
+    tmout = 20 * HZ;
+
+  audio_devs[dev]->dmap_out->flags |= DMA_SYNCING;
+
+  audio_devs[dev]->dmap_out->underrun_count = 0;
+  if (!(current->signal & ~current->blocked)
+      && audio_devs[dev]->dmap_out->qlen
+      && audio_devs[dev]->dmap_out->underrun_count == 0)
+    {
+
+      {
+	unsigned long   tlimit;
+
+	if (tmout)
+	  current->timeout = tlimit = jiffies + (tmout);
+	else
+	  tlimit = (unsigned long) -1;
+	out_sleep_flag[dev].opts = WK_SLEEP;
+	interruptible_sleep_on (&out_sleeper[dev]);
+	if (!(out_sleep_flag[dev].opts & WK_WAKEUP))
+	  {
+	    if (jiffies >= tlimit)
+	      out_sleep_flag[dev].opts |= WK_TIMEOUT;
+	  }
+	out_sleep_flag[dev].opts &= ~WK_SLEEP;
+      };
+    }
+  audio_devs[dev]->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE);
+  audio_devs[dev]->dmap_out->flags |= DMA_RESTART;
+
+/*
+ * Finally shut the device off
+ */
+
   if (!(audio_devs[dev]->flags & DMA_DUPLEX) ||
       !audio_devs[dev]->d->halt_output)
     audio_devs[dev]->d->reset (dev);
   else
     audio_devs[dev]->d->halt_output (dev);
+  audio_devs[dev]->dmap_out->flags &= ~DMA_STARTED;
   restore_flags (flags);
 
   dma_init_buffers (dev, audio_devs[dev]->dmap_out);
@@ -362,29 +431,75 @@
     audio_devs[dev]->d->reset (dev);
   else
     audio_devs[dev]->d->halt_input (dev);
+  audio_devs[dev]->dmap_in->flags &= ~DMA_STARTED;
   restore_flags (flags);
 
   dma_init_buffers (dev, audio_devs[dev]->dmap_in);
   reorganize_buffers (dev, audio_devs[dev]->dmap_in, 1);
 }
 
-static int
-dma_sync (int dev)
+static void
+launch_output (int dev, struct dma_buffparms *dmap)
+{
+  dmap->flags |= DMA_ACTIVE;
+
+  if (dmap->dma_mode == DMODE_NONE || dmap->flags & DMA_RESTART)
+    {
+      reorganize_buffers (dev, audio_devs[dev]->dmap_out, 0);
+      audio_devs[dev]->d->prepare_for_output (dev,
+					  dmap->fragment_size, dmap->nbufs);
+    }
+
+  dmap->dma_mode |= DMODE_OUTPUT;
+
+  audio_devs[dev]->d->output_block (dev, dmap->raw_buf_phys +
+				    dmap->qhead * dmap->fragment_size,
+				    dmap->counts[dmap->qhead], 0,
+				 !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
+				    !(dmap->flags & DMA_STARTED));
+  dmap->flags |= DMA_STARTED;
+  if (audio_devs[dev]->d->trigger)
+    audio_devs[dev]->d->trigger (dev,
+			audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+}
+
+int
+DMAbuf_sync (int dev)
 {
   unsigned long   flags;
+  int             tmout;
 
   if (!audio_devs[dev]->go && (!audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT))
     return 0;
 
   if (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT)
     {
+
+      struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+
       save_flags (flags);
       cli ();
 
+      tmout =
+	(dmap->fragment_size * HZ) / dmap->data_rate;
+
+      tmout += HZ / 10;		/* Some safety distance */
+
+      if (tmout < (HZ / 2))
+	tmout = HZ / 2;
+      if (tmout > 20 * HZ)
+	tmout = 20 * HZ;
+
+      ;
+      if (dmap->qlen > 0)
+	if (!(dmap->flags & DMA_ACTIVE))
+	  launch_output (dev, dmap);
+      ;
+
       audio_devs[dev]->dmap_out->flags |= DMA_SYNCING;
 
       audio_devs[dev]->dmap_out->underrun_count = 0;
-      while (!current_got_fatal_signal ()
+      while (!(current->signal & ~current->blocked)
 	     && audio_devs[dev]->dmap_out->qlen
 	     && audio_devs[dev]->dmap_out->underrun_count == 0)
 	{
@@ -392,29 +507,29 @@
 	  {
 	    unsigned long   tlimit;
 
-	    if (HZ)
-	      current_set_timeout (tlimit = jiffies + (HZ));
+	    if (tmout)
+	      current->timeout = tlimit = jiffies + (tmout);
 	    else
 	      tlimit = (unsigned long) -1;
-	    out_sleep_flag[dev].flags = WK_SLEEP;
-	    module_interruptible_sleep_on (&out_sleeper[dev]);
-	    if (!(out_sleep_flag[dev].flags & WK_WAKEUP))
+	    out_sleep_flag[dev].opts = WK_SLEEP;
+	    interruptible_sleep_on (&out_sleeper[dev]);
+	    if (!(out_sleep_flag[dev].opts & WK_WAKEUP))
 	      {
 		if (jiffies >= tlimit)
-		  out_sleep_flag[dev].flags |= WK_TIMEOUT;
+		  out_sleep_flag[dev].opts |= WK_TIMEOUT;
 	      }
-	    out_sleep_flag[dev].flags &= ~WK_SLEEP;
+	    out_sleep_flag[dev].opts &= ~WK_SLEEP;
 	  };
-	  if ((out_sleep_flag[dev].flags & WK_TIMEOUT))
+	  if ((out_sleep_flag[dev].opts & WK_TIMEOUT))
 	    {
 	      audio_devs[dev]->dmap_out->flags &= ~DMA_SYNCING;
 	      restore_flags (flags);
 	      return audio_devs[dev]->dmap_out->qlen;
 	    }
 	}
-      audio_devs[dev]->dmap_out->flags &= ~DMA_SYNCING;
+      audio_devs[dev]->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE);
+      audio_devs[dev]->dmap_out->flags |= DMA_RESTART;
       restore_flags (flags);
-
       /*
        * Some devices such as GUS have huge amount of on board RAM for the
        * audio data. We have to wait until the device has finished playing.
@@ -424,30 +539,31 @@
       cli ();
       if (audio_devs[dev]->d->local_qlen)	/* Device has hidden buffers */
 	{
-	  while (!(current_got_fatal_signal ())
+	  while (!((current->signal & ~current->blocked))
 		 && audio_devs[dev]->d->local_qlen (dev))
 	    {
 
 	      {
 		unsigned long   tlimit;
 
-		if (HZ)
-		  current_set_timeout (tlimit = jiffies + (HZ));
+		if (tmout)
+		  current->timeout = tlimit = jiffies + (tmout);
 		else
 		  tlimit = (unsigned long) -1;
-		out_sleep_flag[dev].flags = WK_SLEEP;
-		module_interruptible_sleep_on (&out_sleeper[dev]);
-		if (!(out_sleep_flag[dev].flags & WK_WAKEUP))
+		out_sleep_flag[dev].opts = WK_SLEEP;
+		interruptible_sleep_on (&out_sleeper[dev]);
+		if (!(out_sleep_flag[dev].opts & WK_WAKEUP))
 		  {
 		    if (jiffies >= tlimit)
-		      out_sleep_flag[dev].flags |= WK_TIMEOUT;
+		      out_sleep_flag[dev].opts |= WK_TIMEOUT;
 		  }
-		out_sleep_flag[dev].flags &= ~WK_SLEEP;
+		out_sleep_flag[dev].opts &= ~WK_SLEEP;
 	      };
 	    }
 	}
       restore_flags (flags);
     }
+  audio_devs[dev]->dmap_out->dma_mode = DMODE_NONE;
   return audio_devs[dev]->dmap_out->qlen;
 }
 
@@ -459,10 +575,10 @@
   audio_devs[dev]->dmap_out->closing = 1;
   audio_devs[dev]->dmap_in->closing = 1;
 
-  if (!(current_got_fatal_signal ())
+  if (!((current->signal & ~current->blocked))
       && (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT))
     {
-      dma_sync (dev);
+      DMAbuf_sync (dev);
     }
 
   if (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT)
@@ -505,18 +621,17 @@
 
   if (dmap->dma_mode == DMODE_OUTPUT)	/* Direction change */
     {
-      dma_sync (dev);
-      dma_reset (dev);
+      DMAbuf_sync (dev);
+      DMAbuf_reset (dev);
       dmap->dma_mode = DMODE_NONE;
     }
 
-  if (!(dmap->flags & DMA_ALLOC_DONE))
-    reorganize_buffers (dev, dmap, 1);
 
   if (prepare || !dmap->dma_mode)
     {
       int             err;
 
+      reorganize_buffers (dev, dmap, 1);
       if ((err = audio_devs[dev]->d->prepare_for_input (dev,
 				     dmap->fragment_size, dmap->nbufs)) < 0)
 	{
@@ -552,12 +667,19 @@
   if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
     {
       printk ("Sound: Can't read from mmapped device (1)\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
   else if (!dmap->qlen)
     {
       int             tmout;
 
+      if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT) ||
+	  !audio_devs[dev]->go)
+	{
+	  restore_flags (flags);
+	  return -EAGAIN;
+	}
+
       if ((err = activate_recording (dev, dmap)) < 0)
 	{
 	  restore_flags (flags);
@@ -569,39 +691,42 @@
       if (dontblock)
 	{
 	  restore_flags (flags);
-	  return -(EAGAIN);
-	}
-
-      if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT) &
-	  audio_devs[dev]->go)
-	{
-	  restore_flags (flags);
-	  return -(EAGAIN);
+	  return -EAGAIN;
 	}
 
       if (!audio_devs[dev]->go)
 	tmout = 0;
       else
-	tmout = 10 * HZ;
+	{
+	  tmout =
+	    (dmap->fragment_size * HZ) / dmap->data_rate;
+
+	  tmout += HZ / 10;	/* Some safety distance */
+
+	  if (tmout < (HZ / 2))
+	    tmout = HZ / 2;
+	  if (tmout > 20 * HZ)
+	    tmout = 20 * HZ;
+	}
 
 
       {
 	unsigned long   tlimit;
 
 	if (tmout)
-	  current_set_timeout (tlimit = jiffies + (tmout));
+	  current->timeout = tlimit = jiffies + (tmout);
 	else
 	  tlimit = (unsigned long) -1;
-	in_sleep_flag[dev].flags = WK_SLEEP;
-	module_interruptible_sleep_on (&in_sleeper[dev]);
-	if (!(in_sleep_flag[dev].flags & WK_WAKEUP))
+	in_sleep_flag[dev].opts = WK_SLEEP;
+	interruptible_sleep_on (&in_sleeper[dev]);
+	if (!(in_sleep_flag[dev].opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      in_sleep_flag[dev].flags |= WK_TIMEOUT;
+	      in_sleep_flag[dev].opts |= WK_TIMEOUT;
 	  }
-	in_sleep_flag[dev].flags &= ~WK_SLEEP;
+	in_sleep_flag[dev].opts &= ~WK_SLEEP;
       };
-      if ((in_sleep_flag[dev].flags & WK_TIMEOUT))
+      if ((in_sleep_flag[dev].opts & WK_TIMEOUT))
 	{
 	  printk ("Sound: DMA (input) timed out - IRQ/DRQ config error?\n");
 	  err = EIO;
@@ -614,7 +739,7 @@
   restore_flags (flags);
 
   if (!dmap->qlen)
-    return -(err);
+    return -err;
 
   *buf = &dmap->raw_buf[dmap->qhead * dmap->fragment_size + dmap->counts[dmap->qhead]];
   *len = dmap->fragment_size - dmap->counts[dmap->qhead];
@@ -632,7 +757,7 @@
   if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
     {
       printk ("Sound: Can't read from mmapped device (2)\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
   else if (p >= dmap->fragment_size)
     {				/* This buffer is completely empty */
@@ -657,21 +782,21 @@
       fact = dmap->subdivision;
       if (fact == 0)
 	fact = 1;
-      return snd_ioctl_return ((int *) arg, fact);
+      return ioctl_out (arg, fact);
     }
 
   if (dmap->subdivision != 0 ||
       dmap->fragment_size)	/* Too late to change */
-    return -(EINVAL);
+    return -EINVAL;
 
   if (fact > MAX_REALTIME_FACTOR)
-    return -(EINVAL);
+    return -EINVAL;
 
   if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16)
-    return -(EINVAL);
+    return -EINVAL;
 
   dmap->subdivision = fact;
-  return snd_ioctl_return ((int *) arg, fact);
+  return ioctl_out (arg, fact);
 }
 
 static int
@@ -680,11 +805,11 @@
   int             bytes, count;
 
   if (fact == 0)
-    return -(EIO);
+    return -EIO;
 
   if (dmap->subdivision != 0 ||
       dmap->fragment_size)	/* Too late to change */
-    return -(EINVAL);
+    return -EINVAL;
 
   bytes = fact & 0xffff;
   count = (fact >> 16) & 0x7fff;
@@ -693,10 +818,10 @@
     count = MAX_SUB_BUFFERS;
 
   if (bytes < 4 || bytes > 17)	/* <16 || > 512k */
-    return -(EINVAL);
+    return -EINVAL;
 
   if (count < 2)
-    return -(EINVAL);
+    return -EINVAL;
 
   if (audio_devs[dev]->min_fragment > 0)
     if (bytes < audio_devs[dev]->min_fragment)
@@ -719,7 +844,7 @@
 
   dmap->subdivision = 1;	/* Disable SNDCTL_DSP_SUBDIVIDE */
   if (arg)
-    return snd_ioctl_return ((int *) arg, bytes | (count << 16));
+    return ioctl_out (arg, bytes | (count << 16));
   else
     return 0;
 }
@@ -727,6 +852,10 @@
 static int
 get_buffer_pointer (int dev, int chan, struct dma_buffparms *dmap)
 {
+/*
+ * Try to approximate the active byte position of the DMA pointer within the
+ * buffer area as well as possible.
+ */
   int             pos;
   unsigned long   flags;
 
@@ -739,20 +868,19 @@
       clear_dma_ff (chan);
       disable_dma (chan);
       pos = get_dma_residue (chan);
+      if (chan > 3)		/* Word count */
+	pos *= 2;
+      pos = dmap->bytes_in_use - pos;
+      if (pos < 0)
+	pos = 0;
+      if (pos > dmap->bytes_in_use)
+	pos = dmap->bytes_in_use;
       enable_dma (chan);
     }
   restore_flags (flags);
   /* printk ("%04x ", pos); */
 
-  if (audio_devs[dev]->flags & DMA_AUTOMODE)
-    return dmap->bytes_in_use - pos;
-  else
-    {
-      pos = dmap->fragment_size - pos;
-      if (pos < 0)
-	return 0;
-      return pos;
-    }
+  return pos;
 }
 
 
@@ -761,56 +889,9 @@
 {
   struct dma_buffparms *dmap_out = audio_devs[dev]->dmap_out;
   struct dma_buffparms *dmap_in = audio_devs[dev]->dmap_in;
-  long            larg = (long) arg;
 
   switch (cmd)
     {
-    case SOUND_PCM_WRITE_RATE:
-      if (local)
-	return audio_devs[dev]->d->set_speed (dev, larg);
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_speed (dev, get_user ((int *) arg)));
-
-    case SOUND_PCM_READ_RATE:
-      if (local)
-	return audio_devs[dev]->d->set_speed (dev, 0);
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_speed (dev, 0));
-
-    case SNDCTL_DSP_STEREO:
-      if (local)
-	return audio_devs[dev]->d->set_channels (dev, larg + 1) - 1;
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_channels (dev, get_user ((int *) arg) + 1) - 1);
-
-    case SOUND_PCM_WRITE_CHANNELS:
-      if (local)
-	return audio_devs[dev]->d->set_channels (dev, (short) larg);
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_channels (dev, get_user ((int *) arg)));
-
-    case SOUND_PCM_READ_CHANNELS:
-      if (local)
-	return audio_devs[dev]->d->set_channels (dev, 0);
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_channels (dev, 0));
-
-    case SNDCTL_DSP_SAMPLESIZE:
-      if (local)
-	return audio_devs[dev]->d->set_bits (dev, larg);
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_bits (dev, get_user ((int *) arg)));
-
-    case SOUND_PCM_READ_BITS:
-      if (local)
-	return audio_devs[dev]->d->set_bits (dev, 0);
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_bits (dev, 0));
-
-    case SNDCTL_DSP_RESET:
-      dma_reset (dev);
-      return 0;
-      break;
-
-    case SNDCTL_DSP_SYNC:
-      dma_sync (dev);
-      dma_reset (dev);
-      return 0;
-      break;
-
     case SNDCTL_DSP_GETBLKSIZE:
       if (!(dmap_out->flags & DMA_ALLOC_DONE))
 	{
@@ -822,14 +903,19 @@
 				(audio_devs[dev]->open_mode == OPEN_READ));
 	}
 
-      return snd_ioctl_return ((int *) arg, dmap_out->fragment_size);
+      if (local)
+	return dmap_out->fragment_size;
+      else
+	return ioctl_out (arg, dmap_out->fragment_size);
       break;
 
     case SNDCTL_DSP_SUBDIVIDE:
       {
-	int             fact = get_user ((int *) arg);
+	int             fact;
 	int             ret;
 
+	get_user (fact, (int *) arg);
+
 	ret = dma_subdivide (dev, dmap_out, arg, fact);
 	if (ret < 0)
 	  return ret;
@@ -842,18 +928,12 @@
       }
       break;
 
-    case SNDCTL_DSP_SETDUPLEX:
-      if (audio_devs[dev]->flags & DMA_DUPLEX)
-	return 0;
-      else
-	return -(EIO);
-      break;
-
     case SNDCTL_DSP_SETFRAGMENT:
       {
-	int             fact = get_user ((int *) arg);
+	int             fact;
 	int             ret;
 
+	get_user (fact, (int *) arg);
 	ret = dma_set_fragment (dev, dmap_out, arg, fact);
 	if (ret < 0)
 	  return ret;
@@ -869,7 +949,7 @@
     case SNDCTL_DSP_GETISPACE:
     case SNDCTL_DSP_GETOSPACE:
       if (!local)
-	return -(EINVAL);
+	return -EINVAL;
       else
 	{
 	  struct dma_buffparms *dmap = dmap_out;
@@ -878,13 +958,13 @@
 
 	  if (cmd == SNDCTL_DSP_GETISPACE &&
 	      !(audio_devs[dev]->open_mode & OPEN_READ))
-	    return -(EINVAL);
+	    return -EINVAL;
 
 	  if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX)
 	    dmap = dmap_in;
 
 	  if (dmap->mapping_flags & DMA_MAP_MAPPED)
-	    return -(EINVAL);
+	    return -EINVAL;
 
 	  if (!(dmap->flags & DMA_ALLOC_DONE))
 	    reorganize_buffers (dev, dmap, (cmd == SNDCTL_DSP_GETISPACE));
@@ -930,17 +1010,20 @@
       {
 	unsigned long   flags;
 
-	int             bits = get_user ((int *) arg) & audio_devs[dev]->open_mode;
+	int             bits;
 	int             changed;
 
+	get_user (bits, (int *) arg);
+	bits &= audio_devs[dev]->open_mode;
+
 	if (audio_devs[dev]->d->trigger == NULL)
-	  return -(EINVAL);
+	  return -EINVAL;
 
 	if (!(audio_devs[dev]->flags & DMA_DUPLEX))
 	  if ((bits & PCM_ENABLE_INPUT) && (bits & PCM_ENABLE_OUTPUT))
 	    {
 	      printk ("Sound: Device doesn't have full duplex capability\n");
-	      return -(EINVAL);
+	      return -EINVAL;
 	    }
 
 	save_flags (flags);
@@ -951,36 +1034,31 @@
 	  {
 	    int             err;
 
-	    if (!(dmap_in->flags & DMA_ALLOC_DONE))
-	      {
-		reorganize_buffers (dev, dmap_in, 1);
-	      }
+	    reorganize_buffers (dev, dmap_in, 1);
 
 	    if ((err = audio_devs[dev]->d->prepare_for_input (dev,
 			       dmap_in->fragment_size, dmap_in->nbufs)) < 0)
-	      return -(err);
+	      return -err;
 
 	    audio_devs[dev]->enable_bits = bits;
 	    activate_recording (dev, dmap_in);
 	  }
 
+
 	if ((changed & bits) & PCM_ENABLE_OUTPUT &&
 	    dmap_out->mapping_flags & DMA_MAP_MAPPED &&
 	    audio_devs[dev]->go)
 	  {
-	    int             err;
 
 	    if (!(dmap_out->flags & DMA_ALLOC_DONE))
 	      {
 		reorganize_buffers (dev, dmap_out, 0);
 	      }
 
-	    if ((err = audio_devs[dev]->d->prepare_for_output (dev,
-			     dmap_out->fragment_size, dmap_out->nbufs)) < 0)
-	      return -(err);
-
+	    ;
 	    dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size;
-	    DMAbuf_start_output (dev, 0, dmap_out->fragment_size);
+	    launch_output (dev, dmap_out);
+	    ;
 	  }
 
 	audio_devs[dev]->enable_bits = bits;
@@ -991,13 +1069,13 @@
 	restore_flags (flags);
       }
     case SNDCTL_DSP_GETTRIGGER:
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->enable_bits);
+      return ioctl_out (arg, audio_devs[dev]->enable_bits);
       break;
 
     case SNDCTL_DSP_SETSYNCRO:
 
       if (!audio_devs[dev]->d->trigger)
-	return -(EINVAL);
+	return -EINVAL;
 
       audio_devs[dev]->d->trigger (dev, 0);
       audio_devs[dev]->go = 0;
@@ -1010,7 +1088,7 @@
 	unsigned long   flags;
 
 	if (!(audio_devs[dev]->open_mode & OPEN_READ))
-	  return -(EINVAL);
+	  return -EINVAL;
 
 	save_flags (flags);
 	cli ();
@@ -1018,7 +1096,11 @@
 	info.ptr = get_buffer_pointer (dev, audio_devs[dev]->dmachan2, audio_devs[dev]->dmap_in);
 	info.blocks = audio_devs[dev]->dmap_in->qlen;
 	info.bytes += info.ptr;
-	copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+	{
+	  char           *fixit = (char *) &info;
+
+	  copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+	};
 
 	if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
 	  audio_devs[dev]->dmap_in->qlen = 0;	/* Acknowledge interrupts */
@@ -1033,7 +1115,7 @@
 	unsigned long   flags;
 
 	if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
-	  return -(EINVAL);
+	  return -EINVAL;
 
 	save_flags (flags);
 	cli ();
@@ -1041,7 +1123,11 @@
 	info.ptr = get_buffer_pointer (dev, audio_devs[dev]->dmachan1, audio_devs[dev]->dmap_out);
 	info.blocks = audio_devs[dev]->dmap_out->qlen;
 	info.bytes += info.ptr;
-	copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+	{
+	  char           *fixit = (char *) &info;
+
+	  copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+	};
 
 	if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
 	  audio_devs[dev]->dmap_out->qlen = 0;	/* Acknowledge interrupts */
@@ -1051,6 +1137,15 @@
       break;
 
 
+    case SNDCTL_DSP_POST:
+      ;
+      if (audio_devs[dev]->dmap_out->qlen > 0)
+	if (!(audio_devs[dev]->dmap_out->flags & DMA_ACTIVE))
+	  launch_output (dev, audio_devs[dev]->dmap_out);
+      ;
+      return 0;
+      break;
+
     default:
       return audio_devs[dev]->d->ioctl (dev, cmd, arg, local);
     }
@@ -1063,22 +1158,28 @@
  */
 
 void
+DMAbuf_start_device (int dev)
+{
+  if (audio_devs[dev]->open_mode != 0)
+    if (!audio_devs[dev]->go)
+      {
+	/* OK to start the device */
+	audio_devs[dev]->go = 1;
+
+	if (audio_devs[dev]->d->trigger)
+	  audio_devs[dev]->d->trigger (dev,
+			audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+      }
+}
+
+void
 DMAbuf_start_devices (unsigned int devmask)
 {
   int             dev;
 
   for (dev = 0; dev < num_audiodevs; dev++)
     if (devmask & (1 << dev))
-      if (audio_devs[dev]->open_mode != 0)
-	if (!audio_devs[dev]->go)
-	  {
-	    /* OK to start the device */
-	    audio_devs[dev]->go = 1;
-
-	    if (audio_devs[dev]->d->trigger)
-	      audio_devs[dev]->d->trigger (dev,
-			audio_devs[dev]->enable_bits * audio_devs[dev]->go);
-	  }
+      DMAbuf_start_device (dev);
 }
 
 static int
@@ -1087,12 +1188,18 @@
   int             len, max, tmp;
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
 
-  if (dmap->qlen >= dmap->nbufs)	/* No space at all */
+  /* Don't allow touching pages too close to the playing ones */
+  int             lim = dmap->nbufs - 1;
+
+  if (lim < 2)
+    lim = 2;
+
+  if (dmap->qlen >= lim)	/* No space at all */
     return 0;
 
   /*
-     * Verify that there are no more pending buffers than the limit
-     * defined by the process.
+   * Verify that there are no more pending buffers than the limit
+   * defined by the process.
    */
 
   max = dmap->max_fragments;
@@ -1103,7 +1210,7 @@
       tmp = audio_devs[dev]->d->local_qlen (dev);
       if (tmp && len)
 	tmp--;			/*
-				   * This buffer has been counted twice
+				 * This buffer has been counted twice
 				 */
       len += tmp;
     }
@@ -1125,29 +1232,28 @@
   if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
     {
       printk ("Sound: Can't write to mmapped device (3)\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if (dmap->dma_mode == DMODE_INPUT)	/* Direction change */
     {
-      dma_reset (dev);
+      DMAbuf_reset (dev);
       dmap->dma_mode = DMODE_NONE;
     }
   else if (dmap->flags & DMA_RESTART)	/* Restart buffering */
     {
-      dma_sync (dev);
+      DMAbuf_sync (dev);
       dma_reset_output (dev);
+      dmap->dma_mode = DMODE_NONE;
     }
 
   dmap->flags &= ~(DMA_RESTART | DMA_EMPTY);
 
-  if (!(dmap->flags & DMA_ALLOC_DONE))
-    reorganize_buffers (dev, dmap, 0);
-
   if (!dmap->dma_mode)
     {
       int             err;
 
+      reorganize_buffers (dev, dmap, 0);
       dmap->dma_mode = DMODE_OUTPUT;
       if ((err = audio_devs[dev]->d->prepare_for_output (dev,
 				     dmap->fragment_size, dmap->nbufs)) < 0)
@@ -1166,14 +1272,13 @@
       if (dontblock)
 	{
 	  restore_flags (flags);
-	  return -(EAGAIN);
+	  return -EAGAIN;
 	}
 
-      if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT) &&
-	  audio_devs[dev]->go)
+      if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT))
 	{
 	  restore_flags (flags);
-	  return -(EAGAIN);
+	  return -EAGAIN;
 	}
 
       /*
@@ -1182,26 +1287,36 @@
       if (!audio_devs[dev]->go)
 	tmout = 0;
       else
-	tmout = 10 * HZ;
+	{
+	  tmout =
+	    (dmap->fragment_size * HZ) / dmap->data_rate;
+
+	  tmout += HZ / 10;	/* Some safety distance */
+
+	  if (tmout < (HZ / 2))
+	    tmout = HZ / 2;
+	  if (tmout > 20 * HZ)
+	    tmout = 20 * HZ;
+	}
 
 
       {
 	unsigned long   tlimit;
 
 	if (tmout)
-	  current_set_timeout (tlimit = jiffies + (tmout));
+	  current->timeout = tlimit = jiffies + (tmout);
 	else
 	  tlimit = (unsigned long) -1;
-	out_sleep_flag[dev].flags = WK_SLEEP;
-	module_interruptible_sleep_on (&out_sleeper[dev]);
-	if (!(out_sleep_flag[dev].flags & WK_WAKEUP))
+	out_sleep_flag[dev].opts = WK_SLEEP;
+	interruptible_sleep_on (&out_sleeper[dev]);
+	if (!(out_sleep_flag[dev].opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      out_sleep_flag[dev].flags |= WK_TIMEOUT;
+	      out_sleep_flag[dev].opts |= WK_TIMEOUT;
 	  }
-	out_sleep_flag[dev].flags &= ~WK_SLEEP;
+	out_sleep_flag[dev].opts &= ~WK_SLEEP;
       };
-      if ((out_sleep_flag[dev].flags & WK_TIMEOUT))
+      if ((out_sleep_flag[dev].opts & WK_TIMEOUT))
 	{
 	  printk ("Sound: DMA (output) timed out - IRQ/DRQ config error?\n");
 	  err = EIO;
@@ -1213,7 +1328,7 @@
 	    dmap->flags &= ~DMA_RESTART;
 	  audio_devs[dev]->d->reset (dev);
 	}
-      else if (current_got_fatal_signal ())
+      else if ((current->signal & ~current->blocked))
 	{
 	  err = EINTR;
 	  abort = 1;
@@ -1223,7 +1338,7 @@
 
   if (!space_in_queue (dev))
     {
-      return -(err);		/* Caught a signal ? */
+      return -err;		/* Caught a signal ? */
     }
 
   *buf = dmap->raw_buf + dmap->qtail * dmap->fragment_size;
@@ -1267,6 +1382,11 @@
 {
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
   int             restart = 0;
+  int             post = dmap->flags & DMA_POST;
+
+  ;
+
+  dmap->flags &= ~DMA_POST;
 
   dmap->cfrag = -1;
   if (dmap->flags & DMA_RESTART)
@@ -1287,16 +1407,17 @@
     {
 
       dmap->qlen++;
-      if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
-	printk ("\nSound: Audio queue2 corrupted for dev%d (%d/%d)\n",
-		dev, dmap->qlen, dmap->nbufs);
 
       dmap->counts[dmap->qtail] = l;
       if (l < dmap->fragment_size)
 	{
 	  int             p = dmap->fragment_size * dmap->qtail;
 
+#if defined(PPC) || defined(sparc) || defined(HPPA)
+	  dmap->neutral_byte = dmap->raw_buf[p + l - 2];
+#else
 	  dmap->neutral_byte = dmap->raw_buf[p + l - 1];
+#endif
 
 	  memset (dmap->raw_buf + p + l,
 		  dmap->neutral_byte,
@@ -1306,35 +1427,20 @@
 	dmap->neutral_byte =
 	  dmap->raw_buf[dmap->fragment_size * dmap->qtail - 1];
 
-      if ((l != dmap->fragment_size) &&
-	  ((audio_devs[dev]->flags & DMA_AUTOMODE) &&
-	   audio_devs[dev]->flags & NEEDS_RESTART))
-	dmap->flags |= DMA_RESTART;
-      else
-	dmap->flags &= ~DMA_RESTART;
-
       dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
     }
 
-  if (!(dmap->flags & DMA_ACTIVE))
-    {
-      dmap->flags |= DMA_ACTIVE;
-
-      if (restart)
-	audio_devs[dev]->d->prepare_for_output (dev,
-					  dmap->fragment_size, dmap->nbufs);
-
-      audio_devs[dev]->d->output_block (dev, dmap->raw_buf_phys +
-					dmap->qhead * dmap->fragment_size,
-					dmap->counts[dmap->qhead], 0,
-				 !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
-					!(dmap->flags & DMA_STARTED));
-      dmap->flags |= DMA_STARTED;
-      if (audio_devs[dev]->d->trigger)
-	audio_devs[dev]->d->trigger (dev,
-			audio_devs[dev]->enable_bits * audio_devs[dev]->go);
-    }
+  /* Delay playback until there are at least two fragments (to prevent hiccup) */
+  if (dmap->qlen > 1 || post ||
+      (dmap->qlen > 0 && dmap->nbufs <= 2) ||
+      (dmap->qlen > 0 && dmap->flags & DMA_SYNCING) ||
+      restart || l != dmap->fragment_size)
+    if (!(dmap->flags & DMA_ACTIVE))
+      {
+	launch_output (dev, dmap);
+      }
 
+  ;
   return 0;
 }
 
@@ -1343,7 +1449,6 @@
 {
   int             chan;
   struct dma_buffparms *dmap;
-  unsigned long   flags;
 
   if (dma_mode == DMA_MODE_WRITE)
     {
@@ -1356,12 +1461,20 @@
       dmap = audio_devs[dev]->dmap_in;
     }
 
-  if (dmap->raw_buf_phys == 0)
+  if (dmap->raw_buf == NULL)
     {
       printk ("sound: DMA buffer == NULL\n");
       return 0;
     }
 
+  /* Handle cards with non automode DMA in new way */
+  if (physaddr != dmap->raw_buf_phys)	/* Not fragment 0 */
+    return count;
+  count = dmap->bytes_in_use;
+
+  if (chan < 0)
+    return 0;
+
   /*
    * The count must be one less than the actual size. This is handled by
    * set_dma_addr()
@@ -1372,6 +1485,8 @@
 				 * Auto restart mode. Transfer the whole *
 				 * buffer
 				 */
+      unsigned long   flags;
+
       save_flags (flags);
       cli ();
       disable_dma (chan);
@@ -1384,6 +1499,8 @@
     }
   else
     {
+      unsigned long   flags;
+
       save_flags (flags);
       cli ();
       disable_dma (chan);
@@ -1422,33 +1539,10 @@
 }
 
 static void
-polish_buffers (struct dma_buffparms *dmap)
-{
-  int             i;
-  int             p, l;
-
-  i = dmap->qhead;
-
-  p = dmap->fragment_size * i;
-
-  if (i == dmap->cfrag)
-    {
-      l = dmap->fragment_size - dmap->counts[i];
-    }
-  else
-    l = dmap->fragment_size;
-
-  if (l)
-    {
-      memset (dmap->raw_buf + p,
-	      dmap->neutral_byte,
-	      l);
-    }
-}
-
-static void
 force_restart (int dev, struct dma_buffparms *dmap)
 {
+  unsigned long   flags;
+
   if ((audio_devs[dev]->flags & DMA_DUPLEX) &&
       audio_devs[dev]->d->halt_output)
     audio_devs[dev]->d->halt_output (dev);
@@ -1456,10 +1550,19 @@
     audio_devs[dev]->d->halt_xfer (dev);
 
   dmap->flags &= ~(DMA_ACTIVE | DMA_STARTED);
-  if (audio_devs[dev]->flags & DMA_AUTOMODE)
-    dmap->flags |= DMA_RESTART;
-  else
-    dmap->flags &= ~DMA_RESTART;
+  dmap->flags |= DMA_RESTART;
+  dmap->qlen = dmap->qhead = dmap->qtail = 0;
+
+  save_flags (flags);
+  cli ();
+  if ((out_sleep_flag[dev].opts & WK_SLEEP))
+    {
+      {
+	out_sleep_flag[dev].opts = WK_WAKEUP;
+	wake_up (&out_sleeper[dev]);
+      };
+    }
+  restore_flags (flags);
 }
 
 void
@@ -1479,10 +1582,9 @@
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
   int             this_fragment;
 
-  dmap->byte_counter += dmap->counts[dmap->qhead];
-
 #ifdef OS_DMA_INTR
-  sound_dma_intr (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);
+  if (audio_devs[dev]->dmachan1 >= 0)
+    sound_dma_intr (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);
 #endif
 
   if (dmap->raw_buf == NULL)
@@ -1495,6 +1597,8 @@
     {
       /* mmapped access */
       dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+      if (dmap->qhead == 0)	/* Wrapped */
+	dmap->byte_counter += dmap->bytes_in_use;
       dmap->qlen++;		/* Yes increment it (don't decrement) */
       dmap->flags &= ~DMA_ACTIVE;
       dmap->counts[dmap->qhead] = dmap->fragment_size;
@@ -1517,46 +1621,27 @@
 	{
 	  printk ("\nSound: Audio queue3 corrupted for dev%d (%d/%d)\n",
 		  dev, dmap->qlen, dmap->nbufs);
+	  force_restart (dev, dmap);
 	  return;
 	}
 
+      save_flags (flags);
+      cli ();
+
       dmap->qlen--;
       this_fragment = dmap->qhead;
       dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+
+      if (dmap->qhead == 0)	/* Wrapped */
+	dmap->byte_counter += dmap->bytes_in_use;
       dmap->flags &= ~DMA_ACTIVE;
 
       if (event_type == 1 && dmap->qlen < 1)
 	{
 	  dmap->underrun_count++;
 
-	  if ((!(dmap->flags & DMA_CLEAN) &&
-	       (audio_devs[dev]->dmap_out->flags & DMA_SYNCING ||
-		dmap->underrun_count > 5 || dmap->flags & DMA_EMPTY)) ||
-	      audio_devs[dev]->flags & DMA_HARDSTOP)
-
-	    {
-	      dmap->qlen = 0;
-	      force_restart (dev, dmap);
-	    }
-	  else
-	    /* Ignore underrun. Just move the tail pointer forward and go */
-	  if (dmap->closing)
-	    {
-	      polish_buffers (dmap);
-	      audio_devs[dev]->d->halt_xfer (dev);
-	    }
-	  else
-	    {
-	      dmap->qlen++;
-	      dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
-
-	      if (!(dmap->flags & DMA_EMPTY))
-		polish_buffers (dmap);
-
-	      dmap->cfrag = -1;
-	      dmap->flags |= DMA_EMPTY;
-	      dmap->counts[dmap->qtail] = dmap->fragment_size;
-	    }
+	  dmap->qlen = 0;
+	  force_restart (dev, dmap);
 	}
 
       if (dmap->qlen)
@@ -1586,15 +1671,17 @@
 	    }
 	  dmap->flags |= DMA_ACTIVE;
 	}
+
+      restore_flags (flags);
     }				/* event_type != 2 */
 
   save_flags (flags);
   cli ();
-  if ((out_sleep_flag[dev].flags & WK_SLEEP))
+  if ((out_sleep_flag[dev].opts & WK_SLEEP))
     {
       {
-	out_sleep_flag[dev].flags = WK_WAKEUP;
-	module_wake_up (&out_sleeper[dev]);
+	out_sleep_flag[dev].opts = WK_WAKEUP;
+	wake_up (&out_sleeper[dev]);
       };
     }
   restore_flags (flags);
@@ -1606,10 +1693,9 @@
   unsigned long   flags;
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;
 
-  dmap->byte_counter += dmap->fragment_size;
-
 #ifdef OS_DMA_INTR
-  sound_dma_intr (dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2);
+  if (audio_devs[dev]->dmachan2 >= 0)
+    sound_dma_intr (dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2);
 #endif
 
   if (dmap->raw_buf == NULL)
@@ -1621,6 +1707,8 @@
   if (dmap->mapping_flags & DMA_MAP_MAPPED)
     {
       dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+      if (dmap->qtail == 0)	/* Wrapped */
+	dmap->byte_counter += dmap->bytes_in_use;
       dmap->qlen++;
 
       if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
@@ -1638,7 +1726,7 @@
     }
   else if (dmap->qlen == (dmap->nbufs - 1))
     {
-      printk ("Sound: Recording overrun\n");
+      /* printk ("Sound: Recording overrun\n"); */
       dmap->underrun_count++;
 
       if (audio_devs[dev]->flags & DMA_AUTOMODE)
@@ -1664,6 +1752,8 @@
 	printk ("\nSound: Audio queue4 corrupted for dev%d (%d/%d)\n",
 		dev, dmap->qlen, dmap->nbufs);
       dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+      if (dmap->qtail == 0)	/* Wrapped */
+	dmap->byte_counter += dmap->bytes_in_use;
     }
 
   if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
@@ -1681,11 +1771,11 @@
 
   save_flags (flags);
   cli ();
-  if ((in_sleep_flag[dev].flags & WK_SLEEP))
+  if ((in_sleep_flag[dev].opts & WK_SLEEP))
     {
       {
-	in_sleep_flag[dev].flags = WK_WAKEUP;
-	module_wake_up (&in_sleeper[dev]);
+	in_sleep_flag[dev].opts = WK_WAKEUP;
+	wake_up (&in_sleeper[dev]);
       };
     }
   restore_flags (flags);
@@ -1702,19 +1792,22 @@
   int             err;
   unsigned long   flags;
 
-  if ((err = open_dmap (dev, OPEN_READWRITE, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1)) < 0)
+  if ((err = open_dmap (dev, OPEN_READWRITE, audio_devs[dev]->dmap_out, chan)) < 0)
     {
-      return -(EBUSY);
+      return -EBUSY;
     }
   dma_init_buffers (dev, audio_devs[dev]->dmap_out);
   audio_devs[dev]->dmap_out->flags |= DMA_ALLOC_DONE;
   audio_devs[dev]->dmap_out->fragment_size = audio_devs[dev]->buffsize;
 
-  save_flags (flags);
-  cli ();
-  disable_dma (chan);
-  clear_dma_ff (chan);
-  restore_flags (flags);
+  if (chan >= 0)
+    {
+      save_flags (flags);
+      cli ();
+      disable_dma (chan);
+      clear_dma_ff (chan);
+      restore_flags (flags);
+    }
 
   return 0;
 }
@@ -1732,7 +1825,7 @@
 }
 
 int
-DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
+DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
   struct dma_buffparms *dmap;
   unsigned long   flags;
@@ -1740,6 +1833,9 @@
   switch (sel_type)
     {
     case SEL_IN:
+      if (!(audio_devs[dev]->open_mode))
+	return 0;
+
       dmap = audio_devs[dev]->dmap_in;
 
       if (dmap->mapping_flags & DMA_MAP_MAPPED)
@@ -1750,16 +1846,17 @@
 	  save_flags (flags);
 	  cli ();
 
-	  in_sleep_flag[dev].flags = WK_SLEEP;
-	  module_select_wait (&in_sleeper[dev], wait);
+	  in_sleep_flag[dev].opts = WK_SLEEP;
+	  select_wait (&in_sleeper[dev], wait);
 	  restore_flags (flags);
 	  return 0;
 	}
 
       if (dmap->dma_mode != DMODE_INPUT)
 	{
-	  if ((audio_devs[dev]->flags & DMA_DUPLEX) && !dmap->qlen &&
+	  if (dmap->dma_mode == DMODE_NONE &&
 	      audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT &&
+	      !dmap->qlen &&
 	      audio_devs[dev]->go)
 	    {
 	      unsigned long   flags;
@@ -1777,8 +1874,8 @@
 	  save_flags (flags);
 	  cli ();
 
-	  in_sleep_flag[dev].flags = WK_SLEEP;
-	  module_select_wait (&in_sleeper[dev], wait);
+	  in_sleep_flag[dev].opts = WK_SLEEP;
+	  select_wait (&in_sleeper[dev], wait);
 	  restore_flags (flags);
 	  return 0;
 	}
@@ -1796,8 +1893,8 @@
 	  save_flags (flags);
 	  cli ();
 
-	  out_sleep_flag[dev].flags = WK_SLEEP;
-	  module_select_wait (&out_sleeper[dev], wait);
+	  out_sleep_flag[dev].opts = WK_SLEEP;
+	  select_wait (&out_sleeper[dev], wait);
 	  restore_flags (flags);
 	  return 0;
 	}
@@ -1817,8 +1914,8 @@
 	  save_flags (flags);
 	  cli ();
 
-	  out_sleep_flag[dev].flags = WK_SLEEP;
-	  module_select_wait (&out_sleeper[dev], wait);
+	  out_sleep_flag[dev].opts = WK_SLEEP;
+	  select_wait (&out_sleeper[dev], wait);
 	  restore_flags (flags);
 	  return 0;
 	}
@@ -1841,7 +1938,7 @@
 int
 DMAbuf_open (int dev, int mode)
 {
-  return -(ENXIO);
+  return -ENXIO;
 }
 
 int
@@ -1853,31 +1950,31 @@
 int
 DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
 {
-  return -(EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
 {
-  return -(EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_rmchars (int dev, int buff_no, int c)
 {
-  return -(EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_start_output (int dev, int buff_no, int l)
 {
-  return -(EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
-  return -(EIO);
+  return -EIO;
 }
 
 void
@@ -1888,13 +1985,13 @@
 int
 DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
 {
-  return -(EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_open_dma (int dev)
 {
-  return -(ENXIO);
+  return -ENXIO;
 }
 
 void
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c
--- v2.1.5/linux/drivers/sound/dmasound.c	Wed Oct 16 10:48:23 1996
+++ linux/drivers/sound/dmasound.c	Thu Jan  1 02:00:00 1970
@@ -1,3252 +0,0 @@
-
-/* linux/drivers/sound/dmasound.c */
-
-/*
-
-VoxWare compatible Atari TT DMA sound driver for 680x0 Linux
-
-(c) 1995 by Michael Schlueter & Michael Marte
-
-Michael Schlueter (michael@duck.syd.de) did the basic structure of the VFS
-interface and the u-law to signed byte conversion.
-
-Michael Marte (marte@informatik.uni-muenchen.de) did the sound queue,
-/dev/mixer, /dev/sndstat and complemented the VFS interface. He would like
-to thank:
-Michael Schlueter for initial ideas and documentation on the MFP and
-the DMA sound hardware.
-Therapy? for their CD 'Troublegum' which really made me rock.
-
-/dev/sndstat is based on code by Hannu Savolainen, the author of the
-VoxWare family of drivers.
-
-This file is subject to the terms and conditions of the GNU General Public
-License.  See the file COPYING in the main directory of this archive
-for more details.
-
-History:
-1995/8/25	first release
-
-1995/9/02	++roman: fixed atari_stram_alloc() call, the timer programming
-			and several race conditions
-
-1995/9/14	++roman: After some discussion with Michael Schlueter, revised
-			the interrupt disabling
-			Slightly speeded up U8->S8 translation by using long
-			operations where possible
-			Added 4:3 interpolation for /dev/audio
-
-1995/9/20	++TeSche: Fixed a bug in sq_write and changed /dev/audio
-			converting to play at 12517Hz instead of 6258Hz.
-
-1995/9/23	++TeSche: Changed sq_interrupt() and sq_play() to pre-program
-			the DMA for another frame while there's still one
-			running. This allows the IRQ response to be
-			arbitrarily delayed and playing will still continue.
-
-1995/10/14	++Guenther_Kelleter@ac3.maus.de, ++TeSche: better support for
-			Falcon audio (the Falcon doesn't raise an IRQ at the
-			end of a frame, but at the beginning instead!). uses
-			'if (codec_dma)' in lots of places to simply switch
-			between Falcon and TT code.
-
-1995/11/06	++TeSche: started introducing a hardware abstraction scheme
-			(may perhaps also serve for Amigas?), can now play
-			samples at almost all frequencies by means of a more
-			generalized expand routine, takes a good deal of care
-			to cut data only at sample sizes, buffer size is now
-			a kernel runtime option, implemented fsync() & several
-			minor improvements
-		++Guenther: useful hints and bug fixes, cross-checked it for
-			Falcons
-
-1996/3/9	++geert: support added for Amiga, A-law, 16-bit little endian.
-			Unification to drivers/sound/dmasound.c.
-1996/4/6	++Martin Mitchell: updated to 1.3 kernel.
-*/
-
-
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/major.h>
-#include <linux/config.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/bootinfo.h>
-
-#ifdef CONFIG_ATARI
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#endif /* CONFIG_AMIGA */
-
-#include "dmasound.h"
-#include <linux/soundcard.h>
-
-
-#ifdef CONFIG_ATARI
-extern void atari_microwire_cmd(int cmd);
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-   /*
-    *	The minimum period for audio depends on total (for OCS/ECS/AGA)
-    *	(Imported from arch/m68k/amiga/amisound.c)
-    */
-
-extern volatile u_short amiga_audio_min_period;
-
-
-   /*
-    *	amiga_mksound() should be able to restore the period after beeping
-    *	(Imported from arch/m68k/amiga/amisound.c)
-    */
-
-extern u_short amiga_audio_period;
-
-
-   /*
-    *	Audio DMA masks
-    */
-
-#define AMI_AUDIO_OFF	(DMAF_AUD0 | DMAF_AUD1 | DMAF_AUD2 | DMAF_AUD3)
-#define AMI_AUDIO_8	(DMAF_SETCLR | DMAF_MASTER | DMAF_AUD0 | DMAF_AUD1)
-#define AMI_AUDIO_14	(AMI_AUDIO_8 | DMAF_AUD2 | DMAF_AUD3)
-
-#endif /* CONFIG_AMIGA */
-
-
-/*** Some declarations *******************************************************/
-
-
-#define DMASND_TT		1
-#define DMASND_FALCON		2
-#define DMASND_AMIGA		3
-
-#define MAX_CATCH_RADIUS	10
-#define MIN_BUFFERS		4
-#define MIN_BUFSIZE 		4
-#define MAX_BUFSIZE		128	/* Limit for Amiga */
-
-static int catchRadius = 0, numBufs = 4, bufSize = 32;
-
-
-#define arraysize(x)	(sizeof(x)/sizeof(*(x)))
-#define min(x, y)	((x) < (y) ? (x) : (y))
-#define le2be16(x)	(((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
-#define le2be16dbl(x)	(((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff))
-
-#define IOCTL_IN(arg)		get_user((int *)(arg))
-#define IOCTL_OUT(arg, ret)	ioctl_return((int *)arg, ret)
-
-
-/*** Some low level helpers **************************************************/
-
-
-/* 8 bit mu-law */
-
-static char ulaw2dma8[] = {
-    -126,   -122,   -118,   -114,   -110,   -106,   -102,    -98,
-     -94,    -90,    -86,    -82,    -78,    -74,    -70,    -66,
-     -63,    -61,    -59,    -57,    -55,    -53,    -51,    -49,
-     -47,    -45,    -43,    -41,    -39,    -37,    -35,    -33,
-     -31,    -30,    -29,    -28,    -27,    -26,    -25,    -24,
-     -23,    -22,    -21,    -20,    -19,    -18,    -17,    -16,
-     -16,    -15,    -15,    -14,    -14,    -13,    -13,    -12,
-     -12,    -11,    -11,    -10,    -10,     -9,     -9,     -8,
-      -8,     -8,     -7,     -7,     -7,     -7,     -6,     -6,
-      -6,     -6,     -5,     -5,     -5,     -5,     -4,     -4,
-      -4,     -4,     -4,     -4,     -3,     -3,     -3,     -3,
-      -3,     -3,     -3,     -3,     -2,     -2,     -2,     -2,
-      -2,     -2,     -2,     -2,     -2,     -2,     -2,     -2,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,      0,
-     125,    121,    117,    113,    109,    105,    101,     97,
-      93,     89,     85,     81,     77,     73,     69,     65,
-      62,     60,     58,     56,     54,     52,     50,     48,
-      46,     44,     42,     40,     38,     36,     34,     32,
-      30,     29,     28,     27,     26,     25,     24,     23,
-      22,     21,     20,     19,     18,     17,     16,     15,
-      15,     14,     14,     13,     13,     12,     12,     11,
-      11,     10,     10,      9,      9,      8,      8,      7,
-       7,      7,      6,      6,      6,      6,      5,      5,
-       5,      5,      4,      4,      4,      4,      3,      3,
-       3,      3,      3,      3,      2,      2,      2,      2,
-       2,      2,      2,      2,      1,      1,      1,      1,
-       1,      1,      1,      1,      1,      1,      1,      1,
-       0,      0,      0,      0,      0,      0,      0,      0,
-       0,      0,      0,      0,      0,      0,      0,      0,
-       0,      0,      0,      0,      0,      0,      0,      0
-};
-
-/* 8 bit A-law */
-
-static char alaw2dma8[] = {
-     -22,    -21,    -24,    -23,    -18,    -17,    -20,    -19,
-     -30,    -29,    -32,    -31,    -26,    -25,    -28,    -27,
-     -11,    -11,    -12,    -12,     -9,     -9,    -10,    -10,
-     -15,    -15,    -16,    -16,    -13,    -13,    -14,    -14,
-     -86,    -82,    -94,    -90,    -70,    -66,    -78,    -74,
-    -118,   -114,   -126,   -122,   -102,    -98,   -110,   -106,
-     -43,    -41,    -47,    -45,    -35,    -33,    -39,    -37,
-     -59,    -57,    -63,    -61,    -51,    -49,    -55,    -53,
-      -2,     -2,     -2,     -2,     -2,     -2,     -2,     -2,
-      -2,     -2,     -2,     -2,     -2,     -2,     -2,     -2,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
-      -6,     -6,     -6,     -6,     -5,     -5,     -5,     -5,
-      -8,     -8,     -8,     -8,     -7,     -7,     -7,     -7,
-      -3,     -3,     -3,     -3,     -3,     -3,     -3,     -3,
-      -4,     -4,     -4,     -4,     -4,     -4,     -4,     -4,
-      21,     20,     23,     22,     17,     16,     19,     18,
-      29,     28,     31,     30,     25,     24,     27,     26,
-      10,     10,     11,     11,      8,      8,      9,      9,
-      14,     14,     15,     15,     12,     12,     13,     13,
-      86,     82,     94,     90,     70,     66,     78,     74,
-     118,    114,    126,    122,    102,     98,    110,    106,
-      43,     41,     47,     45,     35,     33,     39,     37,
-      59,     57,     63,     61,     51,     49,     55,     53,
-       1,      1,      1,      1,      1,      1,      1,      1,
-       1,      1,      1,      1,      1,      1,      1,      1,
-       0,      0,      0,      0,      0,      0,      0,      0,
-       0,      0,      0,      0,      0,      0,      0,      0,
-       5,      5,      5,      5,      4,      4,      4,      4,
-       7,      7,      7,      7,      6,      6,      6,      6,
-       2,      2,      2,      2,      2,      2,      2,      2,
-       3,      3,      3,      3,      3,      3,      3,      3
-};
-
-
-#ifdef HAS_16BIT_TABLES
-
-/* 16 bit mu-law */
-
-static char ulaw2dma16[] = {
-    -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
-    -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
-    -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
-    -11900, -11388, -10876, -10364,  -9852,  -9340,  -8828,  -8316,
-     -7932,  -7676,  -7420,  -7164,  -6908,  -6652,  -6396,  -6140,
-     -5884,  -5628,  -5372,  -5116,  -4860,  -4604,  -4348,  -4092,
-     -3900,  -3772,  -3644,  -3516,  -3388,  -3260,  -3132,  -3004,
-     -2876,  -2748,  -2620,  -2492,  -2364,  -2236,  -2108,  -1980,
-     -1884,  -1820,  -1756,  -1692,  -1628,  -1564,  -1500,  -1436,
-     -1372,  -1308,  -1244,  -1180,  -1116,  -1052,   -988,   -924,
-      -876,   -844,   -812,   -780,   -748,   -716,   -684,   -652,
-      -620,   -588,   -556,   -524,   -492,   -460,   -428,   -396,
-      -372,   -356,   -340,   -324,   -308,   -292,   -276,   -260,
-      -244,   -228,   -212,   -196,   -180,   -164,   -148,   -132,
-      -120,   -112,   -104,    -96,    -88,    -80,    -72,    -64,
-       -56,    -48,    -40,    -32,    -24,    -16,     -8,      0,
-     32124,  31100,  30076,  29052,  28028,  27004,  25980,  24956,
-     23932,  22908,  21884,  20860,  19836,  18812,  17788,  16764,
-     15996,  15484,  14972,  14460,  13948,  13436,  12924,  12412,
-     11900,  11388,  10876,  10364,   9852,   9340,   8828,   8316,
-      7932,   7676,   7420,   7164,   6908,   6652,   6396,   6140,
-      5884,   5628,   5372,   5116,   4860,   4604,   4348,   4092,
-      3900,   3772,   3644,   3516,   3388,   3260,   3132,   3004,
-      2876,   2748,   2620,   2492,   2364,   2236,   2108,   1980,
-      1884,   1820,   1756,   1692,   1628,   1564,   1500,   1436,
-      1372,   1308,   1244,   1180,   1116,   1052,    988,    924,
-       876,    844,    812,    780,    748,    716,    684,    652,
-       620,    588,    556,    524,    492,    460,    428,    396,
-       372,    356,    340,    324,    308,    292,    276,    260,
-       244,    228,    212,    196,    180,    164,    148,    132,
-       120,    112,    104,     96,     88,     80,     72,     64,
-        56,     48,     40,     32,     24,     16,      8,      0,
-};
-
-/* 16 bit A-law */
-
-static char alaw2dma16[] = {
-     -5504,  -5248,  -6016,  -5760,  -4480,  -4224,  -4992,  -4736,
-     -7552,  -7296,  -8064,  -7808,  -6528,  -6272,  -7040,  -6784,
-     -2752,  -2624,  -3008,  -2880,  -2240,  -2112,  -2496,  -2368,
-     -3776,  -3648,  -4032,  -3904,  -3264,  -3136,  -3520,  -3392,
-    -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
-    -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
-    -11008, -10496, -12032, -11520,  -8960,  -8448,  -9984,  -9472,
-    -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
-      -344,   -328,   -376,   -360,   -280,   -264,   -312,   -296,
-      -472,   -456,   -504,   -488,   -408,   -392,   -440,   -424,
-       -88,    -72,   -120,   -104,    -24,     -8,    -56,    -40,
-      -216,   -200,   -248,   -232,   -152,   -136,   -184,   -168,
-     -1376,  -1312,  -1504,  -1440,  -1120,  -1056,  -1248,  -1184,
-     -1888,  -1824,  -2016,  -1952,  -1632,  -1568,  -1760,  -1696,
-      -688,   -656,   -752,   -720,   -560,   -528,   -624,   -592,
-      -944,   -912,  -1008,   -976,   -816,   -784,   -880,   -848,
-      5504,   5248,   6016,   5760,   4480,   4224,   4992,   4736,
-      7552,   7296,   8064,   7808,   6528,   6272,   7040,   6784,
-      2752,   2624,   3008,   2880,   2240,   2112,   2496,   2368,
-      3776,   3648,   4032,   3904,   3264,   3136,   3520,   3392,
-     22016,  20992,  24064,  23040,  17920,  16896,  19968,  18944,
-     30208,  29184,  32256,  31232,  26112,  25088,  28160,  27136,
-     11008,  10496,  12032,  11520,   8960,   8448,   9984,   9472,
-     15104,  14592,  16128,  15616,  13056,  12544,  14080,  13568,
-       344,    328,    376,    360,    280,    264,    312,    296,
-       472,    456,    504,    488,    408,    392,    440,    424,
-        88,     72,    120,    104,     24,      8,     56,     40,
-       216,    200,    248,    232,    152,    136,    184,    168,
-      1376,   1312,   1504,   1440,   1120,   1056,   1248,   1184,
-      1888,   1824,   2016,   1952,   1632,   1568,   1760,   1696,
-       688,    656,    752,    720,    560,    528,    624,    592,
-       944,    912,   1008,    976,    816,    784,    880,    848,
-};
-#endif /* HAS_16BIT_TABLES */
-
-
-#ifdef HAS_14BIT_TABLES
-
-/* 14 bit mu-law (LSB) */
-
-static char alaw2dma14l[] = {
-        33,     33,     33,     33,     33,     33,     33,     33,
-        33,     33,     33,     33,     33,     33,     33,     33,
-        33,     33,     33,     33,     33,     33,     33,     33,
-        33,     33,     33,     33,     33,     33,     33,     33,
-         1,      1,      1,      1,      1,      1,      1,      1,
-         1,      1,      1,      1,      1,      1,      1,      1,
-        49,     17,     49,     17,     49,     17,     49,     17,
-        49,     17,     49,     17,     49,     17,     49,     17,
-        41,     57,      9,     25,     41,     57,      9,     25,
-        41,     57,      9,     25,     41,     57,      9,     25,
-        37,     45,     53,     61,      5,     13,     21,     29,
-        37,     45,     53,     61,      5,     13,     21,     29,
-        35,     39,     43,     47,     51,     55,     59,     63,
-         3,      7,     11,     15,     19,     23,     27,     31,
-        34,     36,     38,     40,     42,     44,     46,     48,
-        50,     52,     54,     56,     58,     60,     62,      0,
-        31,     31,     31,     31,     31,     31,     31,     31,
-        31,     31,     31,     31,     31,     31,     31,     31,
-        31,     31,     31,     31,     31,     31,     31,     31,
-        31,     31,     31,     31,     31,     31,     31,     31,
-        63,     63,     63,     63,     63,     63,     63,     63,
-        63,     63,     63,     63,     63,     63,     63,     63,
-        15,     47,     15,     47,     15,     47,     15,     47,
-        15,     47,     15,     47,     15,     47,     15,     47,
-        23,      7,     55,     39,     23,      7,     55,     39,
-        23,      7,     55,     39,     23,      7,     55,     39,
-        27,     19,     11,      3,     59,     51,     43,     35,
-        27,     19,     11,      3,     59,     51,     43,     35,
-        29,     25,     21,     17,     13,      9,      5,      1,
-        61,     57,     53,     49,     45,     41,     37,     33,
-        30,     28,     26,     24,     22,     20,     18,     16,
-        14,     12,     10,      8,      6,      4,      2,      0
-};
-
-/* 14 bit A-law (LSB) */
-
-static char alaw2dma14l[] = {
-        32,     32,     32,     32,     32,     32,     32,     32,
-        32,     32,     32,     32,     32,     32,     32,     32,
-        16,     48,     16,     48,     16,     48,     16,     48,
-        16,     48,     16,     48,     16,     48,     16,     48,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-        42,     46,     34,     38,     58,     62,     50,     54,
-        10,     14,      2,      6,     26,     30,     18,     22,
-        42,     46,     34,     38,     58,     62,     50,     54,
-        10,     14,      2,      6,     26,     30,     18,     22,
-        40,     56,      8,     24,     40,     56,      8,     24,
-        40,     56,      8,     24,     40,     56,      8,     24,
-        20,     28,      4,     12,     52,     60,     36,     44,
-        20,     28,      4,     12,     52,     60,     36,     44,
-        32,     32,     32,     32,     32,     32,     32,     32,
-        32,     32,     32,     32,     32,     32,     32,     32,
-        48,     16,     48,     16,     48,     16,     48,     16,
-        48,     16,     48,     16,     48,     16,     48,     16,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-        22,     18,     30,     26,      6,      2,     14,     10,
-        54,     50,     62,     58,     38,     34,     46,     42,
-        22,     18,     30,     26,      6,      2,     14,     10,
-        54,     50,     62,     58,     38,     34,     46,     42,
-        24,      8,     56,     40,     24,      8,     56,     40,
-        24,      8,     56,     40,     24,      8,     56,     40,
-        44,     36,     60,     52,     12,      4,     28,     20,
-        44,     36,     60,     52,     12,      4,     28,     20
-};
-#endif /* HAS_14BIT_TABLES */
-
-
-/*** Translations ************************************************************/
-
-
-#ifdef CONFIG_ATARI
-static long ata_ct_law(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft);
-static long ata_ct_s8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft);
-static long ata_ct_u8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft);
-static long ata_ct_s16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ata_ct_u16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ata_ct_s16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ata_ct_u16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ata_ctx_law(const u_char *userPtr, long userCount, u_char frame[],
-			long *frameUsed, long frameLeft);
-static long ata_ctx_s8(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft);
-static long ata_ctx_u8(const u_char *userPtr, long userCount, u_char frame[],
-		        long *frameUsed, long frameLeft);
-static long ata_ctx_s16be(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft);
-static long ata_ctx_u16be(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft);
-static long ata_ctx_s16le(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft);
-static long ata_ctx_u16le(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft);
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-static long ami_ct_law(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft);
-static long ami_ct_s8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft);
-static long ami_ct_u8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft);
-static long ami_ct_s16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ami_ct_u16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ami_ct_s16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ami_ct_u16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-#endif /* CONFIG_AMIGA */
-
-
-/*** Machine definitions *****************************************************/
-
-
-typedef struct {
-    int type;
-    void *(*dma_alloc)(unsigned int, int);
-    void (*dma_free)(void *, unsigned int);
-    int (*irqinit)(void);
-    void (*init)(void);
-    void (*silence)(void);
-    int (*setFormat)(int);
-    int (*setVolume)(int);
-    int (*setBass)(int);
-    int (*setTreble)(int);
-    void (*play)(void);
-} MACHINE;
-
-
-/*** Low level stuff *********************************************************/
-
-
-typedef struct {
-    int format;		/* AFMT_* */
-    int stereo;		/* 0 = mono, 1 = stereo */
-    int size;		/* 8/16 bit*/
-    int speed;		/* speed */
-} SETTINGS;
-
-typedef struct {
-    long (*ct_ulaw)(const u_char *, long, u_char *, long *, long);
-    long (*ct_alaw)(const u_char *, long, u_char *, long *, long);
-    long (*ct_s8)(const u_char *, long, u_char *, long *, long);
-    long (*ct_u8)(const u_char *, long, u_char *, long *, long);
-    long (*ct_s16be)(const u_char *, long, u_char *, long *, long);
-    long (*ct_u16be)(const u_char *, long, u_char *, long *, long);
-    long (*ct_s16le)(const u_char *, long, u_char *, long *, long);
-    long (*ct_u16le)(const u_char *, long, u_char *, long *, long);
-} TRANS;
-
-struct sound_settings {
-    MACHINE mach;	/* machine dependent things */
-    SETTINGS hard;	/* hardware settings */
-    SETTINGS soft;	/* software settings */
-    SETTINGS dsp;	/* /dev/dsp default settings */
-    TRANS *trans;	/* supported translations */
-    int volume_left;	/* volume (range is machine dependent) */
-    int volume_right;
-    int bass;		/* tone (range is machine dependent) */
-    int treble;
-    int minDev;		/* minor device number currently open */
-#ifdef CONFIG_ATARI
-    int bal;		/* balance factor for expanding (not volume!) */
-    u_long data;	/* data for expanding */
-#endif /* CONFIG_ATARI */
-};
-
-static struct sound_settings sound;
-
-
-#ifdef CONFIG_ATARI
-static void *AtaAlloc(unsigned int size, int flags);
-static void AtaFree(void *, unsigned int size);
-static int AtaIrqInit(void);
-static int AtaSetBass(int bass);
-static int AtaSetTreble(int treble);
-static void TTSilence(void);
-static void TTInit(void);
-static int TTSetFormat(int format);
-static int TTSetVolume(int volume);
-static void FalconSilence(void);
-static void FalconInit(void);
-static int FalconSetFormat(int format);
-static int FalconSetVolume(int volume);
-static void ata_sq_play_next_frame(int index);
-static void AtaPlay(void);
-static void ata_sq_interrupt(int irq, struct pt_regs *fp, void *dummy);
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-static void *AmiAlloc(unsigned int size, int flags);
-static void AmiFree(void *, unsigned int);
-static int AmiIrqInit(void);
-static void AmiSilence(void);
-static void AmiInit(void);
-static int AmiSetFormat(int format);
-static int AmiSetVolume(int volume);
-static int AmiSetTreble(int treble);
-static void ami_sq_play_next_frame(int index);
-static void AmiPlay(void);
-static void ami_sq_interrupt(int irq, struct pt_regs *fp, void *dummy);
-#endif /* CONFIG_AMIGA */
-
-
-/*** Mid level stuff *********************************************************/
-
-
-static void sound_silence(void);
-static void sound_init(void);
-static int sound_set_format(int format);
-static int sound_set_speed(int speed);
-static int sound_set_stereo(int stereo);
-static int sound_set_volume(int volume);
-#ifdef CONFIG_ATARI
-static int sound_set_bass(int bass);
-#endif /* CONFIG_ATARI */
-static int sound_set_treble(int treble);
-static long sound_copy_translate(const u_char *userPtr, long userCount,
-				 u_char frame[], long *frameUsed,
-				 long frameLeft);
-
-
-/*
- * /dev/mixer abstraction
- */
-
-struct sound_mixer {
-    int busy;
-};
-
-static struct sound_mixer mixer;
-
-static void mixer_init(void);
-static int mixer_open(int open_mode);
-static int mixer_release(void);
-static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg);
-
-
-/*
- * Sound queue stuff, the heart of the driver
- */
-
-struct sound_queue {
-    int max_count, block_size;
-    char **buffers;
-
-    /* it shouldn't be necessary to declare any of these volatile */
-    int front, rear, count;
-    int rear_size;
-    /*
-     *	The use of the playing field depends on the hardware
-     *
-     *	Atari: The number of frames that are loaded/playing
-     *
-     *	Amiga: Bit 0 is set: a frame is loaded
-     *	       Bit 1 is set: a frame is playing
-     */
-    int playing;
-    struct wait_queue *write_queue, *open_queue, *sync_queue;
-    int open_mode;
-    int busy, syncing;
-#ifdef CONFIG_ATARI
-    int ignore_int;		/* ++TeSche: used for Falcon */
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-    int block_size_half, block_size_quarter;
-#endif /* CONFIG_AMIGA */
-};
-
-static struct sound_queue sq;
-
-#define sq_block_address(i)	(sq.buffers[i])
-#define SIGNAL_RECEIVED	(current->signal & ~current->blocked)
-#define NON_BLOCKING(open_mode)	(open_mode & O_NONBLOCK)
-#define ONE_SECOND	HZ	/* in jiffies (100ths of a second) */
-#define NO_TIME_LIMIT	0xffffffff
-#define SLEEP(queue, time_limit) \
-	current->timeout = jiffies+(time_limit); \
-	interruptible_sleep_on(&queue);
-#define WAKE_UP(queue)	(wake_up_interruptible(&queue))
-
-static void sq_init(int numBufs, int bufSize, char **buffers);
-static void sq_play(void);
-static int sq_write(const char *src, int uLeft);
-static int sq_open(int open_mode);
-static void sq_reset(void);
-static int sq_sync(void);
-static int sq_release(void);
-
-
-/*
- * /dev/sndstat
- */
-
-struct sound_state {
-    int busy;
-    char buf[512];
-    int len, ptr;
-};
-
-static struct sound_state state;
-
-static void state_init(void);
-static int state_open(int open_mode);
-static int state_release(void);
-static int state_read(char *dest, int count);
-
-
-/*** High level stuff ********************************************************/
-
-
-static int sound_open(struct inode *inode, struct file *file);
-static int sound_fsync(struct inode *inode, struct file *filp);
-static void sound_release(struct inode *inode, struct file *file);
-static int sound_lseek(struct inode *inode, struct file *file, off_t offset,
-		       int orig);
-static int sound_read(struct inode *inode, struct file *file, char *buf,
-		      int count);
-static int sound_write(struct inode *inode, struct file *file, const char *buf,
-		       int count);
-static int ioctl_return(int *addr, int value);
-static int unknown_minor_dev(char *fname, int dev);
-static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg);
-
-
-/*** Config & Setup **********************************************************/
-
-
-void soundcard_init(void);
-void dmasound_setup(char *str, int *ints);
-void sound_setup(char *str, int *ints);		/* ++Martin: stub for now */
-
-
-/*** Translations ************************************************************/
-
-
-/* ++TeSche: radically changed for new expanding purposes...
- *
- * These two routines now deal with copying/expanding/translating the samples
- * from user space into our buffer at the right frequency. They take care about
- * how much data there's actually to read, how much buffer space there is and
- * to convert samples into the right frequency/encoding. They will only work on
- * complete samples so it may happen they leave some bytes in the input stream
- * if the user didn't write a multiple of the current sample size. They both
- * return the number of bytes they've used from both streams so you may detect
- * such a situation. Luckily all programs should be able to cope with that.
- *
- * I think I've optimized anything as far as one can do in plain C, all
- * variables should fit in registers and the loops are really short. There's
- * one loop for every possible situation. Writing a more generalized and thus
- * parameterized loop would only produce slower code. Feel free to optimize
- * this in assembler if you like. :)
- *
- * I think these routines belong here because they're not yet really hardware
- * independent, especially the fact that the Falcon can play 16bit samples
- * only in stereo is hardcoded in both of them!
- *
- * ++geert: split in even more functions (one per format)
- */
-
-#ifdef CONFIG_ATARI
-static long ata_ct_law(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft)
-{
-    char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
-    long count, used;
-    u_char *p = &frame[*frameUsed];
-
-    count = min(userCount, frameLeft);
-    if (sound.soft.stereo)
-	count &= ~1;
-    used = count;
-    while (count > 0) {
-	*p++ = table[get_user(userPtr++)];
-	count--;
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ata_ct_s8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft)
-{
-    long count, used;
-    void *p = &frame[*frameUsed];
-
-    count = min(userCount, frameLeft);
-    if (sound.soft.stereo)
-	count &= ~1;
-    used = count;
-    copy_from_user(p, userPtr, count);
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ata_ct_u8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft)
-{
-    long count, used;
-
-    if (!sound.soft.stereo) {
-	u_char *p = &frame[*frameUsed];
-	count = min(userCount, frameLeft);
-	used = count;
-	while (count > 0) {
-	    *p++ = get_user(userPtr++) ^ 0x80;
-	    count--;
-	}
-    } else {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>1;
-	used = count*2;
-	while (count > 0) {
-	    *p++ = get_user(((u_short *)userPtr)++) ^ 0x8080;
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ata_ct_s16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    *p++ = data;
-	    *p++ = data;
-	    count--;
-	}
-	*frameUsed += used*2;
-    } else {
-	void *p = (u_short *)&frame[*frameUsed];
-	count = min(userCount, frameLeft) & ~3;
-	used = count;
-	copy_from_user(p, userPtr, count);
-	*frameUsed += used;
-    }
-    return(used);
-}
-
-
-static long ata_ct_u16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-	    *p++ = data;
-	    *p++ = data;
-	    count--;
-	}
-	*frameUsed += used*2;
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>2;
-	used = count*4;
-	while (count > 0) {
-	    *p++ = get_user(((u_int *)userPtr)++) ^ 0x80008000;
-	    count--;
-	}
-	*frameUsed += used;
-    }
-    return(used);
-}
-
-
-static long ata_ct_s16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    count = frameLeft;
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data);
-	    *p++ = data;
-	    *p++ = data;
-	    count--;
-	}
-	*frameUsed += used*2;
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>2;
-	used = count*4;
-	while (count > 0) {
-	    data = get_user(((u_int *)userPtr)++);
-	    data = le2be16dbl(data);
-	    *p++ = data;
-	    count--;
-	}
-	*frameUsed += used;
-    }
-    return(used);
-}
-
-
-static long ata_ct_u16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    count = frameLeft;
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data) ^ 0x8000;
-	    *p++ = data;
-	    *p++ = data;
-	}
-	*frameUsed += used*2;
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>2;
-	used = count;
-	while (count > 0) {
-	    data = get_user(((u_int *)userPtr)++);
-	    data = le2be16dbl(data) ^ 0x80008000;
-	    *p++ = data;
-	    count--;
-	}
-	*frameUsed += used;
-    }
-    return(used);
-}
-
-
-static long ata_ctx_law(const u_char *userPtr, long userCount, u_char frame[],
-			long *frameUsed, long frameLeft)
-{
-    char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_char *p = &frame[*frameUsed];
-	while (frameLeft) {
-	    if (bal < 0) {
-		if (!userCount)
-		    break;
-		data = table[get_user(userPtr++)];
-		userCount--;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft--;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 2) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = table[get_user(userPtr++)] << 8;
-		data |= table[get_user(userPtr++)];
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 2;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_s8(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_char *p = &frame[*frameUsed];
-	while (frameLeft) {
-	    if (bal < 0) {
-		if (!userCount)
-		    break;
-		data = get_user(userPtr++);
-		userCount--;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft--;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 2) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = get_user(((u_short *)userPtr)++);
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 2;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_u8(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_char *p = &frame[*frameUsed];
-	while (frameLeft) {
-	    if (bal < 0) {
-		if (!userCount)
-		    break;
-		data = get_user(userPtr++) ^ 0x80;
-		userCount--;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft--;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 2) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = get_user(((u_short *)userPtr)++) ^ 0x8080;
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 2;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_s16be(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = get_user(((u_short *)userPtr)++);
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 4)
-		    break;
-		data = get_user(((u_int *)userPtr)++);
-		userCount -= 4;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_u16be(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 4)
-		    break;
-		data = get_user(((u_int *)userPtr)++) ^ 0x80008000;
-		userCount -= 4;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_s16le(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = get_user(((u_short *)userPtr)++);
-		data = le2be16(data);
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 4)
-		    break;
-		data = get_user(((u_int *)userPtr)++);
-		data = le2be16dbl(data);
-		userCount -= 4;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_u16le(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = get_user(((u_short *)userPtr)++);
-		data = le2be16(data) ^ 0x8000;
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 4)
-		    break;
-		data = get_user(((u_int *)userPtr)++);
-		data = le2be16dbl(data) ^ 0x80008000;
-		userCount -= 4;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-#endif /* CONFIG_ATARI */
-
-
-#ifdef CONFIG_AMIGA
-static long ami_ct_law(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft)
-{
-    char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
-    long count, used;
-
-    if (!sound.soft.stereo) {
-	u_char *p = &frame[*frameUsed];
-	count = min(userCount, frameLeft) & ~1;
-	used = count;
-	while (count > 0) {
-	    *p++ = table[get_user(userPtr++)];
-	    count--;
-	}
-    } else {
-	u_char *left = &frame[*frameUsed>>1];
-	u_char *right = left+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    *left++ = table[get_user(userPtr++)];
-	    *right++ = table[get_user(userPtr++)];
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_s8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft)
-{
-    long count, used;
-
-    if (!sound.soft.stereo) {
-	void *p = &frame[*frameUsed];
-	count = min(userCount, frameLeft) & ~1;
-	used = count;
-	copy_from_user(p, userPtr, count);
-    } else {
-	u_char *left = &frame[*frameUsed>>1];
-	u_char *right = left+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    *left++ = get_user(userPtr++);
-	    *right++ = get_user(userPtr++);
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_u8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft)
-{
-    long count, used;
-
-    if (!sound.soft.stereo) {
-	char *p = &frame[*frameUsed];
-	count = min(userCount, frameLeft) & ~1;
-	used = count;
-	while (count > 0) {
-	    *p++ = get_user(userPtr++) ^ 0x80;
-	    count--;
-	}
-    } else {
-	u_char *left = &frame[*frameUsed>>1];
-	u_char *right = left+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    *left++ = get_user(userPtr++) ^ 0x80;
-	    *right++ = get_user(userPtr++) ^ 0x80;
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_s16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-	u_char *high = &frame[*frameUsed>>1];
-	u_char *low = high+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    *high = data>>8;
-	    *low = (data>>2) & 0x3f;
-	    count--;
-	}
-    } else {
-	u_char *lefth = &frame[*frameUsed>>2];
-	u_char *leftl = lefth+sq.block_size_quarter;
-	u_char *righth = lefth+sq.block_size_half;
-	u_char *rightl = righth+sq.block_size_quarter;
-	count = min(userCount, frameLeft)>>2 & ~1;
-	used = count*4;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    *lefth = data>>8;
-	    *leftl = (data>>2) & 0x3f;
-	    data = get_user(((u_short *)userPtr)++);
-	    *righth = data>>8;
-	    *rightl = (data>>2) & 0x3f;
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_u16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-	u_char *high = &frame[*frameUsed>>1];
-	u_char *low = high+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-	    *high = data>>8;
-	    *low = (data>>2) & 0x3f;
-	    count--;
-	}
-    } else {
-	u_char *lefth = &frame[*frameUsed>>2];
-	u_char *leftl = lefth+sq.block_size_quarter;
-	u_char *righth = lefth+sq.block_size_half;
-	u_char *rightl = righth+sq.block_size_quarter;
-	count = min(userCount, frameLeft)>>2 & ~1;
-	used = count*4;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-	    *lefth = data>>8;
-	    *leftl = (data>>2) & 0x3f;
-	    data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-	    *righth = data>>8;
-	    *rightl = (data>>2) & 0x3f;
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_s16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-	u_char *high = &frame[*frameUsed>>1];
-	u_char *low = high+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data);
-	    *high = data>>8;
-	    *low = (data>>2) & 0x3f;
-	    count--;
-	}
-    } else {
-	u_char *lefth = &frame[*frameUsed>>2];
-	u_char *leftl = lefth+sq.block_size_quarter;
-	u_char *righth = lefth+sq.block_size_half;
-	u_char *rightl = righth+sq.block_size_quarter;
-	count = min(userCount, frameLeft)>>2 & ~1;
-	used = count*4;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data);
-	    *lefth = data>>8;
-	    *leftl = (data>>2) & 0x3f;
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data);
-	    *righth = data>>8;
-	    *rightl = (data>>2) & 0x3f;
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_u16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-	u_char *high = &frame[*frameUsed>>1];
-	u_char *low = high+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data) ^ 0x8000;
-	    *high = data>>8;
-	    *low = (data>>2) & 0x3f;
-	    count--;
-	}
-    } else {
-	u_char *lefth = &frame[*frameUsed>>2];
-	u_char *leftl = lefth+sq.block_size_quarter;
-	u_char *righth = lefth+sq.block_size_half;
-	u_char *rightl = righth+sq.block_size_quarter;
-	count = min(userCount, frameLeft)>>2 & ~1;
-	used = count*4;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data) ^ 0x8000;
-	    *lefth = data>>8;
-	    *leftl = (data>>2) & 0x3f;
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data) ^ 0x8000;
-	    *righth = data>>8;
-	    *rightl = (data>>2) & 0x3f;
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-#endif /* CONFIG_AMIGA */
-
-
-#ifdef CONFIG_ATARI
-static TRANS transTTNormal = {
-    ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, NULL, NULL, NULL, NULL
-};
-
-static TRANS transTTExpanding = {
-    ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, NULL, NULL, NULL, NULL
-};
-
-static TRANS transFalconNormal = {
-    ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, ata_ct_s16be, ata_ct_u16be,
-    ata_ct_s16le, ata_ct_u16le
-};
-
-static TRANS transFalconExpanding = {
-    ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, ata_ctx_s16be,
-    ata_ctx_u16be, ata_ctx_s16le, ata_ctx_u16le
-};
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-static TRANS transAmiga = {
-    ami_ct_law, ami_ct_law, ami_ct_s8, ami_ct_u8, ami_ct_s16be, ami_ct_u16be,
-    ami_ct_s16le, ami_ct_u16le
-};
-#endif /* CONFIG_AMIGA */
-
-
-/*** Low level stuff *********************************************************/
-
-
-#ifdef CONFIG_ATARI
-
-/*
- * Atari (TT/Falcon)
- */
-
-static void *AtaAlloc(unsigned int size, int flags)
-{
-    int order;
-    unsigned int a_size;
-    order = 0;
-    a_size = PAGE_SIZE;
-    while (a_size < size) {
-	order++;
-	a_size <<= 1;
-    }
-    return (void *) __get_dma_pages(flags, order);
-}
-
-static void AtaFree(void *obj, unsigned int size)
-{
-    int order;
-    unsigned int a_size;
-    order = 0;
-    a_size = PAGE_SIZE;
-    while (a_size < size) {
-	order++;
-	a_size <<= 1;
-    }
-    free_pages ((unsigned long) obj, order);
-}
-
-static int AtaIrqInit(void)
-{
-    /* Set up timer A. Timer A
-    will receive a signal upon end of playing from the sound
-    hardware. Furthermore Timer A is able to count events
-    and will cause an interrupt after a programmed number
-    of events. So all we need to keep the music playing is
-    to provide the sound hardware with new data upon
-    an interrupt from timer A. */
-    mfp.tim_ct_a = 0;		/* ++roman: Stop timer before programming! */
-    mfp.tim_dt_a = 1;		/* Cause interrupt after first event. */
-    mfp.tim_ct_a = 8;		/* Turn on event counting. */
-    /* Register interrupt handler. */
-    add_isr(IRQ_MFP_TIMA, ata_sq_interrupt, IRQ_TYPE_SLOW, NULL, "DMA sound");
-    mfp.int_en_a |= 0x20;	/* Turn interrupt on. */
-    mfp.int_mk_a |= 0x20;
-    return(1);
-}
-
-
-#define TONE_VOXWARE_TO_DB(v) \
-	(((v) < 0) ? -12 : ((v) > 100) ? 12 : ((v) - 50) * 6 / 25)
-#define TONE_DB_TO_VOXWARE(v) (((v) * 25 + ((v) > 0 ? 5 : -5)) / 6 + 50)
-
-
-static int AtaSetBass(int bass)
-{
-    sound.bass = TONE_VOXWARE_TO_DB(bass);
-    atari_microwire_cmd(MW_LM1992_BASS(sound.bass));
-    return(TONE_DB_TO_VOXWARE(sound.bass));
-}
-
-
-static int AtaSetTreble(int treble)
-{
-    sound.treble = TONE_VOXWARE_TO_DB(treble);
-    atari_microwire_cmd(MW_LM1992_TREBLE(sound.treble));
-    return(TONE_DB_TO_VOXWARE(sound.treble));
-}
-
-
-
-/*
- * TT
- */
-
-
-static void TTSilence(void)
-{
-    tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-    atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */
-}
-
-
-static void TTInit(void)
-{
-    int mode, i, idx;
-    const int freq[4] = {50066, 25033, 12517, 6258};
-
-    /* search a frequency that fits into the allowed error range */
-
-    idx = -1;
-    for (i = 0; i < arraysize(freq); i++)
-	/* this isn't as much useful for a TT than for a Falcon, but
-	 * then it doesn't hurt very much to implement it for a TT too.
-	 */
-	if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius)
-	    idx = i;
-    if (idx > -1) {
-	sound.soft.speed = freq[idx];
-	sound.trans = &transTTNormal;
-    } else
-	sound.trans = &transTTExpanding;
-
-    TTSilence();
-    sound.hard = sound.soft;
-
-    if (sound.hard.speed > 50066) {
-	/* we would need to squeeze the sound, but we won't do that */
-	sound.hard.speed = 50066;
-	mode = DMASND_MODE_50KHZ;
-	sound.trans = &transTTNormal;
-    } else if (sound.hard.speed > 25033) {
-	sound.hard.speed = 50066;
-	mode = DMASND_MODE_50KHZ;
-    } else if (sound.hard.speed > 12517) {
-	sound.hard.speed = 25033;
-	mode = DMASND_MODE_25KHZ;
-    } else if (sound.hard.speed > 6258) {
-	sound.hard.speed = 12517;
-	mode = DMASND_MODE_12KHZ;
-    } else {
-	sound.hard.speed = 6258;
-	mode = DMASND_MODE_6KHZ;
-    }
-
-    tt_dmasnd.mode = (sound.hard.stereo ?
-		      DMASND_MODE_STEREO : DMASND_MODE_MONO) |
-		     DMASND_MODE_8BIT | mode;
-
-    sound.bal = -sound.soft.speed;
-}
-
-
-static int TTSetFormat(int format)
-{
-    /* TT sound DMA supports only 8bit modes */
-
-    switch (format) {
-	case AFMT_QUERY:
-	    return(sound.soft.format);
-	case AFMT_MU_LAW:
-	case AFMT_A_LAW:
-	case AFMT_S8:
-	case AFMT_U8:
-	    break;
-	default:
-	    format = AFMT_S8;
-    }
-
-    sound.soft.format = format;
-    sound.soft.size = 8;
-    if (sound.minDev == SND_DEV_DSP) {
-	sound.dsp.format = format;
-	sound.dsp.size = 8;
-    }
-    TTInit();
-
-    return(format);
-}
-
-
-#define VOLUME_VOXWARE_TO_DB(v) \
-	(((v) < 0) ? -40 : ((v) > 100) ? 0 : ((v) * 2) / 5 - 40)
-#define VOLUME_DB_TO_VOXWARE(v) ((((v) + 40) * 5 + 1) / 2)
-
-
-static int TTSetVolume(int volume)
-{
-    sound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff);
-    atari_microwire_cmd(MW_LM1992_BALLEFT(sound.volume_left));
-    sound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8);
-    atari_microwire_cmd(MW_LM1992_BALRIGHT(sound.volume_right));
-    return(VOLUME_DB_TO_VOXWARE(sound.volume_left) |
-	   (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8));
-}
-
-
-
-/*
- * Falcon
- */
-
-
-static void FalconSilence(void)
-{
-    /* stop playback, set sample rate 50kHz for PSG sound */
-    tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-    tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT;
-    tt_dmasnd.int_div = 0; /* STE compatible divider */
-    tt_dmasnd.int_ctrl = 0x0;
-    tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */
-    tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */
-    tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */
-    tt_dmasnd.adc_src = 3; /* ADC Input = PSG */
-}
-
-
-static void FalconInit(void)
-{
-    int divider, i, idx;
-    const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195};
-
-    /* search a frequency that fits into the allowed error range */
-
-    idx = -1;
-    for (i = 0; i < arraysize(freq); i++)
-	/* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would
-	 * be playable without expanding, but that now a kernel runtime
-	 * option
-	 */
-	if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius)
-	    idx = i;
-    if (idx > -1) {
-	sound.soft.speed = freq[idx];
-	sound.trans = &transFalconNormal;
-    } else
-	sound.trans = &transFalconExpanding;
-
-    FalconSilence();
-    sound.hard = sound.soft;
-
-    if (sound.hard.size == 16) {
-	/* the Falcon can play 16bit samples only in stereo */
-	sound.hard.stereo = 1;
-    }
-
-    if (sound.hard.speed > 49170) {
-	/* we would need to squeeze the sound, but we won't do that */
-	sound.hard.speed = 49170;
-	divider = 1;
-	sound.trans = &transFalconNormal;
-    } else if (sound.hard.speed > 32780) {
-	sound.hard.speed = 49170;
-	divider = 1;
-    } else if (sound.hard.speed > 24585) {
-	sound.hard.speed = 32780;
-	divider = 2;
-    } else if (sound.hard.speed > 19668) {
-	sound.hard.speed = 24585;
-	divider = 3;
-    } else if (sound.hard.speed > 16390) {
-	sound.hard.speed = 19668;
-	divider = 4;
-    } else if (sound.hard.speed > 12292) {
-	sound.hard.speed = 16390;
-	divider = 5;
-    } else if (sound.hard.speed > 9834) {
-	sound.hard.speed = 12292;
-	divider = 7;
-    } else if (sound.hard.speed > 8195) {
-	sound.hard.speed = 9834;
-	divider = 9;
-    } else {
-	sound.hard.speed = 8195;
-	divider = 11;
-    }
-    tt_dmasnd.int_div = divider;
-
-    /* Setup Falcon sound DMA for playback */
-    tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */
-    tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */
-    tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */
-    tt_dmasnd.cbar_dst = 0x0000;
-    tt_dmasnd.rec_track_select = 0;
-    tt_dmasnd.dac_src = 2; /* connect matrix to DAC */
-    tt_dmasnd.adc_src = 0; /* ADC Input = Mic */
-
-    tt_dmasnd.mode = (sound.hard.stereo ?
-		      DMASND_MODE_STEREO : DMASND_MODE_MONO) |
-		     ((sound.hard.size == 8) ?
-		       DMASND_MODE_8BIT : DMASND_MODE_16BIT) |
-		     DMASND_MODE_6KHZ;
-
-    sound.bal = -sound.soft.speed;
-}
-
-
-static int FalconSetFormat(int format)
-{
-    int size;
-    /* Falcon sound DMA supports 8bit and 16bit modes */
-
-    switch (format) {
-	case AFMT_QUERY:
-	    return(sound.soft.format);
-	case AFMT_MU_LAW:
-	case AFMT_A_LAW:
-	case AFMT_U8:
-	case AFMT_S8:
-	    size = 8;
-	    break;
-	case AFMT_S16_BE:
-	case AFMT_U16_BE:
-	case AFMT_S16_LE:
-	case AFMT_U16_LE:
-	    size = 16;
-	    break;
-	default: /* :-) */
-	    size = 8;
-	    format = AFMT_S8;
-    }
-
-    sound.soft.format = format;
-    sound.soft.size = size;
-    if (sound.minDev == SND_DEV_DSP) {
-	sound.dsp.format = format;
-	sound.dsp.size = sound.soft.size;
-    }
-
-    FalconInit();
-
-    return(format);
-}
-
-
-/* This is for the Falcon output *attenuation* in 1.5dB steps,
- * i.e. output level from 0 to -22.5dB in -1.5dB steps.
- */
-#define VOLUME_VOXWARE_TO_ATT(v) \
-	((v) < 0 ? 15 : (v) > 100 ? 0 : 15 - (v) * 3 / 20)
-#define VOLUME_ATT_TO_VOXWARE(v) (100 - (v) * 20 / 3)
-
-
-static int FalconSetVolume(int volume)
-{
-    sound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff);
-    sound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8);
-    tt_dmasnd.output_atten = sound.volume_left << 8 | sound.volume_right << 4;
-    return(VOLUME_ATT_TO_VOXWARE(sound.volume_left) |
-	   VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8);
-}
-
-
-static void ata_sq_play_next_frame(int index)
-{
-    char *start, *end;
-
-    /* used by AtaPlay() if all doubts whether there really is something
-     * to be played are already wiped out.
-     */
-    start = sq_block_address(sq.front);
-    end = start+((sq.count == index) ? sq.rear_size : sq.block_size);
-    /* end might not be a legal virtual address. */
-    DMASNDSetEnd(VTOP(end - 1) + 1);
-    DMASNDSetBase(VTOP(start));
-	/* Since only an even number of samples per frame can
-	be played, we might lose one byte here. (TO DO) */
-    sq.front = (sq.front+1) % sq.max_count;
-    sq.playing++;
-    tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT;
-}
-
-
-static void AtaPlay(void)
-{
-    /* ++TeSche: Note that sq.playing is no longer just a flag but holds
-     * the number of frames the DMA is currently programmed for instead,
-     * may be 0, 1 (currently being played) or 2 (pre-programmed).
-     *
-     * Changes done to sq.count and sq.playing are a bit more subtle again
-     * so now I must admit I also prefer disabling the irq here rather
-     * than considering all possible situations. But the point is that
-     * disabling the irq doesn't have any bad influence on this version of
-     * the driver as we benefit from having pre-programmed the DMA
-     * wherever possible: There's no need to reload the DMA at the exact
-     * time of an interrupt but only at some time while the pre-programmed
-     * frame is playing!
-     */
-    atari_disable_irq(IRQ_MFP_TIMA);
-
-    if (sq.playing == 2 ||	/* DMA is 'full' */
-	sq.count <= 0) {	/* nothing to do */
-	atari_enable_irq(IRQ_MFP_TIMA);
-	return;
-    }
-
-    if (sq.playing == 0) {
-	/* looks like there's nothing 'in' the DMA yet, so try
-	 * to put two frames into it (at least one is available).
-	 */
-	if (sq.count == 1 && sq.rear_size < sq.block_size && !sq.syncing) {
-	    /* hmmm, the only existing frame is not
-	     * yet filled and we're not syncing?
-	     */
-	    atari_enable_irq(IRQ_MFP_TIMA);
-	    return;
-	}
-	ata_sq_play_next_frame(1);
-	if (sq.count == 1) {
-	    /* no more frames */
-	    atari_enable_irq(IRQ_MFP_TIMA);
-	    return;
-	}
-	if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) {
-	    /* hmmm, there were two frames, but the second
-	     * one is not yet filled and we're not syncing?
-	     */
-	    atari_enable_irq(IRQ_MFP_TIMA);
-	    return;
-	}
-	ata_sq_play_next_frame(2);
-    } else {
-	/* there's already a frame being played so we may only stuff
-	 * one new into the DMA, but even if this may be the last
-	 * frame existing the previous one is still on sq.count.
-	 */
-	if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) {
-	    /* hmmm, the only existing frame is not
-	     * yet filled and we're not syncing?
-	     */
-	    atari_enable_irq(IRQ_MFP_TIMA);
-	    return;
-	}
-	ata_sq_play_next_frame(2);
-    }
-    atari_enable_irq(IRQ_MFP_TIMA);
-}
-
-
-static void ata_sq_interrupt(int irq, struct pt_regs *fp, void *dummy)
-{
-#if 0
-    /* ++TeSche: if you should want to test this... */
-    static int cnt = 0;
-    if (sq.playing == 2)
-	if (++cnt == 10) {
-	    /* simulate losing an interrupt */
-	    cnt = 0;
-	    return;
-	}
-#endif
-
-    if (sq.ignore_int && (sound.mach.type == DMASND_FALCON)) {
-	/* ++TeSche: Falcon only: ignore first irq because it comes
-	 * immediately after starting a frame. after that, irqs come
-	 * (almost) like on the TT.
-	 */
-	sq.ignore_int = 0;
-	return;
-    }
-
-    if (!sq.playing) {
-	/* playing was interrupted and sq_reset() has already cleared
-	 * the sq variables, so better don't do anything here.
-	 */
-	WAKE_UP(sq.sync_queue);
-	return;
-    }
-
-    /* Probably ;) one frame is finished. Well, in fact it may be that a
-     * pre-programmed one is also finished because there has been a long
-     * delay in interrupt delivery and we've completely lost one, but
-     * there's no way to detect such a situation. In such a case the last
-     * frame will be played more than once and the situation will recover
-     * as soon as the irq gets through.
-     */
-    sq.count--;
-    sq.playing--;
-
-    if (!sq.playing) {
-	tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-	sq.ignore_int = 1;
-    }
-
-    WAKE_UP(sq.write_queue);
-	/* At least one block of the queue is free now
-	so wake up a writing process blocked because
-	of a full queue. */
-
-    if ((sq.playing != 1) || (sq.count != 1))
-	/* We must be a bit carefully here: sq.count indicates the
-	 * number of buffers used and not the number of frames to
-	 * be played. If sq.count==1 and sq.playing==1 that means
-	 * the only remaining frame was already programmed earlier
-	 * (and is currently running) so we mustn't call AtaPlay()
-	 * here, otherwise we'll play one frame too much.
-	 */
-	AtaPlay();
-
-    if (!sq.playing) WAKE_UP(sq.sync_queue);
-	/* We are not playing after AtaPlay(), so there
-	is nothing to play any more. Wake up a process
-	waiting for audio output to drain. */
-}
-#endif /* CONFIG_ATARI */
-
-
-#ifdef CONFIG_AMIGA
-
-/*
- * Amiga
- */
-
-
-static void *AmiAlloc(unsigned int size, int flags)
-{
-    return(amiga_chip_alloc((long)size));
-}
-
-static void AmiFree(void *obj, unsigned int size)
-{
-    amiga_chip_free (obj);
-}
-
-static int AmiIrqInit(void)
-{
-    /* turn off DMA for audio channels */
-    custom.dmacon = AMI_AUDIO_OFF;
-
-    /* Register interrupt handler. */
-    if (!add_isr(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0, NULL, "DMA sound"))
-	panic("Couldn't add audio interrupt");
-    return(1);
-}
-
-
-static void AmiSilence(void)
-{
-    /* turn off DMA for audio channels */
-    custom.dmacon = AMI_AUDIO_OFF;
-}
-
-
-static void AmiInit(void)
-{
-    int period, i;
-
-    AmiSilence();
-
-    if (sound.soft.speed)
-	period = amiga_colorclock/sound.soft.speed-1;
-    else
-	period = amiga_audio_min_period;
-    sound.hard = sound.soft;
-    sound.trans = &transAmiga;
-
-    if (period < amiga_audio_min_period) {
-	/* we would need to squeeze the sound, but we won't do that */
-	period = amiga_audio_min_period;
-	sound.hard.speed = amiga_colorclock/(period+1);
-    } else if (period > 65535) {
-	period = 65535;
-	sound.hard.speed = amiga_colorclock/(period+1);
-    }
-    for (i = 0; i < 4; i++)
-	custom.aud[i].audper = period;
-    amiga_audio_period = period;
-}
-
-
-static int AmiSetFormat(int format)
-{
-    int size;
-
-    /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */
-
-    switch (format) {
-	case AFMT_QUERY:
-	    return(sound.soft.format);
-	case AFMT_MU_LAW:
-	case AFMT_A_LAW:
-	case AFMT_U8:
-	case AFMT_S8:
-	    size = 8;
-	    break;
-	case AFMT_S16_BE:
-	case AFMT_U16_BE:
-	case AFMT_S16_LE:
-	case AFMT_U16_LE:
-	    size = 16;
-	    break;
-	default: /* :-) */
-	    size = 8;
-	    format = AFMT_S8;
-    }
-
-    sound.soft.format = format;
-    sound.soft.size = size;
-    if (sound.minDev == SND_DEV_DSP) {
-	sound.dsp.format = format;
-	sound.dsp.size = sound.soft.size;
-    }
-    AmiInit();
-
-    return(format);
-}
-
-
-#define VOLUME_VOXWARE_TO_AMI(v) \
-	(((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100)
-#define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64)
-
-static int AmiSetVolume(int volume)
-{
-    sound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff);
-    custom.aud[0].audvol = sound.volume_left;
-    sound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8);
-    custom.aud[1].audvol = sound.volume_right;
-    return(VOLUME_AMI_TO_VOXWARE(sound.volume_left) |
-	   (VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8));
-}
-
-static int AmiSetTreble(int treble)
-{
-    sound.treble = treble;
-    if (treble > 50)
-	ciaa.pra |= 0x02;
-    else
-	ciaa.pra &= ~0x02;
-    return(treble);
-}
-
-
-#define AMI_PLAY_LOADED		1
-#define AMI_PLAY_PLAYING	2
-#define AMI_PLAY_MASK		3
-
-
-static void ami_sq_play_next_frame(int index)
-{
-    u_char *start, *ch0, *ch1, *ch2, *ch3;
-    u_long size;
-
-    /* used by AmiPlay() if all doubts whether there really is something
-     * to be played are already wiped out.
-     */
-    start = sq_block_address(sq.front);
-    size = (sq.count == index ? sq.rear_size : sq.block_size)>>1;
-
-    if (sound.hard.stereo) {
-	ch0 = start;
-	ch1 = start+sq.block_size_half;
-	size >>= 1;
-    } else {
-	ch0 = start;
-	ch1 = start;
-    }
-    if (sound.hard.size == 8) {
-	custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
-	custom.aud[0].audlen = size;
-	custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
-	custom.aud[1].audlen = size;
-	custom.dmacon = AMI_AUDIO_8;
-    } else {
-	size >>= 1;
-	custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
-	custom.aud[0].audlen = size;
-	custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
-	custom.aud[1].audlen = size;
-	if (sound.volume_left == 64 && sound.volume_right == 64) {
-	    /* We can play pseudo 14-bit only with the maximum volume */
-	    ch3 = ch0+sq.block_size_quarter;
-	    ch2 = ch1+sq.block_size_quarter;
-	    custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2);
-	    custom.aud[2].audlen = size;
-	    custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3);
-	    custom.aud[3].audlen = size;
-	    custom.dmacon = AMI_AUDIO_14;
-	} else
-	    custom.dmacon = AMI_AUDIO_8;
-    }
-    sq.front = (sq.front+1) % sq.max_count;
-    sq.playing |= AMI_PLAY_LOADED;
-}
-
-
-static void AmiPlay(void)
-{
-    int minframes = 1;
-
-    custom.intena = IF_AUD0;
-
-    if (sq.playing & AMI_PLAY_LOADED) {
-	/* There's already a frame loaded */
-	custom.intena = IF_SETCLR | IF_AUD0;
-	return;
-    }
-
-    if (sq.playing & AMI_PLAY_PLAYING)
-	/* Increase threshold: frame 1 is already being played */
-	minframes = 2;
-
-    if (sq.count < minframes) {
-	/* Nothing to do */
-	custom.intena = IF_SETCLR | IF_AUD0;
-	return;
-    }
-
-    if (sq.count <= minframes && sq.rear_size < sq.block_size && !sq.syncing) {
-	/* hmmm, the only existing frame is not
-	 * yet filled and we're not syncing?
-	 */
-	custom.intena = IF_SETCLR | IF_AUD0;
-	return;
-    }
-
-    ami_sq_play_next_frame(minframes);
-
-    custom.intena = IF_SETCLR | IF_AUD0;
-}
-
-
-static void ami_sq_interrupt(int irq, struct pt_regs *fp, void *dummy)
-{
-    int minframes = 1;
-
-    if (!sq.playing) {
-	/* Playing was interrupted and sq_reset() has already cleared
-	 * the sq variables, so better don't do anything here.
-	 */
-	WAKE_UP(sq.sync_queue);
-	return;
-    }
-
-    if (sq.playing & AMI_PLAY_PLAYING) {
-	/* We've just finished a frame */
-	sq.count--;
-	WAKE_UP(sq.write_queue);
-    }
-
-    if (sq.playing & AMI_PLAY_LOADED)
-	/* Increase threshold: frame 1 is already being played */
-	minframes = 2;
-
-    /* Shift the flags */
-    sq.playing = (sq.playing<<1) & AMI_PLAY_MASK;
-
-    if (!sq.playing)
-	/* No frame is playing, disable audio DMA */
-	custom.dmacon = AMI_AUDIO_OFF;
-
-    if (sq.count >= minframes)
-    	/* Try to play the next frame */
-	AmiPlay();
-
-    if (!sq.playing)
-	/* Nothing to play anymore.
-	   Wake up a process waiting for audio output to drain. */
-	WAKE_UP(sq.sync_queue);
-}
-#endif /* CONFIG_AMIGA */
-
-
-/*** Machine definitions *****************************************************/
-
-
-#ifdef CONFIG_ATARI
-static MACHINE machTT = {
-    DMASND_TT, AtaAlloc, AtaFree, AtaIrqInit, TTInit, TTSilence, TTSetFormat,
-    TTSetVolume, AtaSetBass, AtaSetTreble, AtaPlay
-};
-
-static MACHINE machFalcon = {
-    DMASND_FALCON, AtaAlloc, AtaFree, AtaIrqInit, FalconInit, FalconSilence,
-    FalconSetFormat, FalconSetVolume, AtaSetBass, AtaSetTreble, AtaPlay
-};
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-static MACHINE machAmiga = {
-    DMASND_AMIGA, AmiAlloc, AmiFree, AmiIrqInit, AmiInit, AmiSilence,
-    AmiSetFormat, AmiSetVolume, NULL, AmiSetTreble, AmiPlay
-};
-#endif /* CONFIG_AMIGA */
-
-
-/*** Mid level stuff *********************************************************/
-
-
-static void sound_silence(void)
-{
-    /* update hardware settings one more */
-    (*sound.mach.init)();
-
-    (*sound.mach.silence)();
-}
-
-
-static void sound_init(void)
-{
-    (*sound.mach.init)();
-}
-
-
-static int sound_set_format(int format)
-{
-    return(*sound.mach.setFormat)(format);
-}
-
-
-static int sound_set_speed(int speed)
-{
-    if (speed < 0)
-	return(sound.soft.speed);
-
-    sound.soft.speed = speed;
-    (*sound.mach.init)();
-    if (sound.minDev == SND_DEV_DSP)
-	sound.dsp.speed = sound.soft.speed;
-
-    return(sound.soft.speed);
-}
-
-
-static int sound_set_stereo(int stereo)
-{
-    if (stereo < 0)
-	return(sound.soft.stereo);
-
-    stereo = !!stereo;    /* should be 0 or 1 now */
-
-    sound.soft.stereo = stereo;
-    if (sound.minDev == SND_DEV_DSP)
-	sound.dsp.stereo = stereo;
-    (*sound.mach.init)();
-
-    return(stereo);
-}
-
-
-static int sound_set_volume(int volume)
-{
-    return(*sound.mach.setVolume)(volume);
-}
-
-
-#ifdef CONFIG_ATARI
-static int sound_set_bass(int bass)
-{
-    return(sound.mach.setBass ? (*sound.mach.setBass)(bass) : 50);
-}
-#endif /* CONFIG_ATARI */
-
-
-static int sound_set_treble(int treble)
-{
-    return(sound.mach.setTreble ? (*sound.mach.setTreble)(treble) : 50);
-}
-
-
-static long sound_copy_translate(const u_char *userPtr, long userCount,
-				 u_char frame[], long *frameUsed,
-				 long frameLeft)
-{
-    long (*ct_func)(const u_char *, long, u_char *, long *, long) = NULL;
-
-    switch (sound.soft.format) {
-	case AFMT_MU_LAW:
-	    ct_func = sound.trans->ct_ulaw;
-	    break;
-	case AFMT_A_LAW:
-	    ct_func = sound.trans->ct_alaw;
-	    break;
-	case AFMT_S8:
-	    ct_func = sound.trans->ct_s8;
-	    break;
-	case AFMT_U8:
-	    ct_func = sound.trans->ct_u8;
-	    break;
-	case AFMT_S16_BE:
-	    ct_func = sound.trans->ct_s16be;
-	    break;
-	case AFMT_U16_BE:
-	    ct_func = sound.trans->ct_u16be;
-	    break;
-	case AFMT_S16_LE:
-	    ct_func = sound.trans->ct_s16le;
-	    break;
-	case AFMT_U16_LE:
-	    ct_func = sound.trans->ct_u16le;
-	    break;
-    }
-    if (ct_func)
-	return(ct_func(userPtr, userCount, frame, frameUsed, frameLeft));
-    else
-	return(0);
-}
-
-
-/*
- * /dev/mixer abstraction
- */
-
-
-#define RECLEVEL_VOXWARE_TO_GAIN(v) \
-	((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20)
-#define RECLEVEL_GAIN_TO_VOXWARE(v) (((v) * 20 + 2) / 3)
-
-
-static void mixer_init(void)
-{
-    mixer.busy = 0;
-    sound.treble = 0;
-    sound.bass = 0;
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-	case DMASND_TT:
-	    atari_microwire_cmd(MW_LM1992_VOLUME(0));
-	    sound.volume_left = 0;
-	    atari_microwire_cmd(MW_LM1992_BALLEFT(0));
-	    sound.volume_right = 0;
-	    atari_microwire_cmd(MW_LM1992_BALRIGHT(0));
-	    atari_microwire_cmd(MW_LM1992_TREBLE(0));
-	    atari_microwire_cmd(MW_LM1992_BASS(0));
-	    break;
-	case DMASND_FALCON:
-	    sound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8;
-	    sound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4;
-	    break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	case DMASND_AMIGA:
-	    sound.volume_left = 64;
-	    sound.volume_right = 64;
-	    custom.aud[0].audvol = sound.volume_left;
-	    custom.aud[3].audvol = 1;			/* For pseudo 14bit */
-	    custom.aud[1].audvol = sound.volume_right;
-	    custom.aud[2].audvol = 1;			/* For pseudo 14bit */
-	    sound.treble = 50;
-	    break;
-#endif /* CONFIG_AMIGA */
-    }
-}
-
-
-static int mixer_open(int open_mode)
-{
-    if (mixer.busy)
-	return(-EBUSY);
-    mixer.busy = 1;
-    return(0);
-}
-
-
-static int mixer_release(void)
-{
-    mixer.busy = 0;
-    return(0);
-}
-
-
-static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg)
-{
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-	case DMASND_FALCON:
-	    switch (cmd) {
-		case SOUND_MIXER_READ_DEVMASK:
-		    return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
-		case SOUND_MIXER_READ_RECMASK:
-		    return(IOCTL_OUT(arg, SOUND_MASK_MIC));
-		case SOUND_MIXER_READ_STEREODEVS:
-		    return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC));
-		case SOUND_MIXER_READ_CAPS:
-		    return(IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT));
-		case SOUND_MIXER_READ_VOLUME:
-		    return(IOCTL_OUT(arg,
-			VOLUME_ATT_TO_VOXWARE(sound.volume_left) |
-			VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8));
-		case SOUND_MIXER_WRITE_MIC:
-		    tt_dmasnd.input_gain =
-			RECLEVEL_VOXWARE_TO_GAIN(IOCTL_IN(arg) & 0xff) << 4 |
-			RECLEVEL_VOXWARE_TO_GAIN(IOCTL_IN(arg) >> 8 & 0xff);
-		    /* fall thru, return set value */
-		case SOUND_MIXER_READ_MIC:
-		    return(IOCTL_OUT(arg,
-			RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) |
-			RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8));
-		case SOUND_MIXER_READ_SPEAKER:
-		    {
-			int porta;
-			cli();
-			sound_ym.rd_data_reg_sel = 14;
-			porta = sound_ym.rd_data_reg_sel;
-			sti();
-			return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-		    }
-		case SOUND_MIXER_WRITE_VOLUME:
-		    return(IOCTL_OUT(arg, sound_set_volume(IOCTL_IN(arg))));
-		case SOUND_MIXER_WRITE_SPEAKER:
-		    {
-			int porta;
-			cli();
-			sound_ym.rd_data_reg_sel = 14;
-			porta = (sound_ym.rd_data_reg_sel & ~0x40) |
-				(IOCTL_IN(arg) < 50 ? 0x40 : 0);
-			sound_ym.wd_data = porta;
-			sti();
-			return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-		    }
-	    }
-	    break;
-
-	case DMASND_TT:
-	    switch (cmd) {
-		case SOUND_MIXER_READ_DEVMASK:
-		    return(IOCTL_OUT(arg,
-			SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
-			((boot_info.bi_atari.mch_cookie >> 16) == ATARI_MCH_TT ?
-			    SOUND_MASK_SPEAKER : 0)));
-		case SOUND_MIXER_READ_RECMASK:
-		    return(IOCTL_OUT(arg, 0));
-		case SOUND_MIXER_READ_STEREODEVS:
-		    return(IOCTL_OUT(arg, SOUND_MASK_VOLUME));
-		case SOUND_MIXER_READ_VOLUME:
-		    return(IOCTL_OUT(arg,
-			VOLUME_DB_TO_VOXWARE(sound.volume_left) |
-			(VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8)));
-		case SOUND_MIXER_READ_BASS:
-		    return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.bass)));
-		case SOUND_MIXER_READ_TREBLE:
-		    return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.treble)));
-		case SOUND_MIXER_READ_SPEAKER:
-		    {
-			int porta;
-			if ((boot_info.bi_atari.mch_cookie >> 16) == ATARI_MCH_TT) {
-			    cli();
-			    sound_ym.rd_data_reg_sel = 14;
-			    porta = sound_ym.rd_data_reg_sel;
-			    sti();
-			    return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-			} else
-			    return(-EINVAL);
-		    }
-		case SOUND_MIXER_WRITE_VOLUME:
-		    return(IOCTL_OUT(arg, sound_set_volume(IOCTL_IN(arg))));
-		case SOUND_MIXER_WRITE_BASS:
-		    return(IOCTL_OUT(arg, sound_set_bass(IOCTL_IN(arg))));
-		case SOUND_MIXER_WRITE_TREBLE:
-		    return(IOCTL_OUT(arg, sound_set_treble(IOCTL_IN(arg))));
-		case SOUND_MIXER_WRITE_SPEAKER:
-		    if ((boot_info.bi_atari.mch_cookie >> 16) == ATARI_MCH_TT) {
-			int porta;
-			cli();
-			sound_ym.rd_data_reg_sel = 14;
-			porta = (sound_ym.rd_data_reg_sel & ~0x40) |
-				(IOCTL_IN(arg) < 50 ? 0x40 : 0);
-			sound_ym.wd_data = porta;
-			sti();
-			return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-		    } else
-			return(-EINVAL);
-	    }
-	    break;
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-	case DMASND_AMIGA:
-	    switch (cmd) {
-		case SOUND_MIXER_READ_DEVMASK:
-		    return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE));
-		case SOUND_MIXER_READ_RECMASK:
-		    return(IOCTL_OUT(arg, 0));
-		case SOUND_MIXER_READ_STEREODEVS:
-		    return(IOCTL_OUT(arg, SOUND_MASK_VOLUME));
-		case SOUND_MIXER_READ_VOLUME:
-		    return(IOCTL_OUT(arg,
-			VOLUME_AMI_TO_VOXWARE(sound.volume_left) |
-			VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8));
-		case SOUND_MIXER_WRITE_VOLUME:
-		    return(IOCTL_OUT(arg, sound_set_volume(IOCTL_IN(arg))));
-		case SOUND_MIXER_READ_TREBLE:
-		    return(IOCTL_OUT(arg, sound.treble));
-		case SOUND_MIXER_WRITE_TREBLE:
-		    return(IOCTL_OUT(arg, sound_set_treble(IOCTL_IN(arg))));
-	    }
-	    break;
-#endif /* CONFIG_AMIGA */
-    }
-
-    return(-EINVAL);
-}
-
-
-
-/*
- * Sound queue stuff, the heart of the driver
- */
-
-
-static void sq_init(int numBufs, int bufSize, char **buffers)
-{
-    sq.max_count = numBufs;
-    sq.block_size = bufSize;
-    sq.buffers = buffers;
-
-    sq.front = sq.count = 0;
-    sq.rear = -1;
-    sq.write_queue = sq.open_queue = sq.sync_queue = 0;
-    sq.busy = 0;
-    sq.syncing = 0;
-
-    sq.playing = 0;
-
-#ifdef CONFIG_ATARI
-    sq.ignore_int = 0;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-    sq.block_size_half = sq.block_size>>1;
-    sq.block_size_quarter = sq.block_size_half>>1;
-#endif /* CONFIG_AMIGA */
-
-    sound_silence();
-
-    /* whatever you like as startup mode for /dev/dsp,
-     * (/dev/audio hasn't got a startup mode). note that
-     * once changed a new open() will *not* restore these!
-     */
-    sound.dsp.format = AFMT_S8;
-    sound.dsp.stereo = 0;
-    sound.dsp.size = 8;
-
-    /* set minimum rate possible without expanding */
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-	case DMASND_TT:
-	    sound.dsp.speed = 6258;
-	    break;
-	case DMASND_FALCON:
-	    sound.dsp.speed = 8195;
-	    break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	case DMASND_AMIGA:
-	    sound.dsp.speed = 8000;
-	    break;
-#endif /* CONFIG_AMIGA */
-    }
-
-    /* before the first open to /dev/dsp this wouldn't be set */
-    sound.soft = sound.dsp;
-}
-
-
-static void sq_play(void)
-{
-    (*sound.mach.play)();
-}
-
-
-/* ++TeSche: radically changed this one too */
-
-static int sq_write(const char *src, int uLeft)
-{
-    int uWritten = 0;
-    u_char *dest;
-    long uUsed, bUsed, bLeft;
-
-    /* ++TeSche: Is something like this necessary?
-     * Hey, that's an honest question! Or does any other part of the
-     * filesystem already checks this situation? I really don't know.
-     */
-    if (uLeft < 1)
-	return(0);
-
-    /* The interrupt doesn't start to play the last, incomplete frame.
-     * Thus we can append to it without disabling the interrupts! (Note
-     * also that sq.rear isn't affected by the interrupt.)
-     */
-
-    if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) {
-	dest = sq_block_address(sq.rear);
-	bUsed = sq.rear_size;
-	uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
-	src += uUsed;
-	uWritten += uUsed;
-	uLeft -= uUsed;
-	sq.rear_size = bUsed;
-    }
-
-    do {
-	if (sq.count == sq.max_count) {
-	    sq_play();
-	    if (NON_BLOCKING(sq.open_mode))
-		return(uWritten > 0 ? uWritten : -EAGAIN);
-	    SLEEP(sq.write_queue, ONE_SECOND);
-	    if (SIGNAL_RECEIVED)
-		return(uWritten > 0 ? uWritten : -EINTR);
-	}
-
-	/* Here, we can avoid disabling the interrupt by first
-	 * copying and translating the data, and then updating
-	 * the sq variables. Until this is done, the interrupt
-	 * won't see the new frame and we can work on it
-	 * undisturbed.
-	 */
-
-	dest = sq_block_address((sq.rear+1) % sq.max_count);
-	bUsed = 0;
-	bLeft = sq.block_size;
-	uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
-	src += uUsed;
-	uWritten += uUsed;
-	uLeft -= uUsed;
-	if (bUsed) {
-	    sq.rear = (sq.rear+1) % sq.max_count;
-	    sq.rear_size = bUsed;
-	    sq.count++;
-	}
-    } while (bUsed);   /* uUsed may have been 0 */
-
-    sq_play();
-
-    return(uWritten);
-}
-
-
-static int sq_open(int open_mode)
-{
-    if (sq.busy) {
-	if (NON_BLOCKING(open_mode))
-	    return(-EBUSY);
-	while (sq.busy) {
-	    SLEEP(sq.open_queue, ONE_SECOND);
-	    if (SIGNAL_RECEIVED)
-		return(-EINTR);
-	}
-    }
-    sq.open_mode = open_mode;
-    sq.busy = 1;
-#ifdef CONFIG_ATARI
-    sq.ignore_int = 1;
-#endif /* CONFIG_ATARI */
-    return(0);
-}
-
-
-static void sq_reset(void)
-{
-    sound_silence();
-    sq.playing = 0;
-    sq.count = 0;
-    sq.front = (sq.rear+1) % sq.max_count;
-}
-
-
-static int sq_sync(void)
-{
-    int rc = 0;
-
-    sq.syncing = 1;
-    sq_play();	/* there may be an incomplete frame waiting */
-
-    while (sq.playing) {
-	SLEEP(sq.sync_queue, ONE_SECOND);
-	if (SIGNAL_RECEIVED) {
-	    /* While waiting for audio output to drain, an interrupt occurred.
-	       Stop audio output immediately and clear the queue. */
-	    sq_reset();
-	    rc = -EINTR;
-	    break;
-	}
-    }
-
-    sq.syncing = 0;
-    return(rc);
-}
-
-
-static int sq_release(void)
-{
-    int rc = 0;
-    if (sq.busy) {
-	rc = sq_sync();
-	sq.busy = 0;
-	WAKE_UP(sq.open_queue);
-	/* Wake up a process waiting for the queue being released.
-	   Note: There may be several processes waiting for a call to open()
-		 returning. */
-    }
-    return(rc);
-}
-
-
-
-/*
- * /dev/sndstat
- */
-
-
-static void state_init(void)
-{
-    state.busy = 0;
-}
-
-
-/* state.buf should not overflow! */
-
-static int state_open(int open_mode)
-{
-    char *buffer = state.buf, *mach = "";
-    int len = 0;
-
-    if (state.busy)
-	return(-EBUSY);
-
-    state.ptr = 0;
-    state.busy = 1;
-
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-	case DMASND_TT:
-	case DMASND_FALCON:
-	    mach = "Atari ";
-	    break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	case DMASND_AMIGA:
-	    mach = "Amiga ";
-	    break;
-#endif /* CONFIG_AMIGA */
-    }
-    len += sprintf(buffer+len, "%sDMA sound driver:\n", mach);
-
-    len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format);
-    switch (sound.soft.format) {
-	case AFMT_MU_LAW:
-	    len += sprintf(buffer+len, " (mu-law)");
-	    break;
-	case AFMT_A_LAW:
-	    len += sprintf(buffer+len, " (A-law)");
-	    break;
-	case AFMT_U8:
-	    len += sprintf(buffer+len, " (unsigned 8 bit)");
-	    break;
-	case AFMT_S8:
-	    len += sprintf(buffer+len, " (signed 8 bit)");
-	    break;
-	case AFMT_S16_BE:
-	    len += sprintf(buffer+len, " (signed 16 bit big)");
-	    break;
-	case AFMT_U16_BE:
-	    len += sprintf(buffer+len, " (unsigned 16 bit big)");
-	    break;
-	case AFMT_S16_LE:
-	    len += sprintf(buffer+len, " (signed 16 bit little)");
-	    break;
-	case AFMT_U16_LE:
-	    len += sprintf(buffer+len, " (unsigned 16 bit little)");
-	    break;
-    }
-    len += sprintf(buffer+len, "\n");
-    len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n",
-		   sound.soft.speed, sound.hard.speed);
-    len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n",
-		   sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono");
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-	case DMASND_TT:
-	    len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-40...0]\n",
-			   sound.volume_left);
-	    len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-40...0]\n",
-			   sound.volume_right);
-	    len += sprintf(buffer+len, "\tsound.bass = %ddB [-12...+12]\n",
-			   sound.bass);
-	    len += sprintf(buffer+len, "\tsound.treble = %ddB [-12...+12]\n",
-			   sound.treble);
-	    break;
-	case DMASND_FALCON:
-	    len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-22.5...0]\n",
-			   sound.volume_left);
-	    len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-22.5...0]\n",
-			   sound.volume_right);
-	    break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	case DMASND_AMIGA:
-	    len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n",
-			   sound.volume_left);
-	    len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n",
-			   sound.volume_right);
-	    break;
-#endif /* CONFIG_AMIGA */
-    }
-    len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d\n",
-		   sq.block_size, sq.max_count);
-    len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count,
-		   sq.rear_size);
-    len += sprintf(buffer+len, "\tsq.playing = %d sq.syncing = %d\n",
-		   sq.playing, sq.syncing);
-    state.len = len;
-    return(0);
-}
-
-
-static int state_release(void)
-{
-    state.busy = 0;
-    return(0);
-}
-
-
-static int state_read(char *dest, int count)
-{
-    int n = state.len-state.ptr;
-    if (n > count)
-	n = count;
-    if (n <= 0)
-	return(0);
-    copy_to_user(dest, &state.buf[state.ptr], n);
-    state.ptr += n;
-    return(n);
-}
-
-
-
-/*** High level stuff ********************************************************/
-
-
-static int sound_open(struct inode *inode, struct file *file)
-{
-    int dev = MINOR(inode->i_rdev) & 0x0f;
-
-    switch (dev) {
-	case SND_DEV_STATUS:
-	    return(state_open(file->f_flags));
-	case SND_DEV_CTL:
-	    return(mixer_open(file->f_flags));
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-	    {
-		int rc = sq_open(file->f_flags);
-		if (rc == 0) {
-		    sound.minDev = dev;
-		    sound.soft = sound.dsp;
-		    sound_init();
-		    if (dev == SND_DEV_AUDIO) {
-			sound_set_speed(8000);
-			sound_set_stereo(0);
-			sound_set_format(AFMT_MU_LAW);
-		    }
-		}
-		return(rc);
-	    }
-	default:
-	    return(-ENXIO);
-    }
-}
-
-
-static int sound_fsync(struct inode *inode, struct file *filp)
-{
-    int dev = MINOR(inode->i_rdev) & 0x0f;
-
-    switch (dev) {
-	case SND_DEV_STATUS:
-	case SND_DEV_CTL:
-	    return(0);
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-	    return(sq_sync());
-	default:
-	    return(unknown_minor_dev("sound_fsync", dev));
-    }
-}
-
-
-static void sound_release(struct inode *inode, struct file *file)
-{
-    int dev = MINOR(inode->i_rdev);
-
-    switch (dev & 0x0f) {
-	case SND_DEV_STATUS: state_release(); return;
-	case SND_DEV_CTL: mixer_release(); return;
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-	    sq_release(); sound.soft = sound.dsp; sound_silence();
-	    return;
-	default:
-	    unknown_minor_dev("sound_release", dev);
-    }
-}
-
-
-static int sound_lseek(struct inode *inode, struct file *file, off_t offset,
-		       int orig)
-{
-    return(-EPERM);
-}
-
-
-static int sound_read(struct inode *inode, struct file *file, char *buf,
-		      int count)
-{
-    int dev = MINOR(inode->i_rdev);
-
-    switch (dev & 0x0f) {
-	case SND_DEV_STATUS:
-	    return(state_read(buf, count));
-	case SND_DEV_CTL:
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-	    return(-EPERM);
-	default:
-	    return(unknown_minor_dev("sound_read", dev));
-    }
-}
-
-
-static int sound_write(struct inode *inode, struct file *file, const char *buf,
-		       int count)
-{
-    int dev = MINOR(inode->i_rdev);
-
-    switch (dev & 0x0f) {
-	case SND_DEV_STATUS:
-	case SND_DEV_CTL:
-	    return(-EPERM);
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-	    return(sq_write(buf, count));
-	default:
-	    return(unknown_minor_dev("sound_write", dev));
-    }
-}
-
-
-static int ioctl_return(int *addr, int value)
-{
-    int error;
-
-    if (value < 0)
-	return(value);
-
-    error = verify_area(VERIFY_WRITE, addr, sizeof(int));
-    if (error)
-	return(error);
-
-    put_user(value, addr);
-    return(0);
-}
-
-
-static int unknown_minor_dev(char *fname, int dev)
-{
-    /* printk("%s: Unknown minor device %d\n", fname, dev); */
-    return(-ENXIO);
-}
-
-
-static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg)
-{
-    int dev = MINOR(inode->i_rdev);
-    u_long fmt;
-
-    switch (dev & 0x0f) {
-	case SND_DEV_STATUS:
-	    return(-EPERM);
-	case SND_DEV_CTL:
-	    return(mixer_ioctl(inode, file, cmd, arg));
-	case SND_DEV_AUDIO:
-	case SND_DEV_DSP:
-	    switch (cmd) {
-		case SNDCTL_DSP_RESET:
-		    sq_reset();
-		    return(0);
-		case SNDCTL_DSP_POST:
-		case SNDCTL_DSP_SYNC:
-		    return(sound_fsync(inode, file));
-
-		/* ++TeSche: before changing any of these it's probably wise to
-		 * wait until sound playing has settled down
-		 */
-		case SNDCTL_DSP_SPEED:
-		    sound_fsync(inode, file);
-		    return(IOCTL_OUT(arg, sound_set_speed(IOCTL_IN(arg))));
-		case SNDCTL_DSP_STEREO:
-		    sound_fsync(inode, file);
-		    return(IOCTL_OUT(arg, sound_set_stereo(IOCTL_IN(arg))));
-		case SOUND_PCM_WRITE_CHANNELS:
-		    sound_fsync(inode, file);
-		    return(IOCTL_OUT(arg, sound_set_stereo(IOCTL_IN(arg)-1)+1));
-		case SNDCTL_DSP_SETFMT:
-		    sound_fsync(inode, file);
-		    return(IOCTL_OUT(arg, sound_set_format(IOCTL_IN(arg))));
-		case SNDCTL_DSP_GETFMTS:
-		    fmt = 0;
-		    if (sound.trans) {
-			if (sound.trans->ct_ulaw)
-			    fmt |= AFMT_MU_LAW;
-			if (sound.trans->ct_alaw)
-			    fmt |= AFMT_A_LAW;
-			if (sound.trans->ct_s8)
-			    fmt |= AFMT_S8;
-			if (sound.trans->ct_u8)
-			    fmt |= AFMT_U8;
-			if (sound.trans->ct_s16be)
-			    fmt |= AFMT_S16_BE;
-			if (sound.trans->ct_u16be)
-			    fmt |= AFMT_U16_BE;
-			if (sound.trans->ct_s16le)
-			    fmt |= AFMT_S16_LE;
-			if (sound.trans->ct_u16le)
-			    fmt |= AFMT_U16_LE;
-		    }
-		    return(IOCTL_OUT(arg, fmt));
-		case SNDCTL_DSP_GETBLKSIZE:
-		    return(IOCTL_OUT(arg, 10240));
-		case SNDCTL_DSP_SUBDIVIDE:
-		case SNDCTL_DSP_SETFRAGMENT:
-		    break;
-
-		default:
-		    return(mixer_ioctl(inode, file, cmd, arg));
-	    }
-	    break;
-
-	default:
-	    return(unknown_minor_dev("sound_ioctl", dev));
-    }
-    return(-EINVAL);
-}
-
-
-static struct file_operations sound_fops =
-{
-    sound_lseek,
-    sound_read,
-    sound_write,
-    NULL,
-    NULL,                      /* select */
-    sound_ioctl,
-    NULL,
-    sound_open,
-    sound_release,
-    sound_fsync
-};
-
-
-
-/*** Config & Setup **********************************************************/
-
-
-void soundcard_init(void)
-{
-    int has_sound = 0;
-    char **buffers;
-    int i;
-
-    switch (boot_info.machtype) {
-#ifdef CONFIG_ATARI
-	case MACH_ATARI:
-	    if (ATARIHW_PRESENT(PCM_8BIT)) {
-		if (ATARIHW_PRESENT(CODEC))
-		    sound.mach = machFalcon;
-		else if (ATARIHW_PRESENT(MICROWIRE))
-		    sound.mach = machTT;
-		else
-		    break;
-		if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0)
-		    has_sound = 1;
-		else
-		    printk("DMA sound driver: Timer A interrupt already in use\n");
-	    }
-	    break;
-
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	case MACH_AMIGA:
-	    if (AMIGAHW_PRESENT(AMI_AUDIO)) {
-		sound.mach = machAmiga;
-		has_sound = 1;
-	    }
-	    break;
-#endif /* CONFIG_AMIGA */
-    }
-    if (!has_sound)
-	return;
-
-    /* Set up sound queue, /dev/audio and /dev/dsp. */
-    buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
-    if (!buffers) {
-    out_of_memory:
-	printk("DMA sound driver: Not enough buffer memory, driver disabled!\n");
-	return;
-    }
-    for (i = 0; i < numBufs; i++) {
-	buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
-	if (!buffers[i]) {
-	    while (i--)
-		sound.mach.dma_free (buffers[i], bufSize << 10);
-	    kfree (buffers);
-	    goto out_of_memory;
-        }
-    }
-
-    /* Register driver with the VFS. */
-    register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
-
-    sq_init(numBufs, bufSize << 10, buffers);
-
-    /* Set up /dev/sndstat. */
-    state_init();
-
-    /* Set up /dev/mixer. */
-    mixer_init();
-
-    if (!sound.mach.irqinit()) {
-	printk("DMA sound driver: Interrupt initialization failed\n");
-	return;
-    }
-
-    printk("DMA sound driver installed, using %d buffers of %dk.\n", numBufs,
-	   bufSize);
-
-    return;
-}
-
-void sound_setup(char *str, int *ints)
-{
-    /* ++Martin: stub, could possibly be merged with soundcard.c et al later */
-}
-
-void dmasound_setup(char *str, int *ints)
-{
-    /* check the bootstrap parameter for "dmasound=" */
-
-    switch (ints[0]) {
-	case 3:
-	    if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS))
-		printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius);
-	    else
-		catchRadius = ints[3];
-	    /* fall through */
-	case 2:
-	    if (ints[1] < MIN_BUFFERS)
-		printk("dmasound_setup: illegal number of buffers, using default = %d\n", numBufs);
-	    else
-		numBufs = ints[1];
-	    if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE)
-		printk("dmasound_setup: illegal buffer size, using default = %d\n", bufSize);
-	    else
-		bufSize = ints[2];
-	    break;
-	case 0:
-	    break;
-	default:
-	    printk("dmasound_setup: illegal number of arguments\n");
-    }
-}
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/dmasound.h linux/drivers/sound/dmasound.h
--- v2.1.5/linux/drivers/sound/dmasound.h	Sun Jun 30 11:51:45 1996
+++ linux/drivers/sound/dmasound.h	Thu Jan  1 02:00:00 1970
@@ -1,36 +0,0 @@
-
-/* linux/drivers/sound/dmasound.h */
-
-/*
- * Minor numbers for the sound driver.
- *
- * Unfortunately Creative called the codec chip of SB as a DSP. For this
- * reason the /dev/dsp is reserved for digitized audio use. There is a
- * device for true DSP processors but it will be called something else.
- * In v3.0 it's /dev/sndproc but this could be a temporary solution.
- */
-
-#define SND_NDEVS	256	/* Number of supported devices */
-#define SND_DEV_CTL	0	/* Control port /dev/mixer */
-#define SND_DEV_SEQ	1	/* Sequencer output /dev/sequencer (FM
-				   synthesizer and MIDI output) */
-#define SND_DEV_MIDIN	2	/* Raw midi access */
-#define SND_DEV_DSP	3	/* Digitized voice /dev/dsp */
-#define SND_DEV_AUDIO	4	/* Sparc compatible /dev/audio */
-#define SND_DEV_DSP16	5	/* Like /dev/dsp but 16 bits/sample */
-#define SND_DEV_STATUS	6	/* /dev/sndstat */
-/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
-#define SND_DEV_SEQ2	8	/* /dev/sequencer, level 2 interface */
-#define SND_DEV_SNDPROC 9	/* /dev/sndproc for programmable devices */
-#define SND_DEV_PSS	SND_DEV_SNDPROC
-
-#define DSP_DEFAULT_SPEED	8000
-
-#define ON		1
-#define OFF		0
-
-#define MAX_AUDIO_DEV	5
-#define MAX_MIXER_DEV	2
-#define MAX_SYNTH_DEV	3
-#define MAX_MIDI_DEV	6
-#define MAX_TIMER_DEV	3
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/finetune.h linux/drivers/sound/finetune.h
--- v2.1.5/linux/drivers/sound/finetune.h	Sun Jun 30 11:43:37 1996
+++ linux/drivers/sound/finetune.h	Tue Oct 29 09:31:08 1996
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/gus_card.c linux/drivers/sound/gus_card.c
--- v2.1.5/linux/drivers/sound/gus_card.c	Sun Jun 30 11:43:56 1996
+++ linux/drivers/sound/gus_card.c	Tue Oct 29 09:31:32 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -15,7 +15,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIG_GUS)
+#if defined(CONFIG_GUSHW)
 
 #include "gus_hw.h"
 
@@ -27,75 +27,31 @@
 extern int      have_gus_max;
 int             gus_pnp_flag = 0;
 
-int            *gus_osp;
-
 void
 attach_gus_card (struct address_info *hw_config)
 {
-  int             io_addr;
-
-  gus_osp = hw_config->osp;
   snd_set_irq_handler (hw_config->irq, gusintr, "Gravis Ultrasound", hw_config->osp);
 
-  if (gus_wave_detect (hw_config->io_base))	/*
-						 * Try first the default
-						 */
-    {
-      gus_wave_init (hw_config);
-
-      request_region (hw_config->io_base, 16, "GUS");
-      request_region (hw_config->io_base + 0x100, 12, "GUS");	/* 0x10c-> is MAX */
-
-      if (sound_alloc_dma (hw_config->dma, "GUS"))
-	printk ("gus_card.c: Can't allocate DMA channel\n");
-      if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
-	if (sound_alloc_dma (hw_config->dma2, "GUS(2)"))
-	  printk ("gus_card.c: Can't allocate DMA channel2\n");
-#ifdef CONFIG_MIDI
-      gus_midi_init ();
-#endif
-      return;
-    }
-
-#ifndef EXCLUDE_GUS_IODETECT
+  gus_wave_init (hw_config);
 
-  /*
-   * Look at the possible base addresses (0x2X0, X=1, 2, 3, 4, 5, 6)
-   */
+  request_region (hw_config->io_base, 16, "GUS");
+  request_region (hw_config->io_base + 0x100, 12, "GUS");	/* 0x10c-> is MAX */
 
-  for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10)
-    if (io_addr != hw_config->io_base)	/*
-					 * Already tested
-					 */
-      if (gus_wave_detect (io_addr))
-	{
-	  hw_config->io_base = io_addr;
-
-	  printk (" WARNING! GUS found at %x, config was %x ", io_addr, hw_config->io_base);
-	  gus_wave_init (hw_config);
-	  request_region (io_addr, 16, "GUS");
-	  request_region (io_addr + 0x100, 12, "GUS");	/* 0x10c-> is MAX */
-	  if (sound_alloc_dma (hw_config->dma, "GUS"))
-	    printk ("gus_card.c: Can't allocate DMA channel\n");
-	  if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
-	    if (sound_alloc_dma (hw_config->dma2, "GUS"))
-	      printk ("gus_card.c: Can't allocate DMA channel2\n");
+  if (sound_alloc_dma (hw_config->dma, "GUS"))
+    printk ("gus_card.c: Can't allocate DMA channel\n");
+  if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
+    if (sound_alloc_dma (hw_config->dma2, "GUS(2)"))
+      printk ("gus_card.c: Can't allocate DMA channel2\n");
 #ifdef CONFIG_MIDI
-	  gus_midi_init ();
+  gus_midi_init ();
 #endif
-	  return;
-	}
-
-#endif
-
 }
 
 int
 probe_gus (struct address_info *hw_config)
 {
-  int             io_addr, irq;
-
-  gus_osp = hw_config->osp;
+  int             irq;
+  int             io_addr;
 
   if (hw_config->card_subtype == 1)
     gus_pnp_flag = 1;
@@ -226,7 +182,7 @@
 void
 attach_gus_db16 (struct address_info *hw_config)
 {
-#ifdef CONFIG_GUS
+#ifdef CONFIG_GUSHW
   gus_pcm_volume = 100;
   gus_wave_volume = 90;
 #endif
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/gus_midi.c linux/drivers/sound/gus_midi.c
--- v2.1.5/linux/drivers/sound/gus_midi.c	Sun Jun 30 11:43:56 1996
+++ linux/drivers/sound/gus_midi.c	Tue Oct 29 09:31:32 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -17,7 +17,7 @@
 
 #include "gus_hw.h"
 
-#if defined(CONFIG_GUS) && defined(CONFIG_MIDI)
+#if defined(CONFIG_GUSHW) && defined(CONFIG_MIDI)
 
 static int      midi_busy = 0, input_opened = 0;
 static int      my_dev;
@@ -48,10 +48,10 @@
   if (midi_busy)
     {
       printk ("GUS: Midi busy\n");
-      return -(EBUSY);
+      return -EBUSY;
     }
 
-  outb (MIDI_RESET, u_MidiControl);
+  outb ((MIDI_RESET), u_MidiControl);
   gus_delay ();
 
   gus_midi_control = 0;
@@ -64,7 +64,7 @@
     }
 
 
-  outb (gus_midi_control, u_MidiControl);	/* Enable */
+  outb ((gus_midi_control), u_MidiControl);	/* Enable */
 
   midi_busy = 1;
   qlen = qhead = qtail = output_used = 0;
@@ -87,7 +87,7 @@
   if (GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY)
     {
       ok = 1;
-      outb (midi_byte, u_MidiData);
+      outb ((midi_byte), u_MidiData);
     }
   else
     {
@@ -95,7 +95,7 @@
        * Enable Midi xmit interrupts (again)
        */
       gus_midi_control |= MIDI_ENABLE_XMIT;
-      outb (gus_midi_control, u_MidiControl);
+      outb ((gus_midi_control), u_MidiControl);
     }
 
   restore_flags (flags);
@@ -109,7 +109,7 @@
    * Reset FIFO pointers, disable intrs
    */
 
-  outb (MIDI_RESET, u_MidiControl);
+  outb ((MIDI_RESET), u_MidiControl);
   midi_busy = 0;
 }
 
@@ -180,7 +180,7 @@
 static int
 gus_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -242,7 +242,7 @@
       return;
     }
 
-  outb (MIDI_RESET, u_MidiControl);
+  outb ((MIDI_RESET), u_MidiControl);
 
   std_midi_synth.midi_dev = my_dev = num_midis;
   midi_devs[num_midis++] = &gus_midi_operations;
@@ -282,8 +282,8 @@
 	       * Disable Midi output interrupts, since no data in the buffer
 	       */
 	      gus_midi_control &= ~MIDI_ENABLE_XMIT;
-	      outb (gus_midi_control, u_MidiControl);
-	      outb (gus_midi_control, u_MidiControl);
+	      outb ((gus_midi_control), u_MidiControl);
+	      outb ((gus_midi_control), u_MidiControl);
 	    }
 	}
 
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/gus_vol.c linux/drivers/sound/gus_vol.c
--- v2.1.5/linux/drivers/sound/gus_vol.c	Sat Jul  6 11:31:42 1996
+++ linux/drivers/sound/gus_vol.c	Tue Oct 29 09:31:32 1996
@@ -4,14 +4,14 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
 #include <linux/config.h>
 
 #include "sound_config.h"
-#ifdef CONFIG_GUS
+#ifdef CONFIG_GUSHW
 #include "gus_linearvol.h"
 
 #define GUS_VOLUME	gus_wave_volume
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c
--- v2.1.5/linux/drivers/sound/gus_wave.c	Wed Oct 16 10:48:23 1996
+++ linux/drivers/sound/gus_wave.c	Tue Oct 29 09:31:37 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -19,7 +19,9 @@
 #include <linux/ultrasound.h>
 #include "gus_hw.h"
 
-#if defined(CONFIG_GUS)
+#if defined(CONFIG_GUSHW)
+
+#define GUS_BANK_SIZE (256*1024)
 
 #define MAX_SAMPLE	150
 #define MAX_PATCH	256
@@ -103,7 +105,7 @@
 static int      gus_audio_channels;
 static int      gus_audio_bits;
 
-static wait_handle *dram_sleeper = NULL;
+static struct wait_queue *dram_sleeper = NULL;
 static volatile struct snd_wait dram_sleep_flag =
 {0};
 
@@ -130,6 +132,7 @@
 
 static int      freq_div_table[] =
 {
+  44100,
   44100,			/* 14 */
   41160,			/* 15 */
   38587,			/* 16 */
@@ -214,13 +217,13 @@
 
   save_flags (flags);
   cli ();
-  outb (0x43, u_Command);
-  outb (addr & 0xff, u_DataLo);
-  outb ((addr >> 8) & 0xff, u_DataHi);
-
-  outb (0x44, u_Command);
-  outb ((addr >> 16) & 0xff, u_DataHi);
-  outb (data, u_DRAMIO);
+  outb ((0x43), u_Command);
+  outb ((addr & 0xff), u_DataLo);
+  outb (((addr >> 8) & 0xff), u_DataHi);
+
+  outb ((0x44), u_Command);
+  outb (((addr >> 16) & 0xff), u_DataHi);
+  outb ((data), u_DRAMIO);
   restore_flags (flags);
 }
 
@@ -232,12 +235,12 @@
 
   save_flags (flags);
   cli ();
-  outb (0x43, u_Command);
-  outb (addr & 0xff, u_DataLo);
-  outb ((addr >> 8) & 0xff, u_DataHi);
+  outb ((0x43), u_Command);
+  outb ((addr & 0xff), u_DataLo);
+  outb (((addr >> 8) & 0xff), u_DataHi);
 
-  outb (0x44, u_Command);
-  outb ((addr >> 16) & 0xff, u_DataHi);
+  outb ((0x44), u_Command);
+  outb (((addr >> 16) & 0xff), u_DataHi);
   tmp = inb (u_DRAMIO);
   restore_flags (flags);
 
@@ -252,8 +255,8 @@
   save_flags (flags);
   cli ();
 
-  outb (reg, u_Command);
-  outb ((unsigned char) (data & 0xff), u_DataHi);
+  outb ((reg), u_Command);
+  outb (((unsigned char) (data & 0xff)), u_DataHi);
 
   restore_flags (flags);
 }
@@ -266,7 +269,7 @@
 
   save_flags (flags);
   cli ();
-  outb (reg | 0x80, u_Command);
+  outb ((reg | 0x80), u_Command);
   val = inb (u_DataHi);
   restore_flags (flags);
 
@@ -281,7 +284,7 @@
 
   save_flags (flags);
   cli ();
-  outb (reg, u_Command);
+  outb ((reg), u_Command);
   val = inb (u_DataHi);
   restore_flags (flags);
 
@@ -296,10 +299,10 @@
   save_flags (flags);
   cli ();
 
-  outb (reg, u_Command);
+  outb ((reg), u_Command);
 
-  outb ((unsigned char) (data & 0xff), u_DataLo);
-  outb ((unsigned char) ((data >> 8) & 0xff), u_DataHi);
+  outb (((unsigned char) (data & 0xff)), u_DataLo);
+  outb (((unsigned char) ((data >> 8) & 0xff)), u_DataHi);
 
   restore_flags (flags);
 }
@@ -313,7 +316,7 @@
   save_flags (flags);
   cli ();
 
-  outb (reg | 0x80, u_Command);
+  outb ((reg | 0x80), u_Command);
 
   lo = inb (u_DataLo);
   hi = inb (u_DataHi);
@@ -332,7 +335,7 @@
   save_flags (flags);
   cli ();
 
-  outb (reg, u_Command);
+  outb ((reg), u_Command);
 
   lo = inb (u_DataLo);
   hi = inb (u_DataHi);
@@ -379,7 +382,7 @@
   if (voice < 0 || voice > 31)
     return;
 
-  outb (voice, u_Voice);
+  outb ((voice), u_Voice);
 }
 
 static void
@@ -746,14 +749,14 @@
    * Set up for Digital ASIC
    */
 
-  outb (0x05, gus_base + 0x0f);
+  outb ((0x05), gus_base + 0x0f);
 
   mix_image |= 0x02;		/* Disable line out (for a moment) */
-  outb (mix_image, u_Mixer);
+  outb ((mix_image), u_Mixer);
 
-  outb (0x00, u_IRQDMAControl);
+  outb ((0x00), u_IRQDMAControl);
 
-  outb (0x00, gus_base + 0x0f);
+  outb ((0x00), gus_base + 0x0f);
 
   /*
    * Now set up the DMA and IRQ interface
@@ -810,27 +813,27 @@
    * Doing it first time
    */
 
-  outb (mix_image, u_Mixer);	/* Select DMA control */
-  outb (dma_image | 0x80, u_IRQDMAControl);	/* Set DMA address */
+  outb ((mix_image), u_Mixer);	/* Select DMA control */
+  outb ((dma_image | 0x80), u_IRQDMAControl);	/* Set DMA address */
 
-  outb (mix_image | 0x40, u_Mixer);	/* Select IRQ control */
-  outb (irq_image, u_IRQDMAControl);	/* Set IRQ address */
+  outb ((mix_image | 0x40), u_Mixer);	/* Select IRQ control */
+  outb ((irq_image), u_IRQDMAControl);	/* Set IRQ address */
 
   /*
    * Doing it second time
    */
 
-  outb (mix_image, u_Mixer);	/* Select DMA control */
-  outb (dma_image, u_IRQDMAControl);	/* Set DMA address */
+  outb ((mix_image), u_Mixer);	/* Select DMA control */
+  outb ((dma_image), u_IRQDMAControl);	/* Set DMA address */
 
-  outb (mix_image | 0x40, u_Mixer);	/* Select IRQ control */
-  outb (irq_image, u_IRQDMAControl);	/* Set IRQ address */
+  outb ((mix_image | 0x40), u_Mixer);	/* Select IRQ control */
+  outb ((irq_image), u_IRQDMAControl);	/* Set IRQ address */
 
   gus_select_voice (0);		/* This disables writes to IRQ/DMA reg */
 
   mix_image &= ~0x02;		/* Enable line out */
   mix_image |= 0x08;		/* Enable IRQ */
-  outb (mix_image, u_Mixer);	/*
+  outb ((mix_image), u_Mixer);	/*
 				   * Turn mixer channels on
 				   * Note! Mic in is left off.
 				 */
@@ -849,6 +852,7 @@
   restore_flags (flags);
 }
 
+
 static void
 pnp_mem_init (void)
 {
@@ -928,6 +932,7 @@
       printk ("Sound: An Interwave audio chip detected but no DRAM\n");
       printk ("Sound: Unable to work with this card.\n");
       gus_write8 (0x19, gus_read8 (0x19) & ~0x01);
+      gus_mem_size = 0;
       return;
     }
 /*
@@ -1026,6 +1031,7 @@
 {
   unsigned long   i, max_mem = 1024L;
   unsigned long   loc;
+  unsigned char   val;
 
   gus_base = baseaddr;
 
@@ -1037,6 +1043,24 @@
   gus_delay ();
   gus_delay ();
 
+#ifdef GUSPNP_AUTODETECT
+  val = gus_look8 (0x5b);	/* Version number register */
+  gus_write8 (0x5b, ~val);	/* Invert all bits */
+
+  if ((gus_look8 (0x5b) & 0xf0) == (val & 0xf0))	/* No change */
+    if ((gus_look8 (0x5b) & 0x0f) == ((~val) & 0x0f))	/* Change */
+      {
+	DDB (printk ("Interwave chip version %d detected\n", (val & 0xf0) >> 4));
+	gus_pnp_flag = 1;
+      }
+    else
+      {
+	DDB (printk ("Not an Interwave chip (%x)\n", gus_look8 (0x5b)));
+	gus_pnp_flag = 0;
+      }
+  gus_write8 (0x5b, val);	/* Restore all bits */
+#endif
+
   if (gus_pnp_flag)
     pnp_mem_init ();
 
@@ -1083,7 +1107,11 @@
     {
     case SNDCTL_SYNTH_INFO:
       gus_info.nr_voices = nr_voices;
-      copy_to_user (&((char *) arg)[0], &gus_info, sizeof (gus_info));
+      {
+	char           *fixit = (char *) &gus_info;
+
+	copy_to_user (&((char *) arg)[0], fixit, sizeof (gus_info));
+      };
       return 0;
       break;
 
@@ -1097,10 +1125,10 @@
       break;
 
     case SNDCTL_SYNTH_MEMAVL:
-      return gus_mem_size - free_mem_ptr - 32;
+      return (gus_mem_size == 0) ? 0 : gus_mem_size - free_mem_ptr - 32;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -1110,10 +1138,10 @@
   int             sample_no;
 
   if (instr_no < 0 || instr_no > MAX_PATCH)
-    return -(EINVAL);
+    instr_no = 0;		/* Default to acoustic piano */
 
   if (voice < 0 || voice > 31)
-    return -(EINVAL);
+    return -EINVAL;
 
   if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
     {
@@ -1127,14 +1155,14 @@
   if (sample_no == NOT_SAMPLE)
     {
       printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice);
-      return -(EINVAL);		/* Patch not defined */
+      return -EINVAL;		/* Patch not defined */
     }
 
   if (sample_ptrs[sample_no] == -1)	/* Sample not loaded */
     {
       printk ("GUS: Sample #%d not loaded for patch %d (voice %d)\n",
 	      sample_no, instr_no, voice);
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   sample_map[voice] = sample_no;
@@ -1388,7 +1416,7 @@
   if (voice < 0 || voice > 31)
     {
       printk ("GUS: Invalid voice\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if (note_num == 255)
@@ -1406,12 +1434,12 @@
 
   if ((patch = patch_map[voice]) == -1)
     {
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if ((samplep = patch_table[patch]) == NOT_SAMPLE)
     {
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   note_freq = note_to_freq (note_num);
@@ -1492,8 +1520,8 @@
   if (samples[sample].mode & WAVE_16_BITS)
     {
       mode |= 0x04;		/* 16 bits */
-      if ((sample_ptrs[sample] >> 18) !=
-	  ((sample_ptrs[sample] + samples[sample].len) >> 18))
+      if ((sample_ptrs[sample] / GUS_BANK_SIZE) !=
+	  ((sample_ptrs[sample] + samples[sample].len) / GUS_BANK_SIZE))
 	printk ("GUS: Sample address error\n");
     }
 
@@ -1660,7 +1688,7 @@
   int             err;
 
   if (gus_busy)
-    return -(EBUSY);
+    return -EBUSY;
 
   voice_alloc->timestamp = 0;
 
@@ -1672,7 +1700,7 @@
   else
     gus_no_dma = 0;
 
-  dram_sleep_flag.flags = WK_NONE;
+  dram_sleep_flag.opts = WK_NONE;
   gus_busy = 1;
   active_device = GUS_DEV_WAVE;
 
@@ -1710,21 +1738,24 @@
   if (format != GUS_PATCH)
     {
       printk ("GUS Error: Invalid patch format (key) 0x%x\n", format);
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if (count < sizeof_patch)
     {
       printk ("GUS Error: Patch header too short\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   count -= sizeof_patch;
 
+  if (gus_mem_size == 0)
+    return -ENOSPC;
+
   if (free_sample >= MAX_SAMPLE)
     {
       printk ("GUS: Sample table full\n");
-      return -(ENOSPC);
+      return -ENOSPC;
     }
 
   /*
@@ -1739,7 +1770,7 @@
   if (instr < 0 || instr > MAX_PATCH)
     {
       printk ("GUS: Invalid patch number %d\n", instr);
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if (count < patch.len)
@@ -1752,7 +1783,7 @@
   if (patch.len <= 0 || patch.len > gus_mem_size)
     {
       printk ("GUS: Invalid sample length %d\n", (int) patch.len);
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if (patch.mode & WAVE_LOOPING)
@@ -1760,20 +1791,18 @@
       if (patch.loop_start < 0 || patch.loop_start >= patch.len)
 	{
 	  printk ("GUS: Invalid loop start\n");
-	  return -(EINVAL);
+	  return -EINVAL;
 	}
 
       if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len)
 	{
 	  printk ("GUS: Invalid loop end\n");
-	  return -(EINVAL);
+	  return -EINVAL;
 	}
     }
 
   free_mem_ptr = (free_mem_ptr + 31) & ~31;	/* 32 byte alignment */
 
-#define GUS_BANK_SIZE (256*1024)
-
   if (patch.mode & WAVE_16_BITS)
     {
       /*
@@ -1782,7 +1811,7 @@
       if (patch.len >= GUS_BANK_SIZE)
 	{
 	  printk ("GUS: Sample (16 bit) too long %d\n", (int) patch.len);
-	  return -(ENOSPC);
+	  return -ENOSPC;
 	}
 
       if ((free_mem_ptr / GUS_BANK_SIZE) !=
@@ -1792,14 +1821,14 @@
 	  ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
 
 	  if ((tmp_mem + patch.len) > gus_mem_size)
-	    return -(ENOSPC);
+	    return -ENOSPC;
 
 	  free_mem_ptr = tmp_mem;	/* This leaves unusable memory */
 	}
     }
 
   if ((free_mem_ptr + patch.len) > gus_mem_size)
-    return -(ENOSPC);
+    return -ENOSPC;
 
   sample_ptrs[free_sample] = free_mem_ptr;
 
@@ -1839,14 +1868,14 @@
 	blk_sz = left;
 
       /*
-       * DMA cannot cross 256k bank boundaries. Check for that.
+       * DMA cannot cross bank (256k) boundaries. Check for that.
        */
       blk_end = target + blk_sz;
 
-      if ((target >> 18) != (blk_end >> 18))
+      if ((target / GUS_BANK_SIZE) != (blk_end / GUS_BANK_SIZE))
 	{			/* Split the block */
 
-	  blk_end &= ~(256 * 1024 - 1);
+	  blk_end &= ~(GUS_BANK_SIZE - 1);
 	  blk_sz = blk_end - target;
 	}
 
@@ -1858,10 +1887,9 @@
 	  long            i;
 	  unsigned char   data;
 
-
 	  for (i = 0; i < blk_sz; i++)
 	    {
-	      data = get_fs_byte (&((addr)[sizeof_patch + i]));
+	      get_user (data, (unsigned char *) &((addr)[sizeof_patch + i]));
 	      if (patch.mode & WAVE_UNSIGNED)
 
 		if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
@@ -1878,7 +1906,7 @@
 	  if (audio_devs[gus_devnum]->dmap_out->raw_buf == NULL)
 	    {
 	      printk ("GUS: DMA buffer == NULL\n");
-	      return -(EINVAL);
+	      return -ENOSPC;
 	    }
 
 	  /*
@@ -1923,7 +1951,7 @@
 	  if (audio_devs[gus_devnum]->dmachan1 > 3)
 	    dma_command |= 0x04;	/* 16 bit DMA _channel_ */
 
-	  gus_write8 (0x41, dma_command);	/* Lets bo luteet (=bugs) */
+	  gus_write8 (0x41, dma_command);	/* Lets go luteet (=bugs) */
 
 	  /*
 	   * Sleep here until the DRAM DMA done interrupt is served
@@ -1935,19 +1963,19 @@
 	    unsigned long   tlimit;
 
 	    if (HZ)
-	      current_set_timeout (tlimit = jiffies + (HZ));
+	      current->timeout = tlimit = jiffies + (HZ);
 	    else
 	      tlimit = (unsigned long) -1;
-	    dram_sleep_flag.flags = WK_SLEEP;
-	    module_interruptible_sleep_on (&dram_sleeper);
-	    if (!(dram_sleep_flag.flags & WK_WAKEUP))
+	    dram_sleep_flag.opts = WK_SLEEP;
+	    interruptible_sleep_on (&dram_sleeper);
+	    if (!(dram_sleep_flag.opts & WK_WAKEUP))
 	      {
 		if (jiffies >= tlimit)
-		  dram_sleep_flag.flags |= WK_TIMEOUT;
+		  dram_sleep_flag.opts |= WK_TIMEOUT;
 	      }
-	    dram_sleep_flag.flags &= ~WK_SLEEP;
+	    dram_sleep_flag.opts &= ~WK_SLEEP;
 	  };
-	  if ((dram_sleep_flag.flags & WK_TIMEOUT))
+	  if ((dram_sleep_flag.opts & WK_TIMEOUT))
 	    printk ("GUS: DMA Transfer timed out\n");
 	  restore_flags (flags);
 	}
@@ -2190,59 +2218,99 @@
 static int
 gus_audio_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
+  int             val;
+
   switch (cmd)
     {
     case SOUND_PCM_WRITE_RATE:
       if (local)
 	return gus_audio_set_speed ((int) arg);
-      return snd_ioctl_return ((int *) arg, gus_audio_set_speed (get_user ((int *) arg)));
+      get_user (val, (int *) arg);
+      return ioctl_out (arg, gus_audio_set_speed (val));
       break;
 
     case SOUND_PCM_READ_RATE:
       if (local)
 	return gus_audio_speed;
-      return snd_ioctl_return ((int *) arg, gus_audio_speed);
+      return ioctl_out (arg, gus_audio_speed);
       break;
 
     case SNDCTL_DSP_STEREO:
       if (local)
 	return gus_audio_set_channels ((int) arg + 1) - 1;
-      return snd_ioctl_return ((int *) arg, gus_audio_set_channels (get_user ((int *) arg) + 1) - 1);
+      get_user (val, (int *) arg);
+      return ioctl_out (arg, gus_audio_set_channels (val + 1) - 1);
       break;
 
     case SOUND_PCM_WRITE_CHANNELS:
       if (local)
 	return gus_audio_set_channels ((int) arg);
-      return snd_ioctl_return ((int *) arg, gus_audio_set_channels (get_user ((int *) arg)));
+      get_user (val, (int *) arg);
+      return ioctl_out (arg, gus_audio_set_channels (val));
       break;
 
     case SOUND_PCM_READ_CHANNELS:
       if (local)
 	return gus_audio_channels;
-      return snd_ioctl_return ((int *) arg, gus_audio_channels);
+      return ioctl_out (arg, gus_audio_channels);
       break;
 
     case SNDCTL_DSP_SETFMT:
       if (local)
 	return gus_audio_set_bits ((int) arg);
-      return snd_ioctl_return ((int *) arg, gus_audio_set_bits (get_user ((int *) arg)));
+      get_user (val, (int *) arg);
+      return ioctl_out (arg, gus_audio_set_bits (val));
       break;
 
     case SOUND_PCM_READ_BITS:
       if (local)
 	return gus_audio_bits;
-      return snd_ioctl_return ((int *) arg, gus_audio_bits);
+      return ioctl_out (arg, gus_audio_bits);
 
     case SOUND_PCM_WRITE_FILTER:	/* NOT POSSIBLE */
-      return snd_ioctl_return ((int *) arg, -(EINVAL));
+      return ioctl_out (arg, -EINVAL);
       break;
 
     case SOUND_PCM_READ_FILTER:
-      return snd_ioctl_return ((int *) arg, -(EINVAL));
+      return ioctl_out (arg, -EINVAL);
+      break;
+
+/* This is just a temporary hack used for reading the ROM patch set. */
+
+    case SNDCTL_PMGR_ACCESS:
+      {
+	copr_msg       *buf;
+	int             i, pos;
+
+	buf = (copr_msg *) vmalloc (sizeof (copr_msg));
+	if (buf == NULL)
+	  return -ENOSPC;
+
+	copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
+
+	pos = buf->len;
+
+	gus_write8 (0x53, gus_look8 (0x53) | 0x02);	/* Select ROM I/O access */
+
+	for (i = 0; i < 2048; i++)
+	  {
+	    buf->data[i] = gus_peek (pos + i);
+	  }
+	gus_write8 (0x53, gus_look8 (0x53) & ~0x02);	/* Select DRAM I/O access */
+	buf->len = 2048;	/* feed back number of WORDs sent */
+	{
+	  char           *fixit = (char *) buf;
+
+	  copy_to_user (&((char *) arg)[0], fixit, sizeof (*buf));
+	};
+	vfree (buf);
+
+	return 0;
+      }
       break;
 
     }
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -2255,16 +2323,17 @@
     }
 }
 
+
 static int
 gus_audio_open (int dev, int mode)
 {
   if (gus_busy)
-    return -(EBUSY);
+    return -EBUSY;
 
   if (gus_pnp_flag && mode & OPEN_READ)
     {
       printk ("Sound: This audio device doesn't have recording capability\n");
-      return -(EIO);
+      return -EIO;
     }
   gus_initialize ();
 
@@ -2588,7 +2657,7 @@
   if (gus_audio_bits != 8)
     {
       printk ("GUS Error: 16 bit recording not supported\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   return 0;
@@ -2653,9 +2722,9 @@
 
       for (i = 0; i < len; i++)
 	{
-	  *out_left++ = get_fs_byte (&((userbuf)[in_left]));
+	  get_user (*out_left++, (unsigned char *) &((userbuf)[in_left]));
 	  in_left += 2;
-	  *out_right++ = get_fs_byte (&((userbuf)[in_right]));
+	  get_user (*out_right++, (unsigned char *) &((userbuf)[in_right]));
 	  in_right += 2;
 	}
     }
@@ -2674,9 +2743,9 @@
 
       for (i = 0; i < len; i++)
 	{
-	  *out_left++ = get_fs_word (&((userbuf)[in_left]));
+	  get_user (*out_left++, (unsigned short *) &((userbuf)[in_left]));
 	  in_left += 4;
-	  *out_right++ = get_fs_word (&((userbuf)[in_right]));
+	  get_user (*out_right++, (unsigned short *) &((userbuf)[in_right]));
 	  in_right += 4;
 	}
     }
@@ -2798,7 +2867,7 @@
 	struct patch_info *pat;
 
 	if (ptr < 0 || ptr >= free_sample)
-	  return -(EINVAL);
+	  return -EINVAL;
 
 	memcpy (rec->data.data8, (char *) &samples[ptr],
 		sizeof (struct patch_info));
@@ -2818,12 +2887,12 @@
 	struct patch_info *pat;
 
 	if (ptr < 0 || ptr >= free_sample)
-	  return -(EINVAL);
+	  return -EINVAL;
 
 	pat = (struct patch_info *) rec->data.data8;
 
 	if (pat->len > samples[ptr].len)	/* Cannot expand sample */
-	  return -(EINVAL);
+	  return -EINVAL;
 
 	pat->key = samples[ptr].key;	/* Ensure the link is correct */
 
@@ -2843,10 +2912,10 @@
 	int             l = rec->parm3;
 
 	if (sample < 0 || sample >= free_sample)
-	  return -(EINVAL);
+	  return -EINVAL;
 
 	if (offs < 0 || offs >= samples[sample].len)
-	  return -(EINVAL);	/* Invalid offset */
+	  return -EINVAL;	/* Invalid offset */
 
 	n = samples[sample].len - offs;		/* Num of bytes left */
 
@@ -2857,12 +2926,12 @@
 	  l = sizeof (rec->data.data8);
 
 	if (l <= 0)
-	  return -(EINVAL);	/*
+	  return -EINVAL;	/*
 				   * Was there a bug?
 				 */
 
 	offs += sample_ptrs[sample];	/*
-					 * Begin offsets + offset to DRAM
+					 * Begin offset + offset to DRAM
 					 */
 
 	for (n = 0; n < l; n++)
@@ -2884,10 +2953,10 @@
 	int             l = rec->parm3;
 
 	if (sample < 0 || sample >= free_sample)
-	  return -(EINVAL);
+	  return -EINVAL;
 
 	if (offs < 0 || offs >= samples[sample].len)
-	  return -(EINVAL);	/*
+	  return -EINVAL;	/*
 				   * Invalid offset
 				 */
 
@@ -2902,7 +2971,7 @@
 	  l = sizeof (rec->data.data8);
 
 	if (l <= 0)
-	  return -(EINVAL);	/*
+	  return -EINVAL;	/*
 				   * Was there a bug?
 				 */
 
@@ -2920,7 +2989,7 @@
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -3030,7 +3099,7 @@
 
   mix_image &= ~0x07;
   mix_image |= mask & 0x07;
-  outb (mix_image, u_Mixer);
+  outb ((mix_image), u_Mixer);
 
   restore_flags (flags);
 }
@@ -3046,16 +3115,20 @@
 	switch (cmd & 0xff)
 	  {
 	  case SOUND_MIXER_RECSRC:
-	    gus_recmask = get_user ((int *) arg) & MIX_DEVS;
+	    get_user (gus_recmask, (int *) arg);
+	    gus_recmask &= MIX_DEVS;
 	    if (!(gus_recmask & (SOUND_MASK_MIC | SOUND_MASK_LINE)))
 	      gus_recmask = SOUND_MASK_MIC;
 	    /* Note! Input volumes are updated during next open for recording */
-	    return snd_ioctl_return ((int *) arg, gus_recmask);
+	    return ioctl_out (arg, gus_recmask);
 	    break;
 
 	  case SOUND_MIXER_MIC:
 	    {
-	      int             vol = get_user ((int *) arg) & 0xff;
+	      int             vol;
+
+	      get_user (vol, (int *) arg);
+	      vol &= 0xff;
 
 	      if (vol < 0)
 		vol = 0;
@@ -3063,13 +3136,16 @@
 		vol = 100;
 	      gus_mic_vol = vol;
 	      set_input_volumes ();
-	      return snd_ioctl_return ((int *) arg, vol | (vol << 8));
+	      return ioctl_out (arg, vol | (vol << 8));
 	    }
 	    break;
 
 	  case SOUND_MIXER_LINE:
 	    {
-	      int             vol = get_user ((int *) arg) & 0xff;
+	      int             vol;
+
+	      get_user (vol, (int *) arg);
+	      vol &= 0xff;
 
 	      if (vol < 0)
 		vol = 0;
@@ -3077,25 +3153,27 @@
 		vol = 100;
 	      gus_line_vol = vol;
 	      set_input_volumes ();
-	      return snd_ioctl_return ((int *) arg, vol | (vol << 8));
+	      return ioctl_out (arg, vol | (vol << 8));
 	    }
 	    break;
 
 	  case SOUND_MIXER_PCM:
-	    gus_pcm_volume = get_user ((int *) arg) & 0xff;
+	    get_user (gus_pcm_volume, (int *) arg);
+	    gus_pcm_volume &= 0xff;
 	    if (gus_pcm_volume < 0)
 	      gus_pcm_volume = 0;
 	    if (gus_pcm_volume > 100)
 	      gus_pcm_volume = 100;
 	    gus_audio_update_volume ();
-	    return snd_ioctl_return ((int *) arg, gus_pcm_volume | (gus_pcm_volume << 8));
+	    return ioctl_out (arg, gus_pcm_volume | (gus_pcm_volume << 8));
 	    break;
 
 	  case SOUND_MIXER_SYNTH:
 	    {
 	      int             voice;
 
-	      gus_wave_volume = get_user ((int *) arg) & 0xff;
+	      get_user (gus_wave_volume, (int *) arg);
+	      gus_wave_volume &= 0xff;
 
 	      if (gus_wave_volume < 0)
 		gus_wave_volume = 0;
@@ -3106,12 +3184,12 @@
 		for (voice = 0; voice < nr_voices; voice++)
 		  dynamic_volume_change (voice);	/* Apply the new vol */
 
-	      return snd_ioctl_return ((int *) arg, gus_wave_volume | (gus_wave_volume << 8));
+	      return ioctl_out (arg, gus_wave_volume | (gus_wave_volume << 8));
 	    }
 	    break;
 
 	  default:
-	    return -(EINVAL);
+	    return -EINVAL;
 	  }
       else
 	switch (cmd & 0xff)	/*
@@ -3120,47 +3198,47 @@
 	  {
 
 	  case SOUND_MIXER_RECSRC:
-	    return snd_ioctl_return ((int *) arg, gus_recmask);
+	    return ioctl_out (arg, gus_recmask);
 	    break;
 
 	  case SOUND_MIXER_DEVMASK:
-	    return snd_ioctl_return ((int *) arg, MIX_DEVS);
+	    return ioctl_out (arg, MIX_DEVS);
 	    break;
 
 	  case SOUND_MIXER_STEREODEVS:
-	    return snd_ioctl_return ((int *) arg, 0);
+	    return ioctl_out (arg, 0);
 	    break;
 
 	  case SOUND_MIXER_RECMASK:
-	    return snd_ioctl_return ((int *) arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
+	    return ioctl_out (arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
 	    break;
 
 	  case SOUND_MIXER_CAPS:
-	    return snd_ioctl_return ((int *) arg, 0);
+	    return ioctl_out (arg, 0);
 	    break;
 
 	  case SOUND_MIXER_MIC:
-	    return snd_ioctl_return ((int *) arg, gus_mic_vol | (gus_mic_vol << 8));
+	    return ioctl_out (arg, gus_mic_vol | (gus_mic_vol << 8));
 	    break;
 
 	  case SOUND_MIXER_LINE:
-	    return snd_ioctl_return ((int *) arg, gus_line_vol | (gus_line_vol << 8));
+	    return ioctl_out (arg, gus_line_vol | (gus_line_vol << 8));
 	    break;
 
 	  case SOUND_MIXER_PCM:
-	    return snd_ioctl_return ((int *) arg, gus_pcm_volume | (gus_pcm_volume << 8));
+	    return ioctl_out (arg, gus_pcm_volume | (gus_pcm_volume << 8));
 	    break;
 
 	  case SOUND_MIXER_SYNTH:
-	    return snd_ioctl_return ((int *) arg, gus_wave_volume | (gus_wave_volume << 8));
+	    return ioctl_out (arg, gus_wave_volume | (gus_wave_volume << 8));
 	    break;
 
 	  default:
-	    return -(EINVAL);
+	    return -EINVAL;
 	  }
     }
   else
-    return -(EINVAL);
+    return -EINVAL;
 }
 
 static struct mixer_operations gus_mixer_operations =
@@ -3187,7 +3265,7 @@
  */
       mix_image &= ~0x07;
       mix_image |= 0x04;	/* All channels enabled */
-      outb (mix_image, u_Mixer);
+      outb ((mix_image), u_Mixer);
     }
 }
 
@@ -3197,6 +3275,7 @@
   unsigned long   flags;
   unsigned char   val;
   char           *model_num = "2.4";
+  char            tmp[64], tmp2[64];
   int             gus_type = 0x24;	/* 2.4 */
 
   int             irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2;
@@ -3227,27 +3306,9 @@
      *  Versions < 3.6 don't have the digital ASIC. Try to probe it first.
    */
 
-#ifdef GUSPNP_AUTODETECT
-  val = gus_look8 (0x5b);	/* Version number register */
-  gus_write8 (0x5b, ~val);	/* Invert all bits */
-
-  if ((gus_look8 (0x5b) & 0xf0) == (val & 0xf0))	/* No change */
-    if ((gus_look8 (0x5b) & 0x0f) == ((~val) & 0x0f))	/* Change */
-      {
-	DDB (printk ("Interwave chip version %d detected\n", (val & 0xf0) >> 4));
-	gus_pnp_flag = 1;
-      }
-    else
-      {
-	DDB (printk ("Not an Interwave chip\n"));
-	gus_pnp_flag = 0;
-      }
-  gus_write8 (0x5b, val);	/* Restore all bits */
-#endif
-
   save_flags (flags);
   cli ();
-  outb (0x20, gus_base + 0x0f);
+  outb ((0x20), gus_base + 0x0f);
   val = inb (gus_base + 0x0f);
   restore_flags (flags);
 
@@ -3306,12 +3367,16 @@
 
 	    max_config |= (gus_base >> 4) & 0x0f;	/* Extract the X from 2X0 */
 
-	    outb (max_config, gus_base + 0x106);	/* UltraMax control */
+	    outb ((max_config), gus_base + 0x106);	/* UltraMax control */
 	  }
 
 	  if (ad1848_detect (gus_base + 0x10c, &ad_flags, hw_config->osp))
 	    {
 	      char           *name = "GUS MAX";
+	      int             old_num_mixers = num_mixers;
+
+	      if (gus_pnp_flag)
+		name = "GUS PnP";
 
 	      gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
 	      gus_wave_volume = 90;
@@ -3325,6 +3390,13 @@
 			   gus_dma,	/* Capture DMA */
 			   1,	/* Share DMA channels with GF1 */
 			   hw_config->osp);
+
+	      if (num_mixers > old_num_mixers)
+		{		/* GUS has it's own mixer map */
+		  AD1848_REROUTE (SOUND_MIXER_LINE1, SOUND_MIXER_SYNTH);
+		  AD1848_REROUTE (SOUND_MIXER_LINE2, SOUND_MIXER_CD);
+		  AD1848_REROUTE (SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
+		}
 	    }
 	  else
 	    printk ("[Where's the CS4231?]");
@@ -3343,15 +3415,19 @@
 
   if (hw_config->name)
     {
-      char            tmp[20];
 
-      strncpy (tmp, hw_config->name, 20);
-      tmp[19] = 0;
-      sprintf (gus_info.name, "%s (%dk)", tmp, (int) gus_mem_size / 1024);
-      gus_info.name[sizeof (gus_info.name) - 1] = 0;
+      strncpy (tmp, hw_config->name, 45);
+      tmp[45] = 0;
+      sprintf (tmp2, "%s (%dk)", tmp, (int) gus_mem_size / 1024);
+      tmp2[sizeof (tmp2) - 1] = 0;
+    }
+  else if (gus_pnp_flag)
+    {
+      sprintf (tmp2, "Gravis UltraSound PnP (%dk)",
+	       (int) gus_mem_size / 1024);
     }
   else
-    sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
+    sprintf (tmp2, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
 
 
   samples = (struct patch_info *) (sound_mem_blocks[sound_nblocks] = vmalloc ((MAX_SAMPLE + 1) * sizeof (*samples)));
@@ -3363,7 +3439,9 @@
       return;
     }
 
-  conf_printf (gus_info.name, hw_config);
+  conf_printf (tmp2, hw_config);
+  strncpy (gus_info.name, tmp2, sizeof (tmp2));
+  gus_info.name[sizeof (tmp2) - 1] = 0;
 
   if (num_synths >= MAX_SYNTH_DEV)
     printk ("GUS Error: Too many synthesizers\n");
@@ -3380,20 +3458,21 @@
 
   gus_initialize ();
 
-  if (num_audiodevs < MAX_AUDIO_DEV)
-    {
-      audio_devs[gus_devnum = num_audiodevs++] = &gus_audio_operations;
-      audio_devs[gus_devnum]->dmachan1 = dma;
-      audio_devs[gus_devnum]->dmachan2 = dma2;
-      audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE;
-      audio_devs[gus_devnum]->min_fragment = 9;
-      audio_devs[gus_devnum]->mixer_dev = num_mixers;	/* Next mixer# */
-      audio_devs[gus_devnum]->flags |= DMA_HARDSTOP;
-      if (dma2 != dma && dma2 != -1)
-	audio_devs[gus_devnum]->flags |= DMA_DUPLEX;
-    }
-  else
-    printk ("GUS: Too many PCM devices available\n");
+  if (gus_mem_size > 0)
+    if (num_audiodevs < MAX_AUDIO_DEV)
+      {
+	audio_devs[gus_devnum = num_audiodevs++] = &gus_audio_operations;
+	audio_devs[gus_devnum]->dmachan1 = dma;
+	audio_devs[gus_devnum]->dmachan2 = dma2;
+	audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE;
+	audio_devs[gus_devnum]->min_fragment = 9;
+	audio_devs[gus_devnum]->mixer_dev = num_mixers;		/* Next mixer# */
+	audio_devs[gus_devnum]->flags |= DMA_HARDSTOP;
+	if (dma2 != dma && dma2 != -1)
+	  audio_devs[gus_devnum]->flags |= DMA_DUPLEX;
+      }
+    else
+      printk ("GUS: Too many audio devices available\n");
 
   /*
      *  Mixer dependent initialization.
@@ -3648,10 +3727,10 @@
     switch (active_device)
       {
       case GUS_DEV_WAVE:
-	if ((dram_sleep_flag.flags & WK_SLEEP))
+	if ((dram_sleep_flag.opts & WK_SLEEP))
 	  {
-	    dram_sleep_flag.flags = WK_WAKEUP;
-	    module_wake_up (&dram_sleeper);
+	    dram_sleep_flag.opts = WK_WAKEUP;
+	    wake_up (&dram_sleeper);
 	  };
 	break;
 
@@ -3702,12 +3781,12 @@
 {
   int             i;
 
-  outb ((unsigned char) (addr & 0xff), select_addr);
+  outb (((unsigned char) (addr & 0xff)), select_addr);
 
   for (i = 0; i < 2; i++)
     inb (select_addr);
 
-  outb ((unsigned char) (val & 0xff), data_addr);
+  outb (((unsigned char) (val & 0xff)), data_addr);
 
   for (i = 0; i < 2; i++)
     inb (select_addr);
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/ics2101.c linux/drivers/sound/ics2101.c
--- v2.1.5/linux/drivers/sound/ics2101.c	Sun Aug 18 10:46:49 1996
+++ linux/drivers/sound/ics2101.c	Tue Oct 29 09:31:37 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -14,7 +14,7 @@
 
 
 #include "sound_config.h"
-#if defined(CONFIG_GUS)
+#if defined(CONFIG_GUSHW)
 
 #include <linux/ultrasound.h>
 #include "gus_hw.h"
@@ -85,10 +85,10 @@
 
   save_flags (flags);
   cli ();
-  outb (ctrl_addr, u_MixSelect);
-  outb (selector[dev], u_MixData);
-  outb (attn_addr, u_MixSelect);
-  outb ((unsigned char) vol, u_MixData);
+  outb ((ctrl_addr), u_MixSelect);
+  outb ((selector[dev]), u_MixData);
+  outb ((attn_addr), u_MixSelect);
+  outb (((unsigned char) vol), u_MixData);
   restore_flags (flags);
 }
 
@@ -128,27 +128,27 @@
 	    break;
 
 	  case SOUND_MIXER_MIC:
-	    return snd_ioctl_return ((int *) arg, set_volumes (DEV_MIC, get_user ((int *) arg)));
+	    return ioctl_out (arg, set_volumes (DEV_MIC, ioctl_in (arg)));
 	    break;
 
 	  case SOUND_MIXER_CD:
-	    return snd_ioctl_return ((int *) arg, set_volumes (DEV_CD, get_user ((int *) arg)));
+	    return ioctl_out (arg, set_volumes (DEV_CD, ioctl_in (arg)));
 	    break;
 
 	  case SOUND_MIXER_LINE:
-	    return snd_ioctl_return ((int *) arg, set_volumes (DEV_LINE, get_user ((int *) arg)));
+	    return ioctl_out (arg, set_volumes (DEV_LINE, ioctl_in (arg)));
 	    break;
 
 	  case SOUND_MIXER_SYNTH:
-	    return snd_ioctl_return ((int *) arg, set_volumes (DEV_GF1, get_user ((int *) arg)));
+	    return ioctl_out (arg, set_volumes (DEV_GF1, ioctl_in (arg)));
 	    break;
 
 	  case SOUND_MIXER_VOLUME:
-	    return snd_ioctl_return ((int *) arg, set_volumes (DEV_VOL, get_user ((int *) arg)));
+	    return ioctl_out (arg, set_volumes (DEV_VOL, ioctl_in (arg)));
 	    break;
 
 	  default:
-	    return -(EINVAL);
+	    return -EINVAL;
 	  }
       else
 	switch (cmd & 0xff)	/*
@@ -161,47 +161,47 @@
 	    break;
 
 	  case SOUND_MIXER_DEVMASK:
-	    return snd_ioctl_return ((int *) arg, MIX_DEVS);
+	    return ioctl_out (arg, MIX_DEVS);
 	    break;
 
 	  case SOUND_MIXER_STEREODEVS:
-	    return snd_ioctl_return ((int *) arg, SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC);
+	    return ioctl_out (arg, SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC);
 	    break;
 
 	  case SOUND_MIXER_RECMASK:
-	    return snd_ioctl_return ((int *) arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
+	    return ioctl_out (arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
 	    break;
 
 	  case SOUND_MIXER_CAPS:
-	    return snd_ioctl_return ((int *) arg, 0);
+	    return ioctl_out (arg, 0);
 	    break;
 
 	  case SOUND_MIXER_MIC:
-	    return snd_ioctl_return ((int *) arg, volumes[DEV_MIC]);
+	    return ioctl_out (arg, volumes[DEV_MIC]);
 	    break;
 
 	  case SOUND_MIXER_LINE:
-	    return snd_ioctl_return ((int *) arg, volumes[DEV_LINE]);
+	    return ioctl_out (arg, volumes[DEV_LINE]);
 	    break;
 
 	  case SOUND_MIXER_CD:
-	    return snd_ioctl_return ((int *) arg, volumes[DEV_CD]);
+	    return ioctl_out (arg, volumes[DEV_CD]);
 	    break;
 
 	  case SOUND_MIXER_VOLUME:
-	    return snd_ioctl_return ((int *) arg, volumes[DEV_VOL]);
+	    return ioctl_out (arg, volumes[DEV_VOL]);
 	    break;
 
 	  case SOUND_MIXER_SYNTH:
-	    return snd_ioctl_return ((int *) arg, volumes[DEV_GF1]);
+	    return ioctl_out (arg, volumes[DEV_GF1]);
 	    break;
 
 	  default:
-	    return -(EINVAL);
+	    return -EINVAL;
 	  }
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static struct mixer_operations ics2101_mixer_operations =
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/iwmem.h linux/drivers/sound/iwmem.h
--- v2.1.5/linux/drivers/sound/iwmem.h	Sun Jun 30 12:30:15 1996
+++ linux/drivers/sound/iwmem.h	Tue Oct 29 09:31:08 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/lowlevel/ChangeLog.awe linux/drivers/sound/lowlevel/ChangeLog.awe
--- v2.1.5/linux/drivers/sound/lowlevel/ChangeLog.awe	Thu Jan  1 02:00:00 1970
+++ linux/drivers/sound/lowlevel/ChangeLog.awe	Fri Oct 25 13:06:34 1996
@@ -0,0 +1,66 @@
+ver.0.2.0
+	- Includes FreeBSD port
+	- Can load GUS compatible patches
+	- Change values of hardware control parameters for compatibility
+	  with GUS driver
+	- Accept 8bit or unsigned wave data
+	- Accept no blank loop data
+	- Add sample mode flags in sample_info
+
+ver.0.1.6
+	- Add voice effects control
+	- Fix awe_voice.h for word alignment
+
+ver.0.1.5c
+	- Fix FM(OPL) playback problem
+
+ver.0.1.5b
+	- Fix pitch calculation for fixed midi key
+
+ver.0.1.5a
+	- Fix bugs in removing samples from linked list.
+
+ver.0.1.5
+	- Add checksum verification for sample uploading
+	  (not compatible from older sample_info structure)
+	- Fix sample offset pointers to (actual value - 1)
+	- Add sequencer command to initialize awe32
+
+ver.0.1.4c
+	- Fix card detection and memory check function to avoid system crash
+	  at booting
+
+ver.0.1.4b
+	- Add release sustain mode
+	- Initialize FM each time after loading samples
+
+ver.0.1.4a
+	- Fix AWE card detection code
+	- Correct FM initialize position 
+	- Add non-releasing mode on voice info
+
+ver.0.1.4
+	- Add AWE card and DRAM detection codes
+	- Add FM initialization code
+	- Modify volume control
+	- Remove linear volume mode
+	- Change memory management; not using malloc dynamically
+	- Add remove-samples command
+	- Use internal id implicitly at loading samples
+
+ver.0.1.3
+	- Fix a bug on patch uploading to RAM
+
+ver.0.1.2
+	- Divide to separated packages
+	- Fix disagreed macro conditions
+	- Fix unresolved function bugs
+	- Integrate VoxWare and USS-Lite driver source (awe_voice.c)
+	  and remove awe_card.c
+
+ver.0.1.1
+	- Fix wrong sample numbers in sbktext
+	- Fix txt2sfx bug
+	- Fix pan parameter calculation
+	- Append USS-Lite/Linux2.0 driver
+
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/lowlevel/Config.tmpl linux/drivers/sound/lowlevel/Config.tmpl
--- v2.1.5/linux/drivers/sound/lowlevel/Config.tmpl	Thu May 16 11:05:56 1996
+++ linux/drivers/sound/lowlevel/Config.tmpl	Fri Oct 25 13:06:34 1996
@@ -2,4 +2,5 @@
 
 if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
    bool 'ACI mixer (miroPCM12)' CONFIG_ACI_MIXER
+   bool 'AWE32 synth' CONFIG_AWE32_SYNTH
 fi
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/lowlevel/Makefile linux/drivers/sound/lowlevel/Makefile
--- v2.1.5/linux/drivers/sound/lowlevel/Makefile	Wed Sep  4 20:37:14 1996
+++ linux/drivers/sound/lowlevel/Makefile	Fri Oct 25 13:06:34 1996
@@ -1,18 +1,33 @@
 all:	lowlevel.o
 
+ALLOBJS = init.o aci.o awe_wave.o
 OBJS = init.o
 
 ifdef CONFIG_LOWLEVEL_SOUND
 ifdef CONFIG_ACI_MIXER
 OBJS := $(OBJS) aci.o
 endif
+ifdef CONFIG_AWE32_SYNTH
+OBJS := $(OBJS) awe_wave.o
+endif
 endif
 
 lowlevel.o:	$(OBJS)
 	$(LD) -r -o lowlevel.o $(OBJS)
 
+module: manual_config.h
+	rm -f lowlevel.o
+	make CFLAGS="$(CFLAGS) -DLOWLEVEL_MODULE" $(ALLOBJS)
+	$(LD) -r -o lowlevel.o $(ALLOBJS)
+	touch module
+
+manual_config.h:
+	@echo You should create `pwd`/manual_config.h.
+	@echo See `pwd`/README for more info.
+	@exit 1
+
 clean:
-	rm -f core x y z *~ *.o
+	rm -f core x y z *~ *.o module
 
 ifdef HOSTCC
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/lowlevel/README linux/drivers/sound/lowlevel/README
--- v2.1.5/linux/drivers/sound/lowlevel/README	Thu May 16 11:09:13 1996
+++ linux/drivers/sound/lowlevel/README	Fri Oct 25 13:06:34 1996
@@ -1,13 +1,17 @@
 Additional low level sound drivers for Linux
---------------------------------------------
+============================================
 
 This directory contains additional low level sound drivers which
-are not part of USS/Lite (UNIX Sound System). These drivers are
-maintained by their authors.
+are not part of USS/Lite (Open Sound System). These drivers are
+maintained by their authors (not by Hannu Savolainen).
 
-If you like to write a low level sound driver, please contact
+If you like to write a new low level sound driver, please contact
 Hannu Savolainen (hannu@voxware.pp.fi) for more info.
 
 The following low level drivers are included:
 
-- ACI MIXER for miroPCM12 by Markus Kuhn. See aci.readme for more info.
+- ACI MIXER for miroPCM12 by Markus Kuhn
+(mskuhn@cip.informatik.uni-erlangen.de).
+- SB32/AWE synthesizer driver (Emu8000) by Takashi Iwai
+(iwai@dragon.mm.t.u-tokyo.ac.jp). See README.awe for more
+info.
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/lowlevel/README.awe linux/drivers/sound/lowlevel/README.awe
--- v2.1.5/linux/drivers/sound/lowlevel/README.awe	Thu Jan  1 02:00:00 1970
+++ linux/drivers/sound/lowlevel/README.awe	Fri Oct 25 13:06:34 1996
@@ -0,0 +1,69 @@
+================================================================
+	AWE32 Sound Driver for Linux / FreeBSD
+		version 0.2.0; Oct. 16, 1996
+================================================================
+
+* GENERAL NOTES
+
+This is a sound driver extension for SB-AWE32 cards to enable the
+wave synth operations.  The driver is provided for both Linux 1.2.x
+and 2.0.x kernels, and also FreeBSD.  Follow the corresponding
+instruction in the installation document if you use old sound drivers.
+
+This driver was written by Takashi Iwai (iwai@dragon.mm.t.u-tokyo.ac.jp)  
+who also maintains the code.  Please forward any questions, bug fixes
+and suggestions directly to me (_NOT_ to Linus Torvalds or Hannu
+Savolainen).
+
+
+* CAUTION
+
+- In the v0.2.0, parameters of hardware control are changed to have a
+compatibility with GUS driver.  If you have older awesfx and drvmidi
+utilities, please get new versions and install them again.
+
+- The SFX file after v0.1.5 is no more compatible from 0.1.4x.
+Please remake the obsolete SFX files again by txt2sfx utility.
+
+
+* USING THE DRIVER
+
+To load SoundFont files, sfxload utility is required.
+All AWE32 driver and utilities can be downloaded from:
+	http://bahamut.mm.t.u-tokyo.ac.jp/~iwai/awedrv/
+
+Follow the instruction in awesfx package to make patched GM and
+GS presets.  Then, load the SFX file on driver by sfxload utility.
+
+	% sfxload -i gm.sfx
+
+Now you can hear midi musics by supported midi players
+(awemidi-0.1.x.tar.gz or patch file to playmidi-2.3).
+
+	% drvmidi foo.mid
+
+Enjoy.
+
+
+* ACKNOWLEDGMENTS
+
+Thanks to Witold Jachimczyk (witek@xfactor.wpi.edu) for many advices
+to programming of AWE32.  Many codes are brought from his AWE32-native 
+MOD player, ALMP.
+The port of awedrv0.1.6 to FreeBSD is done by Randall Hopper
+(rhh@ct.picker.com).
+I also thank linux-awe-ml members for their efforts
+to reboot their system many times :-)
+
+
+* BUGS & TODO'S
+
+- Some instruments are inaudible, eg. glockenspiel and sinewaves.
+- No stereo sample can be used.
+- More smart patch management
+- More smart DRAM memory control
+- Dynamic buffer allocation
+- etc, etc, etc.
+
+
+Takashi Iwai <iwai@dragon.mm.t.u-tokyo.ac.jp>
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/lowlevel/aci.c linux/drivers/sound/lowlevel/aci.c
--- v2.1.5/linux/drivers/sound/lowlevel/aci.c	Sat Jul  6 11:31:42 1996
+++ linux/drivers/sound/lowlevel/aci.c	Fri Oct 25 13:06:35 1996
@@ -35,7 +35,7 @@
  * This mixer driver identifies itself to applications as "ACI" in
  * mixer_info.id as retrieved by ioctl(fd, SOUND_MIXER_INFO, &mixer_info).
  *
- * Proprietary mixer features that go beyond the standard USS mixer
+ * Proprietary mixer features that go beyond the standard OSS mixer
  * interface are:
  * 
  * Full duplex solo configuration:
@@ -58,7 +58,9 @@
  *
  */
 
+#include "lowlevel.h"
 #include "../sound_config.h"
+#include "lowlevel.h"
 #ifdef CONFIG_ACI_MIXER
 
 #undef  DEBUG             /* if defined, produce a verbose report via syslog */
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/lowlevel/awe_hw.h linux/drivers/sound/lowlevel/awe_hw.h
--- v2.1.5/linux/drivers/sound/lowlevel/awe_hw.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/sound/lowlevel/awe_hw.h	Fri Oct 25 13:06:35 1996
@@ -0,0 +1,89 @@
+/*================================================================
+ * AWE32 access routines
+ *================================================================*/
+
+#ifndef AWE_HW_H_DEF
+#define AWE_HW_H_DEF
+
+/*
+ * user configuration:
+ * if auto detection can't work properly, define the following values
+ * for your machine.
+ */
+/*#define AWE_DEFAULT_BASE_ADDR	0x620*/	/* base port address */
+/*#define AWE_DEFAULT_MEM_SIZE	512*/	/* kbytes */
+
+
+/*
+ * maximum size of sample table:
+ * if your data overflow, increase the following values.
+ */
+#define AWE_MAX_SAMPLES		400
+#define AWE_MAX_INFOS		900	/* GS presets has 801 infos! */
+
+
+/*
+ * Emu-8000 control registers
+ * name(channel)	reg, port
+ */
+
+#define awe_cmd_idx(reg,ch)	(((reg)<< 5) | (ch))
+
+#define Data0    0x620	/* doubleword r/w */
+#define Data1    0xA20	/* doubleword r/w */
+#define Data2    0xA22	/* word r/w */
+#define Data3    0xE20	/* word r/w */
+#define Pointer  0xE22	/* register pointer r/w */
+
+#define AWE_CPF(ch)	awe_cmd_idx(0,ch), Data0	/* DW: current pitch and fractional address */
+#define AWE_PTRX(ch)	awe_cmd_idx(1,ch), Data0	/* DW: pitch target and reverb send */
+#define AWE_CVCF(ch)	awe_cmd_idx(2,ch), Data0	/* DW: current volume and filter cutoff */
+#define AWE_VTFT(ch)	awe_cmd_idx(3,ch), Data0	/* DW: volume and filter cutoff targets */
+#define AWE_PSST(ch)	awe_cmd_idx(6,ch), Data0	/* DW: pan send and loop start address */
+#define AWE_CSL(ch)	awe_cmd_idx(7,ch), Data0	/* DW: chorus send and loop end address */
+#define AWE_CCCA(ch)	awe_cmd_idx(0,ch), Data1	/* DW: Q, control bits, and current address */
+#define AWE_HWCF4	awe_cmd_idx(1,9),  Data1	/* DW: config dw 4 */
+#define AWE_HWCF5	awe_cmd_idx(1,10), Data1	/* DW: config dw 5 */
+#define AWE_HWCF6	awe_cmd_idx(1,13), Data1	/* DW: config dw 6 */
+#define AWE_SMALR	awe_cmd_idx(1,20), Data1	/* DW: sound memory address for left read */
+#define AWE_SMARR	awe_cmd_idx(1,21), Data1	/* DW:    for right read */
+#define AWE_SMALW	awe_cmd_idx(1,22), Data1	/* DW: sound memory address for left write */
+#define AWE_SMARW	awe_cmd_idx(1,23), Data1	/* DW:    for right write */
+#define AWE_SMLD	awe_cmd_idx(1,26), Data1	/* W: sound memory left data */
+#define AWE_SMRD	awe_cmd_idx(1,26), Data2	/* W:    right data */
+#define AWE_WC		awe_cmd_idx(1,27), Data2	/* W: sample counter */
+#define AWE_WC_Cmd	awe_cmd_idx(1,27)
+#define AWE_WC_Port	Data2
+#define AWE_HWCF1	awe_cmd_idx(1,29), Data1	/* W: config w 1 */
+#define AWE_HWCF2	awe_cmd_idx(1,30), Data1	/* W: config w 2 */
+#define AWE_HWCF3	awe_cmd_idx(1,31), Data1	/* W: config w 3 */
+#define AWE_INIT1(ch)	awe_cmd_idx(2,ch), Data1	/* W: init array 1 */
+#define AWE_INIT2(ch)	awe_cmd_idx(2,ch), Data2	/* W: init array 2 */
+#define AWE_INIT3(ch)	awe_cmd_idx(3,ch), Data1	/* W: init array 3 */
+#define AWE_INIT4(ch)	awe_cmd_idx(3,ch), Data2	/* W: init array 4 */
+#define AWE_ENVVOL(ch)	awe_cmd_idx(4,ch), Data1	/* W: volume envelope delay */
+#define AWE_DCYSUSV(ch)	awe_cmd_idx(5,ch), Data1	/* W: volume envelope sustain and decay */
+#define AWE_ENVVAL(ch)	awe_cmd_idx(6,ch), Data1	/* W: modulation envelope delay */
+#define AWE_DCYSUS(ch)	awe_cmd_idx(7,ch), Data1	/* W: modulation envelope sustain and decay */
+#define AWE_ATKHLDV(ch)	awe_cmd_idx(4,ch), Data2	/* W: volume envelope attack and hold */
+#define AWE_LFO1VAL(ch)	awe_cmd_idx(5,ch), Data2	/* W: LFO#1 Delay */
+#define AWE_ATKHLD(ch)	awe_cmd_idx(6,ch), Data2	/* W: modulation envelope attack and hold */
+#define AWE_LFO2VAL(ch)	awe_cmd_idx(7,ch), Data2	/* W: LFO#2 Delay */
+#define AWE_IP(ch)	awe_cmd_idx(0,ch), Data3	/* W: initial pitch */
+#define AWE_IFATN(ch)	awe_cmd_idx(1,ch), Data3	/* W: initial filter cutoff and attenuation */
+#define AWE_PEFE(ch)	awe_cmd_idx(2,ch), Data3	/* W: pitch and filter envelope heights */
+#define AWE_FMMOD(ch)	awe_cmd_idx(3,ch), Data3	/* W: vibrato and filter modulation freq */
+#define AWE_TREMFRQ(ch)	awe_cmd_idx(4,ch), Data3	/* W: LFO#1 tremolo amount and freq */
+#define AWE_FM2FRQ2(ch)	awe_cmd_idx(5,ch), Data3	/* W: LFO#2 vibrato amount and freq */
+
+/*  used during detection (returns ROM version ?)                    */
+#define AWE_U1		0xE0, Data3	  /* (R)(W) used in initialization */
+#define AWE_U2(ch)	0xC0+(ch), Data3  /* (W)(W) used in init envelope  */
+
+
+#define AWE_MAX_VOICES		32
+#define AWE_NORMAL_VOICES	30	/*30&31 are reserved for DRAM refresh*/
+
+#define AWE_DRAM_OFFSET		0x200000
+
+#endif
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/lowlevel/awe_voice.h linux/drivers/sound/lowlevel/awe_voice.h
--- v2.1.5/linux/drivers/sound/lowlevel/awe_voice.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/sound/lowlevel/awe_voice.h	Fri Oct 25 13:06:35 1996
@@ -0,0 +1,242 @@
+#ifndef AWE_VOICE_H
+#define AWE_VOICE_H
+/*================================================================
+ * awe_voice.h -- voice information for AWE32 wave table synth
+ *	ver.0.2.0; Oct. 16, 1996
+ *	copyright (c) 1996  by Takashi Iwai
+ *================================================================*/
+
+#ifndef SAMPLE_TYPE_AWE32
+#define SAMPLE_TYPE_AWE32	0x20
+#endif
+
+#ifndef _PATCHKEY
+#define _PATCHKEY(id) ((id<<8)|0xfd)
+#endif
+
+/*----------------------------------------------------------------
+ * patch information record
+ *----------------------------------------------------------------*/
+
+/* patch interface header: 16 bytes */
+typedef struct awe_patch_info {
+	short key;			/* use AWE_PATCH here */
+#define AWE_PATCH	_PATCHKEY(0x07)
+
+	short device_no;		/* synthesizer number */
+	unsigned short sf_id;		/* file id (should be zero) */
+	short sf_version;		/* patch version (not referred) */
+	long len;			/* data length (without this header) */
+
+	short type;			/* following data type */
+#define AWE_LOAD_INFO		0
+#define AWE_LOAD_DATA		1
+
+	short reserved;			/* word alignment data */
+	char data[0];			/* patch data follows here */
+} awe_patch_info;
+
+
+/*----------------------------------------------------------------
+ * raw voice information record
+ *----------------------------------------------------------------*/
+
+/* wave table envelope & effect parameters to control EMU8000 */
+typedef struct _awe_voice_parm {
+	unsigned short moddelay;	/* modulation delay (0x8000) */
+	unsigned short modatkhld;	/* modulation attack & hold time (0x7f7f) */
+	unsigned short moddcysus;	/* modulation decay & sustain (0x7f7f) */
+	unsigned short modrelease;	/* modulation release time (0x807f) */
+	short modkeyhold, modkeydecay;	/* envelope change per key (not used) */
+	unsigned short voldelay;	/* volume delay (0x8000) */
+	unsigned short volatkhld;	/* volume attack & hold time (0x7f7f) */
+	unsigned short voldcysus;	/* volume decay & sustain (0x7f7f) */
+	unsigned short volrelease;	/* volume release time (0x807f) */
+	short volkeyhold, volkeydecay;	/* envelope change per key (not used) */
+	unsigned short lfo1delay;	/* LFO1 delay (0x8000) */
+	unsigned short lfo2delay;	/* LFO2 delay (0x8000) */
+	unsigned short pefe;		/* modulation pitch & cutoff (0x0000) */
+	unsigned short fmmod;		/* LFO1 pitch & cutoff (0x0000) */
+	unsigned short tremfrq;		/* LFO1 volume & freq (0x0000) */
+	unsigned short fm2frq2;		/* LFO2 pitch & freq (0x0000) */
+	unsigned char cutoff;		/* initial cutoff (0xff) */
+	unsigned char filterQ;		/* initial filter Q [0-15] (0x0) */
+	unsigned char chorus;		/* chorus send (0x00) */
+	unsigned char reverb;		/* reverb send (0x00) */
+	unsigned short reserved[4];	/* not used */
+} awe_voice_parm;
+
+/* wave table parameters: 92 bytes */
+typedef struct _awe_voice_info {
+	unsigned short sf_id;		/* file id (should be zero) */
+	unsigned short sample;		/* sample id */
+	long start, end;		/* sample offset correction */
+	long loopstart, loopend;	/* loop offset correction */
+	short rate_offset;		/* sample rate pitch offset */
+	unsigned short mode;		/* sample mode */
+#define AWE_MODE_ROMSOUND		0x8000
+#define AWE_MODE_STEREO			1
+#define AWE_MODE_LOOPING		2
+#define AWE_MODE_NORELEASE		4	/* obsolete */
+#define AWE_MODE_INIT_PARM		8
+
+	short root;			/* midi root key */
+	short tune;			/* pitch tuning (in cents) */
+	char low, high;			/* key note range */
+	char vellow, velhigh;		/* velocity range */
+	char fixkey, fixvel;		/* fixed key, velocity */
+	char pan, fixpan;		/* panning, fixed panning */
+	short exclusiveClass;		/* exclusive class (0 = none) */
+	unsigned char amplitude;	/* sample volume (127 max) */
+	unsigned char attenuation;	/* attenuation (0.375dB) */
+	short scaleTuning;		/* pitch scale tuning(%), normally 100 */
+	awe_voice_parm parm;		/* voice envelope parameters */
+	short index;			/* internal index (set by driver) */
+} awe_voice_info;
+
+/* instrument info header: 4 bytes */
+typedef struct _awe_voice_rec {
+	unsigned char bank;		/* midi bank number */
+	unsigned char instr;		/* midi preset number */
+	short nvoices;			/* number of voices */
+	awe_voice_info info[0];		/* voice information follows here */
+} awe_voice_rec;
+
+
+/*----------------------------------------------------------------
+ * sample wave information
+ *----------------------------------------------------------------*/
+
+/* wave table sample header: 32 bytes */
+typedef struct awe_sample_info {
+	unsigned short sf_id;		/* file id (should be zero) */
+	unsigned short sample;		/* sample id */
+	long start, end;		/* start & end offset */
+	long loopstart, loopend;	/* loop start & end offset */
+	long size;			/* size (0 = ROM) */
+	short checksum_flag;		/* use check sum = 1 */
+	unsigned short mode_flags;	/* mode flags */
+#define AWE_SAMPLE_8BITS	1	/* wave data is 8bits */
+#define AWE_SAMPLE_UNSIGNED	2	/* wave data is unsigned */
+#define AWE_SAMPLE_NO_BLANK	4	/* no blank loop is attached */
+#define AWE_SAMPLE_SINGLESHOT	8	/* single-shot w/o loop */
+#define AWE_SAMPLE_BIDIR_LOOP	16	/* bidirectional looping */
+#define AWE_SAMPLE_STEREO_LEFT	32	/* stereo left sound */
+#define AWE_SAMPLE_STEREO_RIGHT	64	/* stereo right sound */
+	unsigned long checksum;		/* check sum */
+	unsigned short data[0];		/* sample data follows here */
+} awe_sample_info;
+
+
+/*----------------------------------------------------------------
+ * awe hardware controls
+ *----------------------------------------------------------------*/
+
+#define _AWE_DEBUG_MODE			0x00
+#define _AWE_REVERB_MODE		0x01
+#define _AWE_CHORUS_MODE		0x02
+#define _AWE_REMOVE_LAST_SAMPLES	0x03
+#define _AWE_INITIALIZE_CHIP		0x04
+#define _AWE_SEND_EFFECT		0x05
+#define _AWE_TERMINATE_CHANNEL		0x06
+#define _AWE_TERMINATE_ALL		0x07
+#define _AWE_INITIAL_VOLUME		0x08
+#define _AWE_SET_GUS_BANK		0x09
+
+#define _AWE_MODE_FLAG			0x80
+#define _AWE_COOKED_FLAG		0x40	/* not supported */
+#define _AWE_MODE_VALUE_MASK		0x3F
+
+#define _AWE_CMD(chn, voice, cmd, p1, p2) \
+{_SEQ_NEEDBUF(8); _seqbuf[_seqbufptr] = SEQ_PRIVATE;\
+ _seqbuf[_seqbufptr+1] = chn;\
+ _seqbuf[_seqbufptr+2] = _AWE_MODE_FLAG|(cmd);\
+ _seqbuf[_seqbufptr+3] = voice;\
+ *(unsigned short*)&_seqbuf[_seqbufptr+4] = p1;\
+ *(unsigned short*)&_seqbuf[_seqbufptr+6] = p2;\
+ _SEQ_ADVBUF(8);}
+
+#define AWE_DEBUG_MODE(dev,p1)	_AWE_CMD(dev, 0, _AWE_DEBUG_MODE, p1, 0)
+#define AWE_REVERB_MODE(dev,p1)	_AWE_CMD(dev, 0, _AWE_REVERB_MODE, p1, 0)
+#define AWE_CHORUS_MODE(dev,p1)	_AWE_CMD(dev, 0, _AWE_CHORUS_MODE, p1, 0)
+#define AWE_REMOVE_LAST_SAMPLES(dev) _AWE_CMD(dev, 0, _AWE_REMOVE_LAST_SAMPLES, 0, 0)
+#define AWE_INITIALIZE_CHIP(dev) _AWE_CMD(dev, 0, _AWE_INITIALIZE_CHIP, 0, 0)
+#define AWE_SEND_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,type,value)
+#define AWE_TERMINATE_CHANNEL(dev,voice) _AWE_CMD(dev,voice,_AWE_TERMINATE_CHANNEL,0,0)
+#define AWE_TERMINATE_ALL(dev) _AWE_CMD(dev, 0, _AWE_TERMINATE_ALL, 0, 0)
+#define AWE_INITIAL_VOLUME(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 0)
+#define AWE_SET_GUS_BANK(dev,bank) _AWE_CMD(dev, 0, _AWE_SET_GUS_BANK, bank, 0)
+
+/* reverb mode */
+#define	AWE_REVERB_ROOM1	0
+#define AWE_REVERB_ROOM2	1
+#define	AWE_REVERB_ROOM3	2
+#define	AWE_REVERB_HALL1	3
+#define	AWE_REVERB_HALL2	4
+#define	AWE_REVERB_PLATE	5
+#define	AWE_REVERB_DELAY	6
+#define	AWE_REVERB_PANNINGDELAY 7
+
+/* chorus mode */
+#define AWE_CHORUS_1		0
+#define	AWE_CHORUS_2		1
+#define	AWE_CHORUS_3		2
+#define	AWE_CHORUS_4		3
+#define	AWE_CHORUS_FEEDBACK	4
+#define	AWE_CHORUS_FLANGER	5
+#define	AWE_CHORUS_SHORTDELAY	6
+#define	AWE_CHORUS_SHORTDELAY2	7
+
+/* effects */
+enum {
+
+/* modulation envelope parameters */
+/* 0*/	AWE_FX_ENV1_DELAY,	/* WORD: ENVVAL */
+/* 1*/	AWE_FX_ENV1_ATTACK,	/* BYTE: up ATKHLD */
+/* 2*/	AWE_FX_ENV1_HOLD,	/* BYTE: lw ATKHLD */
+/* 3*/	AWE_FX_ENV1_DECAY,	/* BYTE: lw DCYSUS */
+/* 4*/	AWE_FX_ENV1_RELEASE,	/* BYTE: lw DCYSUS */
+/* 5*/	AWE_FX_ENV1_SUSTAIN,	/* BYTE: up DCYSUS */
+/* 6*/	AWE_FX_ENV1_PITCH,	/* BYTE: up PEFE */
+/* 7*/	AWE_FX_ENV1_CUTOFF,	/* BYTE: lw PEFE */
+
+/* volume envelope parameters */
+/* 8*/	AWE_FX_ENV2_DELAY,	/* WORD: ENVVOL */
+/* 9*/	AWE_FX_ENV2_ATTACK,	/* BYTE: up ATKHLDV */
+/*10*/	AWE_FX_ENV2_HOLD,	/* BYTE: lw ATKHLDV */
+/*11*/	AWE_FX_ENV2_DECAY,	/* BYTE: lw DCYSUSV */
+/*12*/	AWE_FX_ENV2_RELEASE,	/* BYTE: lw DCYSUSV */
+/*13*/	AWE_FX_ENV2_SUSTAIN,	/* BYTE: up DCYSUSV */
+	
+/* LFO1 (tremolo & vibrato) parameters */
+/*14*/	AWE_FX_LFO1_DELAY,	/* WORD: LFO1VAL */
+/*15*/	AWE_FX_LFO1_FREQ,	/* BYTE: lo TREMFRQ */
+/*16*/	AWE_FX_LFO1_VOLUME,	/* BYTE: up TREMFRQ */
+/*17*/	AWE_FX_LFO1_PITCH,	/* BYTE: up FMMOD */
+/*18*/	AWE_FX_LFO1_CUTOFF,	/* BYTE: lo FMMOD */
+
+/* LFO2 (vibrato) parameters */
+/*19*/	AWE_FX_LFO2_DELAY,	/* WORD: LFO2VAL */
+/*20*/	AWE_FX_LFO2_FREQ,	/* BYTE: lo FM2FRQ2 */
+/*21*/	AWE_FX_LFO2_PITCH,	/* BYTE: up FM2FRQ2 */
+
+/* Other overall effect parameters */
+/*22*/	AWE_FX_INIT_PITCH,	/* SHORT: pitch offset */
+/*23*/	AWE_FX_CHORUS,		/* BYTE: chorus effects send (0-255) */
+/*24*/	AWE_FX_REVERB,		/* BYTE: reverb effects send (0-255) */
+/*25*/	AWE_FX_CUTOFF,		/* BYTE: up IFATN */
+/*26*/	AWE_FX_FILTERQ,		/* BYTE: up CCCA */
+
+/* Sample / loop offset changes */
+/*27*/	AWE_FX_SAMPLE_START,	/* SHORT: offset */
+/*28*/	AWE_FX_LOOP_START,	/* SHORT: offset */
+/*29*/	AWE_FX_LOOP_END,	/* SHORT: offset */
+/*30*/	AWE_FX_COARSE_SAMPLE_START,	/* SHORT: upper word offset */
+/*31*/	AWE_FX_COARSE_LOOP_START,	/* SHORT: upper word offset */
+/*32*/	AWE_FX_COARSE_LOOP_END,		/* SHORT: upper word offset */
+
+	AWE_FX_END,
+};
+
+
+#endif /* AWE_VOICE_H */
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/lowlevel/awe_wave.c linux/drivers/sound/lowlevel/awe_wave.c
--- v2.1.5/linux/drivers/sound/lowlevel/awe_wave.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/sound/lowlevel/awe_wave.c	Fri Oct 25 13:06:37 1996
@@ -0,0 +1,3242 @@
+/*================================================================
+ * awe_wave.c -- driver for AWE32 wave table synth
+ *	version 0.2.0; Oct. 16, 1996
+ *	copyright (c) 1996  by Takashi Iwai
+ *================================================================*/
+
+/* if you're using obsolete VoxWare 3.0.x on Linux 1.2.x (or FreeBSD),
+ * uncomment the following line
+ */
+/* #define AWE_OBSOLETE_VOXWARE */
+
+#include "lowlevel.h"
+
+#ifdef AWE_OBSOLETE_VOXWARE
+
+#include "sound_config.h"
+#if !defined(EXCLUDE_AWE32)
+#define CONFIG_AWE32_SYNTH
+#endif
+
+#else /* AWE_OBSOLETE_VOXWARE */
+
+#include "../sound_config.h"
+
+#endif /* AWE_OBSOLETE_VOXWARE */
+
+
+/*----------------------------------------------------------------*
+ * compile condition
+ *----------------------------------------------------------------*/
+
+/* initialize FM passthrough even without extended RAM */
+/*#define AWE_ALWAYS_INIT_FM*/
+
+/* debug on */
+#define AWE_DEBUG_ON
+
+/* verify checksum for uploading samples */
+#define AWE_CHECKSUM_DATA
+#define AWE_CHECKSUM_MEMORY
+
+/* disable interruption during sequencer operation */
+/*#define AWE_NEED_DISABLE_INTR*/
+
+/*----------------------------------------------------------------*/
+
+#ifdef CONFIG_AWE32_SYNTH
+
+#include "awe_hw.h"
+#include "awe_voice.h"
+
+#ifdef AWE_OBSOLETE_VOXWARE
+#include "tuning.h"
+#else
+#include "../tuning.h"
+#endif
+
+#ifdef linux
+#  include <linux/ultrasound.h>
+#elif defined(__FreeBSD__)
+#  include <machine/ultrasound.h>
+#endif
+
+
+/*----------------------------------------------------------------
+ * debug message
+ *----------------------------------------------------------------*/
+
+#ifdef AWE_DEBUG_ON
+static int debug_mode = 0;
+#define DEBUG(LVL,XXX)	{if (debug_mode > LVL) { XXX; }}
+#define ERRMSG(XXX)	{if (debug_mode) { XXX; }}
+#define FATALERR(XXX)	XXX
+#else
+#define DEBUG(LVL,XXX) /**/
+#define ERRMSG(XXX)	XXX
+#define FATALERR(XXX)	XXX
+#endif
+
+/*----------------------------------------------------------------
+ * bank and voice record
+ *----------------------------------------------------------------*/
+
+/* bank record */
+typedef struct _awe_voice_list {
+	unsigned char bank, instr;
+	awe_voice_info v;
+	struct _awe_voice_list *next_instr;
+	struct _awe_voice_list *next_bank;
+} awe_voice_list;
+
+/* sample and information table */
+static awe_sample_info *samples;
+static awe_voice_list *infos;
+
+#define AWE_MAX_PRESETS		256
+#define AWE_DEFAULT_BANK	0
+
+/* preset table index */
+static awe_voice_list *preset_table[AWE_MAX_PRESETS];
+
+/*----------------------------------------------------------------
+ * voice table
+ *----------------------------------------------------------------*/
+
+#define AWE_FX_BYTES	((AWE_FX_END+7)/8)
+
+typedef struct _voice_info {
+	int state;		/* status (on = 1, off = 0) */
+	int note;		/* midi key (0-127) */
+	int velocity;		/* midi velocity (0-127) */
+	int bender;		/* midi pitchbend (-8192 - 8192) */
+	int bender_range;	/* midi bender range (x100) */
+	int panning;		/* panning (0-127) */
+	int main_vol;		/* channel volume (0-127) */
+	int expression_vol;	/* midi expression (0-127) */
+
+	/* EMU8000 parameters */
+	int apitch;		/* pitch parameter */
+	int avol;		/* volume parameter */
+
+	/* instrument parameters */
+	int bank;		/* current tone bank */
+	int instr;		/* current program */
+	awe_voice_list *vrec;
+	awe_voice_info *sample;
+
+	/* channel effects */
+	unsigned char fx_flags[AWE_FX_BYTES];
+	short fx[AWE_FX_END];
+} voice_info;
+
+static voice_info voices[AWE_MAX_VOICES];
+
+
+/*----------------------------------------------------------------
+ * global variables
+ *----------------------------------------------------------------*/
+
+/* awe32 base address (overwritten at initialization) */
+static int awe_base = 0;
+/* memory byte size (overwritten at initialization) */
+static long awe_mem_size = 0;
+
+/* maximum channels for playing */
+static int awe_max_voices = AWE_MAX_VOICES;
+
+static long free_mem_ptr = 0;		/* free word byte size */
+static int free_info = 0;		/* free info tables */
+static int last_info = 0;		/* last loaded info index */
+static int free_sample = 0;		/* free sample tables */
+static int last_sample = 0;		/* last loaded sample index */
+static int loaded_once = 0;		/* samples are loaded after init? */
+static unsigned short current_sf_id = 0;	/* internal id */
+
+static int reverb_mode = 0;		/* reverb mode */
+static int chorus_mode = 0;		/* chorus mode */
+static unsigned short init_atten = 32;  /* 12dB */
+
+static int awe_present = 0;		/* awe device present? */
+static int awe_busy = 0;		/* awe device opened? */
+
+static int awe_gus_bank = AWE_DEFAULT_BANK;	/* GUS default bank number */
+
+
+static struct synth_info awe_info = {
+	"AWE32 Synth",		/* name */
+	0,			/* device */
+	SYNTH_TYPE_SAMPLE,	/* synth_type */
+	SAMPLE_TYPE_AWE32,	/* synth_subtype */
+	0,			/* perc_mode (obsolete) */
+	AWE_MAX_VOICES,		/* nr_voices */
+	0,			/* nr_drums (obsolete) */
+	AWE_MAX_INFOS		/* instr_bank_size */
+};
+
+
+static struct voice_alloc_info *voice_alloc;	/* set at initialization */
+
+
+/*----------------------------------------------------------------
+ * function prototypes
+ *----------------------------------------------------------------*/
+
+#ifndef AWE_OBSOLETE_VOXWARE
+static int awe_check_port(void);
+static void awe_request_region(void);
+static void awe_release_region(void);
+#endif
+
+static void awe_reset_samples(void);
+/* emu8000 chip i/o access */
+static void awe_poke(unsigned short cmd, unsigned short port, unsigned short data);
+static void awe_poke_dw(unsigned short cmd, unsigned short port, unsigned long data);
+static unsigned short awe_peek(unsigned short cmd, unsigned short port);
+static unsigned long awe_peek_dw(unsigned short cmd, unsigned short port);
+static void awe_wait(unsigned short delay);
+
+/* initialize emu8000 chip */
+static void awe_initialize(void);
+
+/* set voice parameters */
+static void awe_init_voice_info(awe_voice_info *vp);
+static void awe_init_voice_parm(awe_voice_parm *pp);
+static int freq_to_note(int freq);
+static int calc_rate_offset(int Hz);
+/*static int calc_parm_delay(int msec);*/
+static int calc_parm_hold(int msec);
+static int calc_parm_attack(int msec);
+static int calc_parm_decay(int msec);
+static int calc_parm_search(int msec, short *table);
+
+/* turn on/off note */
+static void awe_note_on(int voice);
+static void awe_note_off(int voice);
+static void awe_terminate(int voice);
+static void awe_exclusive_off(int voice);
+
+/* calculate voice parameters */
+static void awe_set_pitch(int voice);
+static void awe_set_volume(int voice);
+static void awe_set_pan(int voice, int forced);
+static void awe_fx_fmmod(int voice);
+static void awe_fx_tremfrq(int voice);
+static void awe_fx_fm2frq2(int voice);
+static void awe_fx_cutoff(int voice);
+static void awe_fx_initpitch(int voice);
+static void awe_calc_pitch(int voice);
+static void awe_calc_pitch_from_freq(int voice, int freq);
+static void awe_calc_volume(int voice);
+static void awe_voice_init(int voice, int inst_only);
+
+/* sequencer interface */
+static int awe_open(int dev, int mode);
+static void awe_close(int dev);
+static int awe_ioctl(int dev, unsigned int cmd, caddr_t arg);
+static int awe_kill_note(int dev, int voice, int note, int velocity);
+static int awe_start_note(int dev, int v, int note_num, int volume);
+static int awe_set_instr(int dev, int voice, int instr_no);
+static void awe_reset(int dev);
+static void awe_hw_control(int dev, unsigned char *event);
+static int awe_load_patch(int dev, int format, const char *addr,
+			  int offs, int count, int pmgr_flag);
+static void awe_aftertouch(int dev, int voice, int pressure);
+static void awe_controller(int dev, int voice, int ctrl_num, int value);
+static void awe_panning(int dev, int voice, int value);
+static void awe_volume_method(int dev, int mode);
+static int awe_patchmgr(int dev, struct patmgr_info *rec);
+static void awe_bender(int dev, int voice, int value);
+static int awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc);
+static void awe_setup_voice(int dev, int voice, int chn);
+
+/* hardware controls */
+static void awe_hw_gus_control(int dev, int cmd, unsigned char *event);
+static void awe_hw_awe_control(int dev, int cmd, unsigned char *event);
+
+/* voice search */
+static awe_voice_info *awe_search_voice(int voice, int note);
+static awe_voice_list *awe_search_instr(int bank, int preset);
+
+/* load / remove patches */
+static void awe_check_loaded(void);
+static int awe_load_info(awe_patch_info *patch, const char *addr);
+static int awe_load_data(awe_patch_info *patch, const char *addr);
+static int awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag);
+static int awe_write_wave_data(const char *addr, long offset, int size);
+static awe_voice_list *awe_get_removed_list(awe_voice_list *curp);
+static void awe_remove_samples(void);
+static short awe_set_sample(awe_voice_info *vp);
+
+/* lowlevel functions */
+static void awe_init_audio(void);
+static void awe_init_dma(void);
+static void awe_init_array(void);
+static void awe_send_array(unsigned short *data);
+static void awe_tweak(void);
+static void awe_init_fm(void);
+static int awe_open_dram_for_write(int offset);
+static int awe_open_dram_for_read(int offset);
+static void awe_open_dram_for_check(void);
+static void awe_close_dram(void);
+static void awe_close_dram_for_read(void);
+static void awe_write_dram(unsigned short c);
+static int awe_detect(void);
+static int awe_check_dram(void);
+static void awe_set_chorus_mode(int mode);
+static void awe_set_reverb_mode(int mode);
+
+#ifdef AWE_OBSOLETE_VOXWARE
+
+#define awe_check_port()	0	/* always false */
+#define awe_request_region()	/* nothing */
+#define awe_release_region()	/* nothing */
+
+#else /* AWE_OBSOLETE_VOXWARE */
+
+/* the following macros are osbolete */
+
+#define PERMANENT_MALLOC(type,var,size,memptr) \
+	var = (type)(sound_mem_blocks[sound_nblocks++] = vmalloc(size))
+#define RET_ERROR(err)			-err
+
+#endif /* AWE_OBSOLETE_VOXWARE */
+
+
+#ifdef AWE_NEED_DISABLE_INTR
+#define DECL_INTR_FLAGS(x)	unsigned long x
+#else
+#undef DISABLE_INTR
+#undef RESTORE_INTR
+#define DECL_INTR_FLAGS(x) /**/
+#define DISABLE_INTR(x) /**/
+#define RESTORE_INTR(x) /**/
+#endif
+
+
+/* macros for Linux and FreeBSD compatibility */
+
+#undef OUTW
+#undef COPY_FROM_USER
+#undef GET_BYTE_FROM_USER
+#undef GET_SHORT_FROM_USER
+#undef IOCTL_TO_USER
+  
+#ifdef linux
+#  define NO_DATA_ERR                 ENODATA
+#  define OUTW(data, addr)            outw(data, addr)
+#  define COPY_FROM_USER(target, source, offs, count) \
+              copy_from_user( ((caddr_t)(target)),(source)+(offs),(count) )
+#  define GET_BYTE_FROM_USER(target, addr, offs)      \
+		get_user(target, (unsigned char*)&((addr)[offs]))
+#  define GET_SHORT_FROM_USER(target, addr, offs)     \
+		get_user(target, (unsigned short*)&((addr)[offs]))
+#  define IOCTL_TO_USER(target, offs, source, count)  \
+              copy_to_user  ( ((caddr_t)(target)),(source)+(offs),(count) )
+#  define BZERO(target,len)                           \
+              memset( (caddr_t)target, '\0', len )
+#elif defined(__FreeBSD__)
+#  define NO_DATA_ERR                 EINVAL
+#  define OUTW(data, addr)            outw(addr, data)
+#  define COPY_FROM_USER(target, source, offs, count) \
+              uiomove( ((caddr_t)(target)),(count),((struct uio *)(source)) )
+#  define GET_BYTE_FROM_USER(target, addr, offs)      \
+              uiomove( ((char*)&(target)), 1, ((struct uio *)(addr)) )
+#  define GET_SHORT_FROM_USER(target, addr, offs)     \
+              uiomove( ((char*)&(target)), 2, ((struct uio *)(addr)) )
+#  define IOCTL_TO_USER(target, offs, source, count)  \
+              memcpy( &((target)[offs]), (source), (count) )
+#  define BZERO(target,len)                           \
+              bzero( (caddr_t)target, len )
+#endif
+
+
+/*----------------------------------------------------------------
+ * synth operation table
+ *----------------------------------------------------------------*/
+
+static struct synth_operations awe_operations =
+{
+	&awe_info,
+	0,
+	SYNTH_TYPE_SAMPLE,
+	SAMPLE_TYPE_AWE32,
+	awe_open,
+	awe_close,
+	awe_ioctl,
+	awe_kill_note,
+	awe_start_note,
+	awe_set_instr,
+	awe_reset,
+	awe_hw_control,
+	awe_load_patch,
+	awe_aftertouch,
+	awe_controller,
+	awe_panning,
+	awe_volume_method,
+	awe_patchmgr,
+	awe_bender,
+	awe_alloc,
+	awe_setup_voice
+};
+
+
+
+/*================================================================
+ * attach / unload interface
+ *================================================================*/
+
+#ifdef AWE_OBSOLETE_VOXWARE
+long attach_awe_obsolete(long mem_start, struct address_info *hw_config)
+#else
+int attach_awe(void)
+#endif
+{
+	/* check presence of AWE32 card */
+	if (! awe_detect()) {
+		printk("AWE32: not detected\n");
+		return 0;
+	}
+
+	/* check AWE32 ports are available */
+	if (awe_check_port()) {
+		printk("AWE32: I/O area already used.\n");
+		return 0;
+	}
+
+	/* allocate sample tables */
+	PERMANENT_MALLOC(awe_sample_info *, samples,
+			 AWE_MAX_SAMPLES * sizeof(awe_sample_info), mem_start);
+	PERMANENT_MALLOC(awe_voice_list *, infos,
+			 AWE_MAX_INFOS * sizeof(awe_voice_list), mem_start);
+	if (samples == NULL || infos == NULL) {
+		printk("AWE32: can't allocate sample tables\n");
+		return 0;
+	}
+
+	if (num_synths >= MAX_SYNTH_DEV)
+		printk("AWE32 Error: too many synthesizers\n");
+	else {
+		voice_alloc = &awe_operations.alloc;
+		voice_alloc->max_voice = awe_max_voices;
+		synth_devs[num_synths++] = &awe_operations;
+	}
+
+	/* reserve I/O ports for awedrv */
+	awe_request_region();
+
+	/* clear all samples */
+	awe_reset_samples();
+
+	/* intialize AWE32 hardware */
+	awe_initialize();
+
+	printk("<AWE32 SynthCard (%dk)>\n", (int)awe_mem_size/1024);
+	sprintf(awe_info.name, "AWE32 Synth (%dk)", (int)awe_mem_size/1024);
+
+	/* set reverb & chorus modes */
+	awe_set_reverb_mode(reverb_mode);
+	awe_set_chorus_mode(chorus_mode);
+
+	awe_present = 1;
+
+#ifdef AWE_OBSOLETE_VOXWARE
+	return mem_start;
+#else
+	return 1;
+#endif
+}
+
+
+void unload_awe(void)
+{
+	if (awe_present) {
+		awe_reset_samples();
+		awe_release_region();
+	}
+}
+
+
+#ifdef AWE_OBSOLETE_VOXWARE
+int probe_awe_obsolete(struct address_info *hw_config)
+{
+	return 1;
+	/*return awe_detect();*/
+}
+
+#endif
+
+/*================================================================
+ * clear sample tables 
+ *================================================================*/
+
+static void
+awe_reset_samples(void)
+{
+	int i;
+
+	/* free all bank tables */
+	for (i = 0; i < AWE_MAX_PRESETS; i++) {
+		preset_table[i] = NULL;
+	}
+
+	free_mem_ptr = 0;
+	last_sample = free_sample = 0;
+	last_info = free_info = 0;
+	current_sf_id = 0;
+	loaded_once = 0;
+}
+
+
+/*================================================================
+ * EMU register access
+ *================================================================*/
+
+/* select a given AWE32 pointer */
+#define awe_set_cmd(cmd)	OUTW(cmd, awe_base + 0x802)
+#define awe_port(port)		(awe_base - 0x620 + port)
+
+/* write 16bit data */
+static void
+awe_poke(unsigned short cmd, unsigned short port, unsigned short data)
+{
+	awe_set_cmd(cmd);
+	OUTW(data, awe_port(port));
+}
+
+/* write 32bit data */
+static void
+awe_poke_dw(unsigned short cmd, unsigned short port, unsigned long data)
+{
+	awe_set_cmd(cmd);
+	OUTW(data, awe_port(port));		/* write lower 16 bits */
+	OUTW(data >> 16, awe_port(port)+2);	/* write higher 16 bits */
+}
+
+/* read 16bit data */
+static unsigned short
+awe_peek(unsigned short cmd, unsigned short port)
+{
+	unsigned short k;
+	awe_set_cmd(cmd);
+	k = inw(awe_port(port));
+	return k;
+}
+
+/* read 32bit data */
+static unsigned long
+awe_peek_dw(unsigned short cmd, unsigned short port)
+{
+	unsigned long k1, k2;
+	awe_set_cmd(cmd);
+	k1 = inw(awe_port(port));
+	k2 = inw(awe_port(port)+2);
+	k1 |= k2 << 16;
+	return k1;
+}
+
+/* wait delay number of AWE32 44100Hz clocks */
+static void
+awe_wait(unsigned short delay)
+{
+	unsigned short clock, target;
+	unsigned short port = awe_port(AWE_WC_Port);
+	int counter;
+  
+	/* sample counter */
+	awe_set_cmd(AWE_WC_Cmd);
+	clock = (unsigned short)inw(port);
+	target = clock + delay;
+	counter = 0;
+	if (target < clock) {
+		for (; (unsigned short)inw(port) > target; counter++)
+			if (counter > 65536)
+				break;
+	}
+	for (; (unsigned short)inw(port) < target; counter++)
+		if (counter > 65536)
+			break;
+}
+
+
+#ifndef AWE_OBSOLETE_VOXWARE
+
+/*================================================================
+ * port check / request
+ *  0x620-622, 0xA20-A22, 0xE20-E22
+ *================================================================*/
+
+static int
+awe_check_port(void)
+{
+	return (check_region(awe_port(Data0), 3) ||
+		check_region(awe_port(Data1), 3) ||
+		check_region(awe_port(Data3), 3));
+}
+
+static void
+awe_request_region(void)
+{
+	request_region(awe_port(Data0), 3, "sound driver (AWE32)");
+	request_region(awe_port(Data1), 3, "sound driver (AWE32)");
+	request_region(awe_port(Data3), 3, "sound driver (AWE32)");
+}
+
+static void
+awe_release_region(void)
+{
+	release_region(awe_port(Data0), 3);
+	release_region(awe_port(Data1), 3);
+	release_region(awe_port(Data3), 3);
+}
+
+#endif /* !AWE_OBSOLETE_VOXWARE */
+
+
+/*================================================================
+ * AWE32 initialization
+ *================================================================*/
+static void
+awe_initialize(void)
+{
+	unsigned short data;
+	DECL_INTR_FLAGS(flags);
+
+	DEBUG(0,printk("AWE32: initializing..\n"));
+	DISABLE_INTR(flags);
+
+	/* check for an error condition */
+	data = awe_peek(AWE_U1);
+	if (!(data & 0x000F) == 0x000C) {
+		FATALERR(printk("AWE32: can't initialize AWE32\n"));
+	}
+
+	/* initialize hardware configuration */
+	awe_poke(AWE_HWCF1, 0x0059);
+	awe_poke(AWE_HWCF2, 0x0020);
+
+	/* disable audio output */
+	awe_poke(AWE_HWCF3, 0x0000);
+
+	/* initialize audio channels */
+	awe_init_audio();
+
+	/* initialize init array */
+	awe_init_dma();
+	awe_init_array();
+
+	/* check DRAM memory size */
+	awe_mem_size = awe_check_dram();
+
+	/* initialize the FM section of the AWE32 */
+	awe_init_fm();
+
+	/* set up voice envelopes */
+	awe_tweak();
+
+	/* enable audio */
+	awe_poke(AWE_HWCF3, 0x0004);
+
+	data = awe_peek(AWE_HWCF2);
+	if (~data & 0x40) {
+		FATALERR(printk("AWE32: Unable to initialize AWE32.\n"));
+	}
+
+	RESTORE_INTR(flags);
+}
+
+
+/*================================================================
+ * AWE32 voice parameters
+ *================================================================*/
+
+/* initialize voice_info record */
+static void
+awe_init_voice_info(awe_voice_info *vp)
+{
+	vp->sf_id = 0;
+	vp->sample = 0;
+	vp->rate_offset = 0;
+
+	vp->start = 0;
+	vp->end = 0;
+	vp->loopstart = 0;
+	vp->loopend = 0;
+	vp->mode = 0;
+	vp->root = 60;
+	vp->tune = 0;
+	vp->low = 0;
+	vp->high = 127;
+	vp->vellow = 0;
+	vp->velhigh = 127;
+
+	vp->fixkey = -1;
+	vp->fixvel = -1;
+	vp->fixpan = -1;
+	vp->pan = -1;
+
+	vp->exclusiveClass = 0;
+	vp->amplitude = 127;
+	vp->attenuation = 0;
+	vp->scaleTuning = 100;
+
+	awe_init_voice_parm(&vp->parm);
+}
+
+/* initialize voice_parm record:
+ * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0.
+ * Vibrato and Tremolo effects are zero.
+ * Cutoff is maximum.
+ * Chorus and Reverb effects are zero.
+ */
+static void
+awe_init_voice_parm(awe_voice_parm *pp)
+{
+	pp->moddelay = 0x8000;
+	pp->modatkhld = 0x7f7f;
+	pp->moddcysus = 0x7f7f;
+	pp->modrelease = 0x807f;
+	pp->modkeyhold = 0;
+	pp->modkeydecay = 0;
+
+	pp->voldelay = 0x8000;
+	pp->volatkhld = 0x7f7f;
+	pp->voldcysus = 0x7f7f;
+	pp->volrelease = 0x807f;
+	pp->volkeyhold = 0;
+	pp->volkeydecay = 0;
+
+	pp->lfo1delay = 0x8000;
+	pp->lfo2delay = 0x8000;
+	pp->pefe = 0;
+
+	pp->fmmod = 0;
+	pp->tremfrq = 0;
+	pp->fm2frq2 = 0;
+
+	pp->cutoff = 0xff;
+	pp->filterQ = 0;
+
+	pp->chorus = 0;
+	pp->reverb = 0;
+}	
+
+
+/* convert frequency mHz to abstract cents (= midi key * 100) */
+static int
+freq_to_note(int mHz)
+{
+	/* abscents = log(mHz/8176) / log(2) * 1200 */
+	unsigned long max_val = (unsigned long)0xffffffff / 10000;
+	int i, times;
+	unsigned long base;
+	unsigned long freq;
+	int note, tune;
+
+	if (mHz == 0)
+		return 0;
+	if (mHz < 0)
+		return 12799; /* maximum */
+
+	freq = mHz;
+	note = 0;
+	for (base = 8176 * 2; freq >= base; base *= 2) {
+		note += 12;
+		if (note >= 128) /* over maximum */
+			return 12799;
+	}
+	base /= 2;
+
+	/* to avoid overflow... */
+	times = 10000;
+	while (freq > max_val) {
+		max_val *= 10;
+		times /= 10;
+		base /= 10;
+	}
+
+	freq = freq * times / base;
+	for (i = 0; i < 12; i++) {
+		if (freq < semitone_tuning[i+1])
+			break;
+		note++;
+	}
+
+	tune = 0;
+	freq = freq * 10000 / semitone_tuning[i];
+	for (i = 0; i < 100; i++) {
+		if (freq < cent_tuning[i+1])
+			break;
+		tune++;
+	}
+
+	return note * 100 + tune;
+}
+
+
+/* convert Hz to AWE32 rate offset:
+ * sample pitch offset for the specified sample rate
+ * rate=44100 is no offset, each 4096 is 1 octave (twice).
+ * eg, when rate is 22050, this offset becomes -4096.
+ */
+static int
+calc_rate_offset(int Hz)
+{
+	/* offset = log(Hz / 44100) / log(2) * 4096 */
+	int freq, base, i;
+
+	/* maybe smaller than max (44100Hz) */
+	if (Hz <= 0 || Hz >= 44100) return 0;
+
+	base = 0;
+	for (freq = Hz * 2; freq < 44100; freq *= 2)
+		base++;
+	base *= 1200;
+
+	freq = 44100 * 10000 / (freq/2);
+	for (i = 0; i < 12; i++) {
+		if (freq < semitone_tuning[i+1])
+			break;
+		base += 100;
+	}
+	freq = freq * 10000 / semitone_tuning[i];
+	for (i = 0; i < 100; i++) {
+		if (freq < cent_tuning[i+1])
+			break;
+		base++;
+	}
+	return -base * 4096 / 1200;
+}
+
+
+/*----------------------------------------------------------------
+ * convert envelope time parameter to AWE32 raw parameter
+ *----------------------------------------------------------------*/
+
+/* attack & decay/release time table (mHz) */
+static short attack_time_tbl[128] = {
+32767, 5939, 3959, 2969, 2375, 1979, 1696, 1484, 1319, 1187, 1079, 989, 913, 848, 791, 742,
+ 698, 659, 625, 593, 565, 539, 516, 494, 475, 456, 439, 424, 409, 395, 383, 371,
+ 359, 344, 330, 316, 302, 290, 277, 266, 255, 244, 233, 224, 214, 205, 196, 188,
+ 180, 173, 165, 158, 152, 145, 139, 133, 127, 122, 117, 112, 107, 103, 98, 94,
+ 90, 86, 83, 79, 76, 73, 69, 67, 64, 61, 58, 56, 54, 51, 49, 47,
+ 45, 43, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 27, 25, 24, 23,
+ 22, 21, 20, 20, 19, 18, 17, 16, 16, 15, 14, 14, 13, 13, 12, 11,
+ 11, 10, 10, 10, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 0,
+};
+
+static short decay_time_tbl[128] = {
+32767, 3651, 3508, 3371, 3239, 3113, 2991, 2874, 2761, 2653, 2550, 2450, 2354, 2262, 2174, 2089,
+ 2007, 1928, 1853, 1781, 1711, 1644, 1580, 1518, 1459, 1401, 1347, 1294, 1243, 1195, 1148, 1103,
+ 1060, 1018, 979, 940, 904, 868, 834, 802, 770, 740, 711, 683, 657, 631, 606, 582,
+ 560, 538, 517, 496, 477, 458, 440, 423, 407, 391, 375, 361, 347, 333, 320, 307,
+ 295, 284, 273, 262, 252, 242, 232, 223, 215, 206, 198, 190, 183, 176, 169, 162,
+ 156, 150, 144, 138, 133, 128, 123, 118, 113, 109, 104, 100, 96, 93, 89, 85,
+ 82, 79, 76, 73, 70, 67, 64, 62, 60, 57, 55, 53, 51, 49, 47, 45,
+ 43, 41, 40, 38, 37, 35, 34, 32, 31, 30, 29, 28, 27, 25, 24, 0,
+};
+
+/*
+static int
+calc_parm_delay(int msec)
+{
+	return (0x8000 - msec * 1000 / 725);
+}
+*/
+
+static int
+calc_parm_hold(int msec)
+{
+	int val = 0x7f - (unsigned char)(msec / 92);
+	if (val < 1) val = 1;
+	if (val > 127) val = 127;
+	return val;
+}
+
+static int
+calc_parm_attack(int msec)
+{
+	return calc_parm_search(msec, attack_time_tbl);
+}
+
+static int
+calc_parm_decay(int msec)
+{
+	return calc_parm_search(msec, decay_time_tbl);
+}
+
+static int
+calc_parm_search(int msec, short *table)
+{
+	int left = 0, right = 127, mid;
+	while (left < right) {
+		mid = (left + right) / 2;
+		if (msec < (int)table[mid])
+			left = mid + 1;
+		else
+			right = mid;
+	}
+	return left;
+}
+
+
+/*================================================================
+ * effects table
+ *================================================================*/
+
+/* set an effect value */
+#define FX_SET(v,type,value) \
+(voices[v].fx_flags[(type)/8] |= (1<<((type)%8)),\
+ voices[v].fx[type] = (value))
+/* check the effect value is set */
+#define FX_ON(v,type)	(voices[v].fx_flags[(type)/8] & (1<<((type)%8)))
+
+#if 0
+#define FX_BYTE(v,type,value)\
+	(FX_ON(v,type) ? (unsigned char)voices[v].fx[type] :\
+	 (unsigned char)(value))
+#define FX_WORD(v,type,value)\
+	(FX_ON(v,type) ? (unsigned short)voices[v].fx[type] :\
+	 (unsigned short)(value))
+
+#else
+
+/* get byte effect value */
+static unsigned char FX_BYTE(int v, int type, unsigned char value)
+{
+	unsigned char tmp;
+	if (FX_ON(v,type))
+		tmp = (unsigned char)voices[v].fx[type];
+	else
+		tmp = value;
+	DEBUG(4,printk("AWE32: [-- byte(%d) = %x]\n", type, tmp));
+	return tmp;
+}
+
+/* get word effect value */
+static unsigned short FX_WORD(int v, int type, unsigned short value)
+{
+	unsigned short tmp;
+	if (FX_ON(v,type))
+		tmp = (unsigned short)voices[v].fx[type];
+	else
+		tmp = value;
+	DEBUG(4,printk("AWE32: [-- word(%d) = %x]\n", type, tmp));
+	return tmp;
+}
+
+#endif
+
+/* get word (upper=type1/lower=type2) effect value */
+static unsigned short FX_COMB(int v, int type1, int type2, unsigned short value)
+{
+	unsigned short tmp;
+	if (FX_ON(v, type1))
+		tmp = (unsigned short)(voices[v].fx[type1]) << 8;
+	else
+		tmp = value & 0xff00;
+	if (FX_ON(v, type2))
+		tmp |= (unsigned short)(voices[v].fx[type2]) & 0xff;
+	else
+		tmp |= value & 0xff;
+	DEBUG(4,printk("AWE32: [-- comb(%d/%d) = %x]\n", type1, type2, tmp));
+	return tmp;
+}
+
+/* address offset */
+static long
+FX_OFFSET(int voice, int lo, int hi)
+{
+	awe_voice_info *vp;
+	long addr;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return 0;
+
+	addr = 0;
+	if (FX_ON(voice, hi)) {
+		addr = (short)voices[voice].fx[hi];
+		addr = addr << 15;
+	}
+	if (FX_ON(voice, lo))
+		addr += (short)voices[voice].fx[lo];
+	if (!(vp->mode & (AWE_SAMPLE_8BITS<<6)))
+		addr /= 2;
+	return addr;
+}
+
+
+typedef void (*fx_affect_func)(int voice);
+static fx_affect_func fx_realtime[] = {
+	/* env1: delay, attack, hold, decay, release, sustain, pitch, cutoff*/
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	/* env2: delay, attack, hold, decay, release, sustain */
+	NULL, NULL, NULL, NULL, NULL, NULL,
+	/* lfo1: delay, freq, volume, pitch, cutoff */
+	NULL, awe_fx_tremfrq, awe_fx_tremfrq, awe_fx_fmmod, awe_fx_fmmod,
+	/* lfo2: delay, freq, pitch */
+	NULL, awe_fx_fm2frq2, awe_fx_fm2frq2,
+	/* global: initpitch, chorus, reverb, cutoff, filterQ */
+	awe_fx_initpitch, NULL, NULL, awe_fx_cutoff, NULL,
+	/* sample: start, loopstart, loopend */
+	NULL, NULL, NULL,
+};
+
+
+/*================================================================
+ * turn on/off sample
+ *================================================================*/
+
+static void
+awe_note_on(int voice)
+{
+	unsigned long temp;
+	long addr;
+	unsigned short tmp2;
+	awe_voice_info *vp;
+
+	/* A voice sample must assigned before calling */
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+
+	/* channel to be silent and idle */
+	awe_poke(AWE_DCYSUSV(voice), 0x0080);
+	awe_poke(AWE_VTFT(voice), 0);
+	awe_poke(AWE_CVCF(voice), 0);
+	awe_poke(AWE_PTRX(voice), 0);
+	awe_poke(AWE_CPF(voice), 0);
+
+	/* modulation & volume envelope */
+	awe_poke(AWE_ENVVAL(voice),
+		 FX_WORD(voice, AWE_FX_ENV1_DELAY, vp->parm.moddelay));
+	awe_poke(AWE_ATKHLD(voice),
+		 FX_COMB(voice, AWE_FX_ENV1_ATTACK, AWE_FX_ENV1_HOLD,
+			 vp->parm.modatkhld));
+	awe_poke(AWE_DCYSUS(voice),
+		 FX_COMB(voice, AWE_FX_ENV1_SUSTAIN, AWE_FX_ENV1_DECAY,
+			  vp->parm.moddcysus));
+	awe_poke(AWE_ENVVOL(voice),
+		 FX_WORD(voice, AWE_FX_ENV2_DELAY, vp->parm.voldelay));
+	awe_poke(AWE_ATKHLDV(voice),
+		 FX_COMB(voice, AWE_FX_ENV2_ATTACK, AWE_FX_ENV2_HOLD,
+			 vp->parm.volatkhld));
+	/* decay/sustain parameter for volume envelope must be set at last */
+
+	/* pitch offset */
+	awe_poke(AWE_IP(voice), voices[voice].apitch);
+	DEBUG(3,printk("AWE32: [-- pitch=%x]\n", voices[voice].apitch));
+
+	/* cutoff and volume */
+	tmp2 = FX_BYTE(voice, AWE_FX_CUTOFF, vp->parm.cutoff);
+	tmp2 = (tmp2 << 8) | voices[voice].avol;
+	awe_poke(AWE_IFATN(voice), tmp2);
+
+	/* modulation envelope heights */
+	awe_poke(AWE_PEFE(voice),
+		 FX_COMB(voice, AWE_FX_ENV1_PITCH, AWE_FX_ENV1_CUTOFF,
+			 vp->parm.pefe));
+
+	/* lfo1/2 delay */
+	awe_poke(AWE_LFO1VAL(voice),
+		 FX_WORD(voice, AWE_FX_LFO1_DELAY, vp->parm.lfo1delay));
+	awe_poke(AWE_LFO2VAL(voice),
+		 FX_WORD(voice, AWE_FX_LFO2_DELAY, vp->parm.lfo2delay));
+
+	/* lfo1 pitch & cutoff shift */
+	awe_poke(AWE_FMMOD(voice),
+		 FX_COMB(voice, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF,
+			 vp->parm.fmmod));
+	/* lfo1 volume & freq */
+	awe_poke(AWE_TREMFRQ(voice),
+		 FX_COMB(voice, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ,
+			 vp->parm.tremfrq));
+	/* lfo2 pitch & freq */
+	awe_poke(AWE_FM2FRQ2(voice),
+		 FX_COMB(voice, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ,
+			 vp->parm.fm2frq2));
+
+	/* pan & loop start */
+	 awe_set_pan(voice, 1);
+
+	/* chorus & loop end (chorus 8bit, MSB) */
+	addr = vp->loopend - 1;
+	addr += FX_OFFSET(voice, AWE_FX_LOOP_END,
+			  AWE_FX_COARSE_LOOP_END);
+	temp = FX_BYTE(voice, AWE_FX_CHORUS, vp->parm.chorus);
+	temp = (temp <<24) | (unsigned long)addr;
+	awe_poke_dw(AWE_CSL(voice), temp);
+
+	/* Q & current address (Q 4bit value, MSB) */
+	addr = vp->start - 1;
+	addr += FX_OFFSET(voice, AWE_FX_SAMPLE_START,
+			  AWE_FX_COARSE_SAMPLE_START);
+	temp = FX_BYTE(voice, AWE_FX_FILTERQ, vp->parm.filterQ);
+	temp = (temp<<28) | (unsigned long)addr;
+	awe_poke_dw(AWE_CCCA(voice), temp);
+
+	/* reset volume */
+	awe_poke_dw(AWE_VTFT(voice), 0x0000FFFF);
+	awe_poke_dw(AWE_CVCF(voice), 0x0000FFFF);
+
+	/* turn on envelope */
+	awe_poke(AWE_DCYSUSV(voice),
+		 FX_COMB(voice, AWE_FX_ENV2_SUSTAIN, AWE_FX_ENV2_DECAY,
+			  vp->parm.voldcysus));
+	/* set chorus */
+	temp = FX_BYTE(voice, AWE_FX_REVERB, vp->parm.reverb);
+	temp = (awe_peek_dw(AWE_PTRX(voice)) & 0xffff0000) | (temp<<8);
+	awe_poke_dw(AWE_PTRX(voice), temp);
+	awe_poke_dw(AWE_CPF(voice), 0x40000000);
+
+	DEBUG(3,printk("AWE32: [-- start=%x loop=%x]\n",
+		       (int)vp->start, (int)vp->loopstart));
+}
+
+/* turn off the voice */
+static void
+awe_note_off(int voice)
+{
+	awe_voice_info *vp;
+	unsigned short tmp;
+	if ((vp = voices[voice].sample) == NULL || !voices[voice].state)
+		return;
+	if (FX_ON(voice, AWE_FX_ENV1_RELEASE))
+		tmp = 0x8000 | voices[voice].fx[AWE_FX_ENV1_RELEASE];
+	else
+		tmp = vp->parm.modrelease;
+	awe_poke(AWE_DCYSUS(voice), tmp);
+	if (FX_ON(voice, AWE_FX_ENV2_RELEASE))
+		tmp = 0x8000 | voices[voice].fx[AWE_FX_ENV2_RELEASE];
+	else
+		tmp = vp->parm.volrelease;
+	awe_poke(AWE_DCYSUSV(voice), tmp);
+}
+
+/* force to terminate the voice (no releasing echo) */
+static void
+awe_terminate(int voice)
+{
+	awe_poke(AWE_DCYSUSV(voice), 0x807F);
+}
+
+
+/* turn off other voices with the same exclusive class (for drums) */
+static void
+awe_exclusive_off(int voice)
+{
+	int i, excls;
+
+	if (voices[voice].sample == NULL) /* no sample */
+		return;
+	excls = voices[voice].sample->exclusiveClass;
+	if (excls == 0)	/* not exclusive */
+		return;
+
+	/* turn off voices with the same class */
+	for (i = 0; i < awe_max_voices; i++) {
+		if (i != voice && voices[voice].state &&
+		    voices[i].sample &&
+		    voices[i].sample->exclusiveClass == excls) {
+			DEBUG(4,printk("AWE32: [exoff(%d)]\n", i));
+			awe_note_off(i);
+			awe_voice_init(i, 1);
+		}
+	}
+}
+
+
+/*================================================================
+ * change the parameters of an audible voice
+ *================================================================*/
+
+/* change pitch */
+static void
+awe_set_pitch(int voice)
+{
+	if (!voices[voice].state) return;
+	awe_poke(AWE_IP(voice), voices[voice].apitch);
+}
+
+/* change volume */
+static void
+awe_set_volume(int voice)
+{
+	awe_voice_info *vp;
+	unsigned short tmp2;
+	if (!voices[voice].state) return;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+	tmp2 = FX_BYTE(voice, AWE_FX_CUTOFF, vp->parm.cutoff);
+	tmp2 = (tmp2 << 8) | voices[voice].avol;
+	awe_poke(AWE_IFATN(voice), tmp2);
+}
+
+/* change pan; this could make a click noise.. */
+static void
+awe_set_pan(int voice, int forced)
+{
+	unsigned long temp;
+	long addr;
+	awe_voice_info *vp;
+
+	if (!voices[voice].state && !forced) return;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+
+	/* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */
+	if (vp->fixpan > 0)	/* 0-127 */
+		temp = 255 - (int)vp->fixpan * 2;
+	else {
+		int pos = 0;
+		if (vp->pan >= 0) /* 0-127 */
+			pos = (int)vp->pan * 2 - 128;
+		pos += voices[voice].panning; /* -128 - 127 */
+		pos = 127 - pos;
+		if (pos < 0)
+			temp = 0;
+		else if (pos > 255)
+			temp = 255;
+		else
+			temp = pos;
+	}
+	addr = vp->loopstart - 1;
+	addr += FX_OFFSET(voice, AWE_FX_LOOP_START,
+			  AWE_FX_COARSE_LOOP_START);
+	temp = (temp<<24) | (unsigned long)addr;
+	awe_poke_dw(AWE_PSST(voice), temp);
+}
+
+/* effects change during playing */
+static void
+awe_fx_fmmod(int voice)
+{
+	awe_voice_info *vp;
+	if (!voices[voice].state) return;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+	awe_poke(AWE_FMMOD(voice),
+		 FX_COMB(voice, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF,
+			 vp->parm.fmmod));
+}
+
+static void
+awe_fx_tremfrq(int voice)
+{
+	awe_voice_info *vp;
+	if (!voices[voice].state) return;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+	awe_poke(AWE_TREMFRQ(voice),
+		 FX_COMB(voice, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ,
+			 vp->parm.tremfrq));
+}
+
+static void
+awe_fx_fm2frq2(int voice)
+{
+	awe_voice_info *vp;
+	if (!voices[voice].state) return;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+	awe_poke(AWE_FM2FRQ2(voice),
+		 FX_COMB(voice, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ,
+			 vp->parm.fm2frq2));
+}
+
+static void
+awe_fx_cutoff(int voice)
+{
+	unsigned short tmp2;
+	awe_voice_info *vp;
+	if (!voices[voice].state) return;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+	tmp2 = FX_BYTE(voice, AWE_FX_CUTOFF, vp->parm.cutoff);
+	tmp2 = (tmp2 << 8) | voices[voice].avol;
+	awe_poke(AWE_IFATN(voice), tmp2);
+}
+
+static void
+awe_fx_initpitch(int voice)
+{
+	if (!voices[voice].state) return;
+	if (FX_ON(voice, AWE_FX_INIT_PITCH)) {
+		DEBUG(3,printk("AWE32: initpitch ok\n"));
+	} else {
+		DEBUG(3,printk("AWE32: BAD initpitch %d\n", AWE_FX_INIT_PITCH));
+	}
+	awe_calc_pitch(voice);
+	awe_poke(AWE_IP(voice), voices[voice].apitch);
+}
+
+
+/*================================================================
+ * calculate pitch offset
+ *----------------------------------------------------------------
+ * 0xE000 is no pitch offset at 44100Hz sample.
+ * Every 4096 is one octave.
+ *================================================================*/
+
+static void
+awe_calc_pitch(int voice)
+{
+	voice_info *vp = &voices[voice];
+	awe_voice_info *ap;
+	int offset;
+
+	/* search voice information */
+	if ((ap = vp->sample) == NULL)
+			return;
+	if (ap->index < 0) {
+		if (awe_set_sample(ap) < 0)
+			return;
+	}
+
+	/* calculate offset */
+	if (ap->fixkey >= 0) {
+		DEBUG(3,printk("AWE32: p-> fixkey(%d) tune(%d)\n", ap->fixkey, ap->tune));
+		offset = (ap->fixkey - ap->root) * 4096 / 12;
+	} else {
+		DEBUG(3,printk("AWE32: p(%d)-> root(%d) tune(%d)\n", vp->note, ap->root, ap->tune));
+		offset = (vp->note - ap->root) * 4096 / 12;
+		DEBUG(4,printk("AWE32: p-> ofs=%d\n", offset));
+	}
+	offset += ap->tune * 4096 / 1200;
+	DEBUG(4,printk("AWE32: p-> tune+ ofs=%d\n", offset));
+	if (vp->bender != 0) {
+		DEBUG(3,printk("AWE32: p-> bend(%d) %d\n", voice, vp->bender));
+		/* (819200: 1 semitone) ==> (4096: 12 semitones) */
+		offset += vp->bender * vp->bender_range / 2400;
+	}
+	offset = (offset * ap->scaleTuning) / 100;
+	DEBUG(4,printk("AWE32: p-> scale* ofs=%d\n", offset));
+
+	/* add initial pitch correction */
+	if (FX_ON(voice, AWE_FX_INIT_PITCH)) {
+		DEBUG(3,printk("AWE32: fx_pitch(%d) %d\n", voice, vp->fx[AWE_FX_INIT_PITCH]));
+		offset += vp->fx[AWE_FX_INIT_PITCH];
+	}
+
+	/* 0xe000: root pitch */
+	vp->apitch = 0xe000 + ap->rate_offset + offset;
+	DEBUG(4,printk("AWE32: p-> sum aofs=%x, rate_ofs=%d\n", vp->apitch, ap->rate_offset));
+	if (vp->apitch > 0xffff)
+		vp->apitch = 0xffff;
+	if (vp->apitch < 0)
+		vp->apitch = 0;
+}
+
+
+static void
+awe_calc_pitch_from_freq(int voice, int freq)
+{
+	voice_info *vp = &voices[voice];
+	awe_voice_info *ap;
+	int offset;
+	int note;
+
+	/* search voice information */
+	if ((ap = vp->sample) == NULL)
+		return;
+	if (ap->index < 0) {
+		if (awe_set_sample(ap) < 0)
+			return;
+	}
+	note = freq_to_note(freq);
+	offset = (note - ap->root * 100 + ap->tune) * 4096 / 1200;
+	offset = (offset * ap->scaleTuning) / 100;
+	if (FX_ON(voice, AWE_FX_INIT_PITCH))
+		offset += vp->fx[AWE_FX_INIT_PITCH];
+	vp->apitch = 0xe000 + ap->rate_offset + offset;
+	if (vp->apitch > 0xffff)
+		vp->apitch = 0xffff;
+	if (vp->apitch < 0)
+		vp->apitch = 0;
+}
+
+/*================================================================
+ * calculate volume attenuation
+ *----------------------------------------------------------------
+ * Voice volume is controlled by volume attenuation parameter.
+ * So volume becomes maximum when avol is 0 (no attenuation), and
+ * minimum when 255 (-96dB or silence).
+ *================================================================*/
+
+static int vol_table[128] = {
+	255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49,
+	47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32,
+	31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22,
+	22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16,
+	15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10,
+	10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6,
+	6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3,
+	2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,
+};
+
+static void
+awe_calc_volume(int voice)
+{
+	voice_info *vp = &voices[voice];
+	awe_voice_info *ap;
+	int vol;
+
+	/* search voice information */
+	if ((ap = vp->sample) == NULL)
+		return;
+
+	ap = vp->sample;
+	if (ap->index < 0) {
+		if (awe_set_sample(ap) < 0)
+			return;
+	}
+	
+	if (vp->velocity < ap->vellow)
+		vp->velocity = ap->vellow;
+	else if (vp->velocity > ap->velhigh)
+		vp->velocity = ap->velhigh;
+
+	/* 0 - 127 */
+	vol = (vp->velocity * vp->main_vol * vp->expression_vol) / (127*127);
+	vol = vol * ap->amplitude / 127;
+	if (vol < 0) vol = 0;
+	if (vol > 127) vol = 127;
+
+	/* calc to attenuation */
+	vol = vol_table[vol];
+	vol = vol + (int)ap->attenuation + init_atten;
+	if (vol > 255) vol = 255;
+
+	vp->avol = vol;
+	DEBUG(3,printk("AWE32: [-- voice(%d) vol=%x]\n", voice, vol));
+}
+
+
+/*================================================================
+ * synth operation routines
+ *================================================================*/
+
+/* initialize the voice */
+static void
+awe_voice_init(int voice, int inst_only)
+{
+	if (! inst_only) {
+		/* clear voice parameters */
+		voices[voice].note = -1;
+		voices[voice].velocity = 0;
+		voices[voice].panning = 0; /* zero center */
+		voices[voice].bender = 0; /* zero tune skew */
+		voices[voice].bender_range = 200; /* sense * 100 */
+		voices[voice].main_vol = 127;
+		voices[voice].expression_vol = 127;
+		voices[voice].bank = AWE_DEFAULT_BANK;
+		voices[voice].instr = -1;
+		voices[voice].vrec = NULL;
+		voices[voice].sample = NULL;
+	}
+
+	/* clear voice mapping */
+	voices[voice].state = 0;
+	voice_alloc->map[voice] = 0;
+
+	/* emu8000 parameters */
+	voices[voice].apitch = 0;
+	voices[voice].avol = 255;
+
+	/* clear effects */
+	BZERO(voices[voice].fx_flags, sizeof(voices[voice].fx_flags));
+}
+
+
+/*----------------------------------------------------------------
+ * device open / close
+ *----------------------------------------------------------------*/
+
+/* open device:
+ *   reset status of all voices, and clear sample position flag
+ */
+static int
+awe_open(int dev, int mode)
+{
+	if (awe_busy)
+		return RET_ERROR(EBUSY);
+
+	awe_busy = 1;
+	awe_reset(dev);
+
+	/* clear sample position flag */
+	loaded_once = 0;
+
+	/* set GUS bank to default */
+	awe_gus_bank = AWE_DEFAULT_BANK;
+	return 0;
+}
+
+
+/* close device:
+ *   reset all voices again (terminate sounds)
+ */
+static void
+awe_close(int dev)
+{
+	awe_reset(dev);
+	awe_busy = 0;
+}
+
+
+/* sequencer I/O control:
+ */
+static int
+awe_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+	switch (cmd) {
+	case SNDCTL_SYNTH_INFO:
+		awe_info.nr_voices = awe_max_voices;
+		IOCTL_TO_USER((char*)arg, 0, &awe_info, sizeof(awe_info));
+		return 0;
+		break;
+
+	case SNDCTL_SEQ_RESETSAMPLES:
+		awe_reset_samples();
+		awe_reset(dev); /* better to reset emu8k chip... */
+		return 0;
+		break;
+
+	case SNDCTL_SEQ_PERCMODE:
+		/* what's this? */
+		return 0;
+		break;
+
+	case SNDCTL_SYNTH_MEMAVL:
+		DEBUG(0,printk("AWE32: [ioctl memavl = %d]\n", (int)free_mem_ptr));
+		return awe_mem_size - free_mem_ptr*2;
+
+	default:
+		ERRMSG(printk("AWE32: unsupported ioctl %d\n", cmd));
+		return RET_ERROR(EINVAL);
+	}
+}
+
+
+/* kill a voice:
+ *   not terminate, just release the voice.
+ */
+static int
+awe_kill_note(int dev, int voice, int note, int velocity)
+{
+	awe_voice_info *vp;
+	DECL_INTR_FLAGS(flags);
+
+	DEBUG(2,printk("AWE32: [off(%d)]\n", voice));
+	if (voice < 0 || voice >= awe_max_voices)
+		      return RET_ERROR(EINVAL);
+	if ((vp = voices[voice].sample) == NULL)
+		return 0;
+       
+	if (!(vp->mode & AWE_MODE_NORELEASE)) {
+		DISABLE_INTR(flags);
+		awe_note_off(voice);
+		RESTORE_INTR(flags);
+	}
+	awe_voice_init(voice, 1);
+	return 0;
+}
+
+
+/* search the note with the specified key range */
+static awe_voice_info *
+awe_search_voice(int voice, int note)
+{
+	awe_voice_list *rec;
+	int maxc;
+
+	for (rec = voices[voice].vrec, maxc = AWE_MAX_INFOS;
+	     rec && maxc; rec = rec->next_instr, maxc--) {
+		if (rec->v.low <= note && note <= rec->v.high)
+			return &rec->v;
+	}
+	return NULL;
+}
+
+/* start a voice:
+ *   if note is 255, identical with aftertouch function.
+ *   Otherwise, start a voice with specified not and volume.
+ */
+static int
+awe_start_note(int dev, int v, int note_num, int volume)
+{
+	DECL_INTR_FLAGS(flags);
+
+	DEBUG(2,printk("AWE32: [on(%d) nt=%d vl=%d]\n", v, note_num, volume));
+	if (v < 0 || v >= awe_max_voices)
+		      return RET_ERROR(EINVAL);
+	/* an instrument must be set before starting a note */
+	if (voices[v].vrec == NULL) {
+		DEBUG(1,printk("AWE32: [-- vrec is null]\n"));
+		return 0;
+	}
+
+	if (note_num == 255) {
+		/* dynamic volume change; sample is already assigned */
+		if (! voices[v].state || voices[v].sample == NULL)
+			return 0;
+		/* calculate volume parameter */
+		voices[v].velocity = volume;
+		awe_calc_volume(v);
+		DISABLE_INTR(flags);
+		awe_set_volume(v);
+		RESTORE_INTR(flags);
+		return 0;
+	}
+	/* assign a sample with the corresponding note */
+	if ((voices[v].sample = awe_search_voice(v, note_num)) == NULL) {
+		DEBUG(1,printk("AWE32: [-- sample is null]\n"));
+		return 0;
+	}
+	/* calculate pitch & volume parameters */
+	voices[v].note = note_num;
+	voices[v].velocity = volume;
+	awe_calc_pitch(v);
+	awe_calc_volume(v);
+
+	DISABLE_INTR(flags);
+	/* turn off other voices (for drums) */
+	awe_exclusive_off(v);
+	/* turn on the voice */
+	awe_note_on(v);
+	voices[v].state = 1;	/* flag up */
+	RESTORE_INTR(flags);
+
+	return 0;
+}
+
+
+/* search instrument from preset table with the specified bank */
+static awe_voice_list *
+awe_search_instr(int bank, int preset)
+{
+	awe_voice_list *p;
+	int maxc;
+
+	for (maxc = AWE_MAX_INFOS, p = preset_table[preset];
+	     p && maxc; p = p->next_bank, maxc--) {
+		if (p->bank == bank)
+			return p;
+	}
+	return NULL;
+}
+
+
+/* assign the instrument to a voice */
+static int
+awe_set_instr(int dev, int voice, int instr_no)
+{
+	awe_voice_list *rec;
+
+	if (voice < 0 || voice >= awe_max_voices)
+		return RET_ERROR(EINVAL);
+
+	if (instr_no < 0 || instr_no >= AWE_MAX_PRESETS)
+		return RET_ERROR(EINVAL);
+
+	if ((rec = awe_search_instr(voices[voice].bank, instr_no)) == NULL) {
+		/* if bank is not defined, use the default bank 0 */
+		if (voices[voice].bank != AWE_DEFAULT_BANK &&
+		    (rec = awe_search_instr(AWE_DEFAULT_BANK, instr_no)) == NULL) {
+			DEBUG(1,printk("AWE32 Warning: can't find instrument %d\n", instr_no));
+			return 0;
+		}
+	}
+
+	voices[voice].instr = instr_no;
+	voices[voice].vrec = rec;
+	voices[voice].sample = NULL;  /* not set yet */
+
+	return 0;
+}
+
+
+/* reset all voices; terminate sounds and initialize parameters */
+static void
+awe_reset(int dev)
+{
+	int i;
+	/* don't turn off voice 31 and 32.  they are used also for FM voices */
+	for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+		awe_terminate(i);
+		awe_voice_init(i, 0);
+	}
+	awe_init_fm();
+	awe_tweak();
+}
+
+
+/* hardware specific control:
+ *   GUS specific and AWE32 specific controls are available.
+ */
+static void
+awe_hw_control(int dev, unsigned char *event)
+{
+	int cmd = event[2];
+	if (cmd & _AWE_MODE_FLAG)
+		awe_hw_awe_control(dev, cmd & _AWE_MODE_VALUE_MASK, event);
+	else
+		awe_hw_gus_control(dev, cmd & _AWE_MODE_VALUE_MASK, event);
+}
+
+/* GUS compatible controls */
+static void
+awe_hw_gus_control(int dev, int cmd, unsigned char *event)
+{
+	int voice;
+	unsigned short p1;
+	short p2;
+	int plong;
+	DECL_INTR_FLAGS(flags);
+
+	voice = event[3];
+	p1 = *(unsigned short *) &event[4];
+	p2 = *(short *) &event[6];
+	plong = *(int*) &event[4];
+
+	switch (cmd) {
+	case _GUS_NUMVOICES:
+		if (p1 >= awe_max_voices)
+			printk("AWE32: num_voices: voices out of range %d\n", p1);
+		break;
+	case _GUS_VOICESAMPLE:
+		if (voice < awe_max_voices)
+			awe_set_instr(dev, voice, p1);
+		break;
+
+	case _GUS_VOICEON:
+		if (voice < awe_max_voices) {
+			DISABLE_INTR(flags);
+			awe_note_on(voice);
+			RESTORE_INTR(flags);
+		}
+		break;
+		
+	case _GUS_VOICEOFF:
+		if (voice < awe_max_voices) {
+			DISABLE_INTR(flags);
+			awe_note_off(voice);
+			RESTORE_INTR(flags);
+		}
+		break;
+		
+	case _GUS_VOICEMODE:
+		/* not supported */
+		break;
+
+	case _GUS_VOICEBALA:
+		/* -128 to 127 */
+		if (voice < awe_max_voices)
+			awe_panning(dev, voice, (short)p1);
+		break;
+
+	case _GUS_VOICEFREQ:
+		if (voice < awe_max_voices)
+			awe_calc_pitch_from_freq(voice, plong);
+		break;
+		
+	case _GUS_VOICEVOL:
+	case _GUS_VOICEVOL2:
+		/* not supported yet */
+		break;
+
+	case _GUS_RAMPRANGE:
+	case _GUS_RAMPRATE:
+	case _GUS_RAMPMODE:
+	case _GUS_RAMPON:
+	case _GUS_RAMPOFF:
+		/* volume ramping not supported */
+		break;
+
+	case _GUS_VOLUME_SCALE:
+		break;
+
+	case _GUS_VOICE_POS:
+		if (voice < awe_max_voices) {
+			FX_SET(voice, AWE_FX_SAMPLE_START, (short)(plong & 0x7fff));
+			FX_SET(voice, AWE_FX_COARSE_SAMPLE_START, (plong >> 15) & 0xffff);
+		}
+		break;
+	}
+}
+
+
+/* AWE32 specific controls */
+static void
+awe_hw_awe_control(int dev, int cmd, unsigned char *event)
+{
+	int voice;
+	unsigned short p1;
+	short p2;
+	int chn;
+
+	chn = event[1];
+	voice = event[3];
+	p1 = *(unsigned short *) &event[4];
+	p2 = *(short *) &event[6];
+	
+
+#ifdef AWE_DEBUG_ON
+	switch (cmd) {
+	case _AWE_DEBUG_MODE:
+		debug_mode = p1;
+		printk("AWE32: debug mode = %d\n", debug_mode);
+		break;
+#endif
+	case _AWE_REVERB_MODE:
+		if (p1 <= 7) {
+			reverb_mode = p1;
+			DEBUG(0,printk("AWE32: reverb mode %d\n", reverb_mode));
+			awe_set_reverb_mode(reverb_mode);
+		}
+		break;
+
+	case _AWE_CHORUS_MODE:
+		if (p1 <= 7) {
+			chorus_mode = p1;
+			DEBUG(0,printk("AWE32: chorus mode %d\n", chorus_mode));
+			awe_set_chorus_mode(chorus_mode);
+		}
+		break;
+		      
+	case _AWE_REMOVE_LAST_SAMPLES:
+		DEBUG(0,printk("AWE32: remove last samples\n"));
+		awe_remove_samples();
+		break;
+
+	case _AWE_INITIALIZE_CHIP:
+		awe_initialize();
+		break;
+
+	case _AWE_SEND_EFFECT:
+		if (voice < awe_max_voices && p1 < AWE_FX_END) {
+			FX_SET(voice, p1, p2);
+			DEBUG(0,printk("AWE32: effects (%d) %d %d\n", voice, p1, voices[voice].fx[p1]));
+			if (fx_realtime[p1]) {
+				DEBUG(0,printk("AWE32: fx_realtime (%d)\n", voice));
+				fx_realtime[p1](voice);
+			}
+		}
+		break;
+
+	case _AWE_TERMINATE_CHANNEL:
+		if (voice < awe_max_voices) {
+			DEBUG(0,printk("AWE32: terminate (%d)\n", voice));
+			awe_terminate(voice);
+			awe_voice_init(voice, 1);
+		}
+		break;
+
+	case _AWE_TERMINATE_ALL:
+		DEBUG(0,printk("AWE32: terminate all\n"));
+		awe_reset(0);
+		break;
+
+	case _AWE_INITIAL_VOLUME:
+		DEBUG(0,printk("AWE32: init attenuation %d\n", p1));
+		init_atten = p1;
+		break;
+
+	case _AWE_SET_GUS_BANK:
+		DEBUG(0,printk("AWE32: set gus bank %d\n", p1));
+		awe_gus_bank = p1;
+		break;
+		
+	default:
+		DEBUG(0,printk("AWE32: hw control cmd=%d voice=%d\n", cmd, voice));
+		break;
+	}
+}
+
+
+/*----------------------------------------------------------------
+ * load a sound patch:
+ *   three types of patches are accepted: AWE, GUS, and SYSEX.
+ *----------------------------------------------------------------*/
+
+static int
+awe_load_patch(int dev, int format, const char *addr,
+	       int offs, int count, int pmgr_flag)
+{
+	awe_patch_info patch;
+	int rc = 0;
+
+	if (format == GUS_PATCH) {
+		return awe_load_guspatch(addr, offs, count, pmgr_flag);
+	} else if (format == SYSEX_PATCH) {
+		/* no system exclusive message supported yet */
+		return 0;
+	} else if (format != AWE_PATCH) {
+		FATALERR(printk("AWE32 Error: Invalid patch format (key) 0x%x\n", format));
+		return RET_ERROR(EINVAL);
+	}
+	
+	if (count < sizeof(awe_patch_info)) {
+		FATALERR(printk("AWE32 Error: Patch header too short\n"));
+		return RET_ERROR(EINVAL);
+	}
+	COPY_FROM_USER(((char*)&patch) + offs, addr, offs, 
+		       sizeof(awe_patch_info) - offs);
+
+	count -= sizeof(awe_patch_info);
+	if (count < patch.len) {
+		FATALERR(printk("AWE32 Warning: Patch record too short (%d<%d)\n",
+		       count, (int)patch.len));
+		patch.len = count;
+	}
+	
+	switch (patch.type) {
+	case AWE_LOAD_INFO:
+		rc = awe_load_info(&patch, addr);
+		break;
+
+	case AWE_LOAD_DATA:
+		rc = awe_load_data(&patch, addr);
+		/*
+		if (!pmgr_flag && rc == 0)
+			pmgr_inform(dev, PM_E_PATCH_LOADED, instr, free_sample, 0, 0);
+		*/
+		break;
+
+	default:
+		FATALERR(printk("AWE32 Error: unknown patch format type %d\n",
+		       patch.type));
+		rc = RET_ERROR(EINVAL);
+	}
+
+	return rc;
+}
+
+
+/* load voice information data */
+static int
+awe_load_info(awe_patch_info *patch, const char *addr)
+{
+	awe_voice_list *rec, *curp;
+	long offset;
+	short i, nvoices;
+	unsigned char bank, instr;
+	int total_size;
+
+	if (patch->len < sizeof(awe_voice_rec)) {
+		FATALERR(printk("AWE32 Error: invalid patch info length\n"));
+		return RET_ERROR(EINVAL);
+	}
+
+	offset = sizeof(awe_patch_info);
+	GET_BYTE_FROM_USER(bank, addr, offset); offset++;
+	GET_BYTE_FROM_USER(instr, addr, offset); offset++;
+	GET_SHORT_FROM_USER(nvoices, addr, offset); offset+=2;
+
+	if (nvoices <= 0 || nvoices >= 100) {
+		FATALERR(printk("AWE32 Error: Illegal voice number %d\n", nvoices));
+		return RET_ERROR(EINVAL);
+	}
+	if (free_info + nvoices > AWE_MAX_INFOS) {
+		ERRMSG(printk("AWE32 Error: Too many voice informations\n"));
+		return RET_ERROR(ENOSPC);
+	}
+
+	total_size = sizeof(awe_voice_rec) + sizeof(awe_voice_info) * nvoices;
+	if (patch->len < total_size) {
+		ERRMSG(printk("AWE32 Error: patch length(%d) is smaller than nvoices(%d)\n",
+		       (int)patch->len, nvoices));
+		return RET_ERROR(EINVAL);
+	}
+
+	curp = awe_search_instr(bank, instr);
+	for (i = 0; i < nvoices; i++) {
+		rec = &infos[free_info + i];
+
+		rec->bank = bank;
+		rec->instr = instr;
+		if (i < nvoices - 1)
+			rec->next_instr = rec + 1;
+		else
+			rec->next_instr = curp;
+		rec->next_bank = NULL;
+
+		/* copy awe_voice_info parameters */
+		COPY_FROM_USER(&rec->v, addr, offset, sizeof(awe_voice_info));
+		offset += sizeof(awe_voice_info);
+		rec->v.sf_id = current_sf_id;
+		if (rec->v.mode & AWE_MODE_INIT_PARM)
+			awe_init_voice_parm(&rec->v.parm);
+		awe_set_sample(&rec->v);
+	}
+
+	/* prepend to top of the list */
+	infos[free_info].next_bank = preset_table[instr];
+	preset_table[instr] = &infos[free_info];
+	free_info += nvoices;
+
+	return 0;
+}
+
+
+/* load wave sample data */
+static int
+awe_load_data(awe_patch_info *patch, const char *addr)
+{
+	long offset;
+	int size;
+	int rc;
+
+	if (free_sample >= AWE_MAX_SAMPLES) {
+		ERRMSG(printk("AWE32 Error: Sample table full\n"));
+		return RET_ERROR(ENOSPC);
+	}
+
+	size = (patch->len - sizeof(awe_sample_info)) / 2;
+	offset = sizeof(awe_patch_info);
+	COPY_FROM_USER(&samples[free_sample], addr, offset,
+		       sizeof(awe_sample_info));
+	offset += sizeof(awe_sample_info);
+	if (size != samples[free_sample].size) {
+		ERRMSG(printk("AWE32 Warning: sample size differed (%d != %d)\n",
+		       (int)samples[free_sample].size, (int)size));
+		samples[free_sample].size = size;
+	}
+	if (samples[free_sample].size > 0)
+		if ((rc = awe_write_wave_data(addr, offset, size)) != 0)
+			return rc;
+
+	awe_check_loaded();
+	samples[free_sample].sf_id = current_sf_id;
+
+	free_sample++;
+	return 0;
+}
+
+/* check the other samples are already loaded */
+static void
+awe_check_loaded(void)
+{
+	if (!loaded_once) {
+		/* it's the first time */
+		last_sample = free_sample;
+		last_info = free_info;
+		current_sf_id++;
+		loaded_once = 1;
+	}
+}
+
+
+#define BLANK_LOOP_START	8
+#define BLANK_LOOP_END		40
+#define BLANK_LOOP_SIZE		48
+
+/* loading onto memory */
+static int 
+awe_write_wave_data(const char *addr, long offset, int size)
+{
+	awe_sample_info *sp = &samples[free_sample];
+	int i, truesize;
+	int rc;
+	unsigned long csum1, csum2;
+	DECL_INTR_FLAGS(flags);
+
+	/* be sure loop points start < end */
+	if (sp->loopstart > sp->loopend) {
+		long tmp = sp->loopstart;
+		sp->loopstart = sp->loopend;
+		sp->loopend = tmp;
+	}
+
+	/* compute true data size to be loaded */
+	truesize = size;
+	if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP)
+		truesize += sp->loopend - sp->loopstart;
+	if (sp->mode_flags & AWE_SAMPLE_NO_BLANK)
+		truesize += BLANK_LOOP_SIZE;
+	if (size > 0 && free_mem_ptr + truesize >= awe_mem_size/2) {
+		ERRMSG(printk("AWE32 Error: Sample memory full\n"));
+		return RET_ERROR(ENOSPC);
+	}
+
+	/* recalculate address offset */
+	sp->end -= sp->start;
+	sp->loopstart -= sp->start;
+	sp->loopend -= sp->start;
+	sp->size = truesize;
+
+	sp->start = free_mem_ptr + AWE_DRAM_OFFSET;
+	sp->end += free_mem_ptr + AWE_DRAM_OFFSET;
+	sp->loopstart += free_mem_ptr + AWE_DRAM_OFFSET;
+	sp->loopend += free_mem_ptr + AWE_DRAM_OFFSET;
+
+	DISABLE_INTR(flags);
+	if ((rc = awe_open_dram_for_write(free_mem_ptr)) != 0) {
+		RESTORE_INTR(flags);
+		return rc;
+	}
+
+	csum1 = 0;
+	for (i = 0; i < size; i++) {
+		unsigned char cc;
+		unsigned short c;
+		if (sp->mode_flags & AWE_SAMPLE_8BITS) {
+			GET_BYTE_FROM_USER(cc, addr, offset); offset++;
+			c = cc << 8; /* convert 8bit -> 16bit */
+		} else {
+			GET_SHORT_FROM_USER(c, addr, offset); offset += 2;
+		}
+		if (sp->mode_flags & AWE_SAMPLE_UNSIGNED)
+			c ^= 0x8000; /* unsigned -> signed */
+		csum1 += c;
+		awe_write_dram(c);
+		if (i == sp->loopend &&
+		    (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP)) {
+			int looplen = sp->loopend - sp->loopstart;
+			/* copy reverse loop */
+			int k;
+			for (k = 0; k < looplen; k++) {
+				if (sp->mode_flags & AWE_SAMPLE_8BITS) {
+					GET_BYTE_FROM_USER(cc, addr, offset-k);
+					c = cc << 8;
+				} else {
+					GET_SHORT_FROM_USER(c, addr, offset-k*2);
+				}
+				if (sp->mode_flags & AWE_SAMPLE_UNSIGNED)
+					c ^= 0x8000;
+				awe_write_dram(c);
+			}
+		}
+	}
+
+	/* if no blank loop is attached in the sample, add it */
+	if (sp->mode_flags & AWE_SAMPLE_NO_BLANK) {
+		for (i = 0; i < BLANK_LOOP_SIZE; i++)
+			awe_write_dram(0);
+		if (sp->mode_flags & AWE_SAMPLE_SINGLESHOT) {
+			sp->loopstart = sp->end + BLANK_LOOP_START;
+			sp->loopend = sp->end + BLANK_LOOP_END;
+		}
+		sp->size += BLANK_LOOP_SIZE;
+	}
+
+	awe_close_dram();
+	RESTORE_INTR(flags);
+	if (sp->checksum_flag) {
+#ifdef AWE_CHECKSUM_DATA
+		if (sp->checksum_flag != 2 && csum1 != sp->checksum) {
+			ERRMSG(printk("AWE32: [%d] checksum mismatch on data %x:%x\n",
+			       free_sample,
+			       (int)samples[free_sample].checksum,
+			       (int)csum1));
+			return RET_ERROR(NO_DATA_ERR);
+		}
+#endif /* AWE_CHECKSUM_DATA */
+#ifdef AWE_CHECKSUM_MEMORY
+		DISABLE_INTR(flags);
+		if (awe_open_dram_for_read(free_mem_ptr) == 0) {
+			csum2 = 0;
+			for (i = 0; i < size; i++) {
+				unsigned short c;
+				c = awe_peek(AWE_SMLD);
+				csum2 += c;
+			}
+			awe_close_dram_for_read();
+			if (csum2 != samples[free_sample].checksum) {
+				RESTORE_INTR(flags);
+				ERRMSG(printk("AWE32: [%d] checksum mismatch on DRAM %x:%x\n",
+					      free_sample,
+					      (int)samples[free_sample].checksum,
+					      (int)csum2));
+				return RET_ERROR(NO_DATA_ERR);
+			}
+		}
+		RESTORE_INTR(flags);
+#endif /* AWE_CHECKSUM_MEMORY */
+	}
+	free_mem_ptr += sp->size;
+
+	/* re-initialize FM passthrough */
+	DISABLE_INTR(flags);
+	awe_init_fm();
+	awe_tweak();
+	RESTORE_INTR(flags);
+
+	return 0;
+}
+
+
+/* calculate GUS envelope time:
+ * is this correct?  i have no idea..
+ */
+static int
+calc_gus_envelope_time(int rate, int start, int end)
+{
+	int r, p, t;
+	r = (3 - ((rate >> 6) & 3)) * 3;
+	p = rate & 0x3f;
+	t = end - start;
+	if (t < 0) t = -t;
+	if (13 > r)
+		t = t << (13 - r);
+	else
+		t = t >> (r - 13);
+	return (t * 10) / (p * 441);
+}
+
+#define calc_gus_sustain(val)  (0x7f - vol_table[(val)/2])
+#define calc_gus_attenuation(val)	vol_table[(val)/2]
+
+/* load GUS patch */
+static int
+awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag)
+{
+	struct patch_info patch;
+	awe_voice_list *rec, *curp;
+	long sizeof_patch;
+	int note;
+	int rc;
+
+	sizeof_patch = (long)&patch.data[0] - (long)&patch; /* header size */
+	if (free_sample >= AWE_MAX_SAMPLES) {
+		ERRMSG(printk("AWE32 Error: Sample table full\n"));
+		return RET_ERROR(ENOSPC);
+	}
+	if (free_info >= AWE_MAX_INFOS) {
+		ERRMSG(printk("AWE32 Error: Too many voice informations\n"));
+		return RET_ERROR(ENOSPC);
+	}
+	if (size < sizeof_patch) {
+		ERRMSG(printk("AWE32 Error: Patch header too short\n"));
+		return RET_ERROR(EINVAL);
+	}
+	COPY_FROM_USER(((char*)&patch) + offs, addr, offs, sizeof_patch - offs);
+	size -= sizeof_patch;
+	if (size < patch.len) {
+		FATALERR(printk("AWE32 Warning: Patch record too short (%d<%d)\n",
+		       size, (int)patch.len));
+		patch.len = size;
+	}
+
+	samples[free_sample].sf_id = 0;
+	samples[free_sample].sample = free_sample;
+	samples[free_sample].start = 0;
+	samples[free_sample].end = patch.len;
+	samples[free_sample].loopstart = patch.loop_start;
+	samples[free_sample].loopend = patch.loop_end;
+	samples[free_sample].size = patch.len;
+
+	/* set up mode flags */
+	samples[free_sample].mode_flags = 0;
+	if (!(patch.mode & WAVE_16_BITS))
+		samples[free_sample].mode_flags |= AWE_SAMPLE_8BITS;
+	if (patch.mode & WAVE_UNSIGNED)
+		samples[free_sample].mode_flags |= AWE_SAMPLE_UNSIGNED;
+	samples[free_sample].mode_flags |= AWE_SAMPLE_NO_BLANK;
+	if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP)))
+		samples[free_sample].mode_flags |= AWE_SAMPLE_SINGLESHOT;
+	if (patch.mode & WAVE_BIDIR_LOOP)
+		samples[free_sample].mode_flags |= AWE_SAMPLE_BIDIR_LOOP;
+
+	DEBUG(0,printk("AWE32: [sample %d mode %x]\n", patch.instr_no,
+		       samples[free_sample].mode_flags));
+	if (patch.mode & WAVE_16_BITS) {
+		/* convert to word offsets */
+		samples[free_sample].size /= 2;
+		samples[free_sample].end /= 2;
+		samples[free_sample].loopstart /= 2;
+		samples[free_sample].loopend /= 2;
+	}
+	samples[free_sample].checksum_flag = 0;
+	samples[free_sample].checksum = 0;
+
+	if ((rc = awe_write_wave_data(addr, sizeof_patch,
+				      samples[free_sample].size)) != 0)
+		return rc;
+
+	awe_check_loaded();
+	samples[free_sample].sf_id = current_sf_id;
+	free_sample++;
+
+	/* set up voice info */
+	rec = &infos[free_info];
+	awe_init_voice_info(&rec->v);
+	rec->v.sf_id = current_sf_id;
+	rec->v.sample = free_sample - 1; /* the last sample */
+	rec->v.rate_offset = calc_rate_offset(patch.base_freq);
+	note = freq_to_note(patch.base_note);
+	rec->v.root = note / 100;
+	rec->v.tune = -(note % 100);
+	rec->v.low = freq_to_note(patch.low_note) / 100;
+	rec->v.high = freq_to_note(patch.high_note) / 100;
+	DEBUG(1,printk("AWE32: [gus base offset=%d, note=%d, range=%d-%d(%d-%d)]\n",
+		       rec->v.rate_offset, note,
+		       rec->v.low, rec->v.high,
+	      patch.low_note, patch.high_note));
+	/* panning position; -128 - 127 => 0-127 */
+	rec->v.pan = (patch.panning + 128) / 2;
+
+	/* detuning is ignored */
+	/* 6points volume envelope */
+	if (patch.mode & WAVE_ENVELOPES) {
+		int attack, hold, decay, release;
+		attack = calc_gus_envelope_time
+			(patch.env_rate[0], 0, patch.env_offset[0]);
+		hold = calc_gus_envelope_time
+			(patch.env_rate[1], patch.env_offset[0],
+			 patch.env_offset[1]);
+		decay = calc_gus_envelope_time
+			(patch.env_rate[2], patch.env_offset[1],
+			 patch.env_offset[2]);
+		release = calc_gus_envelope_time
+			(patch.env_rate[3], patch.env_offset[1],
+			 patch.env_offset[4]);
+		release += calc_gus_envelope_time
+			(patch.env_rate[4], patch.env_offset[3],
+			 patch.env_offset[4]);
+		release += calc_gus_envelope_time
+			(patch.env_rate[5], patch.env_offset[4],
+			 patch.env_offset[5]);
+		rec->v.parm.volatkhld = (calc_parm_attack(attack) << 8) |
+			calc_parm_hold(hold);
+		rec->v.parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) |
+			calc_parm_decay(decay);
+		rec->v.parm.volrelease = 0x8000 | calc_parm_decay(release);
+		DEBUG(2,printk("AWE32: [gusenv atk=%d, hld=%d, dcy=%d, rel=%d]\n", attack, hold, decay, release));
+		rec->v.attenuation = calc_gus_attenuation(patch.env_offset[0]);
+	}
+
+	/* tremolo effect */
+	if (patch.mode & WAVE_TREMOLO) {
+		int rate = (patch.tremolo_rate * 1000 / 38) / 42;
+		rec->v.parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate;
+		DEBUG(2,printk("AWE32: [gusenv tremolo rate=%d, dep=%d, tremfrq=%x]\n",
+			       patch.tremolo_rate, patch.tremolo_depth,
+			       rec->v.parm.tremfrq));
+	}
+	/* vibrato effect */
+	if (patch.mode & WAVE_VIBRATO) {
+		int rate = (patch.vibrato_rate * 1000 / 38) / 42;
+		rec->v.parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate;
+		DEBUG(2,printk("AWE32: [gusenv vibrato rate=%d, dep=%d, tremfrq=%x]\n",
+			       patch.tremolo_rate, patch.tremolo_depth,
+			       rec->v.parm.tremfrq));
+	}
+	
+	/* scale_freq, scale_factor, volume, and fractions not implemented */
+
+	/* set the voice index */
+	awe_set_sample(&rec->v);
+
+	/* prepend to top of the list */
+	curp = awe_search_instr(awe_gus_bank, patch.instr_no);
+	rec->bank = awe_gus_bank;
+	rec->instr = patch.instr_no;
+	rec->next_instr = curp;
+	rec->next_bank = preset_table[rec->instr];
+	preset_table[rec->instr] = rec;
+	free_info++;
+
+	return 0;
+}
+
+
+/* remove samples with current sf_id from instrument list */
+static awe_voice_list *
+awe_get_removed_list(awe_voice_list *curp)
+{
+	awe_voice_list *lastp, **prevp;
+	int maxc;
+	lastp = curp;
+	prevp = &lastp;
+	for (maxc = AWE_MAX_INFOS;
+	     curp && maxc; curp = curp->next_instr, maxc--) {
+		if (curp->v.sf_id == current_sf_id)
+			*prevp = curp->next_instr;
+		else
+			prevp = &curp->next_instr;
+	}
+	return lastp;
+}
+
+
+/* remove last loaded samples */
+static void
+awe_remove_samples(void)
+{
+	awe_voice_list **prevp, *p, *nextp;
+	int maxc;
+	int i;
+
+	if (last_sample == free_sample && last_info == free_info)
+		return;
+
+	/* remove the records from preset table */
+	for (i = 0; i < AWE_MAX_PRESETS; i++) {
+		prevp = &preset_table[i];
+		for (maxc = AWE_MAX_INFOS, p = preset_table[i];
+		     p && maxc; p = nextp, maxc--) {
+			nextp = p->next_bank;
+			p = awe_get_removed_list(p);
+			if (p == NULL)
+				*prevp = nextp;
+			else {
+				*prevp = p;
+				prevp = &p->next_bank;
+			}
+		}
+	}
+
+	for (i = last_sample; i < free_sample; i++)
+		free_mem_ptr -= samples[i].size;
+
+	free_sample = last_sample;
+	free_info = last_info;
+	current_sf_id--;
+	loaded_once = 0;
+}
+
+
+/* search the specified sample */
+static short
+awe_set_sample(awe_voice_info *vp)
+{
+	int i;
+	for (i = 0; i < free_sample; i++) {
+		if (samples[i].sf_id == vp->sf_id &&
+		    samples[i].sample == vp->sample) {
+			/* set the actual sample offsets */
+			vp->start += samples[i].start;
+			vp->end += samples[i].end;
+			vp->loopstart += samples[i].loopstart;
+			vp->loopend += samples[i].loopend;
+			/* copy mode flags */
+			vp->mode |= (samples[i].mode_flags << 6);
+			/* set index */
+			vp->index = i;
+			return i;
+		}
+	}
+	return -1;
+}
+
+
+/* voice pressure change */
+static void
+awe_aftertouch(int dev, int voice, int pressure)
+{
+	DECL_INTR_FLAGS(flags);
+
+	DEBUG(2,printk("AWE32: [after(%d) %d]\n", voice, pressure));
+	if (voice < 0 || voice >= awe_max_voices)
+		return;
+	voices[voice].velocity = pressure;
+	awe_calc_volume(voice);
+	DISABLE_INTR(flags);
+	awe_set_volume(voice);
+	RESTORE_INTR(flags);
+}
+
+
+/* voice control change */
+static void
+awe_controller(int dev, int voice, int ctrl_num, int value)
+{
+	DECL_INTR_FLAGS(flags);
+
+	if (voice < 0 || voice >= awe_max_voices)
+		return;
+
+	switch (ctrl_num) {
+	case CTL_BANK_SELECT:
+		DEBUG(2,printk("AWE32: [bank(%d) %d]\n", voice, value));
+		voices[voice].bank = value;
+		break;
+
+	case CTRL_PITCH_BENDER:
+		DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, value));
+		/* zero centered */
+		voices[voice].bender = value;
+		awe_calc_pitch(voice);
+		DISABLE_INTR(flags);
+		awe_set_pitch(voice);
+		RESTORE_INTR(flags);
+		break;
+
+	case CTRL_PITCH_BENDER_RANGE:
+		DEBUG(2,printk("AWE32: [range(%d) %d]\n", voice, value));
+		/* sense x 100 */
+		voices[voice].bender_range = value;
+		/* no audible pitch change yet.. */
+		break;
+
+	case CTL_EXPRESSION:
+		value /= 128;
+	case CTRL_EXPRESSION:
+		DEBUG(2,printk("AWE32: [expr(%d) %d]\n", voice, value));
+		/* 0 - 127 */
+		voices[voice].expression_vol = value;
+		awe_calc_volume(voice);
+		DISABLE_INTR(flags);
+		awe_set_volume(voice);
+		RESTORE_INTR(flags);
+		break;
+
+	case CTL_PAN:
+		DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, value));
+		/* (0-127) -> signed 8bit */
+		voices[voice].panning = value * 2 - 128;
+		DISABLE_INTR(flags);
+		awe_set_pan(voice, 0);
+		RESTORE_INTR(flags);
+		break;
+
+	case CTL_MAIN_VOLUME:
+		value = (value * 127) / 16383;
+	case CTRL_MAIN_VOLUME:
+		DEBUG(2,printk("AWE32: [mainvol(%d) %d]\n", voice, value));
+		/* 0 - 127 */
+		voices[voice].main_vol = value;
+		awe_calc_volume(voice);
+		DISABLE_INTR(flags);
+		awe_set_volume(voice);
+		RESTORE_INTR(flags);
+		break;
+
+	case CTL_EXT_EFF_DEPTH: /* reverb effects: 0-127 */
+		DEBUG(2,printk("AWE32: [reverb(%d) %d]\n", voice, value));
+		FX_SET(voice, AWE_FX_REVERB, value * 2);
+		break;		
+
+	case CTL_CHORUS_DEPTH: /* chorus effects: 0-127 */
+		DEBUG(2,printk("AWE32: [chorus(%d) %d]\n", voice, value));
+		FX_SET(voice, AWE_FX_CHORUS, value * 2);
+		break;		
+
+
+	default:
+		DEBUG(0,printk("AWE32: [control(%d) ctrl=%d val=%d]\n",
+			   voice, ctrl_num, value));
+		break;
+	}
+}
+
+
+/* voice pan change (value = -128 - 127) */
+static void
+awe_panning(int dev, int voice, int value)
+{
+	DECL_INTR_FLAGS(flags);
+	if (voice >= 0 || voice < awe_max_voices) {
+		voices[voice].panning = value;
+		DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, voices[voice].panning));
+		DISABLE_INTR(flags);
+		awe_set_pan(voice, 0);
+		RESTORE_INTR(flags);
+	}
+}
+
+
+/* volume mode change */
+static void
+awe_volume_method(int dev, int mode)
+{
+	/* not impremented */
+	DEBUG(0,printk("AWE32: [volmethod mode=%d]\n", mode));
+}
+
+
+/* patch manager */
+static int
+awe_patchmgr(int dev, struct patmgr_info *rec)
+{
+	FATALERR(printk("AWE32 Warning: patch manager control not supported\n"));
+	return 0;
+}
+
+
+/* pitch wheel change: 0-16384 */
+static void
+awe_bender(int dev, int voice, int value)
+{
+	DECL_INTR_FLAGS(flags);
+
+	if (voice < 0 || voice >= awe_max_voices)
+		return;
+	/* convert to zero centered value */
+	voices[voice].bender = value - 8192;
+	DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, voices[voice].bender));
+	awe_calc_pitch(voice);
+	DISABLE_INTR(flags);
+	awe_set_pitch(voice);
+	RESTORE_INTR(flags);
+}
+
+
+/* search an empty voice; used by sequencer2 */
+static int
+awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc)
+{
+	int i, p, best = -1, best_time = 0x7fffffff;
+
+	p = alloc->ptr;
+	/* First look for a completely stopped voice */
+
+	for (i = 0; i < alloc->max_voice; i++) {
+		if (alloc->map[p] == 0) {
+			alloc->ptr = p;
+			return p;
+		}
+		if (alloc->alloc_times[p] < best_time) {
+			best = p;
+			best_time = alloc->alloc_times[p];
+		}
+		p = (p + 1) % alloc->max_voice;
+	}
+
+	/* Then look for a releasing voice */
+	for (i = 0; i < alloc->max_voice; i++) {
+		if (alloc->map[p] == 0xffff) {
+			alloc->ptr = p;
+			return p;
+		}
+		p = (p + 1) % alloc->max_voice;
+	}
+
+	if (best >= 0)
+		p = best;
+
+	/* terminate the voice */
+	if (voices[p].state)
+		awe_terminate(p);
+
+	alloc->ptr = p;
+	return p;
+}
+
+
+/* set up voice; used by sequencer2 */
+static void
+awe_setup_voice(int dev, int voice, int chn)
+{
+	struct channel_info *info;
+	if (synth_devs[dev] == NULL ||
+	    (info = &synth_devs[dev]->chn_info[chn]) == NULL)
+		return;
+	if (voice < 0 || voice >= awe_max_voices)
+		return;
+
+	DEBUG(2,printk("AWE32: [setup(%d) ch=%d]\n", voice, chn));
+	voices[voice].expression_vol = info->controllers[CTL_EXPRESSION];
+	voices[voice].main_vol =
+		(info->controllers[CTL_MAIN_VOLUME] * 100) / 128; /* 0 - 127 */
+	voices[voice].panning =
+		info->controllers[CTL_PAN] * 2 - 128; /* signed 8bit */
+	voices[voice].bender = info->bender_value; /* zero center */
+	voices[voice].bank = info->controllers[CTL_BANK_SELECT];
+	awe_set_instr(dev, voice, info->pgm_num);
+}
+
+
+/*================================================================
+ * initialization of AWE32
+ *================================================================*/
+
+/* intiailize audio channels */
+static void
+awe_init_audio(void)
+{
+	int ch;
+
+	/* turn off envelope engines */
+	for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
+		awe_poke(AWE_DCYSUSV(ch), 0x0080);
+	}
+  
+	for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
+		awe_poke(AWE_ENVVOL(ch), 0);
+		awe_poke(AWE_ENVVAL(ch), 0);
+		awe_poke(AWE_DCYSUS(ch), 0);
+		awe_poke(AWE_ATKHLDV(ch), 0);
+		awe_poke(AWE_LFO1VAL(ch), 0);
+		awe_poke(AWE_ATKHLD(ch), 0);
+		awe_poke(AWE_LFO2VAL(ch), 0);
+		awe_poke(AWE_IP(ch), 0);
+		awe_poke(AWE_IFATN(ch), 0);
+		awe_poke(AWE_PEFE(ch), 0);
+		awe_poke(AWE_FMMOD(ch), 0);
+		awe_poke(AWE_TREMFRQ(ch), 0);
+		awe_poke(AWE_FM2FRQ2(ch), 0);
+		awe_poke_dw(AWE_PTRX(ch), 0);
+		awe_poke_dw(AWE_VTFT(ch), 0);
+		awe_poke_dw(AWE_PSST(ch), 0);
+		awe_poke_dw(AWE_CSL(ch), 0);
+		awe_poke_dw(AWE_CCCA(ch), 0);
+	}
+
+	for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
+		awe_poke_dw(AWE_CPF(ch), 0);
+		awe_poke_dw(AWE_CVCF(ch), 0);
+	}
+}
+
+
+/* initialize DMA address */
+static void
+awe_init_dma(void)
+{
+	awe_poke_dw(AWE_SMALR, 0x00000000);
+	awe_poke_dw(AWE_SMARR, 0x00000000);
+	awe_poke_dw(AWE_SMALW, 0x00000000);
+	awe_poke_dw(AWE_SMARW, 0x00000000);
+}
+
+
+/* initialization arrays */
+
+static unsigned short init1[128] = {
+	0x03ff, 0x0030,  0x07ff, 0x0130, 0x0bff, 0x0230,  0x0fff, 0x0330,
+	0x13ff, 0x0430,  0x17ff, 0x0530, 0x1bff, 0x0630,  0x1fff, 0x0730,
+	0x23ff, 0x0830,  0x27ff, 0x0930, 0x2bff, 0x0a30,  0x2fff, 0x0b30,
+	0x33ff, 0x0c30,  0x37ff, 0x0d30, 0x3bff, 0x0e30,  0x3fff, 0x0f30,
+
+	0x43ff, 0x0030,  0x47ff, 0x0130, 0x4bff, 0x0230,  0x4fff, 0x0330,
+	0x53ff, 0x0430,  0x57ff, 0x0530, 0x5bff, 0x0630,  0x5fff, 0x0730,
+	0x63ff, 0x0830,  0x67ff, 0x0930, 0x6bff, 0x0a30,  0x6fff, 0x0b30,
+	0x73ff, 0x0c30,  0x77ff, 0x0d30, 0x7bff, 0x0e30,  0x7fff, 0x0f30,
+
+	0x83ff, 0x0030,  0x87ff, 0x0130, 0x8bff, 0x0230,  0x8fff, 0x0330,
+	0x93ff, 0x0430,  0x97ff, 0x0530, 0x9bff, 0x0630,  0x9fff, 0x0730,
+	0xa3ff, 0x0830,  0xa7ff, 0x0930, 0xabff, 0x0a30,  0xafff, 0x0b30,
+	0xb3ff, 0x0c30,  0xb7ff, 0x0d30, 0xbbff, 0x0e30,  0xbfff, 0x0f30,
+
+	0xc3ff, 0x0030,  0xc7ff, 0x0130, 0xcbff, 0x0230,  0xcfff, 0x0330,
+	0xd3ff, 0x0430,  0xd7ff, 0x0530, 0xdbff, 0x0630,  0xdfff, 0x0730,
+	0xe3ff, 0x0830,  0xe7ff, 0x0930, 0xebff, 0x0a30,  0xefff, 0x0b30,
+	0xf3ff, 0x0c30,  0xf7ff, 0x0d30, 0xfbff, 0x0e30,  0xffff, 0x0f30,
+};
+
+static unsigned short init2[128] = {
+	0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
+	0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
+	0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
+	0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30,
+
+	0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330,
+	0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730,
+	0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30,
+	0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30,
+
+	0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330,
+	0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
+	0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
+	0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
+	0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
+	0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
+	0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
+	0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
+};
+
+static unsigned short init3[128] = {
+	0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
+	0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
+	0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
+	0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224,
+
+	0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254,
+	0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264,
+	0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294,
+	0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3,
+
+	0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287,
+	0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7,
+	0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386,
+	0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55,
+
+	0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308,
+	0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F,
+	0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319,
+	0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
+};
+
+static unsigned short init4[128] = {
+	0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
+	0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
+	0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
+	0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224,
+
+	0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254,
+	0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264,
+	0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294,
+	0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3,
+
+	0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287,
+	0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7,
+	0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386,
+	0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55,
+
+	0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308,
+	0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F,
+	0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319,
+	0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570,
+};
+
+
+/* send initialization arrays to start up */
+static void
+awe_init_array(void)
+{
+	awe_send_array(init1);
+	awe_wait(1024);
+	awe_send_array(init2);
+	awe_send_array(init3);
+	awe_poke_dw(AWE_HWCF4, 0);
+	awe_poke_dw(AWE_HWCF5, 0x83);
+	awe_poke_dw(AWE_HWCF6, 0x8000);
+	awe_send_array(init4);
+}
+
+/* send an initialization array */
+static void
+awe_send_array(unsigned short *data)
+{
+	int i;
+	unsigned short *p;
+
+	p = data;
+	for (i = 0; i < AWE_MAX_VOICES; i++, p++)
+		awe_poke(AWE_INIT1(i), *p);
+	for (i = 0; i < AWE_MAX_VOICES; i++, p++)
+		awe_poke(AWE_INIT2(i), *p);
+	for (i = 0; i < AWE_MAX_VOICES; i++, p++)
+		awe_poke(AWE_INIT3(i), *p);
+	for (i = 0; i < AWE_MAX_VOICES; i++, p++)
+		awe_poke(AWE_INIT4(i), *p);
+}
+
+
+/*
+ * set up awe32 channels to some known state.
+ */
+
+static void
+awe_tweak(void)
+{
+	int i;
+
+	/* Set the envelope engine parameters to the "default" values for
+	   simply playing back unarticulated audio at 44.1kHz.  Set all
+	   of the channels: */
+
+	for (i = 0; i < AWE_MAX_VOICES; i++) {
+		awe_poke(AWE_ENVVOL(i)   , 0x8000);
+		awe_poke(AWE_ENVVAL(i)   , 0x8000);
+		awe_poke(AWE_DCYSUS(i)   , 0x7F7F);
+		awe_poke(AWE_ATKHLDV(i)  , 0x7F7F);
+		awe_poke(AWE_LFO1VAL(i)  , 0x8000);
+		awe_poke(AWE_ATKHLD(i)   , 0x7F7F);
+		awe_poke(AWE_LFO2VAL(i)  , 0x8000);
+		awe_poke(AWE_IP(i)       , 0xE000);
+		awe_poke(AWE_IFATN(i)    , 0xFF00);
+		awe_poke(AWE_PEFE(i)     , 0x0000);
+		awe_poke(AWE_FMMOD(i)    , 0x0000);
+		awe_poke(AWE_TREMFRQ(i)  , 0x0010);
+		awe_poke(AWE_FM2FRQ2(i)  , 0x0010);
+	}
+}
+
+
+/*
+ *  initializes the FM section of AWE32
+ */
+
+static void
+awe_init_fm(void)
+{
+#ifndef AWE_ALWAYS_INIT_FM
+	/* if no extended memory is on board.. */
+	if (awe_mem_size <= 0)
+		return;
+#endif
+	DEBUG(0,printk("AWE32: initializing FM\n"));
+
+	/* Initialize the last two channels for DRAM refresh and producing
+	   the reverb and chorus effects for Yamaha OPL-3 synthesizer */
+
+	awe_poke(   AWE_DCYSUSV(30)   , 0x0080);
+	awe_poke_dw(AWE_PSST(30)      , 0xFFFFFFE0);
+	awe_poke_dw(AWE_CSL(30)       , 0xFFFFFFE8);
+	awe_poke_dw(AWE_PTRX(30)      , 0x00FFFF00);
+	awe_poke_dw(AWE_CPF(30)       , 0x00000000);
+	awe_poke_dw(AWE_CCCA(30)      , 0x00FFFFE3);
+
+	awe_poke(   AWE_DCYSUSV(31)   , 0x0080);
+	awe_poke_dw(AWE_PSST(31)      , 0x00FFFFE0);
+	awe_poke_dw(AWE_CSL(31)       , 0xFFFFFFE8);
+	awe_poke_dw(AWE_PTRX(31)      , 0x00FFFF00);
+	awe_poke_dw(AWE_CPF(31)       , 0x00000000);
+	awe_poke_dw(AWE_CCCA(31)      , 0x00FFFFE3);
+
+	/* Timing loop */
+
+	/* PTRX is 32 bit long but do not write to the MS byte */
+	awe_poke(AWE_PTRX(30)      , 0x0000);
+
+	while(! (inw(awe_base-0x620+Pointer) & 0x1000));
+	while(   inw(awe_base-0x620+Pointer) & 0x1000);
+
+	/* now write the MS byte of PTRX */
+	OUTW(0x4828, awe_base-0x620+Data0+0x002);
+
+	awe_poke(   AWE_IFATN(28)     , 0x0000);
+	awe_poke_dw(AWE_VTFT(30)      , 0x8000FFFF);
+	awe_poke_dw(AWE_VTFT(31)      , 0x8000FFFF);
+
+	/* change maximum channels to 30 */
+	awe_max_voices = AWE_NORMAL_VOICES;
+	awe_info.nr_voices = awe_max_voices;
+	voice_alloc->max_voice = awe_max_voices;
+}
+
+/*
+ *  AWE32 DRAM access routines
+ */
+
+/* open DRAM write accessing mode */
+static int
+awe_open_dram_for_write(int offset)
+{
+	int i;
+
+	/* use all channels for DMA transfer */
+	for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+		awe_poke(AWE_DCYSUSV(i), 0x80);
+		awe_poke_dw(AWE_VTFT(i), 0);
+		awe_poke_dw(AWE_CVCF(i), 0);
+		awe_poke_dw(AWE_PTRX(i), 0x40000000);
+		awe_poke_dw(AWE_CPF(i), 0x40000000);
+		awe_poke_dw(AWE_PSST(i), 0);
+		awe_poke_dw(AWE_CSL(i), 0);
+		awe_poke_dw(AWE_CCCA(i), 0x06000000);
+	}
+	/* point channels 31 & 32 to ROM samples for DRAM refresh */
+	awe_poke_dw(AWE_VTFT(30), 0);
+	awe_poke_dw(AWE_PSST(30), 0x1d8);
+	awe_poke_dw(AWE_CSL(30), 0x1e0);
+	awe_poke_dw(AWE_CCCA(30), 0x1d8);
+	awe_poke_dw(AWE_VTFT(31), 0);
+	awe_poke_dw(AWE_PSST(31), 0x1d8);
+	awe_poke_dw(AWE_CSL(31), 0x1e0);
+	awe_poke_dw(AWE_CCCA(31), 0x1d8);
+
+	/* if full bit is on, not ready to write on */
+	if (awe_peek_dw(AWE_SMALW) & 0x80000000) {
+		for (i = 0; i < AWE_NORMAL_VOICES; i++)
+			awe_poke_dw(AWE_CCCA(i), 0);
+		return RET_ERROR(ENOSPC);
+	}
+
+	/* set address to write */
+	awe_poke_dw(AWE_SMALW, offset + AWE_DRAM_OFFSET);
+
+	return 0;
+}
+
+/* open DRAM for RAM size detection */
+static void
+awe_open_dram_for_check(void)
+{
+	int k;
+	unsigned long scratch;
+
+	awe_poke(AWE_HWCF2 , 0x0020);
+
+	for (k = 0; k < AWE_NORMAL_VOICES; k++) {
+		awe_poke(AWE_DCYSUSV(k), 0x0080);
+		awe_poke_dw(AWE_VTFT(k), 0x00000000);
+		awe_poke_dw(AWE_CVCF(k), 0x00000000);
+		awe_poke_dw(AWE_PTRX(k), 0x40000000);
+		awe_poke_dw(AWE_CPF(k), 0x40000000);
+		awe_poke_dw(AWE_PSST(k), 0x00000000);
+		awe_poke_dw(AWE_CSL(k), 0x00000000);
+		scratch = (((k&1) << 9) + 0x400);
+		scratch = scratch << 16;
+		awe_poke_dw(AWE_CCCA(k), scratch);
+	}
+}
+
+
+/* close dram access */
+static void
+awe_close_dram(void)
+{
+	int i;
+	/* wait until FULL bit in SMAxW register be false */
+	for (i = 0; i < 10000; i++) {
+		if (!(awe_peek_dw(AWE_SMALW) & 0x80000000))
+			break;
+		awe_wait(10);
+	}
+
+	for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+		awe_poke_dw(AWE_CCCA(i), 0);
+		awe_poke(AWE_DCYSUSV(i), 0x807F);
+	}
+}
+
+
+#ifdef AWE_CHECKSUM_MEMORY
+/* open DRAM read accessing mode */
+static int
+awe_open_dram_for_read(int offset)
+{
+	int i;
+
+	/* use all channels for DMA transfer */
+	for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+		awe_poke(AWE_DCYSUSV(i), 0x80);
+		awe_poke_dw(AWE_VTFT(i), 0);
+		awe_poke_dw(AWE_CVCF(i), 0);
+		awe_poke_dw(AWE_PTRX(i), 0x40000000);
+		awe_poke_dw(AWE_CPF(i), 0x40000000);
+		awe_poke_dw(AWE_PSST(i), 0);
+		awe_poke_dw(AWE_CSL(i), 0);
+		awe_poke_dw(AWE_CCCA(i), 0x04000000);
+	}
+	/* point channels 31 & 32 to ROM samples for DRAM refresh */
+	awe_poke_dw(AWE_VTFT(30), 0);
+	awe_poke_dw(AWE_PSST(30), 0x1d8);
+	awe_poke_dw(AWE_CSL(30), 0x1e0);
+	awe_poke_dw(AWE_CCCA(30), 0x1d8);
+	awe_poke_dw(AWE_VTFT(31), 0);
+	awe_poke_dw(AWE_PSST(31), 0x1d8);
+	awe_poke_dw(AWE_CSL(31), 0x1e0);
+	awe_poke_dw(AWE_CCCA(31), 0x1d8);
+
+	/* if empty flag is on, not ready to read */
+	if (awe_peek_dw(AWE_SMALR) & 0x80000000) {
+		for (i = 0; i < AWE_NORMAL_VOICES; i++)
+			awe_poke_dw(AWE_CCCA(i), 0);
+		return RET_ERROR(ENOSPC);
+	}
+
+	/* set address to read */
+	awe_poke_dw(AWE_SMALR, offset + AWE_DRAM_OFFSET);
+	/* drop stale data */
+	awe_peek(AWE_SMLD);
+	return 0;
+}
+
+/* close dram access for read */
+static void
+awe_close_dram_for_read(void)
+{
+	int i;
+	/* wait until FULL bit in SMAxW register be false */
+	for (i = 0; i < 10000; i++) {
+		if (!(awe_peek_dw(AWE_SMALR) & 0x80000000))
+			break;
+		awe_wait(10);
+	}
+	for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+		awe_poke_dw(AWE_CCCA(i), 0);
+		awe_poke(AWE_DCYSUSV(i), 0x807F);
+	}
+}
+#endif /* AWE_CHECKSUM_MEMORY */
+
+
+/* write a word data */
+static void
+awe_write_dram(unsigned short c)
+{
+	int k;
+	/* wait until FULL bit in SMAxW register be false */
+	for (k = 0; k < 10000; k++) {
+		if (!(awe_peek_dw(AWE_SMALW) & 0x80000000))
+			break;
+		awe_wait(10);
+	}
+	awe_poke(AWE_SMLD, c);
+}
+
+/*================================================================
+ * detect presence of AWE32 and check memory size
+ *================================================================*/
+
+static int
+awe_detect(void)
+{
+#ifdef AWE_DEFAULT_BASE_ADDR
+	awe_base = AWE_DEFAULT_BASE_ADDR;
+	if (((awe_peek(AWE_U1) & 0x000F) == 0x000C) &&
+	    ((awe_peek(AWE_HWCF1) & 0x007E) == 0x0058) &&
+	    ((awe_peek(AWE_HWCF2) & 0x0003) == 0x0003))
+		return 1;
+#endif
+	if (awe_base == 0) {
+		for (awe_base = 0x620; awe_base <= 0x680; awe_base += 0x20) {
+			if ((awe_peek(AWE_U1) & 0x000F) != 0x000C)
+				continue;
+			if ((awe_peek(AWE_HWCF1) & 0x007E) != 0x0058)
+				continue;
+			if ((awe_peek(AWE_HWCF2) & 0x0003) != 0x0003)
+			        continue;
+		        DEBUG(0,printk("AWE32 found at %x\n", awe_base));
+			return 1;
+		}
+	}
+	FATALERR(printk("AWE32 not found\n"));
+	awe_base = 0;
+	return 0;
+}
+
+
+/*================================================================
+ * check dram size on AWE board
+ *================================================================*/
+static int
+awe_check_dram(void)
+{
+	awe_open_dram_for_check();
+
+	awe_poke_dw(AWE_SMALW    , 0x00200000);     /* DRAM start address */
+	awe_poke(   AWE_SMLD     , 0x1234);
+	awe_poke(   AWE_SMLD     , 0x7777);
+
+	awe_mem_size = 0;
+	while (awe_mem_size < 28*1024) {     /* 28 MB is max onboard memory */
+		awe_wait(2);
+		awe_poke_dw(AWE_SMALR, 0x00200000); /* Address for reading */
+		awe_peek(AWE_SMLD);		/* Discard stale data  */
+		if (awe_peek(AWE_SMLD) != 0x1234)
+			break;
+		if (awe_peek(AWE_SMLD) != 0x7777)
+			break;
+		awe_mem_size += 32;
+		/* Address for writing */
+		awe_poke_dw(AWE_SMALW, 0x00200000+awe_mem_size*512L);
+		awe_poke(AWE_SMLD, 0xFFFF);
+	}
+	awe_close_dram();
+
+	DEBUG(0,printk("AWE32: %d Kbytes memory detected\n", (int)awe_mem_size));
+#ifdef AWE_DEFAULT_MEM_SIZE
+	if (awe_mem_size == 0)
+		awe_mem_size = AWE_DEFAULT_MEM_SIZE;
+#endif
+	/* convert to Kbytes */
+	awe_mem_size *= 1024;
+	return awe_mem_size;
+}
+
+
+/*================================================================
+ * chorus and reverb controls
+ *================================================================*/
+
+static unsigned short ChorusEffects[24] =
+{
+  0xE600,0x03F6,0xBC2C,0xE608,0x031A,0xBC6E,0xE610,0x031A,
+  0xBC84,0xE620,0x0269,0xBC6E,0xE680,0x04D3,0xBCA6,0xE6E0,
+  0x044E,0xBC37,0xE600,0x0B06,0xBC00,0xE6C0,0x0B06,0xBC00
+};
+
+static unsigned long ChorusEffects2[] =
+{
+  0x0000 ,0x006D,0x8000,0x0000,0x0000 ,0x017C,0x8000,0x0000,
+  0x0000 ,0x0083,0x8000,0x0000,0x0000 ,0x017C,0x8000,0x0000,
+  0x0000 ,0x005B,0x8000,0x0000,0x0000 ,0x0026,0x8000,0x0000,
+  0x6E000,0x0083,0x8000,0x0000,0x6E000,0x0083,0x8000,0x0000
+};
+
+static unsigned short ChorusCommand[14] =
+{
+  0x69,0xA20,0x6C,0xA20,0x63,0xA22,0x29,
+  0xA20,0x2A,0xA20,0x2D,0xA20,0x2E,0xA20
+};
+
+static unsigned short ReverbEffects[224] =
+{
+  /* Room 1 */
+  0xB488,0xA450,0x9550,0x84B5,0x383A,0x3EB5,0x72F4,
+  0x72A4,0x7254,0x7204,0x7204,0x7204,0x4416,0x4516,
+  0xA490,0xA590,0x842A,0x852A,0x842A,0x852A,0x8429,
+  0x8529,0x8429,0x8529,0x8428,0x8528,0x8428,0x8528,
+  /* Room 2 */
+  0xB488,0xA458,0x9558,0x84B5,0x383A,0x3EB5,0x7284,
+  0x7254,0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,
+  0xA440,0xA540,0x842A,0x852A,0x842A,0x852A,0x8429,
+  0x8529,0x8429,0x8529,0x8428,0x8528,0x8428,0x8528,
+  /* Room 3 */
+  0xB488,0xA460,0x9560,0x84B5,0x383A,0x3EB5,0x7284,
+  0x7254,0x7224,0x7224,0x7254,0x7284,0x4416,0x4516,
+  0xA490,0xA590,0x842C,0x852C,0x842C,0x852C,0x842B,
+  0x852B,0x842B,0x852B,0x842A,0x852A,0x842A,0x852A,
+  /* Hall 1 */
+  0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7284,
+  0x7254,0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,
+  0xA440,0xA540,0x842B,0x852B,0x842B,0x852B,0x842A,
+  0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
+  /* Hall 2 */
+  0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7254,
+  0x7234,0x7224,0x7254,0x7264,0x7294,0x44C3,0x45C3,
+  0xA404,0xA504,0x842A,0x852A,0x842A,0x852A,0x8429,
+  0x8529,0x8429,0x8529,0x8428,0x8528,0x8428,0x8528,
+  /* Plate */
+  0xB4FF,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7234,
+  0x7234,0x7234,0x7234,0x7234,0x7234,0x4448,0x4548,
+  0xA440,0xA540,0x842A,0x852A,0x842A,0x852A,0x8429,
+  0x8529,0x8429,0x8529,0x8428,0x8528,0x8428,0x8528,
+  /* Delay */
+  0xB4FF,0xA470,0x9500,0x84B5,0x333A,0x39B5,0x7204,
+  0x7204,0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,
+  0xA4FF,0xA5FF,0x8420,0x8520,0x8420,0x8520,0x8420,
+  0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,
+  /* Panning Delay */
+  0xB4FF,0xA490,0x9590,0x8474,0x333A,0x39B5,0x7204,
+  0x7204,0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,
+  0xA4FF,0xA5FF,0x8420,0x8520,0x8420,0x8520,0x8420,
+  0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520
+};
+
+static unsigned short ReverbCommand[56] =
+{
+  0x43,0xA20,0x45,0xA20,0x7F,0xA22,0x47,0xA20,
+  0x54,0xA22,0x56,0xA22,0x4F,0xA20,0x57,0xA20,
+  0x5F,0xA20,0x47,0xA22,0x4F,0xA22,0x57,0xA22,
+  0x5D,0xA22,0x5F,0xA22,0x61,0xA20,0x63,0xA20,
+  0x49,0xA20,0x4B,0xA20,0x51,0xA20,0x53,0xA20,
+  0x59,0xA20,0x5B,0xA20,0x41,0xA22,0x43,0xA22,
+  0x49,0xA22,0x4B,0xA22,0x51,0xA22,0x53,0xA22
+};
+
+static void awe_set_chorus_mode(int effect)
+{
+	int k;
+	DECL_INTR_FLAGS(flags);
+
+	DISABLE_INTR(flags);
+	for (k = 0; k < 3; k++)
+		awe_poke(ChorusCommand[k*2],
+			 ChorusCommand[k*2+1],
+			 ChorusEffects[k+effect*3]);
+	for (k = 0; k < 4; k++)
+		awe_poke_dw(ChorusCommand[6+k*2],
+			    ChorusCommand[6+k*2+1],
+			    ChorusEffects2[k+effect*4]);
+	RESTORE_INTR(flags);
+}
+
+static void awe_set_reverb_mode(int effect)
+{
+	int k;
+	DECL_INTR_FLAGS(flags);
+
+	DISABLE_INTR(flags);
+	for (k = 0; k < 28; k++)
+		awe_poke(ReverbCommand[k*2],
+			 ReverbCommand[k*2+1],
+			 ReverbEffects[k+effect*28]);
+	RESTORE_INTR(flags);
+}
+
+#endif /* CONFIG_AWE32_SYNTH */
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/lowlevel/init.c linux/drivers/sound/lowlevel/init.c
--- v2.1.5/linux/drivers/sound/lowlevel/init.c	Tue May 28 17:45:17 1996
+++ linux/drivers/sound/lowlevel/init.c	Fri Oct 25 13:06:38 1996
@@ -2,11 +2,31 @@
  * lowlevel/init.c - Calls initialization code for configured drivers.
  */
 
+#include "lowlevel.h"
 #include <linux/config.h>
+#include "../soundvers.h"
 
 #ifdef CONFIG_LOWLEVEL_SOUND
+
+#ifdef LOWLEVEL_MODULE
+char *lowlevel_version = SOUND_VERSION_STRING;
+#endif
+
 extern int attach_aci(void);
 extern void unload_aci(void);
+extern int attach_awe(void);
+extern void unload_awe(void);
+
+/*
+ * There are two places where you can insert initialization calls of
+ * low level drivers. sound_init_lowlevel_drivers() is called after
+ * the sound driver has been initialized (the normal case)
+ * while sound_preinit_lowlevel_drivers() is called before that.
+ */
+void
+sound_preinit_lowlevel_drivers(void)
+{
+}
 
 void
 sound_init_lowlevel_drivers(void)
@@ -14,6 +34,10 @@
 #ifdef CONFIG_ACI_MIXER
    attach_aci();
 #endif
+
+#ifdef CONFIG_AWE32_SYNTH
+   attach_awe();
+#endif
 }
 
 void
@@ -21,6 +45,10 @@
 {
 #ifdef CONFIG_ACI_MIXER
    unload_aci();
+#endif
+
+#ifdef CONFIG_AWE32_SYNTH
+   unload_awe();
 #endif
 }
 #endif
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/lowlevel/lowlevel.h linux/drivers/sound/lowlevel/lowlevel.h
--- v2.1.5/linux/drivers/sound/lowlevel/lowlevel.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/sound/lowlevel/lowlevel.h	Fri Oct 25 13:06:38 1996
@@ -0,0 +1,5 @@
+#ifdef LOWLEVEL_MODULE
+#define MODVERSIONS
+#include <linux/modversions.h>
+#include "manual_config.h"
+#endif
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c
--- v2.1.5/linux/drivers/sound/mad16.c	Wed Aug 14 10:21:03 1996
+++ linux/drivers/sound/mad16.c	Tue Oct 29 09:31:38 1996
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -16,6 +16,7 @@
  *      OAK OTI-601D    Mozart
  *      OPTi 82C929     MAD16 Pro
  *      OPTi 82C930
+ *      OPTi 82C924     (in non PnP mode)
  *
  * These audio interface chips don't produce sound themselves. They just
  * connect some other components (OPL-[234] and a WSS compatible codec)
@@ -47,7 +48,7 @@
  *
  *      CD-ROM port: 0x00=340, 0x40=330, 0x80=360 or 0xc0=320
  *      OPL4 select: 0x20=OPL4, 0x00=OPL3
- *      CD-ROM irq: 0x00=disabled, 0x04=IRQ5, 0x08=IRQ7, 0x0a=IRQ3, 0x10=IRQ9,
+ *      CD-ROM irq: 0x00=disabled, 0x04=IRQ5, 0x08=IRQ7, 0x0c=IRQ3, 0x10=IRQ9,
  *                  0x14=IRQ10 and 0x18=IRQ11.
  *
  *      CD-ROM DMA (Sony or Panasonic): 0x00=DMA3, 0x01=DMA2, 0x02=DMA1 or 0x03=disabled
@@ -69,6 +70,7 @@
 #define MOZART	2
 #define C929	3
 #define C930	4
+#define C924    5
 
 /*
  *    Registers
@@ -118,21 +120,25 @@
     {
     case C928:
     case MOZART:
-      outb (0xE2, PASSWD_REG);
+      outb ((0xE2), PASSWD_REG);
       break;
 
     case C929:
-      outb (0xE3, PASSWD_REG);
+      outb ((0xE3), PASSWD_REG);
       break;
 
     case C930:
-      /* outb( 0xE4,  PASSWD_REG); */
+      /* outb(( 0xE4),  PASSWD_REG); */
+      break;
+
+    case C924:
+      outb ((0xE5), PASSWD_REG);
       break;
     }
 
   if (board_type == C930)
     {
-      outb (port - MC0_PORT, 0xe0e);	/* Write to index reg */
+      outb ((port - MC0_PORT), 0xe0e);	/* Write to index reg */
       tmp = inb (0xe0f);	/* Read from data reg */
     }
   else
@@ -154,25 +160,29 @@
     {
     case C928:
     case MOZART:
-      outb (0xE2, PASSWD_REG);
+      outb ((0xE2), PASSWD_REG);
       break;
 
     case C929:
-      outb (0xE3, PASSWD_REG);
+      outb ((0xE3), PASSWD_REG);
       break;
 
     case C930:
-      /* outb( 0xE4,  PASSWD_REG); */
+      /* outb(( 0xE4),  PASSWD_REG); */
+      break;
+
+    case C924:
+      outb ((0xE5), PASSWD_REG);
       break;
     }
 
   if (board_type == C930)
     {
-      outb (port - MC0_PORT, 0xe0e);	/* Write to index reg */
-      outb ((unsigned char) (value & 0xff), 0xe0f);
+      outb ((port - MC0_PORT), 0xe0e);	/* Write to index reg */
+      outb (((unsigned char) (value & 0xff)), 0xe0f);
     }
   else
-    outb ((unsigned char) (value & 0xff), port);
+    outb (((unsigned char) (value & 0xff)), port);
   restore_flags (flags);
 }
 
@@ -354,107 +364,116 @@
   /* MC2 is CD configuration. Don't touch it. */
 
   mad_write (MC3_PORT, 0);	/* Disable SB mode IRQ and DMA */
-
   mad_write (MC4_PORT, 0x52);	/* ??? */
-  mad_write (MC5_PORT, 0x3D);	/* Init it into mode2 */
+  mad_write (MC5_PORT, 0x3C);	/* Init it into mode2 */
   mad_write (MC6_PORT, 0x02);	/* Enable WSS, Disable MPU and SB */
   mad_write (MC7_PORT, 0xCB);
   mad_write (MC10_PORT, 0x11);
 
-  if (!wss_init (hw_config))
-    return 0;
-
-/*
- * A temporary kludge which drops the device back to mode1.
- * This removes problems with interrupts but disables full duplex.
- * A better solution should be introduced later.
- */
-  mad_write (MC5_PORT, 0x1D);	/* Disable mode2 */
   return wss_init (hw_config);
 }
 
-int
-probe_mad16 (struct address_info *hw_config)
+static int
+chip_detect (void)
 {
   int             i;
-  static int      valid_ports[] =
-  {0x530, 0xe80, 0xf40, 0x604};
-  unsigned char   tmp;
-  unsigned char   cs4231_mode = 0;
-
-  int             ad_flags = 0;
-
-  if (already_initialized)
-    return 0;
-
-  mad16_osp = hw_config->osp;
-/*
- *    Check that all ports return 0xff (bus float) when no password
- *      is written to the password register.
- */
-
-  DDB (printk ("--- Detecting MAD16 / Mozart ---\n"));
-
 
 /*
  *    Then try to detect with the old password
  */
-  board_type = C928;
+  board_type = C924;
 
-  DDB (printk ("Detect using password = 0xE2\n"));
+  DDB (printk ("Detect using password = 0xE5\n"));
 
   if (!detect_mad16 ())		/* No luck. Try different model */
     {
-      board_type = C929;
+      board_type = C928;
 
-      DDB (printk ("Detect using password = 0xE3\n"));
+      DDB (printk ("Detect using password = 0xE2\n"));
 
       if (!detect_mad16 ())
 	{
-	  if (inb (PASSWD_REG) != 0xff)
-	    return 0;
+	  board_type = C929;
+
+	  DDB (printk ("Detect using password = 0xE3\n"));
+
+	  if (!detect_mad16 ())
+	    {
+	      if (inb (PASSWD_REG) != 0xff)
+		return 0;
 
 /*
  * First relocate MC# registers to 0xe0e/0xe0f, disable password 
  */
 
-	  outb (0xE4, PASSWD_REG);
-	  outb (0x80, PASSWD_REG);
+	      outb ((0xE4), PASSWD_REG);
+	      outb ((0x80), PASSWD_REG);
 
-	  board_type = C930;
+	      board_type = C930;
 
-	  DDB (printk ("Detect using password = 0xE4\n"));
+	      DDB (printk ("Detect using password = 0xE4\n"));
 
-	  for (i = 0xf8d; i <= 0xf93; i++)
-	    DDB (printk ("port %03x = %02x\n", i, mad_read (i)));
+	      for (i = 0xf8d; i <= 0xf93; i++)
+		DDB (printk ("port %03x = %02x\n", i, mad_read (i)));
 
-	  if (!detect_mad16 ())
-	    return 0;
+	      if (!detect_mad16 ())
+		return 0;
 
-	  DDB (printk ("mad16.c: 82C930 detected\n"));
-	  return init_c930 (hw_config);
+	      DDB (printk ("mad16.c: 82C930 detected\n"));
+	    }
+	  else
+	    {
+	      DDB (printk ("mad16.c: 82C929 detected\n"));
+	    }
 	}
       else
 	{
-	  DDB (printk ("mad16.c: 82C929 detected\n"));
-	}
-    }
-  else
-    {
-      unsigned char   model;
+	  unsigned char   model;
 
-      if (((model = mad_read (MC3_PORT)) & 0x03) == 0x03)
-	{
-	  DDB (printk ("mad16.c: Mozart detected\n"));
-	  board_type = MOZART;
-	}
-      else
-	{
-	  DDB (printk ("mad16.c: 82C928 detected???\n"));
-	  board_type = C928;
+	  if (((model = mad_read (MC3_PORT)) & 0x03) == 0x03)
+	    {
+	      DDB (printk ("mad16.c: Mozart detected\n"));
+	      board_type = MOZART;
+	    }
+	  else
+	    {
+	      DDB (printk ("mad16.c: 82C928 detected???\n"));
+	      board_type = C928;
+	    }
 	}
     }
 
+  return 1;
+}
+
+int
+probe_mad16 (struct address_info *hw_config)
+{
+  int             i;
+  static int      valid_ports[] =
+  {0x530, 0xe80, 0xf40, 0x604};
+  unsigned char   tmp;
+  unsigned char   cs4231_mode = 0;
+
+  int             ad_flags = 0;
+
+  if (already_initialized)
+    return 0;
+
+  mad16_osp = hw_config->osp;
+/*
+ *    Check that all ports return 0xff (bus float) when no password
+ *      is written to the password register.
+ */
+
+  DDB (printk ("--- Detecting MAD16 / Mozart ---\n"));
+  if (!chip_detect ())
+    return 0;
+
+  if (board_type == C930)
+    return init_c930 (hw_config);
+
+
   for (i = 0xf8d; i <= 0xf93; i++)
     DDB (printk ("port %03x = %02x\n", i, mad_read (i)));
 
@@ -462,7 +481,7 @@
  * Set the WSS address
  */
 
-  tmp = 0x80;			/* Enable WSS, Disable SB */
+  tmp = (mad_read (MC1_PORT) & 0x0f) | 0x80;	/* Enable WSS, Disable SB */
 
   for (i = 0; i < 5; i++)
     {
@@ -484,6 +503,7 @@
  */
 
 #ifdef MAD16_CONF
+  tmp &= ~0x0f;
   tmp |= ((MAD16_CONF) & 0x0f);	/* CD-ROM and joystick bits */
 #endif
   mad_write (MC1_PORT, tmp);
@@ -491,7 +511,7 @@
 #if defined(MAD16_CONF) && defined(MAD16_CDSEL)
   tmp = MAD16_CDSEL;
 #else
-  tmp = 0x03;
+  tmp = mad_read (MC2_PORT);
 #endif
 
 #ifdef MAD16_OPL4
@@ -501,6 +521,13 @@
   mad_write (MC2_PORT, tmp);
   mad_write (MC3_PORT, 0xf0);	/* Disable SB */
 
+  if (board_type == C924)	/* Specific C924 init values */
+    {
+      mad_write (MC4_PORT, 0xA0);
+      mad_write (MC5_PORT, 0x05);
+      mad_write (MC6_PORT, 0x03);
+    }
+
   if (!ad1848_detect (hw_config->io_base + 4, &ad_flags, mad16_osp))
     return 0;
 
@@ -554,12 +581,14 @@
   /*
      * Set the IRQ and DMA addresses.
    */
+  if (board_type == C930)
+    interrupt_bits[5] = 0x28;	/* Also IRQ5 is possible on C930 */
 
   bits = interrupt_bits[hw_config->irq];
   if (bits == -1)
     return;
 
-  outb (bits | 0x40, config_port);
+  outb ((bits | 0x40), config_port);
   if ((inb (version_port) & 0x40) == 0)
     printk ("[IRQ Conflict?]");
 
@@ -594,7 +623,7 @@
   else
     dma2 = dma;
 
-  outb (bits | dma_bits[dma] | dma2_bit, config_port);	/* Write IRQ+DMA setup */
+  outb ((bits | dma_bits[dma] | dma2_bit), config_port);	/* Write IRQ+DMA setup */
 
   ad1848_init ("MAD16 WSS", hw_config->io_base + 4,
 	       hw_config->irq,
@@ -766,10 +795,12 @@
     }
 #endif
 
-#if (defined(CONFIG_UART401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+#if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
   unload_uart401 (hw_config);
 #endif
 }
+
+
 
 /* That's all folks */
 #endif
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/maui.c linux/drivers/sound/maui.c
--- v2.1.5/linux/drivers/sound/maui.c	Wed Oct 16 10:48:23 1996
+++ linux/drivers/sound/maui.c	Tue Oct 29 09:31:39 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -47,7 +47,7 @@
 
 #endif
 
-static wait_handle *maui_sleeper = NULL;
+static struct wait_queue *maui_sleeper = NULL;
 static volatile struct snd_wait maui_sleep_flag =
 {0};
 
@@ -84,20 +84,22 @@
 	unsigned long   tlimit;
 
 	if (HZ / 10)
-	  current_set_timeout (tlimit = jiffies + (HZ / 10));
+	  current->timeout = tlimit = jiffies + (HZ / 10);
 	else
 	  tlimit = (unsigned long) -1;
-	maui_sleep_flag.flags = WK_SLEEP;
-	module_interruptible_sleep_on (&maui_sleeper);
-	if (!(maui_sleep_flag.flags & WK_WAKEUP))
+	maui_sleep_flag.opts = WK_SLEEP;
+	interruptible_sleep_on (&maui_sleeper);
+	if (!(maui_sleep_flag.opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      maui_sleep_flag.flags |= WK_TIMEOUT;
+	      maui_sleep_flag.opts |= WK_TIMEOUT;
 	  }
-	maui_sleep_flag.flags &= ~WK_SLEEP;
+	maui_sleep_flag.opts &= ~WK_SLEEP;
       };
-      if (current_got_fatal_signal ())
-	return 0;
+      if ((current->signal & ~current->blocked))
+	{
+	  return 0;
+	}
     }
 
   return 0;
@@ -117,7 +119,7 @@
 {
   if (maui_wait (STAT_TX_AVAIL))
     {
-      outb (data, HOST_DATA_PORT);
+      outb ((data), HOST_DATA_PORT);
       return 1;
     }
   printk ("Maui: Write timeout\n");
@@ -228,29 +230,29 @@
       return 0;
     }
 
-  outb (0x00, HOST_CTRL_PORT);	/* Reset */
+  outb ((0x00), HOST_CTRL_PORT);	/* Reset */
 
-  outb (bits, HOST_DATA_PORT);	/* Set the IRQ bits */
-  outb (bits | 0x80, HOST_DATA_PORT);	/* Set the IRQ bits again? */
+  outb ((bits), HOST_DATA_PORT);	/* Set the IRQ bits */
+  outb ((bits | 0x80), HOST_DATA_PORT);		/* Set the IRQ bits again? */
 
-  outb (0x80, HOST_CTRL_PORT);	/* Leave reset */
-  outb (0x80, HOST_CTRL_PORT);	/* Leave reset */
+  outb ((0x80), HOST_CTRL_PORT);	/* Leave reset */
+  outb ((0x80), HOST_CTRL_PORT);	/* Leave reset */
 
-  outb (0xD0, HOST_CTRL_PORT);	/* Cause interrupt */
+  outb ((0xD0), HOST_CTRL_PORT);	/* Cause interrupt */
 
   for (i = 0; i < 1000000 && !irq_ok; i++);
 
   if (!irq_ok)
     return 0;
 
-  outb (0x80, HOST_CTRL_PORT);	/* Leave reset */
+  outb ((0x80), HOST_CTRL_PORT);	/* Leave reset */
 
   printk ("Turtle Beach Maui initialization\n");
 
   if (!download_code ())
     return 0;
 
-  outb (0xE0, HOST_CTRL_PORT);	/* Normal operation */
+  outb ((0xE0), HOST_CTRL_PORT);	/* Normal operation */
 
   /* Select mpu401 mode */
 
@@ -305,7 +307,7 @@
   if (count < hdr_size)
     {
       printk ("Maui error: Patch header too short\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   count -= hdr_size;
@@ -331,12 +333,12 @@
     {
       unsigned char   data;
 
-      data = get_fs_byte (&((addr)[hdr_size + i]));
+      get_user (data, (unsigned char *) &((addr)[hdr_size + i]));
       if (i == 0 && !(data & 0x80))
-	return -(EINVAL);
+	return -EINVAL;
 
       if (maui_write (data) == -1)
-	return -(EIO);
+	return -EIO;
     }
 
   if ((i = maui_read ()) != 0x80)
@@ -344,7 +346,7 @@
       if (i != -1)
 	printk ("Maui: Error status %02x\n", i);
 
-      return -(EIO);
+      return -EIO;
     }
 
   return 0;
@@ -365,7 +367,7 @@
   if (snd_set_irq_handler (hw_config->irq, mauiintr, "Maui", maui_osp) < 0)
     return 0;
 
-  maui_sleep_flag.flags = WK_NONE;
+  maui_sleep_flag.opts = WK_NONE;
 /*
  * Initialize the processor if necessary
  */
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/midi_synth.c linux/drivers/sound/midi_synth.c
--- v2.1.5/linux/drivers/sound/midi_synth.c	Wed Oct 16 10:48:23 1996
+++ linux/drivers/sound/midi_synth.c	Tue Oct 29 09:31:40 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -22,7 +22,7 @@
 
 #define _MIDI_SYNTH_C_
 
-static wait_handle *sysex_sleeper = NULL;
+static struct wait_queue *sysex_sleeper = NULL;
 static volatile struct snd_wait sysex_sleep_flag =
 {0};
 
@@ -99,8 +99,8 @@
 {
   int             timeout;
 
-  for (timeout = 0; timeout < 32000; timeout++)
-    if (midi_devs[midi_dev]->putc (midi_dev, (unsigned char) (data & 0xff)))
+  for (timeout = 0; timeout < 3200; timeout++)
+    if (midi_devs[midi_dev]->outputc (midi_dev, (unsigned char) (data & 0xff)))
       {
 	if (data & 0x80)	/*
 				 * Status byte
@@ -248,7 +248,7 @@
 
   sysex_state[dev] = 0;
 
-  while (!midi_devs[orig_dev]->putc (orig_dev, 0xf7) &&
+  while (!midi_devs[orig_dev]->outputc (orig_dev, 0xf7) &&
 	 timeout < 1000)
     timeout++;
 
@@ -275,7 +275,10 @@
     {
 
     case SNDCTL_SYNTH_INFO:
-      copy_to_user (&((char *) arg)[0], synth_devs[dev]->info, sizeof (struct synth_info));
+      {
+	char           *fixit = (char *) synth_devs[dev]->info;
+	copy_to_user (&((char *) arg)[0], fixit, sizeof (struct synth_info));
+      };
 
       return 0;
       break;
@@ -285,7 +288,7 @@
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -363,7 +366,7 @@
   int             orig_dev = synth_devs[dev]->midi_dev;
 
   if (instr_no < 0 || instr_no > 127)
-    return 0;
+    instr_no = 0;
   if (channel < 0 || channel > 15)
     return 0;
 
@@ -437,7 +440,7 @@
   struct midi_input_info *inc;
 
   if (orig_dev < 0 || orig_dev > num_midis)
-    return -(ENXIO);
+    return -ENXIO;
 
   midi2synth[orig_dev] = dev;
   sysex_state[dev] = 0;
@@ -458,7 +461,7 @@
   inc->m_prev_status = 0x00;
   restore_flags (flags);
 
-  sysex_sleep_flag.flags = WK_NONE;
+  sysex_sleep_flag.opts = WK_NONE;
 
   return 1;
 }
@@ -473,7 +476,7 @@
   /*
    * Shut up the synths by sending just single active sensing message.
    */
-  midi_devs[orig_dev]->putc (orig_dev, 0xfe);
+  midi_devs[orig_dev]->outputc (orig_dev, 0xfe);
 
   midi_devs[orig_dev]->close (orig_dev);
 }
@@ -503,13 +506,13 @@
   if (format != SYSEX_PATCH)
     {
       printk ("MIDI Error: Invalid patch format (key) 0x%x\n", format);
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if (count < hdr_size)
     {
       printk ("MIDI Error: Patch header too short\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   count -= hdr_size;
@@ -531,13 +534,13 @@
   left = sysex.len;
   src_offs = 0;
 
-  sysex_sleep_flag.flags = WK_NONE;
+  sysex_sleep_flag.opts = WK_NONE;
 
-  for (i = 0; i < left && !current_got_fatal_signal (); i++)
+  for (i = 0; i < left && !(current->signal & ~current->blocked); i++)
     {
       unsigned char   data;
 
-      data = get_fs_byte (&((addr)[hdr_size + i]));
+      get_user (data, (unsigned char *) &((addr)[hdr_size + i]));
 
       eox_seen = (i > 0 && data & 0x80);	/* End of sysex */
 
@@ -549,28 +552,28 @@
 	  if (data != 0xf0)
 	    {
 	      printk ("Error: Sysex start missing\n");
-	      return -(EINVAL);
+	      return -EINVAL;
 	    }
 	}
 
-      while (!midi_devs[orig_dev]->putc (orig_dev, (unsigned char) (data & 0xff)) &&
-	     !current_got_fatal_signal ())
+      while (!midi_devs[orig_dev]->outputc (orig_dev, (unsigned char) (data & 0xff)) &&
+	     !(current->signal & ~current->blocked))
 
 	{
 	  unsigned long   tlimit;
 
 	  if (1)
-	    current_set_timeout (tlimit = jiffies + (1));
+	    current->timeout = tlimit = jiffies + (1);
 	  else
 	    tlimit = (unsigned long) -1;
-	  sysex_sleep_flag.flags = WK_SLEEP;
-	  module_interruptible_sleep_on (&sysex_sleeper);
-	  if (!(sysex_sleep_flag.flags & WK_WAKEUP))
+	  sysex_sleep_flag.opts = WK_SLEEP;
+	  interruptible_sleep_on (&sysex_sleeper);
+	  if (!(sysex_sleep_flag.opts & WK_WAKEUP))
 	    {
 	      if (jiffies >= tlimit)
-		sysex_sleep_flag.flags |= WK_TIMEOUT;
+		sysex_sleep_flag.opts |= WK_TIMEOUT;
 	    }
-	  sysex_sleep_flag.flags &= ~WK_SLEEP;
+	  sysex_sleep_flag.opts &= ~WK_SLEEP;
 	};			/* Wait for timeout */
 
       if (!first_byte && data & 0x80)
@@ -652,7 +655,7 @@
 int
 midi_synth_patchmgr (int dev, struct patmgr_info *rec)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 void
@@ -725,7 +728,7 @@
 	    }
 	}
 
-      if (!midi_devs[orig_dev]->putc (orig_dev, bytes[i]))
+      if (!midi_devs[orig_dev]->outputc (orig_dev, bytes[i]))
 	{
 /*
  * Hardware level buffer is full. Abort the sysex message.
@@ -736,7 +739,7 @@
 	  bytes[i] = 0xf7;
 	  sysex_state[dev] = 0;
 
-	  while (!midi_devs[orig_dev]->putc (orig_dev, bytes[i]) &&
+	  while (!midi_devs[orig_dev]->outputc (orig_dev, bytes[i]) &&
 		 timeout < 1000)
 	    timeout++;
 	}
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/midibuf.c linux/drivers/sound/midibuf.c
--- v2.1.5/linux/drivers/sound/midibuf.c	Wed Oct 16 10:48:23 1996
+++ linux/drivers/sound/midibuf.c	Tue Oct 29 09:31:40 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -23,12 +23,12 @@
 
 #define MAX_QUEUE_SIZE	4000
 
-static wait_handle *midi_sleeper[MAX_MIDI_DEV] =
+static struct wait_queue *midi_sleeper[MAX_MIDI_DEV] =
 {NULL};
 static volatile struct snd_wait midi_sleep_flag[MAX_MIDI_DEV] =
 {
   {0}};
-static wait_handle *input_sleeper[MAX_MIDI_DEV] =
+static struct wait_queue *input_sleeper[MAX_MIDI_DEV] =
 {NULL};
 static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] =
 {
@@ -67,7 +67,7 @@
 	if (SPACE_AVAIL(q)) \
 	{ \
 	  unsigned long flags; \
-	  save_flags(flags);cli(); \
+	  save_flags( flags);cli(); \
 	  q->queue[q->tail] = (data); \
 	  q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
 	  restore_flags(flags); \
@@ -77,7 +77,7 @@
 	if (DATA_AVAIL(q)) \
 	{ \
 	  unsigned long flags; \
-	  save_flags(flags);cli(); \
+	  save_flags( flags);cli(); \
 	  data = q->queue[q->head]; \
 	  q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
 	  restore_flags(flags); \
@@ -92,24 +92,24 @@
    */
 
   if (midi_devs[dev]->buffer_status != NULL)
-    while (!current_got_fatal_signal () &&
+    while (!(current->signal & ~current->blocked) &&
 	   midi_devs[dev]->buffer_status (dev))
 
       {
 	unsigned long   tlimit;
 
 	if (HZ / 10)
-	  current_set_timeout (tlimit = jiffies + (HZ / 10));
+	  current->timeout = tlimit = jiffies + (HZ / 10);
 	else
 	  tlimit = (unsigned long) -1;
-	midi_sleep_flag[dev].flags = WK_SLEEP;
-	module_interruptible_sleep_on (&midi_sleeper[dev]);
-	if (!(midi_sleep_flag[dev].flags & WK_WAKEUP))
+	midi_sleep_flag[dev].opts = WK_SLEEP;
+	interruptible_sleep_on (&midi_sleeper[dev]);
+	if (!(midi_sleep_flag[dev].opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      midi_sleep_flag[dev].flags |= WK_TIMEOUT;
+	      midi_sleep_flag[dev].opts |= WK_TIMEOUT;
 	  }
-	midi_sleep_flag[dev].flags &= ~WK_SLEEP;
+	midi_sleep_flag[dev].opts &= ~WK_SLEEP;
       };
 }
 
@@ -129,10 +129,10 @@
   if (SPACE_AVAIL (midi_in_buf[dev]))
     {
       QUEUE_BYTE (midi_in_buf[dev], data);
-      if ((input_sleep_flag[dev].flags & WK_SLEEP))
+      if ((input_sleep_flag[dev].opts & WK_SLEEP))
 	{
-	  input_sleep_flag[dev].flags = WK_WAKEUP;
-	  module_wake_up (&input_sleeper[dev]);
+	  input_sleep_flag[dev].opts = WK_WAKEUP;
+	  wake_up (&input_sleeper[dev]);
 	};
     }
 
@@ -159,19 +159,25 @@
       for (dev = 0; dev < num_midis; dev++)
 	if (midi_out_buf[dev] != NULL)
 	  {
-	    while (DATA_AVAIL (midi_out_buf[dev]) &&
-		   midi_devs[dev]->putc (dev,
-			 midi_out_buf[dev]->queue[midi_out_buf[dev]->head]))
+	    int             ok = 1;
+
+	    while (DATA_AVAIL (midi_out_buf[dev]) && ok)
 	      {
+		int             c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head];
+
+		restore_flags (flags);	/* Give some time to others */
+		ok = midi_devs[dev]->outputc (dev, c);
+		save_flags (flags);
+		cli ();
 		midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
 		midi_out_buf[dev]->len--;
 	      }
 
 	    if (DATA_AVAIL (midi_out_buf[dev]) < 100 &&
-		(midi_sleep_flag[dev].flags & WK_SLEEP))
+		(midi_sleep_flag[dev].opts & WK_SLEEP))
 	      {
-		midi_sleep_flag[dev].flags = WK_WAKEUP;
-		module_wake_up (&midi_sleeper[dev]);
+		midi_sleep_flag[dev].opts = WK_WAKEUP;
+		wake_up (&midi_sleeper[dev]);
 	      };
 	  }
 
@@ -202,7 +208,7 @@
   if (dev < 0 || dev >= num_midis)
     {
       printk ("Sound: Nonexistent MIDI interface %d\n", dev);
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   /*
@@ -223,7 +229,7 @@
     {
       printk ("midi: Can't allocate buffer\n");
       midi_devs[dev]->close (dev);
-      return -(EIO);
+      return -EIO;
     }
   midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
 
@@ -235,13 +241,13 @@
       midi_devs[dev]->close (dev);
       vfree (midi_in_buf[dev]);
       midi_in_buf[dev] = NULL;
-      return -(EIO);
+      return -EIO;
     }
   midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
   open_devs++;
 
-  midi_sleep_flag[dev].flags = WK_NONE;
-  input_sleep_flag[dev].flags = WK_NONE;
+  midi_sleep_flag[dev].opts = WK_NONE;
+  input_sleep_flag[dev].opts = WK_NONE;
 
   if (open_devs < 2)		/* This was first open */
     {
@@ -277,29 +283,29 @@
 
   if (mode != OPEN_READ)
     {
-      midi_devs[dev]->putc (dev, 0xfe);		/*
+      midi_devs[dev]->outputc (dev, 0xfe);	/*
 						   * Active sensing to shut the
 						   * devices
 						 */
 
-      while (!current_got_fatal_signal () &&
+      while (!(current->signal & ~current->blocked) &&
 	     DATA_AVAIL (midi_out_buf[dev]))
 
 	{
 	  unsigned long   tlimit;
 
 	  if (0)
-	    current_set_timeout (tlimit = jiffies + (0));
+	    current->timeout = tlimit = jiffies + (0);
 	  else
 	    tlimit = (unsigned long) -1;
-	  midi_sleep_flag[dev].flags = WK_SLEEP;
-	  module_interruptible_sleep_on (&midi_sleeper[dev]);
-	  if (!(midi_sleep_flag[dev].flags & WK_WAKEUP))
+	  midi_sleep_flag[dev].opts = WK_SLEEP;
+	  interruptible_sleep_on (&midi_sleeper[dev]);
+	  if (!(midi_sleep_flag[dev].opts & WK_WAKEUP))
 	    {
 	      if (jiffies >= tlimit)
-		midi_sleep_flag[dev].flags |= WK_TIMEOUT;
+		midi_sleep_flag[dev].opts |= WK_TIMEOUT;
 	    }
-	  midi_sleep_flag[dev].flags &= ~WK_SLEEP;
+	  midi_sleep_flag[dev].opts &= ~WK_SLEEP;
 	};			/*
 				   * Sync
 				 */
@@ -352,22 +358,22 @@
 	    unsigned long   tlimit;
 
 	    if (0)
-	      current_set_timeout (tlimit = jiffies + (0));
+	      current->timeout = tlimit = jiffies + (0);
 	    else
 	      tlimit = (unsigned long) -1;
-	    midi_sleep_flag[dev].flags = WK_SLEEP;
-	    module_interruptible_sleep_on (&midi_sleeper[dev]);
-	    if (!(midi_sleep_flag[dev].flags & WK_WAKEUP))
+	    midi_sleep_flag[dev].opts = WK_SLEEP;
+	    interruptible_sleep_on (&midi_sleeper[dev]);
+	    if (!(midi_sleep_flag[dev].opts & WK_WAKEUP))
 	      {
 		if (jiffies >= tlimit)
-		  midi_sleep_flag[dev].flags |= WK_TIMEOUT;
+		  midi_sleep_flag[dev].opts |= WK_TIMEOUT;
 	      }
-	    midi_sleep_flag[dev].flags &= ~WK_SLEEP;
+	    midi_sleep_flag[dev].opts &= ~WK_SLEEP;
 	  };
-	  if (current_got_fatal_signal ())
+	  if ((current->signal & ~current->blocked))
 	    {
 	      restore_flags (flags);
-	      return -(EINTR);
+	      return -EINTR;
 	    }
 
 	  n = SPACE_AVAIL (midi_out_buf[dev]);
@@ -411,20 +417,20 @@
 	unsigned long   tlimit;
 
 	if (parms[dev].prech_timeout)
-	  current_set_timeout (tlimit = jiffies + (parms[dev].prech_timeout));
+	  current->timeout = tlimit = jiffies + (parms[dev].prech_timeout);
 	else
 	  tlimit = (unsigned long) -1;
-	input_sleep_flag[dev].flags = WK_SLEEP;
-	module_interruptible_sleep_on (&input_sleeper[dev]);
-	if (!(input_sleep_flag[dev].flags & WK_WAKEUP))
+	input_sleep_flag[dev].opts = WK_SLEEP;
+	interruptible_sleep_on (&input_sleeper[dev]);
+	if (!(input_sleep_flag[dev].opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      input_sleep_flag[dev].flags |= WK_TIMEOUT;
+	      input_sleep_flag[dev].opts |= WK_TIMEOUT;
 	  }
-	input_sleep_flag[dev].flags &= ~WK_SLEEP;
+	input_sleep_flag[dev].opts &= ~WK_SLEEP;
       };
-      if (current_got_fatal_signal ())
-	c = -(EINTR);		/*
+      if ((current->signal & ~current->blocked))
+	c = -EINTR;		/*
 				   * The user is getting restless
 				 */
     }
@@ -441,7 +447,11 @@
       while (c < n)
 	{
 	  REMOVE_BYTE (midi_in_buf[dev], tmp_data);
-	  copy_to_user (&(buf)[c], (char *) &tmp_data, 1);
+	  {
+	    char           *fixit = (char *) &tmp_data;
+
+	    copy_to_user (&(buf)[c], fixit, 1);
+	  };
 	  c++;
 	}
     }
@@ -466,20 +476,20 @@
       else
 	printk ("/dev/midi%d: No coprocessor for this device\n", dev);
 
-      return -(ENXIO);
+      return -ENXIO;
     }
   else
     switch (cmd)
       {
 
       case SNDCTL_MIDI_PRETIME:
-	val = (int) get_user ((int *) arg);
+	get_user (val, (int *) arg);
 	if (val < 0)
 	  val = 0;
 
 	val = (HZ * val) / 10;
 	parms[dev].prech_timeout = val;
-	return snd_ioctl_return ((int *) arg, val);
+	return ioctl_out (arg, val);
 	break;
 
       default:
@@ -488,7 +498,7 @@
 }
 
 int
-MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
+MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
   dev = dev >> 4;
 
@@ -498,8 +508,8 @@
       if (!DATA_AVAIL (midi_in_buf[dev]))
 	{
 
-	  input_sleep_flag[dev].flags = WK_SLEEP;
-	  module_select_wait (&input_sleeper[dev], wait);
+	  input_sleep_flag[dev].opts = WK_SLEEP;
+	  select_wait (&input_sleeper[dev], wait);
 	  return 0;
 	}
       return 1;
@@ -509,8 +519,8 @@
       if (SPACE_AVAIL (midi_out_buf[dev]))
 	{
 
-	  midi_sleep_flag[dev].flags = WK_SLEEP;
-	  module_select_wait (&midi_sleeper[dev], wait);
+	  midi_sleep_flag[dev].opts = WK_SLEEP;
+	  select_wait (&midi_sleeper[dev], wait);
 	  return 0;
 	}
       return 1;
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/mpu401.c linux/drivers/sound/mpu401.c
--- v2.1.5/linux/drivers/sound/mpu401.c	Wed Oct 16 10:48:23 1996
+++ linux/drivers/sound/mpu401.c	Tue Oct 29 09:31:42 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -23,6 +23,7 @@
 
 static int      init_sequence[20];	/* NOTE! pos 0 = len, start pos 1. */
 
+
 #ifdef CONFIG_SEQUENCER
 static int      timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL;
 
@@ -82,7 +83,7 @@
 static void 
 write_command (struct mpu_config *devc, unsigned char cmd)
 {
-  outb (cmd, COMDPORT (devc->base));
+  outb ((cmd), COMDPORT (devc->base));
 }
 static int 
 read_data (struct mpu_config *devc)
@@ -93,7 +94,7 @@
 static void 
 write_data (struct mpu_config *devc, unsigned char byte)
 {
-  outb (byte, DATAPORT (devc->base));
+  outb ((byte), DATAPORT (devc->base));
 }
 
 #define	OUTPUT_READY	0x40
@@ -492,14 +493,14 @@
   struct mpu_config *devc;
 
   if (dev < 0 || dev >= num_midis)
-    return -(ENXIO);
+    return -ENXIO;
 
   devc = &dev_conf[dev];
 
   if (devc->opened)
     {
       printk ("MPU-401: Midi busy\n");
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   /*
@@ -514,7 +515,7 @@
       if (mpu401_status (devc) == 0xff)		/* Bus float */
 	{
 	  printk ("MPU-401: Device not initialized properly\n");
-	  return -(EIO);
+	  return -EIO;
 	}
       reset_mpu401 (devc);
     }
@@ -608,7 +609,7 @@
 				 */
     {
       printk ("MPU-401 commands not possible in the UART mode\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   /*
@@ -627,7 +628,7 @@
   if (timeout-- <= 0)
     {
       printk ("MPU-401: Command (0x%x) timeout\n", (int) cmd->cmd);
-      return -(EIO);
+      return -EIO;
     }
 
   save_flags (flags);
@@ -661,7 +662,7 @@
     {
       restore_flags (flags);
       /*       printk ("MPU: No ACK to command (0x%x)\n", (int) cmd->cmd); */
-      return -(EIO);
+      return -EIO;
     }
 
   if (cmd->nr_args)
@@ -673,7 +674,7 @@
 	  {
 	    restore_flags (flags);
 	    printk ("MPU: Command (0x%x), parm send failed.\n", (int) cmd->cmd);
-	    return -(EIO);
+	    return -EIO;
 	  }
       }
 
@@ -695,7 +696,7 @@
 	  {
 	    restore_flags (flags);
 	    /* printk ("MPU: No response(%d) to command (0x%x)\n", i, (int) cmd->cmd);  */
-	    return -(EIO);
+	    return -EIO;
 	  }
       }
 
@@ -788,9 +789,9 @@
       if (!(devc->capabilities & MPU_CAP_INTLG))	/* No intelligent mode */
 	{
 	  printk ("MPU-401: Intelligent mode not supported by the HW\n");
-	  return -(EINVAL);
+	  return -EINVAL;
 	}
-      set_uart_mode (dev, devc, !get_user ((int *) arg));
+      set_uart_mode (dev, devc, !ioctl_in (arg));
       return 0;
       break;
 
@@ -804,13 +805,17 @@
 	if ((ret = mpu401_command (dev, &rec)) < 0)
 	  return ret;
 
-	copy_to_user (&((char *) arg)[0], (char *) &rec, sizeof (rec));
+	{
+	  char           *fixit = (char *) &rec;
+
+	  copy_to_user (&((char *) arg)[0], fixit, sizeof (rec));
+	};
 	return 0;
       }
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -837,7 +842,7 @@
   midi_dev = synth_devs[dev]->midi_dev;
 
   if (midi_dev < 0 || midi_dev > num_midis)
-    return -(ENXIO);
+    return -ENXIO;
 
   devc = &dev_conf[midi_dev];
 
@@ -845,7 +850,10 @@
     {
 
     case SNDCTL_SYNTH_INFO:
-      copy_to_user (&((char *) arg)[0], &mpu_synth_info[midi_dev], sizeof (struct synth_info));
+      {
+	char           *fixit = (char *) &mpu_synth_info[midi_dev];
+	copy_to_user (&((char *) arg)[0], fixit, sizeof (struct synth_info));
+      };
 
       return 0;
       break;
@@ -855,7 +863,7 @@
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -869,7 +877,7 @@
 
   if (midi_dev < 0 || midi_dev > num_midis)
     {
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   devc = &dev_conf[midi_dev];
@@ -886,7 +894,7 @@
       if (mpu401_status (devc) == 0xff)		/* Bus float */
 	{
 	  printk ("MPU-401: Device not initialized properly\n");
-	  return -(EIO);
+	  return -EIO;
 	}
       reset_mpu401 (devc);
     }
@@ -894,7 +902,7 @@
   if (devc->opened)
     {
       printk ("MPU-401: Midi busy\n");
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   devc->mode = MODE_SYNTH;
@@ -1464,7 +1472,7 @@
   int             midi_dev = sound_timer_devs[dev]->devlink;
 
   if (timer_open)
-    return -(EBUSY);
+    return -EBUSY;
 
   tmr_reset ();
   curr_tempo = 50;
@@ -1590,7 +1598,10 @@
     {
     case SNDCTL_TMR_SOURCE:
       {
-	int             parm = (int) get_user ((int *) arg) & timer_caps;
+	int             parm;
+
+	get_user (parm, (int *) arg);
+	parm &= timer_caps;
 
 	if (parm != 0)
 	  {
@@ -1602,7 +1613,7 @@
 	      mpu_cmd (midi_dev, 0x3d, 0);	/* Use SMPTE sync */
 	  }
 
-	return snd_ioctl_return ((int *) arg, timer_mode);
+	return ioctl_out (arg, timer_mode);
       }
       break;
 
@@ -1628,18 +1639,18 @@
 
     case SNDCTL_TMR_TIMEBASE:
       {
-	int             val = (int) get_user ((int *) arg);
+	int             val = (int) ioctl_in (arg);
 
 	if (val)
 	  set_timebase (midi_dev, val);
 
-	return snd_ioctl_return ((int *) arg, curr_timebase);
+	return ioctl_out (arg, curr_timebase);
       }
       break;
 
     case SNDCTL_TMR_TEMPO:
       {
-	int             val = (int) get_user ((int *) arg);
+	int             val = (int) ioctl_in (arg);
 	int             ret;
 
 	if (val)
@@ -1657,19 +1668,23 @@
 	    curr_tempo = val;
 	  }
 
-	return snd_ioctl_return ((int *) arg, curr_tempo);
+	return ioctl_out (arg, curr_tempo);
       }
       break;
 
     case SNDCTL_SEQ_CTRLRATE:
-      if (get_user ((int *) arg) != 0)	/* Can't change */
-	return -(EINVAL);
+      if (ioctl_in (arg) != 0)	/* Can't change */
+	return -EINVAL;
+
+      return ioctl_out (arg, ((curr_tempo * curr_timebase) + 30) / 60);
+      break;
 
-      return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60);
+    case SNDCTL_SEQ_GETTIME:
+      return ioctl_out (arg, curr_ticks);
       break;
 
     case SNDCTL_TMR_METRONOME:
-      metronome_mode = (int) get_user ((int *) arg);
+      metronome_mode = (int) ioctl_in (arg);
       setup_metronome (midi_dev);
       return 0;
       break;
@@ -1677,7 +1692,7 @@
     default:;
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/opl3.c linux/drivers/sound/opl3.c
--- v2.1.5/linux/drivers/sound/opl3.c	Wed Oct 16 10:48:23 1996
+++ linux/drivers/sound/opl3.c	Tue Oct 29 09:31:44 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -38,6 +38,7 @@
     unsigned long   current_freq;
     int             volume;
     int             mode;
+    int             panning;	/* 0xffff means not set */
   };
 
 typedef struct opl_devinfo
@@ -123,7 +124,7 @@
 	if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
 	  {
 	    printk ("FM Error: Invalid instrument number %d\n", ins.channel);
-	    return -(EINVAL);
+	    return -EINVAL;
 	  }
 
 	pmgr_inform (dev, PM_E_PATCH_LOADED, ins.channel, 0, 0, 0);
@@ -134,7 +135,11 @@
     case SNDCTL_SYNTH_INFO:
       devc->fm_info.nr_voices = (devc->nr_voice == 12) ? 6 : devc->nr_voice;
 
-      copy_to_user (&((char *) arg)[0], &devc->fm_info, sizeof (devc->fm_info));
+      {
+	char           *fixit = (char *) &devc->fm_info;
+
+	copy_to_user (&((char *) arg)[0], fixit, sizeof (devc->fm_info));
+      };
       return 0;
       break;
 
@@ -149,7 +154,7 @@
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 
 }
@@ -168,7 +173,7 @@
    * Note2! The chip is initialized if detected.
    */
 
-  unsigned char   stat1, stat2, signature;
+  unsigned char   stat1, signature;
   int             i;
 
   if (devc != NULL)
@@ -196,51 +201,12 @@
 
   signature = stat1 = inb (ioaddr);	/* Status register */
 
-  if ((stat1 & 0xE0) != 0x00)
+  if (signature != 0x00 && signature != 0x06 && signature != 0x02)
     {
-      return 0;			/*
-				 * Should be 0x00
-				 */
-    }
-
-  opl3_command (ioaddr, TIMER1_REGISTER, 0xff);		/* Set timer1 to 0xff */
-
-  opl3_command (ioaddr, TIMER_CONTROL_REGISTER,
-		TIMER2_MASK | TIMER1_START);	/*
-						 * Unmask and start timer 1
-						 */
-
-  /*
-   * Now we have to delay at least 80 usec
-   */
-
-  for (i = 0; i < 50; i++)
-    tenmicrosec (devc->osp);
-
-  stat2 = inb (ioaddr);		/*
-				   * Read status after timers have expired
-				 */
-
-  /*
-   * Stop the timers
-   */
-
-  /* Reset timers 1 and 2 */
-  opl3_command (ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK);
-  /* Reset the IRQ of the FM chip */
-  opl3_command (ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET);
-
-  if ((stat2 & 0xE0) != 0xc0)
-    {
-      return 0;			/*
-				 * There is no YM3812
-				 */
+      DDB (printk ("OPL3 not detected %x\n", signature));
+      return 0;
     }
 
-  /*
-   * There is a FM chip in this address. Detect the type (OPL2 to OPL4)
-   */
-
   if (signature == 0x06 && !force_opl3_mode)	/* OPL2 */
     {
       detected_model = 2;
@@ -269,7 +235,7 @@
 	{
 	  int             tmp;
 
-	  outb (0x02, ioaddr - 8);	/* Select OPL4 ID register */
+	  outb ((0x02), ioaddr - 8);	/* Select OPL4 ID register */
 	  tenmicrosec (devc->osp);
 	  tmp = inb (ioaddr - 7);	/* Read it */
 	  tenmicrosec (devc->osp);
@@ -278,9 +244,9 @@
 	    {
 	      detected_model = 4;
 
-	      outb (0xF8, ioaddr - 8);	/* Select OPL4 FM mixer control */
+	      outb ((0xF8), ioaddr - 8);	/* Select OPL4 FM mixer control */
 	      tenmicrosec (devc->osp);
-	      outb (0x1B, ioaddr - 7);	/* Write value */
+	      outb ((0x1B), ioaddr - 7);	/* Write value */
 	      tenmicrosec (devc->osp);
 	    }
 	  else
@@ -297,7 +263,7 @@
 						 */
 
   opl3_command (ioaddr, TEST_REGISTER, ENABLE_WAVE_SELECT);
-  opl3_command (ioaddr, PERCUSSION_REGISTER, 0x00);	/*
+  opl3_command (ioaddr, PERCOSSION_REGISTER, 0x00);	/*
 							 * Melodic mode.
 							 */
 
@@ -326,9 +292,8 @@
   devc->voc[voice].keyon_byte = 0;
   devc->voc[voice].bender = 0;
   devc->voc[voice].volume = 64;
-  devc->voc[voice].bender_range = 200;	/*
-					 * 200 cents = 2 semitones
-					 */
+  devc->voc[voice].panning = 0xffff;	/* Not set */
+  devc->voc[voice].bender_range = 200;
   devc->voc[voice].orig_freq = 0;
   devc->voc[voice].current_freq = 0;
   devc->voc[voice].mode = 0;
@@ -362,7 +327,7 @@
     return 0;
 
   if (instr_no < 0 || instr_no >= SBFM_MAXINSTR)
-    return 0;
+    instr_no = 0;		/* Acoustic piano (usually) */
 
   devc->act_i[voice] = &devc->i_map[instr_no];
   return 0;
@@ -512,7 +477,7 @@
 opl3_start_note (int dev, int voice, int note, int volume)
 {
   unsigned char   data, fpc;
-  int             block, fnum, freq, voice_mode;
+  int             block, fnum, freq, voice_mode, pan;
   struct sbi_instrument *instr;
   struct physical_voice_info *map;
 
@@ -520,6 +485,7 @@
     return 0;
 
   map = &pv_map[devc->lv_map[voice]];
+  pan = devc->voc[voice].panning;
 
   if (map->voice_mode == 0)
     return 0;
@@ -626,6 +592,19 @@
    * Set Feedback/Connection
    */
   fpc = instr->operators[10];
+
+  if (pan != 0xffff)
+    {
+      fpc &= ~STEREO_BITS;
+
+      if (pan < -64)
+	fpc |= VOICE_TO_LEFT;
+      else if (pan > 64)
+	fpc |= VOICE_TO_RIGHT;
+      else
+	fpc |= (VOICE_TO_LEFT | VOICE_TO_RIGHT);
+    }
+
   if (!(fpc & 0x30))
     fpc |= 0x30;		/*
 				 * Ensure that at least one chn is enabled
@@ -761,7 +740,7 @@
    * register. The OPL-3 survives with just two INBs
    */
 
-  outb ((unsigned char) (addr & 0xff), io_addr);
+  outb (((unsigned char) (addr & 0xff)), io_addr);
 
   if (!devc->model != 2)
     tenmicrosec (devc->osp);
@@ -769,7 +748,7 @@
     for (i = 0; i < 2; i++)
       inb (io_addr);
 
-  outb ((unsigned char) (val & 0xff), io_addr + 1);
+  outb (((unsigned char) (val & 0xff)), io_addr + 1);
 
   if (devc->model != 2)
     {
@@ -827,7 +806,7 @@
   int             i;
 
   if (devc->busy)
-    return -(EBUSY);
+    return -EBUSY;
   devc->busy = 1;
 
   devc->v_alloc->max_voice = devc->nr_voice = (devc->model == 2) ? 18 : 9;
@@ -873,7 +852,7 @@
   if (count < sizeof (ins))
     {
       printk ("FM Error: Patch record too short\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   copy_from_user (&((char *) &ins)[offs], &(addr)[offs], sizeof (ins) - offs);
@@ -881,7 +860,7 @@
   if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
     {
       printk ("FM Error: Invalid instrument number %d\n", ins.channel);
-      return -(EINVAL);
+      return -EINVAL;
     }
   ins.key = format;
 
@@ -889,8 +868,9 @@
 }
 
 static void
-opl3_panning (int dev, int voice, int pressure)
+opl3_panning (int dev, int voice, int value)
 {
+  devc->voc[voice].panning = value;
 }
 
 static void
@@ -1004,14 +984,7 @@
 				 */
   opl3_command (map->ioaddr, FNUM_LOW + map->voice_num, data);
 
-  data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3);	/*
-								 * *
-								 * KEYON|OCTAVE|MS
-								 *
-								 * * bits * *
-								 * of * f-num
-								 *
-								 */
+  data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3);
   devc->voc[voice].keyon_byte = data;
   opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, data);
 }
@@ -1035,13 +1008,17 @@
     case CTL_MAIN_VOLUME:
       devc->voc[voice].volume = value / 128;
       break;
+
+    case CTL_PAN:
+      devc->voc[voice].panning = (value * 2) - 128;
+      break;
     }
 }
 
 static int
 opl3_patchmgr (int dev, struct patmgr_info *rec)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -1132,6 +1109,7 @@
   devc->voc[voice].bender = info->bender_value;
   devc->voc[voice].volume =
     info->controllers[CTL_MAIN_VOLUME];
+  devc->voc[voice].panning = (info->controllers[CTL_PAN] * 2) - 128;
 }
 
 static struct synth_operations opl3_operations =
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/opl3.h linux/drivers/sound/opl3.h
--- v2.1.5/linux/drivers/sound/opl3.h	Sat Jul  6 11:31:43 1996
+++ linux/drivers/sound/opl3.h	Tue Oct 29 09:31:08 1996
@@ -4,7 +4,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -69,10 +69,10 @@
 #define   COMPOSITE_SINE_WAVE_MODE	0x80		/* Don't use with OPL-3? */
 #define   KEYBOARD_SPLIT		0x40
 
-#define PERCUSSION_REGISTER			0xbd	/* Left side only */
+#define PERCOSSION_REGISTER			0xbd	/* Left side only */
 #define   TREMOLO_DEPTH			0x80
 #define   VIBRATO_DEPTH			0x40
-#define	  PERCUSSION_ENABLE		0x20
+#define	  PERCOSSION_ENABLE		0x20
 #define   BASSDRUM_ON			0x10
 #define   SNAREDRUM_ON			0x08
 #define   TOMTOM_ON			0x04
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/os.h linux/drivers/sound/os.h
--- v2.1.5/linux/drivers/sound/os.h	Wed Sep 25 12:21:48 1996
+++ linux/drivers/sound/os.h	Tue Oct 29 14:51:02 1996
@@ -1,8 +1,3 @@
-
-#define ALLOW_SELECT
-#undef NO_INLINE_ASM
-#define SHORT_BANNERS
-
 #ifdef MODULE
 #define __NO_VERSION__
 #include <linux/module.h>
@@ -20,7 +15,7 @@
 #include <linux/sched.h>
 #include <linux/ctype.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/dma.h>
 #include <linux/wait.h>
@@ -38,7 +33,7 @@
 #define TRUE	1
 
 struct snd_wait {
-	  int flags;
+	  int opts;
 	};
 
 extern int sound_alloc_dma(int chn, char *deviceID);
@@ -46,11 +41,5 @@
 extern void sound_free_dma(int chn);
 extern void sound_close_dma(int chn);
 
-#define RUNTIME_DMA_ALLOC
-
 extern caddr_t sound_mem_blocks[1024];
 extern int sound_nblocks;
-
-#undef PSEUDO_DMA_AUTOINIT
-#define ALLOW_BUFFER_MAPPING
-
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/pas2_card.c linux/drivers/sound/pas2_card.c
--- v2.1.5/linux/drivers/sound/pas2_card.c	Sat Jul  6 11:31:42 1996
+++ linux/drivers/sound/pas2_card.c	Tue Oct 29 09:31:44 1996
@@ -6,7 +6,6 @@
  */
 
 #include <linux/config.h>
-
 #include "sound_config.h"
 
 #if defined(CONFIG_PAS)
@@ -30,7 +29,6 @@
 static int      pas_irq = 0;
 static int      pas_sb_base = 0;
 
-int            *pas_osp;
 
 char            pas_model;
 static char    *pas_model_names[] =
@@ -52,7 +50,7 @@
 void
 pas_write (unsigned char data, int ioaddr)
 {
-  outb (data, ioaddr ^ translate_code);
+  outb ((data), ioaddr ^ translate_code);
 }
 
 /******************* Begin of the Interrupt Handler ********************/
@@ -203,8 +201,8 @@
      * as per Media Vision.  Only define this if your PAS doesn't work correctly.
    */
 #ifdef SYMPHONY_PAS
-  outb (0x05, 0xa8);
-  outb (0x60, 0xa9);
+  outb ((0x05), 0xa8);
+  outb ((0x60), 0xa9);
 #endif
 
 #ifdef BROKEN_BUS_CLOCK
@@ -282,8 +280,8 @@
    * you have something on base port 0x388. SO be forewarned.
    */
 
-  outb (0xBC, 0x9A01);		/* Activate first board */
-  outb (hw_config->io_base >> 2, 0x9A01);	/* Set base address */
+  outb ((0xBC), 0x9A01);	/* Activate first board */
+  outb ((hw_config->io_base >> 2), 0x9A01);	/* Set base address */
   translate_code = 0x388 ^ hw_config->io_base;
   pas_write (1, 0xBF88);	/* Select one wait states */
 
@@ -318,7 +316,6 @@
 attach_pas_card (struct address_info *hw_config)
 {
   pas_irq = hw_config->irq;
-  pas_osp = hw_config->osp;
 
   if (detect_pas_hw (hw_config))
     {
@@ -359,7 +356,6 @@
 int
 probe_pas (struct address_info *hw_config)
 {
-  pas_osp = hw_config->osp;
   return detect_pas_hw (hw_config);
 }
 
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/pas2_midi.c linux/drivers/sound/pas2_midi.c
--- v2.1.5/linux/drivers/sound/pas2_midi.c	Sun Jun 30 12:31:09 1996
+++ linux/drivers/sound/pas2_midi.c	Tue Oct 29 16:36:36 1996
@@ -4,15 +4,13 @@
  * The low level driver for the PAS Midi Interface.
  */
 
-#include <linux/config.h>
-
 #include "sound_config.h"
+#include <linux/config.h>
 
 #if defined(CONFIG_PAS) && defined(CONFIG_MIDI)
 
 static int      midi_busy = 0, input_opened = 0;
 static int      my_dev;
-static volatile int ofifo_bytes = 0;
 
 static unsigned char tmp_queue[256];
 static volatile int qlen;
@@ -34,7 +32,7 @@
   if (midi_busy)
     {
       printk ("PAS2: Midi busy\n");
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   /*
@@ -59,29 +57,22 @@
 
   if (mode == OPEN_READ || mode == OPEN_READWRITE)
     {
-      ctrl |= 0x04;		/*
-				   * Enable input
-				 */
+      ctrl |= 0x04;		/* Enable input */
       input_opened = 1;
     }
 
   if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
     {
-      ctrl |= 0x08 |		/*
-				   * Enable output
-				 */
-	0x10;
+      ctrl |= 0x08 | 0x10;	/* Enable output */
     }
 
-  pas_write (ctrl,
-	     0x178b);
+  pas_write (ctrl, 0x178b);
 
   /*
    * Acknowledge any pending interrupts
    */
 
   pas_write (0xff, 0x1B88);
-  ofifo_bytes = 0;
 
   restore_flags (flags);
 
@@ -110,18 +101,19 @@
 
   fifo_space = ((x = pas_read (0x1B89)) >> 4) & 0x0f;
 
-  if (fifo_space == 15 || (fifo_space < 2 && ofifo_bytes > 13))		/*
-									   * Fifo
-									   * full
-									 */
+/*
+ * The MIDI FIFO space register and it's documentation is nonunderstandable.
+ * There seem to be no way to differentiate between buffer full and buffer
+ * empty situations. For this reason we don't never write the buffer
+ * completely full. In this way we can assume that 0 (or is it 15)
+ * means that the buffer is empty.
+ */
+
+  if (fifo_space < 2 && fifo_space != 0)	/* Full (almost) */
     {
-      return 0;			/*
-				 * Upper layer will call again
-				 */
+      return 0;			/* Ask upper layers to retry after some time */
     }
 
-  ofifo_bytes++;
-
   pas_write (midi_byte, 0x178A);
 
   return 1;
@@ -154,18 +146,14 @@
 
   if (!qlen)
     if (dump_to_midi (midi_byte))
-      return 1;			/*
-				 * OK
-				 */
+      return 1;
 
   /*
    * Put to the local queue
    */
 
   if (qlen >= 256)
-    return 0;			/*
-				 * Local queue full
-				 */
+    return 0;			/* Local queue full */
 
   save_flags (flags);
   cli ();
@@ -194,13 +182,12 @@
 static int
 pas_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
 pas_midi_kick (int dev)
 {
-  ofifo_bytes = 0;
 }
 
 static int
@@ -225,9 +212,7 @@
   pas_midi_start_read,
   pas_midi_end_read,
   pas_midi_kick,
-  NULL,				/*
-				 * command
-				 */
+  NULL,
   pas_buffer_status,
   NULL
 };
@@ -254,13 +239,9 @@
 
   stat = pas_read (0x1B88);
 
-  if (stat & 0x04)		/*
-				   * Input byte available
-				 */
+  if (stat & 0x04)		/* Input data available */
     {
-      incount = pas_read (0x1B89) & 0x0f;	/*
-						   * Input FIFO count
-						 */
+      incount = pas_read (0x1B89) & 0x0f;	/* Input FIFO size */
       if (!incount)
 	incount = 16;
 
@@ -270,22 +251,11 @@
 	    midi_input_intr (my_dev, pas_read (0x178A));
 	  }
 	else
-	  pas_read (0x178A);	/*
-				 * Flush
-				 */
+	  pas_read (0x178A);	/* Flush */
     }
 
   if (stat & (0x08 | 0x10))
     {
-      if (!(stat & 0x08))
-	{
-	  ofifo_bytes = 8;
-	}
-      else
-	{
-	  ofifo_bytes = 0;
-	}
-
       save_flags (flags);
       cli ();
 
@@ -301,13 +271,10 @@
 
   if (stat & 0x40)
     {
-      printk ("MIDI output overrun %x,%x,%d \n", pas_read (0x1B89), stat, ofifo_bytes);
-      ofifo_bytes = 100;
+      printk ("MIDI output overrun %x,%x\n", pas_read (0x1B89), stat);
     }
 
-  pas_write (stat, 0x1B88);	/*
-				   * Acknowledge interrupts
-				 */
+  pas_write (stat, 0x1B88);	/* Acknowledge interrupts */
 }
 
 #endif
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/pas2_mixer.c linux/drivers/sound/pas2_mixer.c
--- v2.1.5/linux/drivers/sound/pas2_mixer.c	Sun Aug 18 10:46:49 1996
+++ linux/drivers/sound/pas2_mixer.c	Tue Oct 29 09:31:45 1996
@@ -5,9 +5,8 @@
  *
  * Mixer routines for the Pro Audio Spectrum cards.
  */
-   
-#include <linux/config.h>
 
+#include <linux/config.h>
 #include "sound_config.h"
 
 #if defined(CONFIG_PAS)
@@ -31,8 +30,9 @@
 					 SOUND_MASK_CD | SOUND_MASK_ALTPCM | SOUND_MASK_IMIX | \
 					 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_RECLEV)
 
+static int     *levels;
 
-static unsigned short levels[SOUND_MIXER_NRDEVICES] =
+static int      default_levels[32] =
 {
   0x3232,			/* Master Volume */
   0x3232,			/* Bass */
@@ -62,7 +62,7 @@
   if (pas_model == 4)
     {
       outw (data | (data << 8), (ioaddr ^ translate_code) - 1);
-      outb (0x80, 0);
+      outb ((0x80), 0);
     }
   else
     pas_write (data, ioaddr);
@@ -190,7 +190,7 @@
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   return (levels[whichDev]);
@@ -218,14 +218,16 @@
 
   if (cmd == SOUND_MIXER_PRIVATE1)	/* Set loudness bit */
     {
-      int             level = get_user ((int *) arg);
+      int             level;
+
+      get_user (level, (int *) arg);
 
       if (level == -1)		/* Return current settings */
 	{
 	  if (mode_control & 0x04)
-	    return snd_ioctl_return ((int *) arg, 1);
+	    return ioctl_out (arg, 1);
 	  else
-	    return snd_ioctl_return ((int *) arg, 0);
+	    return ioctl_out (arg, 0);
 	}
       else
 	{
@@ -233,20 +235,22 @@
 	  if (level)
 	    mode_control |= 0x04;
 	  set_mode (mode_control);
-	  return snd_ioctl_return ((int *) arg, !!level);	/* 0 or 1 */
+	  return ioctl_out (arg, !!level);	/* 0 or 1 */
 	}
     }
 
 
   if (cmd == SOUND_MIXER_PRIVATE2)	/* Set enhance bit */
     {
-      int             level = get_user ((int *) arg);
+      int             level;
+
+      get_user (level, (int *) arg);
 
       if (level == -1)		/* Return current settings */
 	{
 	  if (!(mode_control & 0x03))
-	    return snd_ioctl_return ((int *) arg, 0);
-	  return snd_ioctl_return ((int *) arg, ((mode_control & 0x03) + 1) * 20);
+	    return ioctl_out (arg, 0);
+	  return ioctl_out (arg, ((mode_control & 0x03) + 1) * 20);
 	}
       else
 	{
@@ -269,13 +273,13 @@
 
   if (cmd == SOUND_MIXER_PRIVATE3)	/* Set mute bit */
     {
-      int             level = get_user ((int *) arg);
+      int             level;
+
+      get_user (level, (int *) arg);
 
       if (level == -1)		/* Return current settings */
 	{
-	  return snd_ioctl_return ((int *) arg,
-				   !(pas_read (0x0B8A) &
-				     0x20));
+	  return ioctl_out (arg, !(pas_read (0x0B8A) & 0x20));
 	}
       else
 	{
@@ -293,7 +297,7 @@
   if (((cmd >> 8) & 0xff) == 'M')
     {
       if (_IOC_DIR (cmd) & _IOC_WRITE)
-	return snd_ioctl_return ((int *) arg, pas_mixer_set (cmd & 0xff, get_user ((int *) arg)));
+	return ioctl_out (arg, pas_mixer_set (cmd & 0xff, ioctl_in (arg)));
       else
 	{			/*
 				 * Read parameters
@@ -303,32 +307,32 @@
 	    {
 
 	    case SOUND_MIXER_RECSRC:
-	      return snd_ioctl_return ((int *) arg, rec_devices);
+	      return ioctl_out (arg, rec_devices);
 	      break;
 
 	    case SOUND_MIXER_STEREODEVS:
-	      return snd_ioctl_return ((int *) arg, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE));
+	      return ioctl_out (arg, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE));
 	      break;
 
 	    case SOUND_MIXER_DEVMASK:
-	      return snd_ioctl_return ((int *) arg, SUPPORTED_MIXER_DEVICES);
+	      return ioctl_out (arg, SUPPORTED_MIXER_DEVICES);
 	      break;
 
 	    case SOUND_MIXER_RECMASK:
-	      return snd_ioctl_return ((int *) arg, POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES);
+	      return ioctl_out (arg, POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES);
 	      break;
 
 	    case SOUND_MIXER_CAPS:
-	      return snd_ioctl_return ((int *) arg, 0);		/* No special capabilities */
+	      return ioctl_out (arg, 0);	/* No special capabilities */
 	      break;
 
 
 	    default:
-	      return snd_ioctl_return ((int *) arg, levels[cmd & 0xff]);
+	      return ioctl_out (arg, levels[cmd & 0xff]);
 	    }
 	}
     }
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static struct mixer_operations pas_mixer_operations =
@@ -341,6 +345,8 @@
 int
 pas_init_mixer (void)
 {
+  levels = load_mixer_volumes ("PAS16_1", default_levels, 1);
+
   pas_mixer_reset ();
 
   if (num_mixers < MAX_MIXER_DEV)
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/pas2_pcm.c linux/drivers/sound/pas2_pcm.c
--- v2.1.5/linux/drivers/sound/pas2_pcm.c	Sun Aug 18 10:46:49 1996
+++ linux/drivers/sound/pas2_pcm.c	Tue Oct 29 09:31:46 1996
@@ -4,9 +4,8 @@
  *
  * The low level driver for the Pro Audio Spectrum ADC/DAC.
  */
-   
-#include <linux/config.h>
 
+#include <linux/config.h>
 #include "sound_config.h"
 
 #if defined(CONFIG_PAS) && defined(CONFIG_AUDIO)
@@ -42,7 +41,7 @@
   unsigned long   flags;
 
   if (arg == 0)
-     return pcm_speed;
+    return pcm_speed;
 
   if (arg > 44100)
     arg = 44100;
@@ -131,7 +130,7 @@
 pcm_set_bits (int arg)
 {
   if (arg == 0)
-     return pcm_bits;
+    return pcm_bits;
 
   if ((arg & pcm_bitsok) != arg)
     return pcm_bits;
@@ -156,61 +155,61 @@
     case SOUND_PCM_WRITE_RATE:
       if (local)
 	return pcm_set_speed ((int) arg);
-      return snd_ioctl_return ((int *) arg, pcm_set_speed (get_user ((int *) arg)));
+      return ioctl_out (arg, pcm_set_speed (ioctl_in (arg)));
       break;
 
     case SOUND_PCM_READ_RATE:
       if (local)
 	return pcm_speed;
-      return snd_ioctl_return ((int *) arg, pcm_speed);
+      return ioctl_out (arg, pcm_speed);
       break;
 
     case SNDCTL_DSP_STEREO:
       if (local)
 	return pcm_set_channels ((int) arg + 1) - 1;
-      return snd_ioctl_return ((int *) arg, pcm_set_channels (get_user ((int *) arg) + 1) - 1);
+      return ioctl_out (arg, pcm_set_channels (ioctl_in (arg) + 1) - 1);
       break;
 
     case SOUND_PCM_WRITE_CHANNELS:
       if (local)
 	return pcm_set_channels ((int) arg);
-      return snd_ioctl_return ((int *) arg, pcm_set_channels (get_user ((int *) arg)));
+      return ioctl_out (arg, pcm_set_channels (ioctl_in (arg)));
       break;
 
     case SOUND_PCM_READ_CHANNELS:
       if (local)
 	return pcm_channels;
-      return snd_ioctl_return ((int *) arg, pcm_channels);
+      return ioctl_out (arg, pcm_channels);
       break;
 
     case SNDCTL_DSP_SETFMT:
       if (local)
 	return pcm_set_bits ((int) arg);
-      return snd_ioctl_return ((int *) arg, pcm_set_bits (get_user ((int *) arg)));
+      return ioctl_out (arg, pcm_set_bits (ioctl_in (arg)));
       break;
 
     case SOUND_PCM_READ_BITS:
       if (local)
 	return pcm_bits;
-      return snd_ioctl_return ((int *) arg, pcm_bits);
+      return ioctl_out (arg, pcm_bits);
 
     case SOUND_PCM_WRITE_FILTER:	/*
 					 * NOT YET IMPLEMENTED
 					 */
-      if (get_user ((int *) arg) > 1)
-	return -(EINVAL);
-      pcm_filter = get_user ((int *) arg);
+      if (ioctl_in (arg) > 1)
+	return -EINVAL;
+      pcm_filter = ioctl_in (arg);
       break;
 
     case SOUND_PCM_READ_FILTER:
-      return snd_ioctl_return ((int *) arg, pcm_filter);
+      return ioctl_out (arg, pcm_filter);
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -234,7 +233,7 @@
   if (pcm_busy)
     {
       restore_flags (flags);
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   pcm_busy = 1;
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/patmgr.c linux/drivers/sound/patmgr.c
--- v2.1.5/linux/drivers/sound/patmgr.c	Wed Oct 16 10:48:23 1996
+++ linux/drivers/sound/patmgr.c	Tue Oct 29 09:31:46 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -18,7 +18,7 @@
 
 #if defined(CONFIG_SEQUENCER)
 
-static wait_handle *server_procs[MAX_SYNTH_DEV] =
+static struct wait_queue *server_procs[MAX_SYNTH_DEV] =
 {NULL};
 static volatile struct snd_wait server_wait_flag[MAX_SYNTH_DEV] =
 {
@@ -35,7 +35,7 @@
 #define A_TO_S	1
 #define S_TO_A 	2
 
-static wait_handle *appl_proc = NULL;
+static struct wait_queue *appl_proc = NULL;
 static volatile struct snd_wait appl_wait_flag =
 {0};
 
@@ -43,13 +43,13 @@
 pmgr_open (int dev)
 {
   if (dev < 0 || dev >= num_synths)
-    return -(ENXIO);
+    return -ENXIO;
 
   if (pmgr_opened[dev])
-    return -(EBUSY);
+    return -EBUSY;
   pmgr_opened[dev] = 1;
 
-  server_wait_flag[dev].flags = WK_NONE;
+  server_wait_flag[dev].opts = WK_NONE;
 
   return 0;
 }
@@ -64,12 +64,12 @@
     {
 
       mbox[dev]->key = PM_ERROR;
-      mbox[dev]->parm1 = -(EIO);
+      mbox[dev]->parm1 = -EIO;
 
-      if ((appl_wait_flag.flags & WK_SLEEP))
+      if ((appl_wait_flag.opts & WK_SLEEP))
 	{
-	  appl_wait_flag.flags = WK_WAKEUP;
-	  module_wake_up (&appl_proc);
+	  appl_wait_flag.opts = WK_WAKEUP;
+	  wake_up (&appl_proc);
 	};
     }
 
@@ -85,26 +85,30 @@
   if (count != sizeof (struct patmgr_info))
     {
       printk ("PATMGR%d: Invalid read count\n", dev);
-      return -(EIO);
+      return -EIO;
     }
 
-  while (!ok && !current_got_fatal_signal ())
+  while (!ok && !(current->signal & ~current->blocked))
     {
       save_flags (flags);
       cli ();
 
       while (!(mbox[dev] && msg_direction[dev] == A_TO_S) &&
-	     !current_got_fatal_signal ())
+	     !(current->signal & ~current->blocked))
 	{
 
-	  server_wait_flag[dev].flags = WK_SLEEP;
-	  module_interruptible_sleep_on (&server_procs[dev]);
-	  server_wait_flag[dev].flags &= ~WK_SLEEP;;
+	  server_wait_flag[dev].opts = WK_SLEEP;
+	  interruptible_sleep_on (&server_procs[dev]);
+	  server_wait_flag[dev].opts &= ~WK_SLEEP;;
 	}
 
       if (mbox[dev] && msg_direction[dev] == A_TO_S)
 	{
-	  copy_to_user (&(buf)[0], (char *) mbox[dev], count);
+	  {
+	    char           *fixit = (char *) mbox[dev];
+
+	    copy_to_user (&(buf)[0], fixit, count);
+	  };
 	  msg_direction[dev] = 0;
 	  ok = 1;
 	}
@@ -114,7 +118,7 @@
     }
 
   if (!ok)
-    return -(EINTR);
+    return -EINTR;
   return count;
 }
 
@@ -126,7 +130,7 @@
   if (count < 4)
     {
       printk ("PATMGR%d: Write count < 4\n", dev);
-      return -(EIO);
+      return -EIO;
     }
 
   copy_from_user ((char *) mbox[dev], &(buf)[0], 4);
@@ -137,7 +141,7 @@
 
       tmp_dev = ((unsigned short *) mbox[dev])[2];
       if (tmp_dev != dev)
-	return -(ENXIO);
+	return -ENXIO;
 
       return synth_devs[dev]->load_patch (dev, *(unsigned short *) mbox[dev],
 					  buf, 4, count, 1);
@@ -146,7 +150,7 @@
   if (count != sizeof (struct patmgr_info))
     {
       printk ("PATMGR%d: Invalid write count\n", dev);
-      return -(EIO);
+      return -EIO;
     }
 
   /*
@@ -162,11 +166,11 @@
       copy_from_user (&((char *) mbox[dev])[4], &(buf)[4], count - 4);
       msg_direction[dev] = S_TO_A;
 
-      if ((appl_wait_flag.flags & WK_SLEEP))
+      if ((appl_wait_flag.opts & WK_SLEEP))
 	{
 	  {
-	    appl_wait_flag.flags = WK_WAKEUP;
-	    module_wake_up (&appl_proc);
+	    appl_wait_flag.opts = WK_WAKEUP;
+	    wake_up (&appl_proc);
 	  };
 	}
     }
@@ -193,23 +197,23 @@
       mbox[dev] = rec;
       msg_direction[dev] = A_TO_S;
 
-      if ((server_wait_flag[dev].flags & WK_SLEEP))
+      if ((server_wait_flag[dev].opts & WK_SLEEP))
 	{
 	  {
-	    server_wait_flag[dev].flags = WK_WAKEUP;
-	    module_wake_up (&server_procs[dev]);
+	    server_wait_flag[dev].opts = WK_WAKEUP;
+	    wake_up (&server_procs[dev]);
 	  };
 	}
 
 
-      appl_wait_flag.flags = WK_SLEEP;
-      module_interruptible_sleep_on (&appl_proc);
-      appl_wait_flag.flags &= ~WK_SLEEP;;
+      appl_wait_flag.opts = WK_SLEEP;
+      interruptible_sleep_on (&appl_proc);
+      appl_wait_flag.opts &= ~WK_SLEEP;;
 
       if (msg_direction[dev] != S_TO_A)
 	{
 	  rec->key = PM_ERROR;
-	  rec->parm1 = -(EIO);
+	  rec->parm1 = -EIO;
 	}
       else if (rec->key == PM_ERROR)
 	{
@@ -263,18 +267,18 @@
       mbox[dev]->parm3 = p3;
       msg_direction[dev] = A_TO_S;
 
-      if ((server_wait_flag[dev].flags & WK_SLEEP))
+      if ((server_wait_flag[dev].opts & WK_SLEEP))
 	{
 	  {
-	    server_wait_flag[dev].flags = WK_WAKEUP;
-	    module_wake_up (&server_procs[dev]);
+	    server_wait_flag[dev].opts = WK_WAKEUP;
+	    wake_up (&server_procs[dev]);
 	  };
 	}
 
 
-      appl_wait_flag.flags = WK_SLEEP;
-      module_interruptible_sleep_on (&appl_proc);
-      appl_wait_flag.flags &= ~WK_SLEEP;;
+      appl_wait_flag.opts = WK_SLEEP;
+      interruptible_sleep_on (&appl_proc);
+      appl_wait_flag.opts &= ~WK_SLEEP;;
       mbox[dev] = NULL;
       msg_direction[dev] = 0;
     }
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/pss.c linux/drivers/sound/pss.c
--- v2.1.5/linux/drivers/sound/pss.c	Wed Oct 16 10:48:24 1996
+++ linux/drivers/sound/pss.c	Tue Oct 29 09:31:47 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -74,6 +74,31 @@
 static int      pss_initialized = 0;
 static int      nonstandard_microcode = 0;
 
+static void
+pss_write (int data)
+{
+  int             i, limit;
+
+  limit = jiffies + 10;		/* The timeout is 0.1 seconds */
+  /*
+   * Note! the i<5000000 is an emergency exit. The dsp_command() is sometimes
+   * called while interrupts are disabled. This means that the timer is
+   * disabled also. However the timeout situation is a abnormal condition.
+   * Normally the DSP should be ready to accept commands after just couple of
+   * loops.
+   */
+
+  for (i = 0; i < 5000000 && jiffies < limit; i++)
+    {
+      if (inw (devc->base + PSS_STATUS) & PSS_WRITE_EMPTY)
+	{
+	  outw (devc->base + PSS_DATA, data);
+	  return;
+	}
+    }
+  printk ("PSS: DSP Command (%04x) Timeout.\n", data);
+}
+
 int
 probe_pss (struct address_info *hw_config)
 {
@@ -354,6 +379,22 @@
   conf_printf (tmp, hw_config);
 }
 
+static void
+pss_init_speaker (void)
+{
+/* Don't ask what are these commands. I really don't know */
+  pss_write (0x0010);
+  pss_write (0x0000 | 252);	/* Left master volume */
+  pss_write (0x0010);
+  pss_write (0x0100 | 252);	/* Right master volume */
+  pss_write (0x0010);
+  pss_write (0x0200 | 246);	/* Bass */
+  pss_write (0x0010);
+  pss_write (0x0300 | 246);	/* Treble */
+  pss_write (0x0010);
+  pss_write (0x0800 | 0x00ce);	/* Stereo switch? */
+}
+
 int
 probe_pss_mpu (struct address_info *hw_config)
 {
@@ -392,6 +433,8 @@
       return 0;
     }
 
+  pss_init_speaker ();
+
 /*
  * Finally wait until the DSP algorithm has initialized itself and
  * deactivates receive interrupt.
@@ -422,14 +465,14 @@
       if (pss_synthLen == 0)
 	{
 	  printk ("PSS: MIDI synth microcode not available.\n");
-	  return -(EIO);
+	  return -EIO;
 	}
 
       if (nonstandard_microcode)
 	if (!pss_download_boot (devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
 	  {
 	    printk ("PSS: Unable to load MIDI synth microcode to DSP.\n");
-	    return -(EIO);
+	    return -EIO;
 	  }
       nonstandard_microcode = 0;
       break;
@@ -460,12 +503,12 @@
 download_boot_block (void *dev_info, copr_buffer * buf)
 {
   if (buf->len <= 0 || buf->len > sizeof (buf->data))
-    return -(EINVAL);
+    return -EINVAL;
 
   if (!pss_download_boot (devc, buf->data, buf->len, buf->flags))
     {
       printk ("PSS: Unable to load microcode block to DSP.\n");
-      return -(EIO);
+      return -EIO;
     }
   nonstandard_microcode = 1;	/* The MIDI microcode has been overwritten */
 
@@ -491,7 +534,7 @@
 
 	buf = (copr_buffer *) vmalloc (sizeof (copr_buffer));
 	if (buf == NULL)
-	  return -(ENOSPC);
+	  return -ENOSPC;
 
 	copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
 	err = download_boot_block (dev_info, buf);
@@ -509,7 +552,7 @@
 
 	buf = (copr_msg *) vmalloc (sizeof (copr_msg));
 	if (buf == NULL)
-	  return -(ENOSPC);
+	  return -ENOSPC;
 
 	copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
 
@@ -524,9 +567,13 @@
 	      {
 		restore_flags (flags);
 		buf->len = i;	/* feed back number of WORDs sent */
-		copy_to_user (&((char *) arg)[0], &buf, sizeof (buf));
+		{
+		  char           *fixit = (char *) buf;
+
+		  copy_to_user (&((char *) arg)[0], fixit, sizeof (*buf));
+		};
 		vfree (buf);
-		return -(EIO);
+		return -EIO;
 	      }
 	  }
 
@@ -548,7 +595,7 @@
 
 	buf = (copr_msg *) vmalloc (sizeof (copr_msg));
 	if (buf == NULL)
-	  return -(ENOSPC);
+	  return -ENOSPC;
 
 
 	data = (unsigned short *) buf->data;
@@ -562,14 +609,18 @@
 	    if (!pss_get_dspword (devc, data++))
 	      {
 		if (i == 0)
-		  err = -(EIO);
+		  err = -EIO;
 		break;
 	      }
 	  }
 
 	restore_flags (flags);
 
-	copy_to_user (&((char *) arg)[0], &buf, sizeof (buf));
+	{
+	  char           *fixit = (char *) buf;
+
+	  copy_to_user (&((char *) arg)[0], fixit, sizeof (*buf));
+	};
 	vfree (buf);
 
 	return err;
@@ -590,25 +641,29 @@
 	if (!pss_put_dspword (devc, 0x00d0))
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	if (!pss_get_dspword (devc, &tmp))
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	buf.parm1 = tmp;
 	restore_flags (flags);
 
-	copy_to_user (&((char *) arg)[0], &buf, sizeof (buf));
+	{
+	  char           *fixit = (char *) &buf;
+
+	  copy_to_user (&((char *) arg)[0], fixit, sizeof (buf));
+	};
 	return 0;
       }
       break;
@@ -626,20 +681,20 @@
 	if (!pss_put_dspword (devc, 0x00d1))
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	tmp = (unsigned int) buf.parm2 & 0xffff;
 	if (!pss_put_dspword (devc, tmp))
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	restore_flags (flags);
@@ -660,27 +715,27 @@
 	if (!pss_put_dspword (devc, 0x00d3))
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	tmp = (unsigned int) buf.parm2 & 0x00ff;
 	if (!pss_put_dspword (devc, tmp))
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	tmp = ((unsigned int) buf.parm2 >> 8) & 0xffff;
 	if (!pss_put_dspword (devc, tmp))
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	restore_flags (flags);
@@ -701,19 +756,19 @@
 	if (!pss_put_dspword (devc, 0x00d2))
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	if (!pss_get_dspword (devc, &tmp))	/* Read MSB */
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	buf.parm1 = tmp << 8;
@@ -721,23 +776,27 @@
 	if (!pss_get_dspword (devc, &tmp))	/* Read LSB */
 	  {
 	    restore_flags (flags);
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	buf.parm1 |= tmp & 0x00ff;
 
 	restore_flags (flags);
 
-	copy_to_user (&((char *) arg)[0], &buf, sizeof (buf));
+	{
+	  char           *fixit = (char *) &buf;
+
+	  copy_to_user (&((char *) arg)[0], fixit, sizeof (buf));
+	};
 	return 0;
       }
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static coproc_operations pss_coproc_operations =
@@ -769,7 +828,7 @@
 int
 probe_pss_mss (struct address_info *hw_config)
 {
-  int             timeout;
+  volatile int    timeout;
 
   if (!pss_initialized)
     return 0;
@@ -808,7 +867,11 @@
        timeout < 100000 && (inb (hw_config->io_base + 3) & 0x3f) != 0x04;
        timeout++);
 
-  outb (0x0b, hw_config->io_base + 4);	/* Required by some cards */
+  outb ((0x0b), hw_config->io_base + 4);	/* Required by some cards */
+
+  for (timeout = 0;
+       timeout < 100000;
+       timeout++);
   return probe_ms_sound (hw_config);
 }
 
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sb.h linux/drivers/sound/sb.h
--- v2.1.5/linux/drivers/sound/sb.h	Sun Jul  7 20:08:16 1996
+++ linux/drivers/sound/sb.h	Tue Oct 29 09:31:09 1996
@@ -36,6 +36,7 @@
 #define MDL_SB201	3	/* SB2.01 */
 #define MDL_SBPRO	4	/* SB Pro */
 #define MDL_SB16	5	/* SB16/32/AWE */
+#define MDL_SBPNP 	6	/* SB16/32/AWE PnP */
 #define MDL_JAZZ	10	/* Media Vision Jazz16 */
 #define MDL_SMW		11	/* Logitech SoundMan Wave (Jazz16) */
 #define MDL_ESS		12	/* ESS ES688 and ES1688 */
@@ -83,11 +84,12 @@
 	   volatile int intr_active, irq_mode;
 
 	/* Mixer fields */
-	   unsigned short levels[SOUND_MIXER_NRDEVICES];
+	   int *levels;
 	   mixer_tab *iomap;
 	   int mixer_caps, recmask, supported_devices;
 	   int supported_rec_devices;
 	   int my_mixerdev;
+	   int sbmixnum;
 
 	/* Audio fields */
 	   unsigned long trg_buf;
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sb_audio.c linux/drivers/sound/sb_audio.c
--- v2.1.5/linux/drivers/sound/sb_audio.c	Wed Aug 14 10:21:03 1996
+++ linux/drivers/sound/sb_audio.c	Tue Oct 29 09:31:49 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -29,13 +29,13 @@
   if (devc == NULL)
     {
       printk ("SB: Incomplete initialization\n");
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   if (devc->caps & SB_NO_RECORDING && mode & OPEN_READ)
     {
       printk ("SB: Recording is not possible with this device\n");
-      return -(EPERM);
+      return -EPERM;
     }
 
   save_flags (flags);
@@ -43,14 +43,14 @@
   if (devc->opened)
     {
       restore_flags (flags);
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   if (devc->dma16 != -1 && devc->dma16 != devc->dma8)
     {
       if (sound_open_dma (devc->dma16, "Sound Blaster 16 bit"))
 	{
-	  return -(EBUSY);
+	  return -EBUSY;
 	}
     }
   devc->opened = mode;
@@ -541,7 +541,8 @@
     if (channels != devc->channels)
       {
 	devc->channels = channels;
-	sbpro_audio_set_speed (dev, devc->speed);
+	if (devc->model == MDL_SBPRO)
+	  sbpro_audio_set_speed (dev, devc->speed);
       }
   return devc->channels;
 }
@@ -578,6 +579,37 @@
  * ESS specific routines
  */
 
+static int
+ess_audio_set_speed (int dev, int speed)
+{
+  sb_devc        *devc = audio_devs[dev]->devc;
+  int             divider;
+
+  if (speed > 0)
+    {
+      if (speed < 5000)
+	speed = 4000;
+
+      if (speed > 48000)
+	speed = 48000;
+
+      if (speed > 22000)
+	{
+	  divider = (795500 + speed / 2) / speed;
+	  speed = (795500 + divider / 2) / divider;
+	}
+      else
+	{
+	  divider = (397700 + speed / 2) / speed;
+	  speed = (397700 + divider / 2) / divider;
+	}
+
+      devc->speed = speed;
+    }
+
+  return devc->speed;
+}
+
 static void
 ess_speed (sb_devc * devc)
 {
@@ -965,7 +997,7 @@
 static int
 sb_audio_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -1122,7 +1154,7 @@
   NULL,
   NULL,
   ess_audio_trigger,
-  sb16_audio_set_speed,
+  ess_audio_set_speed,
   sb16_audio_set_bits,
   sbpro_audio_set_channels
 };
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.1.5/linux/drivers/sound/sb_card.c	Thu Aug  1 15:43:05 1996
+++ linux/drivers/sound/sb_card.c	Tue Oct 29 09:31:49 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
--- v2.1.5/linux/drivers/sound/sb_common.c	Wed Oct  9 08:55:22 1996
+++ linux/drivers/sound/sb_common.c	Tue Oct 29 09:31:50 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -41,7 +41,7 @@
 static unsigned char jazz16_bits = 0;	/* I/O relocation bits */
 
 /*
- * Logitech SoundMan Wave specific initialization code
+ * Logitech Soundman Wave specific initialization code
  */
 
 #ifdef SMW_MIDI0001_INCLUDED
@@ -65,7 +65,7 @@
   /*
    * Note! the i<500000 is an emergency exit. The sb_dsp_command() is sometimes
    * called while interrupts are disabled. This means that the timer is
-   * disabled also. However the timeout situation is an abnormal condition.
+   * disabled also. However the timeout situation is a abnormal condition.
    * Normally the DSP should be ready to accept commands after just couple of
    * loops.
    */
@@ -74,7 +74,7 @@
     {
       if ((inb (DSP_STATUS) & 0x80) == 0)
 	{
-	  outb (val, DSP_COMMAND);
+	  outb ((val), DSP_COMMAND);
 	  return 1;
 	}
     }
@@ -192,12 +192,12 @@
   int             loopc;
 
   if (devc->model == MDL_ESS)
-    outb (3, DSP_RESET);	/* Reset FIFO too */
+    outb ((3), DSP_RESET);	/* Reset FIFO too */
   else
-    outb (1, DSP_RESET);
+    outb ((1), DSP_RESET);
 
   tenmicrosec (devc->osp);
-  outb (0, DSP_RESET);
+  outb ((0), DSP_RESET);
   tenmicrosec (devc->osp);
   tenmicrosec (devc->osp);
   tenmicrosec (devc->osp);
@@ -261,28 +261,31 @@
   return 1;
 }
 
+#if defined(CONFIG_MIDI) && defined(CONFIG_UART401)
 static void
-sb16_set_mpu_port(sb_devc *devc, struct address_info *hw_config)
+sb16_set_mpu_port (sb_devc * devc, struct address_info *hw_config)
 {
 /*
- * This routine initializes new MIDI port setup register of SB Vibra.
+ * This routine initializes new MIDI port setup register of SB Vibra (CT2502).
  */
-	unsigned char bits = sb_getmixer(devc, 0x84) & ~0x06;
-	switch (hw_config->io_base)
-	{
-	case 0x300:
-  		sb_setmixer (devc, 0x84, bits | 0x04);
-		break;
-
-	case 0x330:
-  		sb_setmixer (devc, 0x84, bits | 0x00);
-		break;
-
-	default:
-  		sb_setmixer (devc, 0x84, bits | 0x02); /* Disable MPU */
-		printk("SB16: Invalid MIDI I/O port %x\n", hw_config->io_base);
-	}
+  unsigned char   bits = sb_getmixer (devc, 0x84) & ~0x06;
+
+  switch (hw_config->io_base)
+    {
+    case 0x300:
+      sb_setmixer (devc, 0x84, bits | 0x04);
+      break;
+
+    case 0x330:
+      sb_setmixer (devc, 0x84, bits | 0x00);
+      break;
+
+    default:
+      sb_setmixer (devc, 0x84, bits | 0x02);	/* Disable MPU */
+      printk ("SB16: Invalid MIDI I/O port %x\n", hw_config->io_base);
+    }
 }
+#endif
 
 static int
 sb16_set_irq_hw (sb_devc * devc, int level)
@@ -304,6 +307,8 @@
       ival = 8;
       break;
     default:
+      if (devc->type == MDL_SBPNP)
+	return 1;
       printk ("SB16 IRQ%d is not possible\n", level);
       return 0;
     }
@@ -345,9 +350,9 @@
  */
   save_flags (flags);
   cli ();
-  outb (0xAF, 0x201);
-  outb (0x50, 0x201);
-  outb (bits, 0x201);
+  outb ((0xAF), 0x201);
+  outb ((0x50), 0x201);
+  outb ((bits), 0x201);
   restore_flags (flags);
 }
 
@@ -425,6 +430,7 @@
   return 1;
 }
 
+
 static int
 ess_init (sb_devc * devc, struct address_info *hw_config)
 {
@@ -466,9 +472,14 @@
     }
   else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80)
     {
+      char           *chip = "ES688";
+
+      if ((ess_minor & 0x0f) >= 8)
+	chip = "ES1688";
+
       sprintf (name,
-	       "ESS ES1688 AudioDrive (rev %d)",
-	       ess_minor & 0x0f);
+	       "ESS %s AudioDrive (rev %d)",
+	       chip, ess_minor & 0x0f);
     }
   else
     strcpy (name, "Jazz16");
@@ -570,7 +581,6 @@
 
   memset ((char *) &sb_info, 0, sizeof (sb_info));	/* Zero everything */
 
-  devc->osp = hw_config->osp;
   devc->type = hw_config->card_subtype;
 
   devc->base = hw_config->io_base;
@@ -592,6 +602,7 @@
     if (devc->major == 0 || (devc->major == 3 && devc->minor == 1))
       relocate_Jazz16 (devc, hw_config);
 
+
   if (!sb_dsp_reset (devc))
     {
       DDB (printk ("SB reset failed\n"));
@@ -642,16 +653,14 @@
 sb_dsp_init (struct address_info *hw_config)
 {
   sb_devc        *devc;
-  char            name[100];
-
-#ifndef NO_SB_IRQ_TEST
   int             n;
-#endif
+  char            name[100];
 
 /*
  * Check if we had detected a SB device earlier
  */
   DDB (printk ("sb_dsp_init(%x) entered\n", hw_config->io_base));
+  name[0] = 0;
 
   if (detected_devc == NULL)
     {
@@ -674,61 +683,64 @@
   devc->dev = num_audiodevs;
   devc->caps = hw_config->driver_use_1;
 
-  if (snd_set_irq_handler (hw_config->irq,
-			   sbintr, "sound blaster", devc->osp) < 0)
-    {
-      printk ("SB: Can't allocate IRQ%d\n", hw_config->irq);
-      irq2devc[hw_config->irq] = NULL;
-      return;
-    }
-
-  irq2devc[hw_config->irq] = devc;
-  devc->irq_ok = 0;
+  if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) &&
+      hw_config->irq > 0)
+    {				/* IRQ setup */
+      if (snd_set_irq_handler (hw_config->irq,
+			       sbintr, "soundblaster", devc->osp) < 0)
+	{
+	  printk ("SB: Can't allocate IRQ%d\n", hw_config->irq);
+	  return;
+	}
 
-  if (devc->major == 4)
-    if (!sb16_set_irq_hw (devc, devc->irq))	/* Unsupported IRQ */
-      {
-	snd_release_irq (devc->irq);
-	return;
-      }
+      irq2devc[hw_config->irq] = devc;
+      devc->irq_ok = 0;
 
-  if ((devc->type == 0 || devc->type == MDL_ESS) &&
-      devc->major == 3 && devc->minor == 1)
-    {				/* Handle various chipsets which claim they are SB Pro compatible */
-      if ((devc->type != 0 && devc->type != MDL_ESS) ||
-	  !ess_init (devc, hw_config))
-	if ((devc->type != 0 && devc->type != MDL_JAZZ &&
-	     devc->type != MDL_SMW) || !init_Jazz16 (devc, hw_config))
+      if (devc->major == 4)
+	if (!sb16_set_irq_hw (devc, devc->irq))		/* Unsupported IRQ */
 	  {
-	    DDB (printk ("This is a genuine SB Pro\n"));
+	    snd_release_irq (devc->irq);
+	    irq2devc[hw_config->irq] = NULL;
+	    return;
 	  }
-    }
 
-#ifndef NO_SB_IRQ_TEST
-  if (devc->major != 4 || devc->minor > 11) /* Not Sb16 v4.5 or v4.11 */
-  {
-    for (n = 0; n < 3 && devc->irq_ok == 0; n++)
-    if (sb_dsp_command (devc, 0xf2))	/* Cause interrupt immediately */
-      {
-	int             i;
+      if ((devc->type == 0 || devc->type == MDL_ESS) &&
+	  devc->major == 3 && devc->minor == 1)
+	{			/* Handle various chipsets which claim they are SB Pro compatible */
+	  if ((devc->type != 0 && devc->type != MDL_ESS) ||
+	      !ess_init (devc, hw_config))
+	    if ((devc->type != 0 && devc->type != MDL_JAZZ &&
+		 devc->type != MDL_SMW) || !init_Jazz16 (devc, hw_config))
+	      {
+		DDB (printk ("This is a genuine SB Pro\n"));
+	      }
+	}
 
-	for (i = 0; !devc->irq_ok && i < 10000; i++);
-      }
+      if (devc->major == 4 && devc->minor <= 11)	/* Won't work */
+	devc->irq_ok = 1;
+      else
+	{
+	  for (n = 0; n < 3 && devc->irq_ok == 0; n++)
+	    if (sb_dsp_command (devc, 0xf2))	/* Cause interrupt immediately */
+	      {
+		int             i;
 
-  if (!devc->irq_ok)
-    {
-      printk ("sb: Interrupt test on IRQ%d failed - device disabled\n", devc->irq);
-      snd_release_irq (devc->irq);
-      return;
-    }
-  else
-    {
-      DDB (printk ("IRQ test OK (IRQ%d)\n", devc->irq));
+		for (i = 0; !devc->irq_ok && i < 10000; i++);
+	      }
+
+	  if (!devc->irq_ok)
+	    {
+	      printk ("sb: Interrupt test on IRQ%d failed - Propable IRQ conflict\n", devc->irq);
+	    }
+	  else
+	    {
+	      DDB (printk ("IRQ test OK (IRQ%d)\n", devc->irq));
+	    }
+
+	}			/* IRQ setup */
     }
-  }
-#endif
 
-  request_region (hw_config->io_base, 16, "sound blaster");
+  request_region (hw_config->io_base, 16, "soundblaster");
 
   switch (devc->major)
     {
@@ -788,14 +800,14 @@
   hw_config->card_subtype = devc->model;
   last_devc = devc;		/* For SB MPU detection */
 
-  if (!(devc->caps & SB_NO_AUDIO))
+  if (!(devc->caps & SB_NO_AUDIO) && devc->dma8 >= 0)
     {
-      if (sound_alloc_dma (devc->dma8, "Sound Blaster8"))
+      if (sound_alloc_dma (devc->dma8, "SoundBlaster8"))
 	{
 	  printk ("SB: Can't allocate 8 bit DMA channel %d\n", devc->dma8);
 	}
       if (devc->dma16 >= 0 && devc->dma16 != devc->dma8)
-	if (sound_alloc_dma (devc->dma16, "Sound Blaster16"))
+	if (sound_alloc_dma (devc->dma16, "SoundBlaster16"))
 	  {
 	    printk ("SB: Can't allocate 16 bit DMA channel %d\n", devc->dma16);
 	  }
@@ -822,11 +834,15 @@
   if (irq < 0)
     irq *= -1;
 
-  devc = irq2devc[irq];
+  if (irq > 2 && irq < 16)
+    devc = irq2devc[irq];
+  else
+    devc = NULL;
 
   if (devc && devc->base == hw_config->io_base)
     {
       release_region (devc->base, 16);
+
       if (!(devc->caps & SB_NO_AUDIO))
 	{
 	  sound_free_dma (devc->dma8);
@@ -835,9 +851,15 @@
 	    sound_free_dma (devc->dma16);
 	}
 
-      snd_release_irq (devc->irq);
-      irq2devc[devc->irq] = NULL;
+      if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) &&
+	  devc->irq > 0)
+	{
+	  snd_release_irq (devc->irq);
+	  irq2devc[devc->irq] = NULL;
+	}
     }
+  else
+    release_region (hw_config->io_base, 16);
 }
 
 /*
@@ -851,10 +873,12 @@
 
   save_flags (flags);
   cli ();
-  outb ((unsigned char) (port & 0xff), MIXER_ADDR);
+  outb (((unsigned char) (port & 0xff)), MIXER_ADDR);
 
   tenmicrosec (devc->osp);
-  outb ((unsigned char) (value & 0xff), MIXER_DATA);
+  tenmicrosec (devc->osp);
+  outb (((unsigned char) (value & 0xff)), MIXER_DATA);
+  tenmicrosec (devc->osp);
   tenmicrosec (devc->osp);
   restore_flags (flags);
 }
@@ -867,9 +891,10 @@
 
   save_flags (flags);
   cli ();
-  outb ((unsigned char) (port & 0xff), MIXER_ADDR);
+  outb (((unsigned char) (port & 0xff)), MIXER_ADDR);
 
   tenmicrosec (devc->osp);
+  tenmicrosec (devc->osp);
   val = inb (MIXER_DATA);
   tenmicrosec (devc->osp);
   restore_flags (flags);
@@ -890,9 +915,9 @@
   save_flags (flags);
   cli ();
 
-  outb (addr & 0xff, base + 1);	/* Low address bits */
-  outb (addr >> 8, base + 2);	/* High address bits */
-  outb (val, base);		/* Data */
+  outb ((addr & 0xff), base + 1);	/* Low address bits */
+  outb ((addr >> 8), base + 2);	/* High address bits */
+  outb ((val), base);		/* Data */
 
   restore_flags (flags);
 }
@@ -906,8 +931,8 @@
   save_flags (flags);
   cli ();
 
-  outb (addr & 0xff, base + 1);	/* Low address bits */
-  outb (addr >> 8, base + 2);	/* High address bits */
+  outb ((addr & 0xff), base + 1);	/* Low address bits */
+  outb ((addr >> 8), base + 2);	/* High address bits */
   val = inb (base);		/* Data */
 
   restore_flags (flags);
@@ -928,13 +953,13 @@
    */
 
   control = inb (mpu_base + 7);
-  outb (control | 3, mpu_base + 7);	/* Set last two bits to 1 (?) */
-  outb ((control & 0xfe) | 2, mpu_base + 7);	/* xxxxxxx0 resets the mc */
+  outb ((control | 3), mpu_base + 7);	/* Set last two bits to 1 (?) */
+  outb (((control & 0xfe) | 2), mpu_base + 7);	/* xxxxxxx0 resets the mc */
 
   for (i = 0; i < 300; i++)	/* Wait at least 1ms */
     tenmicrosec (devc->osp);
 
-  outb (control & 0xfc, mpu_base + 7);	/* xxxxxx00 enables RAM */
+  outb ((control & 0xfc), mpu_base + 7);	/* xxxxxx00 enables RAM */
 
   /*
      *  Detect microcontroller by probing the 8k RAM area
@@ -1012,7 +1037,7 @@
   /* control |= 0x20;      Uncomment this if you want to use IRQ7 */
 #endif
 
-  outb (control | 0x03, mpu_base + 7);	/* xxxxxx11 restarts */
+  outb ((control | 0x03), mpu_base + 7);	/* xxxxxx11 restarts */
   hw_config->name = "SoundMan Wave";
   return 1;
 }
@@ -1125,9 +1150,9 @@
  */
   save_flags (flags);
   cli ();
-  outb (0xAF, 0x201);
-  outb (0x50, 0x201);
-  outb (bits, 0x201);
+  outb ((0xAF), 0x201);
+  outb ((0x50), 0x201);
+  outb ((bits), 0x201);
   restore_flags (flags);
 
   hw_config->name = "Jazz16";
@@ -1167,7 +1192,7 @@
   last_devc = 0;
 
   if (hw_config->io_base <= 0)
-     return 0;
+    return 0;
 
   if (check_region (hw_config->io_base, 4))
     {
@@ -1185,7 +1210,8 @@
 	}
       hw_config->name = "Sound Blaster 16";
       hw_config->irq = -devc->irq;
-      sb16_set_mpu_port(devc, hw_config);
+      if (devc->minor > 12)	/* What is Vibra's version??? */
+	sb16_set_mpu_port (devc, hw_config);
       break;
 
     case MDL_ESS:
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sb_midi.c linux/drivers/sound/sb_midi.c
--- v2.1.5/linux/drivers/sound/sb_midi.c	Wed Aug  7 12:31:22 1996
+++ linux/drivers/sound/sb_midi.c	Tue Oct 29 09:31:51 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -40,14 +40,14 @@
   unsigned long   flags;
 
   if (devc == NULL)
-    return -(ENXIO);
+    return -ENXIO;
 
   save_flags (flags);
   cli ();
   if (devc->opened)
     {
       restore_flags (flags);
-      return -(EBUSY);
+      return -EBUSY;
     }
   devc->opened = 1;
   restore_flags (flags);
@@ -59,7 +59,7 @@
   if (!sb_dsp_command (devc, 0x35))	/* Start MIDI UART mode */
     {
       devc->opened = 0;
-      return -(EIO);
+      return -EIO;
     }
 
   devc->intr_active = 1;
@@ -97,7 +97,7 @@
   sb_devc        *devc = midi_devs[dev]->devc;
 
   if (devc == NULL)
-    return -(ENXIO);
+    return -ENXIO;
 
   sb_dsp_command (devc, midi_byte);
 
@@ -116,7 +116,7 @@
   sb_devc        *devc = midi_devs[dev]->devc;
 
   if (devc == NULL)
-    return -(ENXIO);
+    return -ENXIO;
 
   sb_dsp_reset (devc);
   devc->intr_active = 0;
@@ -126,7 +126,7 @@
 static int
 sb_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
-  return -(EPERM);
+  return -EPERM;
 }
 
 void
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sb_mixer.c linux/drivers/sound/sb_mixer.c
--- v2.1.5/linux/drivers/sound/sb_mixer.c	Sun Aug 18 10:46:49 1996
+++ linux/drivers/sound/sb_mixer.c	Tue Oct 29 09:31:51 1996
@@ -7,7 +7,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -22,6 +22,8 @@
 #include "sb.h"
 #include "sb_mixer.h"
 
+static int      sbmixnum = 1;
+
 void            sb_mixer_reset (sb_devc * devc);
 
 void
@@ -69,7 +71,7 @@
 sb_mixer_get (sb_devc * devc, int dev)
 {
   if (!((1 << dev) & devc->supported_devices))
-    return -(EINVAL);
+    return -EINVAL;
 
   return devc->levels[dev];
 }
@@ -107,10 +109,10 @@
     right = 100;
 
   if (dev > 31)
-    return -(EINVAL);
+    return -EINVAL;
 
   if (!(devc->supported_devices & (1 << dev)))	/* Not supported */
-    return -(EINVAL);
+    return -EINVAL;
 
   switch (dev)
     {
@@ -137,7 +139,7 @@
     default:
       reg = smw_mix_regs[dev];
       if (reg == 0)
-	return -(EINVAL);
+	return -EINVAL;
       sb_setmixer (devc, reg, (24 - (24 * left / 100)) | 0x20);		/* 24=mute, 0=max */
       sb_setmixer (devc, reg + 1, (24 - (24 * right / 100)) | 0x40);
     }
@@ -164,17 +166,17 @@
     right = 100;
 
   if (dev > 31)
-    return -(EINVAL);
+    return -EINVAL;
 
   if (!(devc->supported_devices & (1 << dev)))	/*
 						 * Not supported
 						 */
-    return -(EINVAL);
+    return -EINVAL;
 
   regoffs = (*devc->iomap)[dev][LEFT_CHN].regno;
 
   if (regoffs == 0)
-    return -(EINVAL);
+    return -EINVAL;
 
   val = sb_getmixer (devc, regoffs);
   change_bits (devc, &val, dev, LEFT_CHN, left);
@@ -300,6 +302,7 @@
 sb_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 {
   sb_devc        *devc = mixer_devs[dev]->devc;
+  int             val;
 
   if (((cmd >> 8) & 0xff) == 'M')
     {
@@ -307,46 +310,48 @@
 	switch (cmd & 0xff)
 	  {
 	  case SOUND_MIXER_RECSRC:
-	    return snd_ioctl_return ((int *) arg, set_recmask (devc, get_user ((int *) arg)));
+	    get_user (val, (int *) arg);
+	    return ioctl_out (arg, set_recmask (devc, val));
 	    break;
 
 	  default:
 
-	    return snd_ioctl_return ((int *) arg, sb_mixer_set (devc, cmd & 0xff, get_user ((int *) arg)));
+	    get_user (val, (int *) arg);
+	    return ioctl_out (arg, sb_mixer_set (devc, cmd & 0xff, val));
 	  }
       else
 	switch (cmd & 0xff)
 	  {
 
 	  case SOUND_MIXER_RECSRC:
-	    return snd_ioctl_return ((int *) arg, devc->recmask);
+	    return ioctl_out (arg, devc->recmask);
 	    break;
 
 	  case SOUND_MIXER_DEVMASK:
-	    return snd_ioctl_return ((int *) arg, devc->supported_devices);
+	    return ioctl_out (arg, devc->supported_devices);
 	    break;
 
 	  case SOUND_MIXER_STEREODEVS:
 	    if (devc->model == MDL_JAZZ || devc->model == MDL_SMW)
-	      return snd_ioctl_return ((int *) arg, devc->supported_devices);
+	      return ioctl_out (arg, devc->supported_devices);
 	    else
-	      return snd_ioctl_return ((int *) arg, devc->supported_devices & ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
+	      return ioctl_out (arg, devc->supported_devices & ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX));
 	    break;
 
 	  case SOUND_MIXER_RECMASK:
-	    return snd_ioctl_return ((int *) arg, devc->supported_rec_devices);
+	    return ioctl_out (arg, devc->supported_rec_devices);
 	    break;
 
 	  case SOUND_MIXER_CAPS:
-	    return snd_ioctl_return ((int *) arg, devc->mixer_caps);
+	    return ioctl_out (arg, devc->mixer_caps);
 	    break;
 
 	  default:
-	    return snd_ioctl_return ((int *) arg, sb_mixer_get (devc, cmd & 0xff));
+	    return ioctl_out (arg, sb_mixer_get (devc, cmd & 0xff));
 	  }
     }
   else
-    return -(EINVAL);
+    return -EINVAL;
 }
 
 static struct mixer_operations sb_mixer_operations =
@@ -359,10 +364,16 @@
 void
 sb_mixer_reset (sb_devc * devc)
 {
+  char            name[32];
   int             i;
 
+  sprintf (name, "SB_%d", devc->sbmixnum);
+
+  devc->levels = load_mixer_volumes (name, default_levels, 1);
+
   for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
     sb_mixer_set (devc, i, devc->levels[i]);
+
   set_recmask (devc, SOUND_MASK_MIC);
 }
 
@@ -371,6 +382,9 @@
 {
   int             mixer_type = 0;
 
+  devc->sbmixnum = sbmixnum++;
+  devc->levels = NULL;
+
   sb_setmixer (devc, 0x00, 0);	/* Reset mixer */
 
   if (!(mixer_type = detect_mixer (devc)))
@@ -431,7 +445,6 @@
 	  sizeof (struct mixer_operations));
 
   mixer_devs[num_mixers]->devc = devc;
-  memcpy ((char *) devc->levels, (char *) &default_levels, sizeof (default_levels));
 
   sb_mixer_reset (devc);
   devc->my_mixerdev = num_mixers++;
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sb_mixer.h linux/drivers/sound/sb_mixer.h
--- v2.1.5/linux/drivers/sound/sb_mixer.h	Sun Jun 30 11:43:39 1996
+++ linux/drivers/sound/sb_mixer.h	Tue Oct 29 09:31:09 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -43,7 +43,8 @@
 #define SB16_MIXER_DEVICES		(SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
 					 SOUND_MASK_CD | \
 					 SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
-					 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE)
+					 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
+					SOUND_MASK_IMIX)
 
 /*
  * Mixer registers
@@ -160,7 +161,7 @@
 MIX_ENT(SOUND_MIXER_LINE,	0x38, 7, 5, 0x39, 7, 5),
 MIX_ENT(SOUND_MIXER_MIC,	0x3a, 7, 5, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_CD,		0x36, 7, 5, 0x37, 7, 5),
-MIX_ENT(SOUND_MIXER_IMIX,	0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_IMIX,	0x3c, 0, 1, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_ALTPCM,	0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_RECLEV,	0x3f, 7, 2, 0x40, 7, 2), /* Obsolete. Use IGAIN */
 MIX_ENT(SOUND_MIXER_IGAIN,	0x3f, 7, 2, 0x40, 7, 2),
@@ -171,7 +172,7 @@
 			     higher than with SB Pro. This improves the
 			     sound quality */
 
-static unsigned short default_levels[SOUND_MIXER_NRDEVICES] =
+static int default_levels[32] =
 {
   0x2020,			/* Master Volume */
   0x4b4b,			/* Bass */
@@ -194,7 +195,7 @@
 
 #else  /* If the user selected just plain SB Pro */
 
-static unsigned short default_levels[SOUND_MIXER_NRDEVICES] =
+static int default_levels[32] =
 {
   0x5a5a,			/* Master Volume */
   0x4b4b,			/* Bass */
@@ -205,7 +206,7 @@
   0x4b4b,			/* Ext Line */
   0x1010,			/* Mic */
   0x4b4b,			/* CD */
-  0x4b4b,			/* Recording monitor */
+  0x0000,			/* Recording monitor */
   0x4b4b,			/* SB PCM */
   0x4b4b,			/* Recording level */
   0x4b4b,			/* Input gain */
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c
--- v2.1.5/linux/drivers/sound/sequencer.c	Wed Oct 16 10:48:24 1996
+++ linux/drivers/sound/sequencer.c	Tue Oct 29 09:31:53 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -42,10 +42,10 @@
 #define SEQ_2	2
 static int      seq_mode = SEQ_1;
 
-static wait_handle *seq_sleeper = NULL;
+static struct wait_queue *seq_sleeper = NULL;
 static volatile struct snd_wait seq_sleep_flag =
 {0};
-static wait_handle *midi_sleeper = NULL;
+static struct wait_queue *midi_sleeper = NULL;
 static volatile struct snd_wait midi_sleep_flag =
 {0};
 
@@ -108,7 +108,7 @@
 	   1 : 0))
 	{
 	  restore_flags (flags);
-	  return -(EAGAIN);
+	  return -EAGAIN;
 	}
 
 
@@ -116,17 +116,17 @@
 	unsigned long   tlimit;
 
 	if (pre_event_timeout)
-	  current_set_timeout (tlimit = jiffies + (pre_event_timeout));
+	  current->timeout = tlimit = jiffies + (pre_event_timeout);
 	else
 	  tlimit = (unsigned long) -1;
-	midi_sleep_flag.flags = WK_SLEEP;
-	module_interruptible_sleep_on (&midi_sleeper);
-	if (!(midi_sleep_flag.flags & WK_WAKEUP))
+	midi_sleep_flag.opts = WK_SLEEP;
+	interruptible_sleep_on (&midi_sleeper);
+	if (!(midi_sleep_flag.opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      midi_sleep_flag.flags |= WK_TIMEOUT;
+	      midi_sleep_flag.opts |= WK_TIMEOUT;
 	  }
-	midi_sleep_flag.flags &= ~WK_SLEEP;
+	midi_sleep_flag.opts &= ~WK_SLEEP;
       };
 
       if (!iqlen)
@@ -139,7 +139,11 @@
   while (iqlen && c >= ev_len)
     {
 
-      copy_to_user (&(buf)[p], (char *) &iqueue[iqhead * IEV_SZ], ev_len);
+      {
+	char           *fixit = (char *) &iqueue[iqhead * IEV_SZ];
+
+	copy_to_user (&(buf)[p], fixit, ev_len);
+      };
       p += ev_len;
       c -= ev_len;
 
@@ -182,11 +186,11 @@
   iqlen++;
   iqtail = (iqtail + 1) % SEQ_MAX_QUEUE;
 
-  if ((midi_sleep_flag.flags & WK_SLEEP))
+  if ((midi_sleep_flag.opts & WK_SLEEP))
     {
       {
-	midi_sleep_flag.flags = WK_WAKEUP;
-	module_wake_up (&midi_sleeper);
+	midi_sleep_flag.opts = WK_WAKEUP;
+	wake_up (&midi_sleeper);
       };
     }
   restore_flags (flags);
@@ -258,7 +262,7 @@
   DEB (printk ("sequencer_write(dev=%d, count=%d)\n", dev, count));
 
   if (mode == OPEN_READ)
-    return -(EIO);
+    return -EIO;
 
   if (dev)
     return pmgr_write (dev - 1, file, buf, count);
@@ -276,10 +280,10 @@
 
 	  dev = *(unsigned short *) &event_rec[2];
 	  if (dev < 0 || dev >= max_synthdev)
-	    return -(ENXIO);
+	    return -ENXIO;
 
 	  if (!(synth_open_mask & (1 << dev)))
-	    return -(ENXIO);
+	    return -ENXIO;
 
 	  err = synth_devs[dev]->load_patch (dev, *(short *) &event_rec[0], buf, p + 4, c, 0);
 	  if (err < 0)
@@ -293,7 +297,7 @@
 	  if (seq_mode == SEQ_2 && ev_code == SEQ_EXTENDED)
 	    {
 	      printk ("Sequencer: Invalid level 2 event %x\n", ev_code);
-	      return -(EINVAL);
+	      return -EINVAL;
 	    }
 
 	  ev_size = 8;
@@ -313,7 +317,7 @@
 	  if (seq_mode == SEQ_2)
 	    {
 	      printk ("Sequencer: 4 byte event in level 2 mode\n");
-	      return -(EINVAL);
+	      return -EINVAL;
 	    }
 	  ev_size = 4;
 	}
@@ -329,7 +333,7 @@
 	      if (dev >= max_mididev)
 		{
 		  printk ("Sequencer Error: Nonexistent MIDI device %d\n", dev);
-		  return -(ENXIO);
+		  return -ENXIO;
 		}
 
 	      mode = file->mode & O_ACCMODE;
@@ -357,7 +361,7 @@
 
 	  if (!processed && (file->flags & (O_NONBLOCK) ?
 			     1 : 0))
-	    return -(EAGAIN);
+	    return -EAGAIN;
 	  else
 	    return processed;
 	}
@@ -388,15 +392,15 @@
 				 * Give chance to drain the queue
 				 */
 
-  if (!nonblock && qlen >= SEQ_MAX_QUEUE && !(seq_sleep_flag.flags & WK_SLEEP))
+  if (!nonblock && qlen >= SEQ_MAX_QUEUE && !(seq_sleep_flag.opts & WK_SLEEP))
     {
       /*
        * Sleep until there is enough space on the queue
        */
 
-      seq_sleep_flag.flags = WK_SLEEP;
-      module_interruptible_sleep_on (&seq_sleeper);
-      seq_sleep_flag.flags &= ~WK_SLEEP;;
+      seq_sleep_flag.opts = WK_SLEEP;
+      interruptible_sleep_on (&seq_sleeper);
+      seq_sleep_flag.opts &= ~WK_SLEEP;;
     }
 
   if (qlen >= SEQ_MAX_QUEUE)
@@ -419,10 +423,10 @@
   int             dev = q[2];
 
   if (dev < 0 || dev >= max_synthdev)
-    return -(ENXIO);
+    return -ENXIO;
 
   if (!(synth_open_mask & (1 << dev)))
-    return -(ENXIO);
+    return -ENXIO;
 
   switch (q[1])
     {
@@ -459,7 +463,7 @@
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   return 0;
@@ -549,7 +553,7 @@
 	  if (chn == 9)
 	    {
 	      synth_devs[dev]->set_instr (dev, voice, 128 + note);
-              synth_devs[dev]->chn_info[chn].pgm_num = 128 + note;
+	      synth_devs[dev]->chn_info[chn].pgm_num = 128 + note;
 	      note = 60;	/* Middle C */
 
 	    }
@@ -695,11 +699,11 @@
 
 	      save_flags (flags);
 	      cli ();
-	      if ((seq_sleep_flag.flags & WK_SLEEP))
+	      if ((seq_sleep_flag.opts & WK_SLEEP))
 		{
 		  {
-		    seq_sleep_flag.flags = WK_WAKEUP;
-		    module_wake_up (&seq_sleeper);
+		    seq_sleep_flag.opts = WK_WAKEUP;
+		    wake_up (&seq_sleeper);
 		  };
 		}
 	      restore_flags (flags);
@@ -723,10 +727,10 @@
 	{
 	  long            time;
 
-	  seq_playing = 1;
 	  time = parm;
 	  prev_event_time = time;
 
+	  seq_playing = 1;
 	  request_sound_timer (time);
 
 	  if ((SEQ_MAX_QUEUE - qlen) >= output_threshold)
@@ -735,11 +739,11 @@
 
 	      save_flags (flags);
 	      cli ();
-	      if ((seq_sleep_flag.flags & WK_SLEEP))
+	      if ((seq_sleep_flag.opts & WK_SLEEP))
 		{
 		  {
-		    seq_sleep_flag.flags = WK_WAKEUP;
-		    module_wake_up (&seq_sleeper);
+		    seq_sleep_flag.opts = WK_WAKEUP;
+		    wake_up (&seq_sleeper);
 		  };
 		}
 	      restore_flags (flags);
@@ -871,11 +875,11 @@
 
 	      save_flags (flags);
 	      cli ();
-	      if ((seq_sleep_flag.flags & WK_SLEEP))
+	      if ((seq_sleep_flag.opts & WK_SLEEP))
 		{
 		  {
-		    seq_sleep_flag.flags = WK_WAKEUP;
-		    module_wake_up (&seq_sleeper);
+		    seq_sleep_flag.opts = WK_WAKEUP;
+		    wake_up (&seq_sleeper);
 		  };
 		}
 	      restore_flags (flags);
@@ -914,7 +918,7 @@
 	  if (dev < 0 || dev >= num_midis)
 	    break;
 
-	  if (!midi_devs[dev]->putc (dev, q[1]))
+	  if (!midi_devs[dev]->outputc (dev, q[1]))
 	    {
 	      /*
 	         * Output FIFO is full. Wait one timer cycle and try again.
@@ -1010,11 +1014,11 @@
 
       save_flags (flags);
       cli ();
-      if ((seq_sleep_flag.flags & WK_SLEEP))
+      if ((seq_sleep_flag.opts & WK_SLEEP))
 	{
 	  {
-	    seq_sleep_flag.flags = WK_WAKEUP;
-	    module_wake_up (&seq_sleeper);
+	    seq_sleep_flag.opts = WK_WAKEUP;
+	    wake_up (&seq_sleeper);
 	  };
 	}
       restore_flags (flags);
@@ -1080,22 +1084,21 @@
   if (!sequencer_ok)
     {
       printk ("Soundcard: Sequencer not initialized\n");
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   if (dev)			/* Patch manager device */
     {
       printk ("Patch manager interface is currently broken. Sorry\n");
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   save_flags (flags);
   cli ();
   if (sequencer_busy)
     {
-      printk ("Sequencer busy\n");
       restore_flags (flags);
-      return -(EBUSY);
+      return -EBUSY;
     }
   sequencer_busy = 1;
   restore_flags (flags);
@@ -1135,21 +1138,21 @@
 	{
 	  printk ("sequencer: No timer for level 2\n");
 	  sequencer_busy = 0;
-	  return -(ENXIO);
+	  return -ENXIO;
 	}
       setup_mode2 ();
     }
 
-  if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE))
+  if (seq_mode == SEQ_1 && mode == OPEN_READ)
     if (!max_mididev)
       {
 	printk ("Sequencer: No Midi devices. Input not possible\n");
 	sequencer_busy = 0;
-	return -(ENXIO);
+	return -ENXIO;
       }
 
   if (!max_synthdev && !max_mididev)
-    return -(ENXIO);
+    return -ENXIO;
 
   synth_open_mask = 0;
 
@@ -1202,8 +1205,8 @@
       tmr->open (tmr_no, seq_mode);
     }
 
-  seq_sleep_flag.flags = WK_NONE;
-  midi_sleep_flag.flags = WK_NONE;
+  seq_sleep_flag.opts = WK_NONE;
+  midi_sleep_flag.opts = WK_NONE;
   output_threshold = SEQ_MAX_QUEUE / 2;
 
   for (i = 0; i < num_synths; i++)
@@ -1224,7 +1227,7 @@
 
   n = 1;
 
-  while (!current_got_fatal_signal () && n)
+  while (!(current->signal & ~current->blocked) && n)
     {
       n = 0;
 
@@ -1244,17 +1247,17 @@
 	    unsigned long   tlimit;
 
 	    if (HZ / 10)
-	      current_set_timeout (tlimit = jiffies + (HZ / 10));
+	      current->timeout = tlimit = jiffies + (HZ / 10);
 	    else
 	      tlimit = (unsigned long) -1;
-	    seq_sleep_flag.flags = WK_SLEEP;
-	    module_interruptible_sleep_on (&seq_sleeper);
-	    if (!(seq_sleep_flag.flags & WK_WAKEUP))
+	    seq_sleep_flag.opts = WK_SLEEP;
+	    interruptible_sleep_on (&seq_sleeper);
+	    if (!(seq_sleep_flag.opts & WK_WAKEUP))
 	      {
 		if (jiffies >= tlimit)
-		  seq_sleep_flag.flags |= WK_TIMEOUT;
+		  seq_sleep_flag.opts |= WK_TIMEOUT;
 	      }
-	    seq_sleep_flag.flags &= ~WK_SLEEP;
+	    seq_sleep_flag.opts &= ~WK_SLEEP;
 	  };
 	}
     }
@@ -1286,7 +1289,7 @@
 
   if (mode != OPEN_READ && !(file->flags & (O_NONBLOCK) ?
 			     1 : 0))
-    while (!current_got_fatal_signal () && qlen)
+    while (!(current->signal & ~current->blocked) && qlen > 0)
       {
 	seq_sync ();
       }
@@ -1302,24 +1305,28 @@
 				 */
 
   for (i = 0; i < max_synthdev; i++)
-    if (synth_open_mask & (1 << i))	/*
+    {
+      if (synth_open_mask & (1 << i))	/*
 					 * Actually opened
 					 */
-      if (synth_devs[i])
-	{
-	  synth_devs[i]->close (i);
+	if (synth_devs[i])
+	  {
+	    synth_devs[i]->close (i);
 
-	  if (synth_devs[i]->midi_dev)
-	    midi_opened[synth_devs[i]->midi_dev] = 0;
-	}
+	    if (synth_devs[i]->midi_dev)
+	      midi_opened[synth_devs[i]->midi_dev] = 0;
+	  }
+    }
 
   for (i = 0; i < num_synths; i++)
     if (pmgr_present[i])
       pmgr_inform (i, PM_E_CLOSED, 0, 0, 0, 0);
 
   for (i = 0; i < max_mididev; i++)
-    if (midi_opened[i])
-      midi_devs[i]->close (i);
+    {
+      if (midi_opened[i])
+	midi_devs[i]->close (i);
+    }
 
   if (seq_mode == SEQ_2)
     tmr->close (tmr_no);
@@ -1332,29 +1339,29 @@
 {
   unsigned long   flags;
 
-  if (qlen && !seq_playing && !current_got_fatal_signal ())
+  if (qlen && !seq_playing && !(current->signal & ~current->blocked))
     seq_startplay ();
 
   save_flags (flags);
   cli ();
-  if (qlen && !(seq_sleep_flag.flags & WK_SLEEP))
+  if (qlen > 0)
     {
 
       {
 	unsigned long   tlimit;
 
 	if (HZ)
-	  current_set_timeout (tlimit = jiffies + (HZ));
+	  current->timeout = tlimit = jiffies + (HZ);
 	else
 	  tlimit = (unsigned long) -1;
-	seq_sleep_flag.flags = WK_SLEEP;
-	module_interruptible_sleep_on (&seq_sleeper);
-	if (!(seq_sleep_flag.flags & WK_WAKEUP))
+	seq_sleep_flag.opts = WK_SLEEP;
+	interruptible_sleep_on (&seq_sleeper);
+	if (!(seq_sleep_flag.opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      seq_sleep_flag.flags |= WK_TIMEOUT;
+	      seq_sleep_flag.opts |= WK_TIMEOUT;
 	  }
-	seq_sleep_flag.flags &= ~WK_SLEEP;
+	seq_sleep_flag.opts &= ~WK_SLEEP;
       };
     }
   restore_flags (flags);
@@ -1382,24 +1389,24 @@
 
   save_flags (flags);
   cli ();
-  while (n && !midi_devs[dev]->putc (dev, data))
+  while (n && !midi_devs[dev]->outputc (dev, data))
     {
 
       {
 	unsigned long   tlimit;
 
 	if (4)
-	  current_set_timeout (tlimit = jiffies + (4));
+	  current->timeout = tlimit = jiffies + (4);
 	else
 	  tlimit = (unsigned long) -1;
-	seq_sleep_flag.flags = WK_SLEEP;
-	module_interruptible_sleep_on (&seq_sleeper);
-	if (!(seq_sleep_flag.flags & WK_WAKEUP))
+	seq_sleep_flag.opts = WK_SLEEP;
+	interruptible_sleep_on (&seq_sleeper);
+	if (!(seq_sleep_flag.opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      seq_sleep_flag.flags |= WK_TIMEOUT;
+	      seq_sleep_flag.opts |= WK_TIMEOUT;
 	  }
-	seq_sleep_flag.flags &= ~WK_SLEEP;
+	seq_sleep_flag.opts &= ~WK_SLEEP;
       };
       n--;
     }
@@ -1478,12 +1485,12 @@
 
   save_flags (flags);
   cli ();
-  if ((seq_sleep_flag.flags & WK_SLEEP))
+  if ((seq_sleep_flag.opts & WK_SLEEP))
     {
       /*      printk ("Sequencer Warning: Unexpected sleeping process - Waking up\n"); */
       {
-	seq_sleep_flag.flags = WK_WAKEUP;
-	module_wake_up (&seq_sleeper);
+	seq_sleep_flag.opts = WK_WAKEUP;
+	wake_up (&seq_sleeper);
       };
     }
   restore_flags (flags);
@@ -1531,28 +1538,28 @@
     case SNDCTL_TMR_METRONOME:
     case SNDCTL_TMR_SOURCE:
       if (dev)			/* Patch manager */
-	return -(EIO);
+	return -EIO;
 
       if (seq_mode != SEQ_2)
-	return -(EINVAL);
+	return -EINVAL;
       return tmr->ioctl (tmr_no, cmd, arg);
       break;
 
     case SNDCTL_TMR_SELECT:
       if (dev)			/* Patch manager */
-	return -(EIO);
+	return -EIO;
 
       if (seq_mode != SEQ_2)
-	return -(EINVAL);
-      pending_timer = get_user ((int *) arg);
+	return -EINVAL;
+      get_user (pending_timer, (int *) arg);
 
       if (pending_timer < 0 || pending_timer >= num_sound_timers)
 	{
 	  pending_timer = -1;
-	  return -(EINVAL);
+	  return -EINVAL;
 	}
 
-      return snd_ioctl_return ((int *) arg, pending_timer);
+      return ioctl_out (arg, pending_timer);
       break;
 
     case SNDCTL_SEQ_PANIC:
@@ -1563,14 +1570,14 @@
       if (dev)			/*
 				 * Patch manager
 				 */
-	return -(EIO);
+	return -EIO;
 
       if (mode == OPEN_READ)
 	return 0;
-      while (qlen && !current_got_fatal_signal ())
+      while (qlen > 0 && !(current->signal & ~current->blocked))
 	seq_sync ();
       if (qlen)
-	return -(EINTR);
+	return -EINTR;
       else
 	return 0;
       break;
@@ -1579,7 +1586,7 @@
       if (dev)			/*
 				 * Patch manager
 				 */
-	return -(EIO);
+	return -EIO;
 
       seq_reset ();
       return 0;
@@ -1589,11 +1596,11 @@
       if (dev)			/*
 				 * Patch manager
 				 */
-	return -(EIO);
+	return -EIO;
 
-      midi_dev = get_user ((int *) arg);
+      get_user (midi_dev, (int *) arg);
       if (midi_dev >= max_mididev)
-	return -(ENXIO);
+	return -ENXIO;
 
       if (!midi_opened[midi_dev])
 	{
@@ -1615,23 +1622,30 @@
       if (dev)			/*
 				 * Patch manager
 				 */
-	return -(EIO);
+	return -EIO;
 
       if (mode == OPEN_WRITE)
 	return 0;
-      return snd_ioctl_return ((int *) arg, iqlen);
+      return ioctl_out (arg, iqlen);
       break;
 
     case SNDCTL_SEQ_GETOUTCOUNT:
 
       if (mode == OPEN_READ)
 	return 0;
-      return snd_ioctl_return ((int *) arg, SEQ_MAX_QUEUE - qlen);
+      return ioctl_out (arg, SEQ_MAX_QUEUE - qlen);
+      break;
+
+    case SNDCTL_SEQ_GETTIME:
+      if (seq_mode == SEQ_2)
+	return tmr->ioctl (tmr_no, cmd, arg);
+
+      return ioctl_out (arg, jiffies - seq_time);
       break;
 
     case SNDCTL_SEQ_CTRLRATE:
       if (dev)			/* Patch manager */
-	return -(EIO);
+	return -EIO;
 
       /*
        * If *arg == 0, just return the current rate
@@ -1639,25 +1653,25 @@
       if (seq_mode == SEQ_2)
 	return tmr->ioctl (tmr_no, cmd, arg);
 
-      if (get_user ((int *) arg) != 0)
-	return -(EINVAL);
+      if (ioctl_in (arg) != 0)
+	return -EINVAL;
 
-      return snd_ioctl_return ((int *) arg, HZ);
+      return ioctl_out (arg, HZ);
       break;
 
     case SNDCTL_SEQ_RESETSAMPLES:
       {
 	int             err;
 
-	dev = get_user ((int *) arg);
+	get_user (dev, (int *) arg);
 	if (dev < 0 || dev >= num_synths)
 	  {
-	    return -(ENXIO);
+	    return -ENXIO;
 	  }
 
 	if (!(synth_open_mask & (1 << dev)) && !orig_dev)
 	  {
-	    return -(EBUSY);
+	    return -EBUSY;
 	  }
 
 	if (!orig_dev && pmgr_present[dev])
@@ -1669,36 +1683,38 @@
       break;
 
     case SNDCTL_SEQ_NRSYNTHS:
-      return snd_ioctl_return ((int *) arg, max_synthdev);
+      return ioctl_out (arg, max_synthdev);
       break;
 
     case SNDCTL_SEQ_NRMIDIS:
-      return snd_ioctl_return ((int *) arg, max_mididev);
+      return ioctl_out (arg, max_mididev);
       break;
 
     case SNDCTL_SYNTH_MEMAVL:
       {
-	int             dev = get_user ((int *) arg);
+	int             dev;
+
+	get_user (dev, (int *) arg);
 
 	if (dev < 0 || dev >= num_synths)
-	  return -(ENXIO);
+	  return -ENXIO;
 
 	if (!(synth_open_mask & (1 << dev)) && !orig_dev)
-	  return -(EBUSY);
+	  return -EBUSY;
 
-	return snd_ioctl_return ((int *) arg, synth_devs[dev]->ioctl (dev, cmd, arg));
+	return ioctl_out (arg, synth_devs[dev]->ioctl (dev, cmd, arg));
       }
       break;
 
     case SNDCTL_FM_4OP_ENABLE:
       {
-	int             dev = get_user ((int *) arg);
+	int             dev = ioctl_in (arg);
 
 	if (dev < 0 || dev >= num_synths)
-	  return -(ENXIO);
+	  return -ENXIO;
 
 	if (!(synth_open_mask & (1 << dev)))
-	  return -(ENXIO);
+	  return -ENXIO;
 
 	synth_devs[dev]->ioctl (dev, cmd, arg);
 	return 0;
@@ -1714,10 +1730,10 @@
 	dev = inf.device;
 
 	if (dev < 0 || dev >= max_synthdev)
-	  return -(ENXIO);
+	  return -ENXIO;
 
 	if (!(synth_open_mask & (1 << dev)) && !orig_dev)
-	  return -(EBUSY);
+	  return -EBUSY;
 
 	return synth_devs[dev]->ioctl (dev, cmd, arg);
       }
@@ -1743,14 +1759,20 @@
       {
 	struct midi_info inf;
 	int             dev;
+	char           *pp;
 
 	copy_from_user ((char *) &inf, &((char *) arg)[0], sizeof (inf));
 	dev = inf.device;
 
 	if (dev < 0 || dev >= max_mididev)
-	  return -(ENXIO);
+	  return -ENXIO;
+
+	pp = (char *) &midi_devs[dev]->info;
+	{
+	  char           *fixit = pp;
 
-	copy_to_user (&((char *) arg)[0], (char *) &(midi_devs[dev]->info), sizeof (inf));
+	  copy_to_user (&((char *) arg)[0], fixit, sizeof (inf));
+	};
 	return 0;
       }
       break;
@@ -1763,7 +1785,7 @@
 	if ((inf = (struct patmgr_info *) vmalloc (sizeof (*inf))) == NULL)
 	  {
 	    printk ("patmgr: Can't allocate memory for a message\n");
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	copy_from_user ((char *) inf, &((char *) arg)[0], sizeof (*inf));
@@ -1772,13 +1794,13 @@
 	if (dev < 0 || dev >= num_synths)
 	  {
 	    vfree (inf);
-	    return -(ENXIO);
+	    return -ENXIO;
 	  }
 
 	if (!synth_devs[dev]->pmgr_interface)
 	  {
 	    vfree (inf);
-	    return -(ENXIO);
+	    return -ENXIO;
 	  }
 
 	if ((err = synth_devs[dev]->pmgr_interface (dev, inf)) == -1)
@@ -1787,7 +1809,11 @@
 	    return err;
 	  }
 
-	copy_to_user (&((char *) arg)[0], (char *) inf, sizeof (*inf));
+	{
+	  char           *fixit = (char *) inf;
+
+	  copy_to_user (&((char *) arg)[0], fixit, sizeof (*inf));
+	};
 	vfree (inf);
 	return 0;
       }
@@ -1801,7 +1827,7 @@
 	if ((inf = (struct patmgr_info *) vmalloc (sizeof (*inf))) == NULL)
 	  {
 	    printk ("patmgr: Can't allocate memory for a message\n");
-	    return -(EIO);
+	    return -EIO;
 	  }
 
 	copy_from_user ((char *) inf, &((char *) arg)[0], sizeof (*inf));
@@ -1810,13 +1836,13 @@
 	if (dev < 0 || dev >= num_synths)
 	  {
 	    vfree (inf);
-	    return -(ENXIO);
+	    return -ENXIO;
 	  }
 
 	if (!pmgr_present[dev])
 	  {
 	    vfree (inf);
-	    return -(ESRCH);
+	    return -ESRCH;
 	  }
 
 	if ((err = pmgr_access (dev, inf)) < 0)
@@ -1825,7 +1851,11 @@
 	    return err;
 	  }
 
-	copy_to_user (&((char *) arg)[0], (char *) inf, sizeof (*inf));
+	{
+	  char           *fixit = (char *) inf;
+
+	  copy_to_user (&((char *) arg)[0], fixit, sizeof (*inf));
+	};
 	vfree (inf);
 	return 0;
       }
@@ -1833,12 +1863,12 @@
 
     case SNDCTL_SEQ_THRESHOLD:
       {
-	int             tmp = get_user ((int *) arg);
+	int             tmp = ioctl_in (arg);
 
 	if (dev)		/*
 				 * Patch manager
 				 */
-	  return -(EIO);
+	  return -EIO;
 
 	if (tmp < 1)
 	  tmp = 1;
@@ -1851,14 +1881,14 @@
 
     case SNDCTL_MIDI_PRETIME:
       {
-	int             val = get_user ((int *) arg);
+	int             val = ioctl_in (arg);
 
 	if (val < 0)
 	  val = 0;
 
 	val = (HZ * val) / 10;
 	pre_event_timeout = val;
-	return snd_ioctl_return ((int *) arg, val);
+	return ioctl_out (arg, val);
       }
       break;
 
@@ -1866,24 +1896,24 @@
       if (dev)			/*
 				 * Patch manager
 				 */
-	return -(EIO);
+	return -EIO;
 
       if (mode == OPEN_READ)
-	return -(EIO);
+	return -EIO;
 
       if (!synth_devs[0])
-	return -(ENXIO);
+	return -ENXIO;
       if (!(synth_open_mask & (1 << 0)))
-	return -(ENXIO);
+	return -ENXIO;
       return synth_devs[0]->ioctl (0, cmd, arg);
       break;
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 int
-sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
+sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
   unsigned long   flags;
 
@@ -1897,8 +1927,8 @@
       if (!iqlen)
 	{
 
-	  midi_sleep_flag.flags = WK_SLEEP;
-	  module_select_wait (&midi_sleeper, wait);
+	  midi_sleep_flag.opts = WK_SLEEP;
+	  select_wait (&midi_sleeper, wait);
 	  restore_flags (flags);
 	  return 0;
 	}
@@ -1912,8 +1942,8 @@
       if ((SEQ_MAX_QUEUE - qlen) < output_threshold)
 	{
 
-	  seq_sleep_flag.flags = WK_SLEEP;
-	  module_select_wait (&seq_sleeper, wait);
+	  seq_sleep_flag.opts = WK_SLEEP;
+	  select_wait (&seq_sleeper, wait);
 	  restore_flags (flags);
 	  return 0;
 	}
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sound_calls.h linux/drivers/sound/sound_calls.h
--- v2.1.5/linux/drivers/sound/sound_calls.h	Sun Jun 30 11:43:39 1996
+++ linux/drivers/sound/sound_calls.h	Tue Oct 29 09:31:09 1996
@@ -18,8 +18,11 @@
 void DMAbuf_reset_dma (int dev);
 void DMAbuf_inputintr(int dev);
 void DMAbuf_outputintr(int dev, int underflow_flag);
-int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait);
+int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
+void DMAbuf_start_device(int dev);
 void DMAbuf_start_devices(unsigned int devmask);
+void DMAbuf_reset (int dev);
+int DMAbuf_sync (int dev);
 
 /*
  *	System calls for /dev/dsp and /dev/audio
@@ -31,10 +34,9 @@
 void audio_release (int dev, struct fileinfo *file);
 int audio_ioctl (int dev, struct fileinfo *file,
 	   unsigned int cmd, caddr_t arg);
-int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
-void audio_init (void);
+void audio_init_devices (void);
 
-int audio_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait);
+int audio_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
 
 /*
  *	System calls for the /dev/sequencer
@@ -54,7 +56,7 @@
 void seq_input_event(unsigned char *event, int len);
 void seq_copy_to_input (unsigned char *event, int len);
 
-int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait);
+int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
 
 /*
  *	System calls for the /dev/midi
@@ -70,7 +72,7 @@
 void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count);
 void MIDIbuf_init(void);
 
-int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait);
+int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
 
 /*
  *
@@ -89,6 +91,8 @@
 void sound_dma_free(int dev);
 void conf_printf(char *name, struct address_info *hw_config);
 void conf_printf2(char *name, int base, int irq, int dma, int dma2);
+int ioctl_in(caddr_t arg);
+int ioctl_out(caddr_t arg, int result);
 
 /*	From sound_switch.c	*/
 int sound_read_sw (int dev, struct fileinfo *file, char *buf, int count);
@@ -202,6 +206,12 @@
 #define AD_F_CS4231	0x0001	/* Returned if a CS4232 (or compatible) detected */
 #define AD_F_CS4248	0x0001	/* Returned if a CS4248 (or compatible) detected */
 
+void	 ad1848_control(int cmd, int arg);
+#define		AD1848_SET_XTAL		1
+#define		AD1848_MIXER_REROUTE	2
+#define AD1848_REROUTE(oldctl, newctl) \
+		ad1848_control(AD1848_MIXER_REROUTE, ((oldctl)<<8)|(newctl))
+
 void     ad1848_interrupt (int irq, void *dev_id, struct pt_regs * dummy);
 void attach_ms_sound(struct address_info * hw_config);
 int probe_ms_sound(struct address_info *hw_config);
@@ -223,15 +233,6 @@
 int probe_ss_ms_sound (struct address_info *hw_config);
 void attach_ss_ms_sound(struct address_info * hw_config);
 
-int pss_read (int dev, struct fileinfo *file, char *buf, int count);
-int pss_write (int dev, struct fileinfo *file, char *buf, int count);
-int pss_open (int dev, struct fileinfo *file);
-void pss_release (int dev, struct fileinfo *file);
-int pss_ioctl (int dev, struct fileinfo *file,
-	   unsigned int cmd, caddr_t arg);
-int pss_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
-void pss_init(void);
-
 /* From aedsp16.c */
 int InitAEDSP16_SBPRO(struct address_info *hw_config);
 int InitAEDSP16_MSS(struct address_info *hw_config);
@@ -291,6 +292,3 @@
 void attach_maui(struct address_info * hw_config);
 int probe_maui(struct address_info *hw_config);
 
-/*	From sound_pnp.c */
-void sound_pnp_init(int *osp);
-void sound_pnp_disconnect(void);
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sound_config.h linux/drivers/sound/sound_config.h
--- v2.1.5/linux/drivers/sound/sound_config.h	Tue Aug 20 17:36:20 1996
+++ linux/drivers/sound/sound_config.h	Tue Oct 29 09:31:10 1996
@@ -5,7 +5,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -15,10 +15,6 @@
 #include "os.h"
 #include "soundvers.h"
 
-#if defined(ISC) || defined(SCO) || defined(SVR42)
-#define GENERIC_SYSV
-#endif
-
 
 
 
@@ -32,20 +28,11 @@
 #define MAX_REALTIME_FACTOR	4
 #endif
 
-/************* PCM DMA buffer sizes *******************/
-
-/* If you are using high playback or recording speeds, the default buffer size
-   is too small. DSP_BUFFSIZE must be 64k or less.
-
-   A rule of thumb is 64k for PAS16, 32k for PAS+, 16k for SB Pro and
-   4k for SB.
-
-   If you change the DSP_BUFFSIZE, don't modify this file.
-   Use the make config command instead. */
-
-#ifndef DSP_BUFFSIZE
-#define DSP_BUFFSIZE		(4096)
-#endif
+/*
+ * Use always 64k buffer size. There is no reason to use shorter.
+ */
+#undef DSP_BUFFSIZE
+#define DSP_BUFFSIZE		(16*1024)
 
 #ifndef DSP_BUFFCOUNT
 #define DSP_BUFFCOUNT		1	/* 1 is recommended. */
@@ -128,7 +115,7 @@
 	int driver_use_1;	/* Driver defined field 1 */
 	int driver_use_2;	/* Driver defined field 2 */
 	int *osp;	/* OS specific info */
-	int card_subtype;	/* Driver specific. Usually 0 */
+	int card_subtype;	/* Driver spesific. Usually 0 */
 };
 
 #define SYNTH_MAX_VOICES	32
@@ -170,7 +157,7 @@
 #endif
 
 #ifndef DDB
-#define DDB(x)
+#define DDB(x) {}
 #endif
 
 #define TIMER_ARMED	121234
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sound_switch.c linux/drivers/sound/sound_switch.c
--- v2.1.5/linux/drivers/sound/sound_switch.c	Wed Oct 16 10:48:24 1996
+++ linux/drivers/sound/sound_switch.c	Tue Oct 29 09:31:55 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -15,20 +15,107 @@
 
 #include "sound_config.h"
 
-struct sbc_device
-  {
-    int             usecount;
-  };
-
 static int      in_use = 0;	/* Total # of open devices */
 
 /*
+ * Table for configurable mixer volume handling
+ */
+static mixer_vol_table mixer_vols[MAX_MIXER_DEV];
+static int      num_mixer_volumes = 0;
+
+/*
  * /dev/sndstatus -device
  */
 static char    *status_buf = NULL;
 static int      status_len, status_ptr;
 static int      status_busy = 0;
 
+int
+               *
+load_mixer_volumes (char *name, int *levels, int present)
+{
+  int             i, n;
+
+  for (i = 0; i < num_mixer_volumes; i++)
+    if (strcmp (name, mixer_vols[i].name) == 0)
+      {
+	if (present)
+	  mixer_vols[i].num = i;
+	return mixer_vols[i].levels;
+      }
+
+  if (num_mixer_volumes >= MAX_MIXER_DEV)
+    {
+      printk ("Sound: Too many mixers (%s)\n", name);
+      return levels;
+    }
+
+  n = num_mixer_volumes++;
+
+  strcpy (mixer_vols[n].name, name);
+
+  if (present)
+    mixer_vols[n].num = n;
+  else
+    mixer_vols[n].num = -1;
+
+  for (i = 0; i < 32; i++)
+    mixer_vols[n].levels[i] = levels[i];
+  return mixer_vols[n].levels;
+}
+
+static int
+set_mixer_levels (caddr_t arg)
+{
+  mixer_vol_table *buf = NULL;
+  int             err = 0;
+
+  if ((buf = (mixer_vol_table *) vmalloc (sizeof (mixer_vol_table))) == NULL)
+    return -ENOSPC;
+
+  copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
+
+  load_mixer_volumes (buf->name, buf->levels, 0);
+
+  {
+    char           *fixit = (char *) buf;
+
+    copy_to_user (&((char *) arg)[0], fixit, sizeof (*buf));
+  };
+  vfree (buf);
+
+  return err;
+}
+
+static int
+get_mixer_levels (caddr_t arg)
+{
+  mixer_vol_table *buf = NULL;
+  int             n, err = 0;
+
+  if ((buf = (mixer_vol_table *) vmalloc (sizeof (mixer_vol_table))) == NULL)
+    return -ENOSPC;
+
+  copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
+
+  n = buf->num;
+  if (n < 0 || n >= num_mixer_volumes)
+    err = -EINVAL;
+  else
+    {
+      memcpy ((char *) buf, (char *) &mixer_vols[n], sizeof (*buf));
+    }
+
+  {
+    char           *fixit = (char *) buf;
+
+    copy_to_user (&((char *) arg)[0], fixit, sizeof (*buf));
+  };
+  vfree (buf);
+
+  return err;
+}
+
 static int
 put_status (char *s)
 {
@@ -111,6 +198,7 @@
   put_status (system_utsname.machine);
   put_status ("\n");
 
+
   if (!put_status ("Config options: "))
     return;
   if (!put_status_int (SELECTED_SOUND_OPTIONS, 16))
@@ -135,6 +223,7 @@
 	  return;
       }
 
+
   if (!put_status ("\nCard config: \n"))
     return;
 
@@ -269,6 +358,7 @@
     }
 #endif
 
+#ifdef CONFIG_MIDI
   if (!put_status ("\nTimers:\n"))
     return;
 
@@ -283,6 +373,7 @@
       if (!put_status ("\n"))
 	return;
     }
+#endif
 
   if (!put_status ("\nMixers:\n"))
     return;
@@ -316,7 +407,11 @@
   if (l <= 0)
     return 0;
 
-  copy_to_user (&(buf)[0], &status_buf[status_ptr], l);
+  {
+    char           *fixit = &status_buf[status_ptr];
+
+    copy_to_user (&(buf)[0], fixit, l);
+  };
   status_ptr += l;
 
   return l;
@@ -353,11 +448,10 @@
       return MIDIbuf_read (dev, file, buf, count);
 #endif
 
-    default:
-      printk ("Sound: Undefined minor device %d\n", dev);
+    default:;
     }
 
-  return -(EPERM);
+  return -EINVAL;
 }
 
 int
@@ -366,6 +460,7 @@
 
   DEB (printk ("sound_write_sw(dev=%d, count=%d)\n", dev, count));
 
+
   switch (dev & 0x0f)
     {
 
@@ -391,7 +486,7 @@
 
     }
 
-  return -(EPERM);
+  return -EINVAL;
 }
 
 int
@@ -404,24 +499,25 @@
   if ((dev >= SND_NDEVS) || (dev < 0))
     {
       printk ("Invalid minor device %d\n", dev);
-      return -(ENXIO);
+      return -ENXIO;
     }
 
+
   switch (dev & 0x0f)
     {
     case SND_DEV_STATUS:
       if (status_busy)
-	return -(EBUSY);
+	return -EBUSY;
       status_busy = 1;
       if ((status_buf = (char *) vmalloc (4000)) == NULL)
-	return -(EIO);
+	return -EIO;
       status_len = status_ptr = 0;
       init_status ();
       break;
 
     case SND_DEV_CTL:
       if ((dev & 0xf0) && ((dev & 0xf0) >> 4) >= num_mixers)
-	return -(ENXIO);
+	return -ENXIO;
       return 0;
       break;
 
@@ -451,7 +547,7 @@
 
     default:
       printk ("Invalid minor device %d\n", dev);
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   in_use++;
@@ -510,21 +606,64 @@
   mixer_info      info;
 
   if (dev < 0 || dev >= num_mixers)
-    return -(ENXIO);
+    return -ENXIO;
+
+  strcpy (info.id, mixer_devs[dev]->id);
+  strcpy (info.name, mixer_devs[dev]->name);
+  info.modify_counter = mixer_devs[dev]->modify_counter;
+
+  {
+    char           *fixit = (char *) &info;
+
+    copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+  };
+  return 0;
+}
+
+static int
+get_old_mixer_info (int dev, caddr_t arg)
+{
+  _old_mixer_info info;
+
+  if (dev < 0 || dev >= num_mixers)
+    return -ENXIO;
 
   strcpy (info.id, mixer_devs[dev]->id);
   strcpy (info.name, mixer_devs[dev]->name);
 
-  copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+  {
+    char           *fixit = (char *) &info;
+
+    copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+  };
   return 0;
 }
 
+static int
+sound_mixer_ioctl (int mixdev,
+		   unsigned int cmd, caddr_t arg)
+{
+  if (cmd == SOUND_MIXER_INFO)
+    return get_mixer_info (mixdev, arg);
+  if (cmd == SOUND_OLD_MIXER_INFO)
+    return get_old_mixer_info (mixdev, arg);
+
+  if (_IOC_DIR (cmd) & _IOC_WRITE)
+    mixer_devs[mixdev]->modify_counter++;
+
+  return mixer_devs[mixdev]->ioctl (mixdev, cmd, arg);
+}
+
 int
 sound_ioctl_sw (int dev, struct fileinfo *file,
 		unsigned int cmd, caddr_t arg)
 {
   DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
 
+  if (cmd == OSS_GETVERSION)
+    return ioctl_out (arg, SOUND_VERSION);
+
+
   if (((cmd >> 8) & 0xff) == 'M' && num_mixers > 0)	/* Mixer ioctl */
     if ((dev & 0x0f) != SND_DEV_CTL)
       {
@@ -539,17 +678,13 @@
 	  case SND_DEV_AUDIO:
 	    mixdev = audio_devs[dev >> 4]->mixer_dev;
 	    if (mixdev < 0 || mixdev >= num_mixers)
-	      return -(ENXIO);
-	    if (cmd == SOUND_MIXER_INFO)
-	      return get_mixer_info (mixdev, arg);
-	    return mixer_devs[mixdev]->ioctl (mixdev, cmd, arg);
+	      return -ENXIO;
+	    return sound_mixer_ioctl (mixdev, cmd, arg);
 	    break;
 #endif
 
 	  default:
-	    if (cmd == SOUND_MIXER_INFO)
-	      return get_mixer_info (0, arg);
-	    return mixer_devs[0]->ioctl (0, cmd, arg);
+	    return sound_mixer_ioctl (dev, cmd, arg);
 	  }
       }
 
@@ -557,18 +692,20 @@
     {
 
     case SND_DEV_CTL:
+      if (cmd == SOUND_MIXER_GETLEVELS)
+	return get_mixer_levels (arg);
+      if (cmd == SOUND_MIXER_SETLEVELS)
+	return set_mixer_levels (arg);
 
       if (!num_mixers)
-	return -(ENXIO);
+	return -ENXIO;
 
       dev = dev >> 4;
 
       if (dev >= num_mixers)
-	return -(ENXIO);
+	return -ENXIO;
 
-      if (cmd == SOUND_MIXER_INFO)
-	return get_mixer_info (dev, arg);
-      return mixer_devs[dev]->ioctl (dev, cmd, arg);
+      return sound_mixer_ioctl (dev, cmd, arg);
       break;
 
 #ifdef CONFIG_SEQUENCER
@@ -594,5 +731,5 @@
 
     }
 
-  return -(EPERM);
+  return -EINVAL;
 }
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sound_timer.c linux/drivers/sound/sound_timer.c
--- v2.1.5/linux/drivers/sound/sound_timer.c	Sun Aug 18 10:46:49 1996
+++ linux/drivers/sound/sound_timer.c	Tue Oct 29 09:31:56 1996
@@ -4,7 +4,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -94,7 +94,7 @@
 timer_open (int dev, int mode)
 {
   if (opened)
-    return -(EBUSY);
+    return -EBUSY;
 
   tmr_reset ();
   curr_tempo = 60;
@@ -193,7 +193,7 @@
   switch (cmd)
     {
     case SNDCTL_TMR_SOURCE:
-      return snd_ioctl_return ((int *) arg, TMR_INTERNAL);
+      return ioctl_out (arg, TMR_INTERNAL);
       break;
 
     case SNDCTL_TMR_START:
@@ -214,7 +214,9 @@
 
     case SNDCTL_TMR_TIMEBASE:
       {
-	int             val = get_user ((int *) arg);
+	int             val;
+
+	get_user (val, (int *) arg);
 
 	if (val)
 	  {
@@ -225,13 +227,15 @@
 	    curr_timebase = val;
 	  }
 
-	return snd_ioctl_return ((int *) arg, curr_timebase);
+	return ioctl_out (arg, curr_timebase);
       }
       break;
 
     case SNDCTL_TMR_TEMPO:
       {
-	int             val = get_user ((int *) arg);
+	int             val;
+
+	get_user (val, (int *) arg);
 
 	if (val)
 	  {
@@ -246,15 +250,19 @@
 	    reprogram_timer ();
 	  }
 
-	return snd_ioctl_return ((int *) arg, curr_tempo);
+	return ioctl_out (arg, curr_tempo);
       }
       break;
 
     case SNDCTL_SEQ_CTRLRATE:
-      if (get_user ((int *) arg) != 0)	/* Can't change */
-	return -(EINVAL);
+      if (ioctl_in (arg) != 0)	/* Can't change */
+	return -EINVAL;
+
+      return ioctl_out (arg, ((curr_tempo * curr_timebase) + 30) / 60);
+      break;
 
-      return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60);
+    case SNDCTL_SEQ_GETTIME:
+      return ioctl_out (arg, curr_ticks);
       break;
 
     case SNDCTL_TMR_METRONOME:
@@ -264,7 +272,7 @@
     default:;
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v2.1.5/linux/drivers/sound/soundcard.c	Sat Oct  5 16:58:35 1996
+++ linux/drivers/sound/soundcard.c	Tue Oct 29 09:41:23 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -18,7 +18,7 @@
 #include <linux/major.h>
 
 
-int            *sound_global_osp = NULL;
+int            *sound_osp = NULL;
 static int      chrdev_registered = 0;
 static int      sound_major = SOUND_MAJOR;
 
@@ -43,47 +43,63 @@
 
 
 int
+ioctl_in (caddr_t arg)
+{
+  int             xx;
+
+  get_user (xx, (int *) arg);
+  return xx;
+}
+
+int
+ioctl_out (caddr_t arg, int result)
+{
+  put_user (result, (int *) arg);
+  return 0;
+}
+
+int
 snd_ioctl_return (int *addr, int value)
 {
   if (value < 0)
     return value;
 
-  put_user (value, addr);
+  put_user (value, (int *) &((addr)[0]));
   return 0;
 }
 
 static long
-sound_read (inode_handle * inode, file_handle * file, char *buf, unsigned long count)
+sound_read (struct inode *inode, struct file *file, char *buf, unsigned long count)
 {
   int             dev;
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
-  files[dev].flags = file_get_flags (file);
+  files[dev].flags = file->f_flags;
 
   return sound_read_sw (dev, &files[dev], buf, count);
 }
 
 static long
-sound_write (inode_handle * inode, file_handle * file, const char *buf, unsigned long count)
+sound_write (struct inode *inode, struct file *file, const char *buf, unsigned long count)
 {
   int             dev;
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
-  files[dev].flags = file_get_flags (file);
+  files[dev].flags = file->f_flags;
 
   return sound_write_sw (dev, &files[dev], buf, count);
 }
 
 static long long
-sound_lseek (inode_handle * inode, file_handle * file, long long offset, int orig)
+sound_lseek (struct inode *inode, struct file *file, long long offset, int orig)
 {
-  return -(EPERM);
+  return -EPERM;
 }
 
 static int
-sound_open (inode_handle * inode, file_handle * file)
+sound_open (struct inode *inode, struct file *file)
 {
   int             dev, retval;
   struct fileinfo tmp_file;
@@ -91,19 +107,19 @@
   if (is_unloading)
     {
       printk ("Sound: Driver partially removed. Can't open device\n");
-      return -(EBUSY);
+      return -EBUSY;
     }
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
   if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS)
     {
-      printk ("Sound Card Error: The soundcard system has not been configured\n");
-      return -(ENXIO);
+      printk ("SoundCard Error: The soundcard system has not been configured\n");
+      return -ENXIO;
     }
 
   tmp_file.mode = 0;
-  tmp_file.flags = file_get_flags (file);
+  tmp_file.flags = file->f_flags;
 
   if ((tmp_file.flags & O_ACCMODE) == O_RDWR)
     tmp_file.mode = OPEN_READWRITE;
@@ -124,13 +140,13 @@
 }
 
 static void
-sound_release (inode_handle * inode, file_handle * file)
+sound_release (struct inode *inode, struct file *file)
 {
   int             dev;
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
-  files[dev].flags = file_get_flags (file);
+  files[dev].flags = file->f_flags;
 
   sound_release_sw (dev, &files[dev]);
 #ifdef MODULE
@@ -139,14 +155,14 @@
 }
 
 static int
-sound_ioctl (inode_handle * inode, file_handle * file,
+sound_ioctl (struct inode *inode, struct file *file,
 	     unsigned int cmd, unsigned long arg)
 {
   int             dev, err;
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
-  files[dev].flags = file_get_flags (file);
+  files[dev].flags = file->f_flags;
 
   if (_IOC_DIR (cmd) != _IOC_NONE)
     {
@@ -177,13 +193,13 @@
 }
 
 static int
-sound_select (inode_handle * inode, file_handle * file, int sel_type, select_table_handle * wait)
+sound_select (struct inode *inode, struct file *file, int sel_type, select_table * wait)
 {
   int             dev;
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
-  files[dev].flags = file_get_flags (file);
+  files[dev].flags = file->f_flags;
 
   DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type));
 
@@ -218,15 +234,15 @@
 }
 
 static int
-sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma)
+sound_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma)
 {
   int             dev, dev_class;
   unsigned long   size;
   struct dma_buffparms *dmap = NULL;
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
-  files[dev].flags = file_get_flags (file);
+  files[dev].flags = file->f_flags;
 
   dev_class = dev & 0x0f;
   dev >>= 4;
@@ -237,17 +253,17 @@
       return -EINVAL;
     }
 
-  if ((vma_get_flags (vma) & (VM_READ | VM_WRITE)) == (VM_READ | VM_WRITE))
+  if ((vma->vm_flags & (VM_READ | VM_WRITE)) == (VM_READ | VM_WRITE))
     {
       printk ("Sound: Cannot do read/write mmap()\n");
       return -EINVAL;
     }
 
-  if (vma_get_flags (vma) & VM_READ)
+  if (vma->vm_flags & VM_READ)
     {
       dmap = audio_devs[dev]->dmap_in;
     }
-  else if (vma_get_flags (vma) & VM_WRITE)
+  else if (vma->vm_flags & VM_WRITE)
     {
       dmap = audio_devs[dev]->dmap_out;
     }
@@ -275,13 +291,13 @@
       return -EIO;
     }
 
-  if (vma_get_offset (vma) != 0)
+  if (vma->vm_offset != 0)
     {
       printk ("Sound: mmap() offset must be 0.\n");
       return -EINVAL;
     }
 
-  size = vma_get_end (vma) - vma_get_start (vma);
+  size = vma->vm_end - vma->vm_start;
 
   if (size != dmap->bytes_in_use)
     {
@@ -289,13 +305,13 @@
 	      size, dmap->bytes_in_use);
     }
 
-  if (remap_page_range (vma_get_start (vma), virt_to_phys(dmap->raw_buf),
-			vma_get_end (vma) - vma_get_start (vma),
-			vma_get_page_prot (vma)))
+  if (remap_page_range (vma->vm_start, virt_to_phys (dmap->raw_buf),
+			vma->vm_end - vma->vm_start,
+			vma->vm_page_prot))
     return -EAGAIN;
 
-  vma_set_inode (vma, inode);
-  inode_inc_count (inode);
+  vma->vm_inode = inode;
+  inode->i_count++;
 
   dmap->mapping_flags |= DMA_MAP_MAPPED;
 
@@ -305,7 +321,7 @@
   return 0;
 }
 
-static struct file_operation_handle sound_fops =
+static struct file_operations sound_fops =
 {
   sound_lseek,
   sound_read,
@@ -322,7 +338,7 @@
 soundcard_init (void)
 {
 #ifndef MODULE
-  module_register_chrdev (sound_major, "sound", &sound_fops);
+  register_chrdev (sound_major, "sound", &sound_fops);
   chrdev_registered = 1;
 #endif
 
@@ -331,15 +347,6 @@
   sndtable_init ();		/* Initialize call tables and detect cards */
 
 
-
-#ifdef CONFIG_LOWLEVEL_SOUND
-  {
-    extern void     sound_init_lowlevel_drivers (void);
-
-    sound_init_lowlevel_drivers ();
-  }
-#endif
-
   if (sndtable_get_cardcount () == 0)
     return;			/* No cards detected */
 
@@ -347,7 +354,7 @@
   if (num_audiodevs)		/* Audio devices present */
     {
       DMAbuf_init ();
-      audio_init ();
+      audio_init_devices ();
     }
 #endif
 
@@ -396,7 +403,7 @@
   int             ints[21];
   int             i;
 
-  if (connect_wrapper (WRAPPER_VERSION) < 0)
+  if (0 < 0)
     {
       printk ("Sound: Incompatible kernel (wrapper) version\n");
       return -EINVAL;
@@ -413,7 +420,7 @@
   if (i)
     sound_setup ("sound=", ints);
 
-  err = module_register_chrdev (sound_major, "sound", &sound_fops);
+  err = register_chrdev (sound_major, "sound", &sound_fops);
   if (err)
     {
       printk ("sound: driver already loaded/included in kernel\n");
@@ -443,7 +450,7 @@
     }
 
   if (chrdev_registered)
-    module_unregister_chrdev (sound_major, "sound");
+    unregister_chrdev (sound_major, "sound");
 
 #ifdef CONFIG_SEQUENCER
   sound_stop_timer ();
@@ -491,7 +498,6 @@
 
   save_flags (flags);
   cli ();
-
   retcode = request_irq (interrupt_level, iproc, 0 /* SA_INTERRUPT */ , name, NULL);
   if (retcode < 0)
     {
@@ -595,14 +601,25 @@
   extern unsigned long seq_time;
 
   if (count < 0)
-    count = jiffies + (-count);
-  else
-    count += seq_time;
+    {
+
+      {
+	seq_timer.expires = (-count) + jiffies;
+	add_timer (&seq_timer);
+      };
+      return;
+    }
+
+  count += seq_time;
+
+  count -= jiffies;
+
+  if (count < 1)
+    count = 1;
 
-  ;
 
   {
-    seq_timer.expires = ((count - jiffies)) + jiffies;
+    seq_timer.expires = (count) + jiffies;
     add_timer (&seq_timer);
   };
 }
@@ -668,14 +685,14 @@
 
       audio_devs[dev]->buffsize = PAGE_SIZE * (1 << sz);
 
-      if ((start_addr = (char *) __get_dma_pages (GFP_ATOMIC, sz)) == NULL)
+      if ((start_addr = (char *) __get_free_pages (GFP_ATOMIC, sz, MAX_DMA_ADDRESS)) == NULL)
 	audio_devs[dev]->buffsize /= 2;
     }
 
   if (start_addr == NULL)
     {
       printk ("Sound error: Couldn't allocate DMA buffer\n");
-      return -(ENOMEM);
+      return -ENOMEM;
     }
   else
     {
@@ -696,7 +713,7 @@
 		   "sound: Got invalid address 0x%lx for %ldb DMA-buffer\n",
 		   (long) start_addr,
 		   audio_devs[dev]->buffsize);
-	  return -(EFAULT);
+	  return -EFAULT;
 	}
     }
   dmap->raw_buf = start_addr;
@@ -704,14 +721,14 @@
 
   for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
     {
-      mem_map_reserve (i);
+      set_bit (PG_reserved, &mem_map[i].flags);;
     }
 
   return 0;
 }
 
 void
-sound_free_dmap (int dev, struct dma_buffparms *dmap)
+sound_free_dmap (int dev, struct dma_buffparms *dmap, int chan)
 {
   int             sz, size, i;
   unsigned long   start_addr, end_addr;
@@ -731,7 +748,7 @@
 
   for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
     {
-      mem_map_unreserve (i);
+      clear_bit (PG_reserved, &mem_map[i].flags);;
     }
 
   free_pages ((unsigned long) dmap->raw_buf, sz);
@@ -743,7 +760,7 @@
 {
   printk ("Entered sound_map_buffer()\n");
   printk ("Exited sound_map_buffer()\n");
-  return -(EINVAL);
+  return -EINVAL;
 }
 #endif
 
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/soundvers.h linux/drivers/sound/soundvers.h
--- v2.1.5/linux/drivers/sound/soundvers.h	Mon Jul  1 06:30:35 1996
+++ linux/drivers/sound/soundvers.h	Tue Oct 29 09:31:11 1996
@@ -1,2 +1,2 @@
-#define SOUND_VERSION_STRING "3.5.4-960630"
-#define SOUND_INTERNAL_VERSION 0x030504
+#define SOUND_VERSION_STRING "3.7-beta6-961029"
+#define SOUND_INTERNAL_VERSION 0x030701
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c
--- v2.1.5/linux/drivers/sound/sscape.c	Wed Oct 16 10:48:24 1996
+++ linux/drivers/sound/sscape.c	Tue Oct 29 09:31:58 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -15,7 +15,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIG_SSCAPE)
+#if defined(CONFIG_SSCAPEHW)
 
 #include "coproc.h"
 
@@ -88,7 +88,7 @@
 {0};
 static struct sscape_info *devc = &dev_info;
 
-static wait_handle *sscape_sleeper = NULL;
+static struct wait_queue *sscape_sleeper = NULL;
 static volatile struct snd_wait sscape_sleep_flag =
 {0};
 
@@ -117,7 +117,7 @@
 
   save_flags (flags);
   cli ();
-  outb (reg, PORT (ODIE_ADDR));
+  outb ((reg), PORT (ODIE_ADDR));
   val = inb (PORT (ODIE_DATA));
   restore_flags (flags);
   return val;
@@ -130,21 +130,21 @@
 
   save_flags (flags);
   cli ();
-  outb (reg, PORT (ODIE_ADDR));
-  outb (data, PORT (ODIE_DATA));
+  outb ((reg), PORT (ODIE_ADDR));
+  outb ((data), PORT (ODIE_DATA));
   restore_flags (flags);
 }
 
 static void
 host_open (struct sscape_info *devc)
 {
-  outb (0x00, PORT (HOST_CTRL));	/* Put the board to the host mode */
+  outb ((0x00), PORT (HOST_CTRL));	/* Put the board to the host mode */
 }
 
 static void
 host_close (struct sscape_info *devc)
 {
-  outb (0x03, PORT (HOST_CTRL));	/* Put the board to the MIDI mode */
+  outb ((0x03), PORT (HOST_CTRL));	/* Put the board to the MIDI mode */
 }
 
 static int
@@ -172,7 +172,7 @@
 	  return 0;
 	}
 
-      outb (data[i], PORT (HOST_DATA));
+      outb ((data[i]), PORT (HOST_DATA));
     }
 
 
@@ -291,11 +291,11 @@
   static int      debug = 0;
 
   bits = sscape_read (devc, GA_INTSTAT_REG);
-  if ((sscape_sleep_flag.flags & WK_SLEEP))
+  if ((sscape_sleep_flag.opts & WK_SLEEP))
     {
       {
-	sscape_sleep_flag.flags = WK_WAKEUP;
-	module_wake_up (&sscape_sleeper);
+	sscape_sleep_flag.opts = WK_WAKEUP;
+	wake_up (&sscape_sleeper);
       };
     }
 
@@ -387,10 +387,10 @@
     {
       set_mt32 (devc, 0);
       if (!verify_mpu (devc))
-	return -(EIO);
+	return -EIO;
     }
 
-  sscape_sleep_flag.flags = WK_NONE;
+  sscape_sleep_flag.opts = WK_NONE;
   return 0;
 }
 
@@ -407,7 +407,7 @@
       sscape_write (devc, GA_DMAA_REG, 0x20);	/* DMA channel disabled */
       devc->dma_allocated = 0;
     }
-  sscape_sleep_flag.flags = WK_NONE;
+  sscape_sleep_flag.opts = WK_NONE;
   restore_flags (flags);
 
   return;
@@ -436,10 +436,6 @@
       save_flags (flags);
       cli ();
       codec_dma_bits = sscape_read (devc, GA_CDCFG_REG);
-#if 0
-      sscape_write (devc, GA_CDCFG_REG,
-		    codec_dma_bits & ~0x08);	/* Disable codec DMA */
-#endif
 
       if (devc->dma_allocated == 0)
 	{
@@ -473,7 +469,7 @@
   /*
    * Wait until transfer completes.
    */
-  sscape_sleep_flag.flags = WK_NONE;
+  sscape_sleep_flag.opts = WK_NONE;
   done = 0;
   timeout_val = 100;
   while (!done && timeout_val-- > 0)
@@ -485,17 +481,17 @@
 	unsigned long   tlimit;
 
 	if (1)
-	  current_set_timeout (tlimit = jiffies + (1));
+	  current->timeout = tlimit = jiffies + (1);
 	else
 	  tlimit = (unsigned long) -1;
-	sscape_sleep_flag.flags = WK_SLEEP;
-	module_interruptible_sleep_on (&sscape_sleeper);
-	if (!(sscape_sleep_flag.flags & WK_WAKEUP))
+	sscape_sleep_flag.opts = WK_SLEEP;
+	interruptible_sleep_on (&sscape_sleeper);
+	if (!(sscape_sleep_flag.opts & WK_WAKEUP))
 	  {
 	    if (jiffies >= tlimit)
-	      sscape_sleep_flag.flags |= WK_TIMEOUT;
+	      sscape_sleep_flag.opts |= WK_TIMEOUT;
 	  }
-	sscape_sleep_flag.flags &= ~WK_SLEEP;
+	sscape_sleep_flag.opts &= ~WK_SLEEP;
       };
       clear_dma_ff (devc->dma);
       if ((resid = get_dma_residue (devc->dma)) == 0)
@@ -513,8 +509,8 @@
       /*
          * Take the board out of reset
        */
-      outb (0x00, PORT (HOST_CTRL));
-      outb (0x00, PORT (MIDI_CTRL));
+      outb ((0x00), PORT (HOST_CTRL));
+      outb ((0x00), PORT (MIDI_CTRL));
 
       temp = sscape_read (devc, GA_HMCTL_REG);
       temp |= 0x40;
@@ -530,25 +526,31 @@
       timeout_val = 5 * HZ;
       while (!done && timeout_val-- > 0)
 	{
+	  unsigned char   x;
+
 
 	  {
 	    unsigned long   tlimit;
 
 	    if (1)
-	      current_set_timeout (tlimit = jiffies + (1));
+	      current->timeout = tlimit = jiffies + (1);
 	    else
 	      tlimit = (unsigned long) -1;
-	    sscape_sleep_flag.flags = WK_SLEEP;
-	    module_interruptible_sleep_on (&sscape_sleeper);
-	    if (!(sscape_sleep_flag.flags & WK_WAKEUP))
+	    sscape_sleep_flag.opts = WK_SLEEP;
+	    interruptible_sleep_on (&sscape_sleeper);
+	    if (!(sscape_sleep_flag.opts & WK_WAKEUP))
 	      {
 		if (jiffies >= tlimit)
-		  sscape_sleep_flag.flags |= WK_TIMEOUT;
+		  sscape_sleep_flag.opts |= WK_TIMEOUT;
 	      }
-	    sscape_sleep_flag.flags &= ~WK_SLEEP;
+	    sscape_sleep_flag.opts &= ~WK_SLEEP;
 	  };
-	  if (inb (PORT (HOST_DATA)) == 0xff)	/* OBP startup acknowledge */
-	    done = 1;
+	  x = inb (PORT (HOST_DATA));
+	  if (x == 0xff || x == 0xfe)	/* OBP startup acknowledge */
+	    {
+	      printk ("Soundscape: Acknowledge = %x\n", x);
+	      done = 1;
+	    }
 	}
       sscape_write (devc, GA_CDCFG_REG, codec_dma_bits);
 
@@ -570,17 +572,17 @@
 	    unsigned long   tlimit;
 
 	    if (1)
-	      current_set_timeout (tlimit = jiffies + (1));
+	      current->timeout = tlimit = jiffies + (1);
 	    else
 	      tlimit = (unsigned long) -1;
-	    sscape_sleep_flag.flags = WK_SLEEP;
-	    module_interruptible_sleep_on (&sscape_sleeper);
-	    if (!(sscape_sleep_flag.flags & WK_WAKEUP))
+	    sscape_sleep_flag.opts = WK_SLEEP;
+	    interruptible_sleep_on (&sscape_sleeper);
+	    if (!(sscape_sleep_flag.opts & WK_WAKEUP))
 	      {
 		if (jiffies >= tlimit)
-		  sscape_sleep_flag.flags |= WK_TIMEOUT;
+		  sscape_sleep_flag.opts |= WK_TIMEOUT;
 	      }
-	    sscape_sleep_flag.flags &= ~WK_SLEEP;
+	    sscape_sleep_flag.opts &= ~WK_SLEEP;
 	  };
 	  if (inb (PORT (HOST_DATA)) == 0xfe)	/* Host startup acknowledge */
 	    done = 1;
@@ -620,12 +622,12 @@
 download_boot_block (void *dev_info, copr_buffer * buf)
 {
   if (buf->len <= 0 || buf->len > sizeof (buf->data))
-    return -(EINVAL);
+    return -EINVAL;
 
   if (!sscape_download_boot (devc, buf->data, buf->len, buf->flags))
     {
       printk ("SSCAPE: Unable to load microcode block to the OBP.\n");
-      return -(EIO);
+      return -EIO;
     }
 
   return 0;
@@ -649,7 +651,7 @@
 
 	buf = (copr_buffer *) vmalloc (sizeof (copr_buffer));
 	if (buf == NULL)
-	  return -(ENOSPC);
+	  return -ENOSPC;
 	copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
 	err = download_boot_block (dev_info, buf);
 	vfree (buf);
@@ -658,7 +660,7 @@
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 
 }
@@ -760,7 +762,8 @@
 		      (sscape_read (devc, i) & 0xc0));
 	break;
 
-      case 6:			/* CD-ROM config. Don't touch. */
+      case 6:			/* CD-ROM config (WSS codec actually) */
+	sscape_write (devc, i, regs[i]);
 	break;
 
       case 9:			/* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
@@ -815,11 +818,11 @@
 {
   unsigned char   save;
 
-  devc->failed = 1;
   devc->base = hw_config->io_base;
   devc->irq = hw_config->irq;
   devc->dma = hw_config->dma;
-  devc->osp = hw_config->osp;
+
+  devc->failed = 1;
 
   if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
     return 0;
@@ -830,17 +833,26 @@
      * First 4 bits
    */
   if ((save = inb (PORT (ODIE_ADDR))) & 0xf0)
-    return 0;
+    {
+      DDB (printk ("soundscape: Detect error A\n"));
+      return 0;
+    }
 
-  outb (0x00, PORT (ODIE_ADDR));
+  outb ((0x00), PORT (ODIE_ADDR));
   if (inb (PORT (ODIE_ADDR)) != 0x00)
-    return 0;
+    {
+      DDB (printk ("soundscape: Detect error B\n"));
+      return 0;
+    }
 
-  outb (0xff, PORT (ODIE_ADDR));
+  outb ((0xff), PORT (ODIE_ADDR));
   if (inb (PORT (ODIE_ADDR)) != 0x0f)
-    return 0;
+    {
+      DDB (printk ("soundscape: Detect error C\n"));
+      return 0;
+    }
 
-  outb (save, PORT (ODIE_ADDR));
+  outb ((save), PORT (ODIE_ADDR));
 
   /*
      * Now verify that some indirect registers return zero on some bits.
@@ -848,13 +860,22 @@
    */
 
   if (sscape_read (devc, 0) & 0x0c)
-    return 0;
+    {
+      DDB (printk ("soundscape: Detect error D (%x)\n", sscape_read (devc, 0)));
+      return 0;
+    }
 
   if (sscape_read (devc, 1) & 0x0f)
-    return 0;
+    {
+      DDB (printk ("soundscape: Detect error E\n"));
+      return 0;
+    }
 
   if (sscape_read (devc, 5) & 0x0f)
-    return 0;
+    {
+      DDB (printk ("soundscape: Detect error F\n"));
+      return 0;
+    }
 
 #ifdef SSCAPE_DEBUG1
   /*
@@ -896,7 +917,10 @@
   int             i, irq_bits = 0xff;
 
   if (devc->failed)
-    return 0;
+    {
+      printk ("Soundscape: Card not detected\n");
+      return 0;
+    }
 
   if (devc->ok == 0)
     {
@@ -915,6 +939,7 @@
       printk ("SoundScape: Invalid MSS IRQ%d\n", hw_config->irq);
       return 0;
     }
+
 
   return ad1848_detect (hw_config->io_base, NULL, hw_config->osp);
 }
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/sys_timer.c linux/drivers/sound/sys_timer.c
--- v2.1.5/linux/drivers/sound/sys_timer.c	Sun Aug 18 10:46:49 1996
+++ linux/drivers/sound/sys_timer.c	Tue Oct 29 09:31:58 1996
@@ -7,7 +7,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -90,7 +90,7 @@
 def_tmr_open (int dev, int mode)
 {
   if (opened)
-    return -(EBUSY);
+    return -EBUSY;
 
   tmr_reset ();
   curr_tempo = 60;
@@ -192,7 +192,7 @@
   switch (cmd)
     {
     case SNDCTL_TMR_SOURCE:
-      return snd_ioctl_return ((int *) arg, TMR_INTERNAL);
+      return ioctl_out (arg, TMR_INTERNAL);
       break;
 
     case SNDCTL_TMR_START:
@@ -213,7 +213,9 @@
 
     case SNDCTL_TMR_TIMEBASE:
       {
-	int             val = get_user ((int *) arg);
+	int             val;
+
+	get_user (val, (int *) arg);
 
 	if (val)
 	  {
@@ -224,13 +226,15 @@
 	    curr_timebase = val;
 	  }
 
-	return snd_ioctl_return ((int *) arg, curr_timebase);
+	return ioctl_out (arg, curr_timebase);
       }
       break;
 
     case SNDCTL_TMR_TEMPO:
       {
-	int             val = get_user ((int *) arg);
+	int             val;
+
+	get_user (val, (int *) arg);
 
 	if (val)
 	  {
@@ -244,15 +248,19 @@
 	    curr_tempo = val;
 	  }
 
-	return snd_ioctl_return ((int *) arg, curr_tempo);
+	return ioctl_out (arg, curr_tempo);
       }
       break;
 
     case SNDCTL_SEQ_CTRLRATE:
-      if (get_user ((int *) arg) != 0)	/* Can't change */
-	return -(EINVAL);
+      if (ioctl_in (arg) != 0)	/* Can't change */
+	return -EINVAL;
+
+      return ioctl_out (arg, ((curr_tempo * curr_timebase) + 30) / 60);
+      break;
 
-      return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60);
+    case SNDCTL_SEQ_GETTIME:
+      return ioctl_out (arg, curr_ticks);
       break;
 
     case SNDCTL_TMR_METRONOME:
@@ -262,7 +270,7 @@
     default:;
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/trix.c linux/drivers/sound/trix.c
--- v2.1.5/linux/drivers/sound/trix.c	Sat Jul 20 08:56:29 1996
+++ linux/drivers/sound/trix.c	Tue Oct 29 09:31:59 1996
@@ -7,7 +7,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -37,15 +37,15 @@
 static unsigned char
 trix_read (int addr)
 {
-  outb ((unsigned char) addr, 0x390);	/* MT-0002-PC ASIC address */
+  outb (((unsigned char) addr), 0x390);		/* MT-0002-PC ASIC address */
   return inb (0x391);		/* MT-0002-PC ASIC data */
 }
 
 static void
 trix_write (int addr, int data)
 {
-  outb ((unsigned char) addr, 0x390);	/* MT-0002-PC ASIC address */
-  outb ((unsigned char) data, 0x391);	/* MT-0002-PC ASIC data */
+  outb (((unsigned char) addr), 0x390);		/* MT-0002-PC ASIC address */
+  outb (((unsigned char) data), 0x391);		/* MT-0002-PC ASIC data */
 }
 
 static void
@@ -57,22 +57,22 @@
     return;
 
   trix_write (0xf8, 0x00);	/* ??????? */
-  outb (0x01, base + 6);	/* Clear the internal data pointer */
-  outb (0x00, base + 6);	/* Restart */
+  outb ((0x01), base + 6);	/* Clear the internal data pointer */
+  outb ((0x00), base + 6);	/* Restart */
 
   /*
      *  Write the boot code to the RAM upload/download register.
      *  Each write increments the internal data pointer.
    */
-  outb (0x01, base + 6);	/* Clear the internal data pointer */
-  outb (0x1A, 0x390);		/* Select RAM download/upload port */
+  outb ((0x01), base + 6);	/* Clear the internal data pointer */
+  outb ((0x1A), 0x390);		/* Select RAM download/upload port */
 
   for (i = 0; i < n; i++)
-    outb (trix_boot[i], 0x391);
+    outb ((trix_boot[i]), 0x391);
   for (i = n; i < 10016; i++)	/* Clear up to first 16 bytes of data RAM */
-    outb (0x00, 0x391);
-  outb (0x00, base + 6);	/* Reset */
-  outb (0x50, 0x390);		/* ?????? */
+    outb ((0x00), 0x391);
+  outb ((0x00), base + 6);	/* Reset */
+  outb ((0x50), 0x390);		/* ?????? */
 
 }
 
@@ -175,7 +175,7 @@
       return 0;
     }
 
-  if (hw_config->dma2 != -1)
+  if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
     if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3)
       {
 	printk ("AudioTrix: Bad capture DMA %d\n", hw_config->dma2);
@@ -218,6 +218,7 @@
 
   int             config_port = hw_config->io_base + 0;
   int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
+  int             old_num_mixers = num_mixers;
 
   trix_osp = hw_config->osp;
 
@@ -238,7 +239,7 @@
       return;
     }
 
-  outb (bits | 0x40, config_port);
+  outb ((bits | 0x40), config_port);
 
   if (hw_config->dma2 == -1 || hw_config->dma2 == hw_config->dma)
     {
@@ -256,7 +257,7 @@
       trix_write (0x14, tmp | 0x80 | (dma2 << 4));
     }
 
-  outb (bits, config_port);	/* Write IRQ+DMA setup */
+  outb ((bits), config_port);	/* Write IRQ+DMA setup */
 
   ad1848_init ("AudioTrix Pro", hw_config->io_base + 4,
 	       hw_config->irq,
@@ -265,6 +266,14 @@
 	       0,
 	       hw_config->osp);
   request_region (hw_config->io_base, 4, "MSS config");
+
+  if (num_mixers > old_num_mixers)	/* Mixer got installed */
+    {
+      AD1848_REROUTE (SOUND_MIXER_LINE1, SOUND_MIXER_LINE);	/* Line in */
+      AD1848_REROUTE (SOUND_MIXER_LINE2, SOUND_MIXER_CD);
+      AD1848_REROUTE (SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH);	/* OPL4 */
+      AD1848_REROUTE (SOUND_MIXER_SPEAKER, SOUND_MIXER_ALTPCM);		/* SB */
+    }
 }
 
 int
@@ -316,7 +325,7 @@
 
   hw_config->name = "AudioTrix SB";
 #ifdef CONFIG_SBDSP
-  return probe_sb (hw_config);
+  return sb_dsp_detect (hw_config);
 #else
   return 0;
 #endif
@@ -327,7 +336,7 @@
 {
 #ifdef CONFIG_SBDSP
   hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING;
-  attach_sb_card (hw_config);
+  sb_dsp_init (hw_config);
 #endif
 }
 
@@ -443,7 +452,7 @@
 unload_trix_sb (struct address_info *hw_config)
 {
 #ifdef CONFIG_SBDSP
-  unload_sb (hw_config);
+  sb_dsp_unload (hw_config);
 #endif
 }
 
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/uart401.c linux/drivers/sound/uart401.c
--- v2.1.5/linux/drivers/sound/uart401.c	Wed Aug 14 10:21:03 1996
+++ linux/drivers/sound/uart401.c	Tue Oct 29 09:31:59 1996
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -23,7 +23,7 @@
     int             irq;
     int            *osp;
     void            (*midi_input_intr) (int dev, unsigned char data);
-    int             opened;
+    int             opened, disabled;
     volatile unsigned char input_byte;
     int             my_dev;
     int             share_irq;
@@ -48,7 +48,7 @@
 static void 
 uart401_cmd (uart401_devc * devc, unsigned char cmd)
 {
-  outb (cmd, COMDPORT);
+  outb ((cmd), COMDPORT);
 }
 static int 
 uart401_read (uart401_devc * devc)
@@ -58,7 +58,7 @@
 static void 
 uart401_write (uart401_devc * devc, unsigned char byte)
 {
-  outb (byte, DATAPORT);
+  outb ((byte), DATAPORT);
 }
 
 #define	OUTPUT_READY	0x40
@@ -68,6 +68,7 @@
 #define	UART_MODE_ON	0x3F
 
 static int      reset_uart401 (uart401_devc * devc);
+static void     enter_uart_mode (uart401_devc * devc);
 
 static void
 uart401_input_loop (uart401_devc * devc)
@@ -110,7 +111,7 @@
 
   if (devc->opened)
     {
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   while (input_avail (devc))
@@ -118,6 +119,8 @@
 
   devc->midi_input_intr = input;
   devc->opened = mode;
+  enter_uart_mode (devc);
+  devc->disabled = 0;
 
   return 0;
 }
@@ -127,6 +130,7 @@
 {
   uart401_devc   *devc = (uart401_devc *) midi_devs[dev]->devc;
 
+  reset_uart401 (devc);
   devc->opened = 0;
 }
 
@@ -137,6 +141,8 @@
   unsigned long   flags;
   uart401_devc   *devc = (uart401_devc *) midi_devs[dev]->devc;
 
+  if (devc->disabled)
+    return 1;
   /*
    * Test for input since pending input seems to block the output.
    */
@@ -158,8 +164,11 @@
 
   if (!output_ready (devc))
     {
-      printk ("MPU-401: Timeout\n");
-      return 0;
+      printk ("MPU-401: Timeout - Device not responding\n");
+      devc->disabled = 1;
+      reset_uart401 (devc);
+      enter_uart_mode (devc);
+      return 1;
     }
 
   uart401_write (devc, midi_byte);
@@ -181,7 +190,7 @@
 static int
 uart401_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -347,8 +356,6 @@
 
   ok = 0;
 
-  /* save_flags(flags);cli(); */
-
   for (n = 0; n < 2 && !ok; n++)
     {
       for (timeout = 30000; timeout < 0 && !output_ready (devc); timeout--);
@@ -370,13 +377,19 @@
 
     }
 
+
+  if (ok)
+    {
+      DDB (printk ("Reset UART401 OK\n"));
+    }
+  else
+    DDB (printk ("Reset UART401 failed - No hardware detected.\n"));
+
   if (ok)
     uart401_input_loop (devc);	/*
 				 * Flush input before enabling interrupts
 				 */
 
-  /* restore_flags(flags); */
-
   return ok;
 }
 
@@ -388,6 +401,8 @@
   static uart401_devc hw_info;
   uart401_devc   *devc = &hw_info;
 
+  DDB (printk ("Entered probe_uart401()\n"));
+
   detected_devc = NULL;
 
   if (check_region (hw_config->io_base, 4))
@@ -428,7 +443,6 @@
     return;
 
   reset_uart401 (devc);
-
   release_region (hw_config->io_base, 4);
 
   if (!devc->share_irq)
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/uart6850.c linux/drivers/sound/uart6850.c
--- v2.1.5/linux/drivers/sound/uart6850.c	Sun Jun 30 11:44:22 1996
+++ linux/drivers/sound/uart6850.c	Tue Oct 29 09:32:00 1996
@@ -4,7 +4,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -36,7 +36,7 @@
 static void 
 uart6850_cmd (unsigned char cmd)
 {
-  outb (cmd, COMDPORT);
+  outb ((cmd), COMDPORT);
 }
 static int 
 uart6850_read (void)
@@ -46,7 +46,7 @@
 static void 
 uart6850_write (unsigned char byte)
 {
-  outb (byte, DATAPORT);
+  outb ((byte), DATAPORT);
 }
 
 #define	OUTPUT_READY	0x02	/* Mask for data ready Bit */
@@ -138,7 +138,7 @@
   if (uart6850_opened)
     {
       printk ("Midi6850: Midi busy\n");
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   ;
@@ -222,7 +222,7 @@
 static int
 uart6850_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
diff -u --recursive --new-file v2.1.5/linux/fs/affs/dir.c linux/fs/affs/dir.c
--- v2.1.5/linux/fs/affs/dir.c	Sun May 19 15:22:19 1996
+++ linux/fs/affs/dir.c	Mon Oct 28 14:29:24 1996
@@ -13,7 +13,7 @@
  *
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.5/linux/fs/affs/file.c linux/fs/affs/file.c
--- v2.1.5/linux/fs/affs/file.c	Wed Oct 16 10:48:24 1996
+++ linux/fs/affs/file.c	Mon Oct 28 14:29:24 1996
@@ -12,7 +12,7 @@
  *  affs regular file handling primitives
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/sched.h>
 #include <linux/affs_fs.h>
diff -u --recursive --new-file v2.1.5/linux/fs/affs/inode.c linux/fs/affs/inode.c
--- v2.1.5/linux/fs/affs/inode.c	Wed Oct 16 10:48:24 1996
+++ linux/fs/affs/inode.c	Mon Oct 28 14:29:24 1996
@@ -27,7 +27,7 @@
 #include <linux/major.h>
 #include <linux/blkdev.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 extern int *blk_size[];
 extern struct timezone sys_tz;
diff -u --recursive --new-file v2.1.5/linux/fs/affs/namei.c linux/fs/affs/namei.c
--- v2.1.5/linux/fs/affs/namei.c	Wed Jul  3 12:03:47 1996
+++ linux/fs/affs/namei.c	Mon Oct 28 14:29:25 1996
@@ -16,7 +16,7 @@
 #include <linux/fcntl.h>
 #include <linux/locks.h>
 #include <linux/amigaffs.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 
diff -u --recursive --new-file v2.1.5/linux/fs/affs/symlink.c linux/fs/affs/symlink.c
--- v2.1.5/linux/fs/affs/symlink.c	Sun May 19 15:22:20 1996
+++ linux/fs/affs/symlink.c	Mon Oct 28 14:29:25 1996
@@ -15,7 +15,7 @@
 #include <linux/stat.h>
 #include <linux/affs_fs.h>
 #include <linux/amigaffs.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 
diff -u --recursive --new-file v2.1.5/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- v2.1.5/linux/fs/binfmt_aout.c	Wed Oct 16 10:48:24 1996
+++ linux/fs/binfmt_aout.c	Mon Oct 28 14:21:41 1996
@@ -24,7 +24,7 @@
 #include <linux/personality.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
diff -u --recursive --new-file v2.1.5/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.1.5/linux/fs/binfmt_elf.c	Sat Oct 19 10:07:31 1996
+++ linux/fs/binfmt_elf.c	Mon Oct 28 17:37:10 1996
@@ -28,7 +28,7 @@
 #include <linux/personality.h>
 #include <linux/elfcore.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 #include <linux/config.h>
@@ -98,65 +98,68 @@
 				  unsigned long interp_load_addr, int ibcs)
 {
 	char **argv, **envp;
-	unsigned long *dlinfo;
 	unsigned long *sp;
 
 	/*
 	 * Force 16 byte alignment here for generality.
 	 */
 	sp = (unsigned long *) (~15UL & (unsigned long) p);
-	sp -= exec ? DLINFO_ITEMS*2 : 2;
-	dlinfo = sp;
+
+	/*
+	 * Put the ELF interpreter info on the stack
+	 */
+#define NEW_AUX_ENT(nr, id, val) \
+	  __put_user ((id), sp+(nr*2)); \
+	  __put_user ((val), sp+(nr*2+1)); \
+
+	sp -= 2;
+	NEW_AUX_ENT(0, AT_NULL, 0);
+
+	if (exec) {
+		sp -= 11*2;
+
+	  NEW_AUX_ENT (0, AT_PHDR, load_addr + exec->e_phoff);
+	  NEW_AUX_ENT (1, AT_PHENT, sizeof (struct elf_phdr));
+	  NEW_AUX_ENT (2, AT_PHNUM, exec->e_phnum);
+	  NEW_AUX_ENT (3, AT_PAGESZ, PAGE_SIZE);
+	  NEW_AUX_ENT (4, AT_BASE, interp_load_addr);
+	  NEW_AUX_ENT (5, AT_FLAGS, 0);
+	  NEW_AUX_ENT (6, AT_ENTRY, (unsigned long) exec->e_entry);
+	  NEW_AUX_ENT (7, AT_UID, (unsigned long) current->uid);
+	  NEW_AUX_ENT (8, AT_EUID, (unsigned long) current->euid);
+	  NEW_AUX_ENT (9, AT_GID, (unsigned long) current->gid);
+	  NEW_AUX_ENT (10, AT_EGID, (unsigned long) current->egid);
+	}
+#undef NEW_AUX_ENT
+
 	sp -= envc+1;
 	envp = (char **) sp;
 	sp -= argc+1;
 	argv = (char **) sp;
 	if (!ibcs) {
-		put_user((unsigned long) envp,--sp);
-		put_user((unsigned long) argv,--sp);
+		__put_user((unsigned long) envp,--sp);
+		__put_user((unsigned long) argv,--sp);
 	}
 
-#define NEW_AUX_ENT(id, val) \
-	  put_user ((id), dlinfo++); \
-	  put_user ((val), dlinfo++)
-
-	if (exec) { /* Put this here for an ELF program interpreter */
-	  struct elf_phdr * eppnt;
-	  eppnt = (struct elf_phdr *) exec->e_phoff;
-
-	  NEW_AUX_ENT (AT_PHDR, load_addr + exec->e_phoff);
-	  NEW_AUX_ENT (AT_PHENT, sizeof (struct elf_phdr));
-	  NEW_AUX_ENT (AT_PHNUM, exec->e_phnum);
-	  NEW_AUX_ENT (AT_PAGESZ, PAGE_SIZE);
-	  NEW_AUX_ENT (AT_BASE, interp_load_addr);
-	  NEW_AUX_ENT (AT_FLAGS, 0);
-	  NEW_AUX_ENT (AT_ENTRY, (unsigned long) exec->e_entry);
-	  NEW_AUX_ENT (AT_UID, (unsigned long) current->uid);
-	  NEW_AUX_ENT (AT_EUID, (unsigned long) current->euid);
-	  NEW_AUX_ENT (AT_GID, (unsigned long) current->gid);
-	  NEW_AUX_ENT (AT_EGID, (unsigned long) current->egid);
-	}
-	NEW_AUX_ENT (AT_NULL, 0);
-#undef NEW_AUX_ENT
-	put_user((unsigned long)argc,--sp);
+	__put_user((unsigned long)argc,--sp);
 	current->mm->arg_start = (unsigned long) p;
 	while (argc-->0) {
 		char c;
-		put_user(p,argv++);
+		__put_user(p,argv++);
 		do {
 			get_user(c,p++);
 		} while (c);
 	}
-	put_user(NULL, argv);
+	__put_user(NULL, argv);
 	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
 	while (envc-->0) {
 		char c;
-		put_user(p,envp++);
+		__put_user(p,envp++);
 		do {
 			get_user(c,p++);
 		} while (c);
 	}
-	put_user(NULL, envp);
+	__put_user(NULL, envp);
 	current->mm->env_end = (unsigned long) p;
 	return sp;
 }
diff -u --recursive --new-file v2.1.5/linux/fs/block_dev.c linux/fs/block_dev.c
--- v2.1.5/linux/fs/block_dev.c	Wed Oct 16 10:48:24 1996
+++ linux/fs/block_dev.c	Mon Oct 28 14:21:41 1996
@@ -11,7 +11,7 @@
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 extern int *blk_size[];
diff -u --recursive --new-file v2.1.5/linux/fs/buffer.c linux/fs/buffer.c
--- v2.1.5/linux/fs/buffer.c	Sat Oct 19 10:07:31 1996
+++ linux/fs/buffer.c	Mon Oct 28 14:21:41 1996
@@ -33,7 +33,7 @@
 #include <linux/vmalloc.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 #define NR_SIZES 5
diff -u --recursive --new-file v2.1.5/linux/fs/dquot.c linux/fs/dquot.c
--- v2.1.5/linux/fs/dquot.c	Wed Oct 16 10:48:24 1996
+++ linux/fs/dquot.c	Mon Oct 28 14:21:41 1996
@@ -35,7 +35,7 @@
 #include <linux/malloc.h>
 #include <linux/mount.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define __DQUOT_VERSION__	"dquot_5.6.0"
 
diff -u --recursive --new-file v2.1.5/linux/fs/exec.c linux/fs/exec.c
--- v2.1.5/linux/fs/exec.c	Wed Oct 16 10:48:24 1996
+++ linux/fs/exec.c	Mon Oct 28 14:21:41 1996
@@ -40,7 +40,7 @@
 #include <linux/personality.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 #include <linux/config.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ext/dir.c linux/fs/ext/dir.c
--- v2.1.5/linux/fs/ext/dir.c	Mon Sep 30 11:01:41 1996
+++ linux/fs/ext/dir.c	Mon Oct 28 14:29:25 1996
@@ -12,7 +12,7 @@
  *  ext directory handling functions
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ext/file.c linux/fs/ext/file.c
--- v2.1.5/linux/fs/ext/file.c	Wed Oct 16 10:48:25 1996
+++ linux/fs/ext/file.c	Mon Oct 28 14:29:25 1996
@@ -12,7 +12,7 @@
  *  ext regular file handling primitives
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ext/fsync.c linux/fs/ext/fsync.c
--- v2.1.5/linux/fs/ext/fsync.c	Sun Nov 26 19:23:10 1995
+++ linux/fs/ext/fsync.c	Mon Oct 28 14:29:25 1996
@@ -11,7 +11,7 @@
  *  extfs fsync primitive
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ext/inode.c linux/fs/ext/inode.c
--- v2.1.5/linux/fs/ext/inode.c	Wed Oct 16 10:48:25 1996
+++ linux/fs/ext/inode.c	Mon Oct 28 14:29:25 1996
@@ -21,7 +21,7 @@
 #include <linux/locks.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 void ext_put_inode(struct inode *inode)
 {
diff -u --recursive --new-file v2.1.5/linux/fs/ext/namei.c linux/fs/ext/namei.c
--- v2.1.5/linux/fs/ext/namei.c	Wed Jul  3 16:19:00 1996
+++ linux/fs/ext/namei.c	Mon Oct 28 14:29:25 1996
@@ -18,7 +18,7 @@
 #include <linux/fcntl.h>
 #include <linux/errno.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /*
  * comment out this line if you want names > EXT_NAME_LEN chars to be
diff -u --recursive --new-file v2.1.5/linux/fs/ext/symlink.c linux/fs/ext/symlink.c
--- v2.1.5/linux/fs/ext/symlink.c	Fri Dec 22 13:00:19 1995
+++ linux/fs/ext/symlink.c	Mon Oct 28 14:29:25 1996
@@ -12,7 +12,7 @@
  *  ext symlink handling code
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ext2/dir.c linux/fs/ext2/dir.c
--- v2.1.5/linux/fs/ext2/dir.c	Sat Sep 28 23:24:16 1996
+++ linux/fs/ext2/dir.c	Mon Oct 28 14:29:25 1996
@@ -15,7 +15,7 @@
  *  ext2 directory handling functions
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v2.1.5/linux/fs/ext2/file.c	Wed Oct 16 10:48:25 1996
+++ linux/fs/ext2/file.c	Mon Oct 28 14:29:25 1996
@@ -15,7 +15,7 @@
  *  ext2 fs regular file handling primitives
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ext2/fsync.c linux/fs/ext2/fsync.c
--- v2.1.5/linux/fs/ext2/fsync.c	Sun Nov 26 19:23:10 1995
+++ linux/fs/ext2/fsync.c	Mon Oct 28 14:29:25 1996
@@ -12,7 +12,7 @@
  *  ext2fs fsync primitive
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v2.1.5/linux/fs/ext2/inode.c	Mon Sep 23 08:38:18 1996
+++ linux/fs/ext2/inode.c	Mon Oct 28 14:29:25 1996
@@ -15,7 +15,7 @@
  *  Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ext2/ioctl.c linux/fs/ext2/ioctl.c
--- v2.1.5/linux/fs/ext2/ioctl.c	Wed Oct 16 10:48:25 1996
+++ linux/fs/ext2/ioctl.c	Mon Oct 28 14:29:25 1996
@@ -7,7 +7,7 @@
  * Universite Pierre et Marie Curie (Paris VI)
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.1.5/linux/fs/ext2/namei.c	Mon Sep 23 08:38:18 1996
+++ linux/fs/ext2/namei.c	Mon Oct 28 14:29:25 1996
@@ -13,7 +13,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.1.5/linux/fs/ext2/super.c	Wed Oct 16 10:48:26 1996
+++ linux/fs/ext2/super.c	Mon Oct 28 14:29:25 1996
@@ -18,7 +18,7 @@
 #include <stdarg.h>
 
 #include <asm/bitops.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ext2/symlink.c linux/fs/ext2/symlink.c
--- v2.1.5/linux/fs/ext2/symlink.c	Sat Oct 19 10:07:32 1996
+++ linux/fs/ext2/symlink.c	Mon Oct 28 14:29:25 1996
@@ -15,7 +15,7 @@
  *  ext2 symlink handling code
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
diff -u --recursive --new-file v2.1.5/linux/fs/fat/dir.c linux/fs/fat/dir.c
--- v2.1.5/linux/fs/fat/dir.c	Wed Oct 16 10:48:26 1996
+++ linux/fs/fat/dir.c	Mon Oct 28 14:29:25 1996
@@ -21,7 +21,7 @@
 #include <linux/dirent.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "msbuffer.h"
 #include "tables.h"
diff -u --recursive --new-file v2.1.5/linux/fs/fat/file.c linux/fs/fat/file.c
--- v2.1.5/linux/fs/fat/file.c	Wed Oct 16 10:48:26 1996
+++ linux/fs/fat/file.c	Mon Oct 28 14:29:25 1996
@@ -16,7 +16,7 @@
 #include <linux/string.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include "msbuffer.h"
diff -u --recursive --new-file v2.1.5/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.1.5/linux/fs/fat/inode.c	Wed Oct 16 10:48:26 1996
+++ linux/fs/fat/inode.c	Mon Oct 28 14:29:25 1996
@@ -22,7 +22,7 @@
 #include "msbuffer.h"
 #include "tables.h"
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
 
diff -u --recursive --new-file v2.1.5/linux/fs/fat/mmap.c linux/fs/fat/mmap.c
--- v2.1.5/linux/fs/fat/mmap.c	Fri Feb  9 07:47:16 1996
+++ linux/fs/fat/mmap.c	Mon Oct 28 14:29:25 1996
@@ -18,7 +18,7 @@
 #include <linux/malloc.h>
 #include <linux/msdos_fs.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 /*
diff -u --recursive --new-file v2.1.5/linux/fs/fcntl.c linux/fs/fcntl.c
--- v2.1.5/linux/fs/fcntl.c	Thu Jul  4 21:23:45 1996
+++ linux/fs/fcntl.c	Mon Oct 28 14:21:41 1996
@@ -4,8 +4,6 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <asm/segment.h>
-
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -14,6 +12,7 @@
 #include <linux/string.h>
 
 #include <asm/bitops.h>
+#include <asm/uaccess.h>
 
 extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
 
diff -u --recursive --new-file v2.1.5/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c
--- v2.1.5/linux/fs/hpfs/hpfs_fs.c	Wed Oct 16 10:48:26 1996
+++ linux/fs/hpfs/hpfs_fs.c	Mon Oct 28 14:29:25 1996
@@ -24,7 +24,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <asm/bitops.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "hpfs.h"
 #include "hpfs_caps.h"
diff -u --recursive --new-file v2.1.5/linux/fs/ioctl.c linux/fs/ioctl.c
--- v2.1.5/linux/fs/ioctl.c	Wed Oct 16 10:48:27 1996
+++ linux/fs/ioctl.c	Mon Oct 28 14:21:41 1996
@@ -4,8 +4,6 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <asm/segment.h>
-
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
@@ -13,6 +11,8 @@
 #include <linux/stat.h>
 #include <linux/termios.h>
 #include <linux/fcntl.h> /* for f_flags values */
+
+#include <asm/uaccess.h>
 
 static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
 {
diff -u --recursive --new-file v2.1.5/linux/fs/isofs/dir.c linux/fs/isofs/dir.c
--- v2.1.5/linux/fs/isofs/dir.c	Tue Jul 23 10:26:40 1996
+++ linux/fs/isofs/dir.c	Mon Oct 28 14:29:25 1996
@@ -21,7 +21,7 @@
 #include <linux/sched.h>
 #include <linux/locks.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int isofs_readdir(struct inode *, struct file *, void *, filldir_t);
 
diff -u --recursive --new-file v2.1.5/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.1.5/linux/fs/isofs/inode.c	Wed Oct 16 10:48:27 1996
+++ linux/fs/isofs/inode.c	Mon Oct 28 14:29:25 1996
@@ -23,7 +23,7 @@
 #include <linux/cdrom.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /*
  * We have no support for "multi volume" CDs, but more and more disks carry
diff -u --recursive --new-file v2.1.5/linux/fs/isofs/namei.c linux/fs/isofs/namei.c
--- v2.1.5/linux/fs/isofs/namei.c	Sat Apr 13 12:14:45 1996
+++ linux/fs/isofs/namei.c	Mon Oct 28 14:29:25 1996
@@ -12,7 +12,7 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/malloc.h>
 
 #include <linux/errno.h>
diff -u --recursive --new-file v2.1.5/linux/fs/isofs/symlink.c linux/fs/isofs/symlink.c
--- v2.1.5/linux/fs/isofs/symlink.c	Fri Dec 22 13:00:19 1995
+++ linux/fs/isofs/symlink.c	Mon Oct 28 14:29:25 1996
@@ -16,7 +16,7 @@
 #include <linux/stat.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int isofs_readlink(struct inode *, char *, int);
 static int isofs_follow_link(struct inode *, struct inode *, int, int, struct inode **);
diff -u --recursive --new-file v2.1.5/linux/fs/locks.c linux/fs/locks.c
--- v2.1.5/linux/fs/locks.c	Wed Oct 16 10:48:27 1996
+++ linux/fs/locks.c	Mon Oct 28 14:21:41 1996
@@ -106,7 +106,7 @@
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define OFFSET_MAX	((off_t)0x7fffffff)	/* FIXME: move elsewhere? */
 
diff -u --recursive --new-file v2.1.5/linux/fs/minix/dir.c linux/fs/minix/dir.c
--- v2.1.5/linux/fs/minix/dir.c	Sat Sep 28 23:23:42 1996
+++ linux/fs/minix/dir.c	Mon Oct 28 14:29:25 1996
@@ -12,7 +12,7 @@
 #include <linux/minix_fs.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static long minix_dir_read(struct inode * inode, struct file * filp,
 	char * buf, unsigned long count)
diff -u --recursive --new-file v2.1.5/linux/fs/minix/file.c linux/fs/minix/file.c
--- v2.1.5/linux/fs/minix/file.c	Wed Oct 16 10:48:27 1996
+++ linux/fs/minix/file.c	Mon Oct 28 14:29:25 1996
@@ -16,7 +16,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #define	NBUF	32
diff -u --recursive --new-file v2.1.5/linux/fs/minix/fsync.c linux/fs/minix/fsync.c
--- v2.1.5/linux/fs/minix/fsync.c	Thu Jan  4 14:07:58 1996
+++ linux/fs/minix/fsync.c	Mon Oct 28 14:29:26 1996
@@ -20,7 +20,7 @@
 #include <linux/fs.h>
 #include <linux/minix_fs.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #define blocksize BLOCK_SIZE
diff -u --recursive --new-file v2.1.5/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.1.5/linux/fs/minix/inode.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/minix/inode.c	Mon Oct 28 14:29:26 1996
@@ -18,7 +18,7 @@
 #include <linux/locks.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 void minix_put_inode(struct inode *inode)
diff -u --recursive --new-file v2.1.5/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v2.1.5/linux/fs/minix/namei.c	Wed Jul  3 13:13:21 1996
+++ linux/fs/minix/namei.c	Mon Oct 28 14:29:26 1996
@@ -12,7 +12,7 @@
 #include <linux/fcntl.h>
 #include <linux/errno.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /*
  * comment out this line if you want names > info->s_namelen chars to be
diff -u --recursive --new-file v2.1.5/linux/fs/minix/symlink.c linux/fs/minix/symlink.c
--- v2.1.5/linux/fs/minix/symlink.c	Fri Dec 22 13:00:19 1995
+++ linux/fs/minix/symlink.c	Mon Oct 28 14:29:26 1996
@@ -12,7 +12,7 @@
 #include <linux/minix_fs.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int minix_readlink(struct inode *, char *, int);
 static int minix_follow_link(struct inode *, struct inode *, int, int, struct inode **);
diff -u --recursive --new-file v2.1.5/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v2.1.5/linux/fs/msdos/namei.c	Wed Jul  3 12:08:03 1996
+++ linux/fs/msdos/namei.c	Mon Oct 28 14:29:26 1996
@@ -15,7 +15,7 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "../fat/msbuffer.h"
 
diff -u --recursive --new-file v2.1.5/linux/fs/namei.c linux/fs/namei.c
--- v2.1.5/linux/fs/namei.c	Sat Oct 19 10:07:32 1996
+++ linux/fs/namei.c	Mon Oct 28 14:21:41 1996
@@ -16,7 +16,7 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
 
diff -u --recursive --new-file v2.1.5/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.1.5/linux/fs/ncpfs/dir.c	Sat Oct  5 16:58:35 1996
+++ linux/fs/ncpfs/dir.c	Mon Oct 28 14:29:26 1996
@@ -13,7 +13,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/ncp_fs.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
 #include "ncplib_kernel.h"
diff -u --recursive --new-file v2.1.5/linux/fs/ncpfs/file.c linux/fs/ncpfs/file.c
--- v2.1.5/linux/fs/ncpfs/file.c	Sat Oct  5 16:58:35 1996
+++ linux/fs/ncpfs/file.c	Mon Oct 28 14:29:26 1996
@@ -5,7 +5,7 @@
  *
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.1.5/linux/fs/ncpfs/inode.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/ncpfs/inode.c	Mon Oct 28 14:29:26 1996
@@ -9,7 +9,7 @@
 #include <linux/config.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/sched.h>
 #include <linux/ncp_fs.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ncpfs/ioctl.c linux/fs/ncpfs/ioctl.c
--- v2.1.5/linux/fs/ncpfs/ioctl.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/ncpfs/ioctl.c	Mon Oct 28 14:29:26 1996
@@ -5,7 +5,7 @@
  *
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ncp_fs.h>
diff -u --recursive --new-file v2.1.5/linux/fs/ncpfs/mmap.c linux/fs/ncpfs/mmap.c
--- v2.1.5/linux/fs/ncpfs/mmap.c	Sat Mar  2 13:15:35 1996
+++ linux/fs/ncpfs/mmap.c	Mon Oct 28 14:29:26 1996
@@ -18,7 +18,7 @@
 #include <linux/ncp_fs.h>
 
 #include "ncplib_kernel.h"
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 static inline int min(int a, int b)
diff -u --recursive --new-file v2.1.5/linux/fs/ncpfs/sock.c linux/fs/ncpfs/sock.c
--- v2.1.5/linux/fs/ncpfs/sock.c	Wed Jul 10 13:19:24 1996
+++ linux/fs/ncpfs/sock.c	Mon Oct 28 14:29:26 1996
@@ -13,7 +13,7 @@
 #include <linux/socket.h>
 #include <linux/fcntl.h>
 #include <linux/stat.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/in.h>
 #include <linux/net.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.5/linux/fs/nfs/bio.c linux/fs/nfs/bio.c
--- v2.1.5/linux/fs/nfs/bio.c	Sat Jun 29 12:00:46 1996
+++ linux/fs/nfs/bio.c	Mon Oct 28 14:29:26 1996
@@ -32,7 +32,7 @@
 #include <linux/malloc.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #undef DEBUG_BIO
diff -u --recursive --new-file v2.1.5/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.1.5/linux/fs/nfs/dir.c	Sat Sep 28 23:42:49 1996
+++ linux/fs/nfs/dir.c	Mon Oct 28 14:29:26 1996
@@ -18,7 +18,7 @@
 #include <linux/malloc.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>	/* for fs functions */
+#include <asm/uaccess.h>	/* for fs functions */
 
 static int nfs_dir_open(struct inode * inode, struct file * file);
 static long nfs_dir_read(struct inode *, struct file *, char *, unsigned long);
diff -u --recursive --new-file v2.1.5/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v2.1.5/linux/fs/nfs/file.c	Sat Sep 28 23:26:24 1996
+++ linux/fs/nfs/file.c	Mon Oct 28 14:29:26 1996
@@ -26,7 +26,7 @@
 #include <linux/malloc.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 static int nfs_file_mmap(struct inode *, struct file *, struct vm_area_struct *);
diff -u --recursive --new-file v2.1.5/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.1.5/linux/fs/nfs/inode.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/nfs/inode.c	Mon Oct 28 14:29:26 1996
@@ -28,7 +28,7 @@
 #include <linux/smp_lock.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /* This is for kernel_thread */
 #define __KERNEL_SYSCALLS__
diff -u --recursive --new-file v2.1.5/linux/fs/nfs/nfsroot.c linux/fs/nfs/nfsroot.c
--- v2.1.5/linux/fs/nfs/nfsroot.c	Fri May 31 13:46:27 1996
+++ linux/fs/nfs/nfsroot.c	Mon Oct 28 14:29:26 1996
@@ -92,7 +92,7 @@
 #include <net/route.h>
 #include <net/sock.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /* Range of privileged ports */
 #define STARTPORT	600
diff -u --recursive --new-file v2.1.5/linux/fs/nfs/proc.c linux/fs/nfs/proc.c
--- v2.1.5/linux/fs/nfs/proc.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/nfs/proc.c	Mon Oct 28 14:29:26 1996
@@ -44,7 +44,7 @@
 #include <linux/in.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #ifdef NFS_PROC_DEBUG
 
diff -u --recursive --new-file v2.1.5/linux/fs/nfs/rpcsock.c linux/fs/nfs/rpcsock.c
--- v2.1.5/linux/fs/nfs/rpcsock.c	Tue Sep  3 20:10:17 1996
+++ linux/fs/nfs/rpcsock.c	Mon Oct 28 14:29:26 1996
@@ -44,7 +44,7 @@
 #include <linux/udp.h>
 #include <net/sock.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define msleep(sec)	{ current->timeout = sec * HZ / 1000; \
 			  current->state = TASK_INTERRUPTIBLE; \
diff -u --recursive --new-file v2.1.5/linux/fs/nfs/sock.c linux/fs/nfs/sock.c
--- v2.1.5/linux/fs/nfs/sock.c	Sun Mar 31 00:05:22 1996
+++ linux/fs/nfs/sock.c	Mon Oct 28 14:29:26 1996
@@ -28,7 +28,7 @@
 #include <linux/mm.h>
 #include <linux/rpcsock.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define _S(nr) (1<<((nr)-1))
 
diff -u --recursive --new-file v2.1.5/linux/fs/nfs/symlink.c linux/fs/nfs/symlink.c
--- v2.1.5/linux/fs/nfs/symlink.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/nfs/symlink.c	Mon Oct 28 14:29:26 1996
@@ -16,7 +16,7 @@
 #include <linux/malloc.h>
 #include <linux/string.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int nfs_readlink(struct inode *, char *, int);
 static int nfs_follow_link(struct inode *, struct inode *, int, int,
diff -u --recursive --new-file v2.1.5/linux/fs/noquot.c linux/fs/noquot.c
--- v2.1.5/linux/fs/noquot.c	Wed Oct  9 08:55:22 1996
+++ linux/fs/noquot.c	Mon Oct 28 14:21:41 1996
@@ -19,7 +19,7 @@
 #include <linux/malloc.h>
 #include <linux/mount.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #ifndef min
 #define min(a,b) ((a) < (b)) ? (a) : (b)
diff -u --recursive --new-file v2.1.5/linux/fs/open.c linux/fs/open.c
--- v2.1.5/linux/fs/open.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/open.c	Mon Oct 28 14:21:41 1996
@@ -19,7 +19,7 @@
 #include <linux/mm.h>
 #include <linux/file.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 asmlinkage int sys_statfs(const char * path, struct statfs * buf)
diff -u --recursive --new-file v2.1.5/linux/fs/pipe.c linux/fs/pipe.c
--- v2.1.5/linux/fs/pipe.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/pipe.c	Mon Oct 28 14:21:41 1996
@@ -4,8 +4,6 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <asm/segment.h>
-
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -13,6 +11,8 @@
 #include <linux/fcntl.h>
 #include <linux/termios.h>
 #include <linux/mm.h>
+
+#include <asm/uaccess.h>
 
 /*
  * Define this if you want SunOS compatibility wrt braindead
diff -u --recursive --new-file v2.1.5/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.1.5/linux/fs/proc/array.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/proc/array.c	Mon Oct 28 14:29:26 1996
@@ -47,7 +47,7 @@
 #include <linux/pagemap.h>
 #include <linux/swap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 
diff -u --recursive --new-file v2.1.5/linux/fs/proc/base.c linux/fs/proc/base.c
--- v2.1.5/linux/fs/proc/base.c	Thu Oct 10 19:10:56 1996
+++ linux/fs/proc/base.c	Mon Oct 28 14:29:26 1996
@@ -6,7 +6,7 @@
  *  proc base directory handling functions
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.5/linux/fs/proc/fd.c linux/fs/proc/fd.c
--- v2.1.5/linux/fs/proc/fd.c	Fri Dec 22 13:00:19 1995
+++ linux/fs/proc/fd.c	Mon Oct 28 14:29:26 1996
@@ -6,7 +6,7 @@
  *  proc fd directory handling functions
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.5/linux/fs/proc/inode.c linux/fs/proc/inode.c
--- v2.1.5/linux/fs/proc/inode.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/proc/inode.c	Mon Oct 28 14:29:26 1996
@@ -14,7 +14,7 @@
 #include <linux/limits.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static void proc_put_inode(struct inode *inode)
 {
diff -u --recursive --new-file v2.1.5/linux/fs/proc/kmsg.c linux/fs/proc/kmsg.c
--- v2.1.5/linux/fs/proc/kmsg.c	Sat Sep 28 23:32:52 1996
+++ linux/fs/proc/kmsg.c	Mon Oct 28 14:29:26 1996
@@ -10,7 +10,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 extern unsigned long log_size;
diff -u --recursive --new-file v2.1.5/linux/fs/proc/link.c linux/fs/proc/link.c
--- v2.1.5/linux/fs/proc/link.c	Fri Dec 22 13:00:19 1995
+++ linux/fs/proc/link.c	Mon Oct 28 14:29:26 1996
@@ -6,7 +6,7 @@
  *  /proc link-file handling code
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.5/linux/fs/proc/mem.c linux/fs/proc/mem.c
--- v2.1.5/linux/fs/proc/mem.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/proc/mem.c	Mon Oct 28 14:29:27 1996
@@ -11,7 +11,7 @@
 #include <linux/mm.h>
 
 #include <asm/page.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.5/linux/fs/proc/net.c linux/fs/proc/net.c
--- v2.1.5/linux/fs/proc/net.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/proc/net.c	Mon Oct 28 14:29:27 1996
@@ -31,7 +31,7 @@
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define PROC_BLOCK_SIZE	(3*1024)		/* 4K page size but our output routines use some slack for overruns */
 
diff -u --recursive --new-file v2.1.5/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.1.5/linux/fs/proc/root.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/proc/root.c	Mon Oct 28 14:29:27 1996
@@ -6,7 +6,7 @@
  *  proc root directory handling functions
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.5/linux/fs/proc/scsi.c linux/fs/proc/scsi.c
--- v2.1.5/linux/fs/proc/scsi.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/proc/scsi.c	Mon Oct 28 14:29:27 1996
@@ -26,7 +26,7 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /* forward references */
 static long proc_readscsi(struct inode * inode, struct file * file,
diff -u --recursive --new-file v2.1.5/linux/fs/read_write.c linux/fs/read_write.c
--- v2.1.5/linux/fs/read_write.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/read_write.c	Mon Oct 28 14:21:41 1996
@@ -14,7 +14,7 @@
 #include <linux/mm.h>
 #include <linux/uio.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static long long default_llseek(struct inode *inode,
 	struct file *file,
diff -u --recursive --new-file v2.1.5/linux/fs/readdir.c linux/fs/readdir.c
--- v2.1.5/linux/fs/readdir.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/readdir.c	Mon Oct 28 14:21:41 1996
@@ -11,7 +11,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /*
  * Traditional linux readdir() handling..
diff -u --recursive --new-file v2.1.5/linux/fs/select.c linux/fs/select.c
--- v2.1.5/linux/fs/select.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/select.c	Mon Oct 28 14:21:41 1996
@@ -22,7 +22,7 @@
 #include <linux/personality.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #define ROUND_UP(x,y) (((x)+(y)-1)/(y))
diff -u --recursive --new-file v2.1.5/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v2.1.5/linux/fs/smbfs/dir.c	Mon Sep 30 11:13:36 1996
+++ linux/fs/smbfs/dir.c	Mon Oct 28 14:29:27 1996
@@ -12,7 +12,7 @@
 #include <linux/malloc.h>
 #include <linux/mm.h>
 #include <linux/smb_fs.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 
 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
diff -u --recursive --new-file v2.1.5/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
--- v2.1.5/linux/fs/smbfs/file.c	Mon Sep 30 11:13:09 1996
+++ linux/fs/smbfs/file.c	Mon Oct 28 14:29:27 1996
@@ -5,7 +5,7 @@
  *
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.5/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.1.5/linux/fs/smbfs/inode.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/smbfs/inode.c	Mon Oct 28 14:29:27 1996
@@ -8,7 +8,7 @@
 #include <linux/module.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/sched.h>
 #include <linux/smb_fs.h>
diff -u --recursive --new-file v2.1.5/linux/fs/smbfs/ioctl.c linux/fs/smbfs/ioctl.c
--- v2.1.5/linux/fs/smbfs/ioctl.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/smbfs/ioctl.c	Mon Oct 28 14:29:27 1996
@@ -5,7 +5,7 @@
  *
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/smb_fs.h>
diff -u --recursive --new-file v2.1.5/linux/fs/smbfs/mmap.c linux/fs/smbfs/mmap.c
--- v2.1.5/linux/fs/smbfs/mmap.c	Wed Jun  5 13:22:48 1996
+++ linux/fs/smbfs/mmap.c	Mon Oct 28 14:29:27 1996
@@ -17,7 +17,7 @@
 #include <linux/smb_fs.h>
 #include <linux/fcntl.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 /*
diff -u --recursive --new-file v2.1.5/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c
--- v2.1.5/linux/fs/smbfs/proc.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/smbfs/proc.c	Mon Oct 28 14:29:27 1996
@@ -15,7 +15,7 @@
 #include <linux/malloc.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/string.h>
 
 #define ARCH i386
diff -u --recursive --new-file v2.1.5/linux/fs/smbfs/sock.c linux/fs/smbfs/sock.c
--- v2.1.5/linux/fs/smbfs/sock.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/smbfs/sock.c	Mon Oct 28 14:29:27 1996
@@ -11,7 +11,7 @@
 #include <linux/socket.h>
 #include <linux/fcntl.h>
 #include <linux/stat.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/in.h>
 #include <linux/net.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.5/linux/fs/stat.c linux/fs/stat.c
--- v2.1.5/linux/fs/stat.c	Wed Oct 16 10:48:28 1996
+++ linux/fs/stat.c	Mon Oct 28 14:21:41 1996
@@ -12,7 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #ifndef __alpha__
 
diff -u --recursive --new-file v2.1.5/linux/fs/super.c linux/fs/super.c
--- v2.1.5/linux/fs/super.c	Wed Oct 16 10:48:29 1996
+++ linux/fs/super.c	Mon Oct 28 14:21:41 1996
@@ -33,7 +33,7 @@
 #include <linux/fd.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #ifdef CONFIG_KERNELD
diff -u --recursive --new-file v2.1.5/linux/fs/sysv/dir.c linux/fs/sysv/dir.c
--- v2.1.5/linux/fs/sysv/dir.c	Mon Sep 30 11:11:25 1996
+++ linux/fs/sysv/dir.c	Mon Oct 28 14:29:27 1996
@@ -19,7 +19,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static long sysv_dir_read(struct inode * inode, struct file * filp,
 	char * buf, unsigned long count)
diff -u --recursive --new-file v2.1.5/linux/fs/sysv/file.c linux/fs/sysv/file.c
--- v2.1.5/linux/fs/sysv/file.c	Wed Oct 16 10:48:29 1996
+++ linux/fs/sysv/file.c	Mon Oct 28 14:29:27 1996
@@ -23,7 +23,7 @@
 #include <linux/locks.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define	NBUF	32
 
diff -u --recursive --new-file v2.1.5/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v2.1.5/linux/fs/sysv/inode.c	Wed Oct 16 10:48:29 1996
+++ linux/fs/sysv/inode.c	Mon Oct 28 14:29:27 1996
@@ -30,7 +30,7 @@
 #include <linux/string.h>
 #include <linux/locks.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 void sysv_put_inode(struct inode *inode)
 {
diff -u --recursive --new-file v2.1.5/linux/fs/sysv/symlink.c linux/fs/sysv/symlink.c
--- v2.1.5/linux/fs/sysv/symlink.c	Fri Dec 22 13:00:19 1995
+++ linux/fs/sysv/symlink.c	Mon Oct 28 14:29:27 1996
@@ -18,7 +18,7 @@
 #include <linux/sysv_fs.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int sysv_readlink(struct inode *, char *, int);
 static int sysv_follow_link(struct inode *, struct inode *, int, int, struct inode **);
diff -u --recursive --new-file v2.1.5/linux/fs/ufs/ufs_super.c linux/fs/ufs/ufs_super.c
--- v2.1.5/linux/fs/ufs/ufs_super.c	Wed Oct 16 10:48:29 1996
+++ linux/fs/ufs/ufs_super.c	Mon Oct 28 14:29:27 1996
@@ -25,7 +25,7 @@
 #include <linux/ufs_fs.h>
 #include <linux/locks.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 int ufs_need_swab = 0;
 
diff -u --recursive --new-file v2.1.5/linux/fs/ufs/ufs_symlink.c linux/fs/ufs/ufs_symlink.c
--- v2.1.5/linux/fs/ufs/ufs_symlink.c	Sat Oct  5 16:58:36 1996
+++ linux/fs/ufs/ufs_symlink.c	Mon Oct 28 14:29:27 1996
@@ -14,7 +14,7 @@
 #include <linux/ufs_fs.h>
 #include <linux/sched.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int
 ufs_readlink(struct inode * inode, char * buffer, int buflen)
diff -u --recursive --new-file v2.1.5/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c
--- v2.1.5/linux/fs/umsdos/dir.c	Mon Sep 30 11:05:34 1996
+++ linux/fs/umsdos/dir.c	Mon Oct 28 14:29:27 1996
@@ -17,7 +17,7 @@
 #include <linux/umsdos_fs.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define PRINTK(x)
 #define Printk(x) printk x
diff -u --recursive --new-file v2.1.5/linux/fs/umsdos/emd.c linux/fs/umsdos/emd.c
--- v2.1.5/linux/fs/umsdos/emd.c	Sat Oct  5 16:58:36 1996
+++ linux/fs/umsdos/emd.c	Mon Oct 28 14:29:27 1996
@@ -15,7 +15,7 @@
 #include <linux/msdos_fs.h>
 #include <linux/umsdos_fs.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define PRINTK(x)
 #define Printk(x) printk x
diff -u --recursive --new-file v2.1.5/linux/fs/umsdos/file.c linux/fs/umsdos/file.c
--- v2.1.5/linux/fs/umsdos/file.c	Mon Sep 30 11:06:07 1996
+++ linux/fs/umsdos/file.c	Mon Oct 28 14:29:27 1996
@@ -16,7 +16,7 @@
 #include <linux/msdos_fs.h>
 #include <linux/umsdos_fs.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #define PRINTK(x)
diff -u --recursive --new-file v2.1.5/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- v2.1.5/linux/fs/umsdos/inode.c	Tue Sep  3 20:10:17 1996
+++ linux/fs/umsdos/inode.c	Mon Oct 28 14:29:27 1996
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/umsdos_fs.h>
diff -u --recursive --new-file v2.1.5/linux/fs/umsdos/ioctl.c linux/fs/umsdos/ioctl.c
--- v2.1.5/linux/fs/umsdos/ioctl.c	Wed Oct 16 10:48:29 1996
+++ linux/fs/umsdos/ioctl.c	Mon Oct 28 14:29:27 1996
@@ -6,7 +6,7 @@
  *  Extended MS-DOS ioctl directory handling functions
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.5/linux/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c
--- v2.1.5/linux/fs/umsdos/rdir.c	Wed Feb  7 09:39:29 1996
+++ linux/fs/umsdos/rdir.c	Mon Oct 28 14:29:27 1996
@@ -16,7 +16,7 @@
 #include <linux/umsdos_fs.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define PRINTK(x)
 #define Printk(x) printk x
diff -u --recursive --new-file v2.1.5/linux/fs/umsdos/symlink.c linux/fs/umsdos/symlink.c
--- v2.1.5/linux/fs/umsdos/symlink.c	Mon Sep 30 11:07:22 1996
+++ linux/fs/umsdos/symlink.c	Mon Oct 28 14:29:28 1996
@@ -16,7 +16,7 @@
 #include <linux/umsdos_fs.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #define PRINTK(x)
diff -u --recursive --new-file v2.1.5/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.1.5/linux/fs/vfat/namei.c	Wed Jul  3 11:58:01 1996
+++ linux/fs/vfat/namei.c	Mon Oct 28 14:29:28 1996
@@ -20,7 +20,7 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "../fat/msbuffer.h"
 #include "../fat/tables.h"
diff -u --recursive --new-file v2.1.5/linux/fs/xiafs/dir.c linux/fs/xiafs/dir.c
--- v2.1.5/linux/fs/xiafs/dir.c	Mon Sep 30 11:04:58 1996
+++ linux/fs/xiafs/dir.c	Mon Oct 28 14:29:28 1996
@@ -16,7 +16,7 @@
 #include <linux/xia_fs.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "xiafs_mac.h"
 
diff -u --recursive --new-file v2.1.5/linux/fs/xiafs/file.c linux/fs/xiafs/file.c
--- v2.1.5/linux/fs/xiafs/file.c	Wed Oct 16 10:48:29 1996
+++ linux/fs/xiafs/file.c	Mon Oct 28 14:29:28 1996
@@ -19,7 +19,7 @@
 #include <linux/locks.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include "xiafs_mac.h"
diff -u --recursive --new-file v2.1.5/linux/fs/xiafs/fsync.c linux/fs/xiafs/fsync.c
--- v2.1.5/linux/fs/xiafs/fsync.c	Sun Nov 26 19:23:10 1995
+++ linux/fs/xiafs/fsync.c	Mon Oct 28 14:29:28 1996
@@ -17,7 +17,7 @@
 #include <linux/fs.h>
 #include <linux/xia_fs.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include "xiafs_mac.h"
diff -u --recursive --new-file v2.1.5/linux/fs/xiafs/inode.c linux/fs/xiafs/inode.c
--- v2.1.5/linux/fs/xiafs/inode.c	Wed Oct 16 10:48:29 1996
+++ linux/fs/xiafs/inode.c	Mon Oct 28 14:29:28 1996
@@ -19,7 +19,7 @@
 #include <linux/stat.h>
 #include <linux/locks.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "xiafs_mac.h"
 
diff -u --recursive --new-file v2.1.5/linux/fs/xiafs/namei.c linux/fs/xiafs/namei.c
--- v2.1.5/linux/fs/xiafs/namei.c	Wed Jul  3 16:28:55 1996
+++ linux/fs/xiafs/namei.c	Mon Oct 28 14:29:28 1996
@@ -17,7 +17,7 @@
 #include <linux/fcntl.h>
 #include <linux/errno.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "xiafs_mac.h"
 
diff -u --recursive --new-file v2.1.5/linux/fs/xiafs/symlink.c linux/fs/xiafs/symlink.c
--- v2.1.5/linux/fs/xiafs/symlink.c	Fri Dec 22 13:00:19 1995
+++ linux/fs/xiafs/symlink.c	Mon Oct 28 14:29:28 1996
@@ -15,7 +15,7 @@
 #include <linux/xia_fs.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int 
 xiafs_readlink(struct inode *, char *, int);
diff -u --recursive --new-file v2.1.5/linux/include/asm-alpha/segment.h linux/include/asm-alpha/segment.h
--- v2.1.5/linux/include/asm-alpha/segment.h	Sat Oct 19 10:07:32 1996
+++ linux/include/asm-alpha/segment.h	Tue Oct 29 17:11:33 1996
@@ -1,300 +1,6 @@
-#ifndef _ASM_SEGMENT_H
-#define _ASM_SEGMENT_H
+#ifndef __ALPHA_SEGMENT_H
+#define __ALPHA_SEGMENT_H
 
-/*
- * The fs value determines whether argument validity checking should be
- * performed or not.  If get_fs() == USER_DS, checking is performed, with
- * get_fs() == KERNEL_DS, checking is bypassed.
- *
- * For historical reasons, these macros are grossly misnamed.
- */
+/* Only here because we have some old header files that expect it.. */
 
-#define KERNEL_DS	0
-#define USER_DS		1
-
-#define get_fs()  (current->tss.flags & 0x1)
-#define set_fs(x) (current->tss.flags = (current->tss.flags & ~0x1) | ((x) & 0x1))
-
-static inline unsigned long get_ds(void)
-{
-	return 0;
-}
-
-/*
- * Is a address valid? This does a straighforward calculation rather
- * than tests.
- *
- * Address valid if:
- *  - "addr" doesn't have any high-bits set
- *  - AND "size" doesn't have any high-bits set
- *  - AND "addr+size" doesn't have any high-bits set
- *  - OR we are in kernel mode.
- */
-#define __access_ok(addr,size,mask) \
-	(((mask)&((addr | size | (addr+size)) >> 42))==0)
-#define __access_mask (-(long)get_fs())
-
-#define access_ok(type,addr,size) \
-	__access_ok(((unsigned long)(addr)),(size),__access_mask)
-
-/*
- * These are the main single-value transfer routines.  They automatically
- * use the right size if we just have the right pointer type.
- *
- * As the alpha uses the same address space for kernel and user
- * data, we can just do these as direct assignments.  (Of course, the
- * exception handling means that it's no longer "just"...)
- *
- * Careful to not
- * (a) re-use the arguments for side effects (sizeof/typeof is ok)
- * (b) require any knowledge of processes at this stage
- */
-#define put_user(x,ptr)	__put_user((x),(ptr),sizeof(*(ptr)),__access_mask)
-#define get_user(x,ptr) __get_user((x),(ptr),sizeof(*(ptr)),__access_mask)
-
-#define copy_to_user(to,from,n)   __copy_tofrom_user((to),(from),(n),__cu_to)
-#define copy_from_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_from)
-
-/*
- * Not pretty? What do you mean not "not pretty"?
- */
-extern void __copy_user(void);
-
-#define __copy_tofrom_user(to,from,n,v)					    \
-({									    \
-	register void * __cu_to __asm__("$6") = (to);			    \
-	register const void * __cu_from __asm__("$7") = (from);		    \
-	register long __cu_len __asm__("$0") = (n);			    \
-	if (__access_ok(((long)(v)),__cu_len,__access_mask)) {		    \
-		register void * __cu_ex __asm__("$8");			    \
-		__cu_ex = &current->tss.ex;				    \
-		__asm__ __volatile__(					    \
-			"jsr $28,(%7),__copy_user"			    \
-			: "=r" (__cu_len), "=r" (__cu_from), "=r" (__cu_to) \
-			: "0" (__cu_len), "1" (__cu_from), "2" (__cu_to),   \
-			  "r" (__cu_ex), "r" (__copy_user)		    \
-			: "$1","$2","$3","$4","$5","$28","memory");	    \
-	}								    \
-	__cu_len;							    \
-})
-
-extern void __get_user_unknown(void);
-
-#define __get_user(x,ptr,size,mask)				\
-({								\
-	long __gu_err = -EFAULT, __gu_val = 0;			\
-	const __typeof__(*(ptr)) *__gu_addr = (ptr);		\
-	if (__access_ok((long)__gu_addr,size,mask)) {		\
-		long __gu_ex_count = current->tss.ex.count;	\
-		switch (size) {					\
-		case 1: __get_user_8; break;			\
-		case 2: __get_user_16; break;			\
-		case 4: __get_user_32; break;			\
-		case 8: __get_user_64; break;			\
-		default: __get_user_unknown(); break;		\
-		}						\
-	}							\
-	(x) = (__typeof__(*(ptr))) __gu_val;			\
-	__gu_err;						\
-})
-
-#define __get_user_64							   \
-	__asm__("/* Inline __get_user_64 */\n\t"			   \
-		"br $28,1f\n\t"		/* set up exception address */	   \
-		"br 2f\n"		/* exception! */		   \
-		"1:\t"							   \
-		"stq %5,%3\n\t"		/* store inc'ed exception count */ \
-		"ldq %1,%2\n\t"		/* actual data load */		   \
-		"stq %4,%3\n\t"		/* restore exception count */	   \
-		"clr %0\n"		/* no exception: error = 0 */	   \
-		"2:\t/* End __get_user_64 */"				   \
-		: "=r"(__gu_err), "=r"(__gu_val)			   \
-		: "m"(*__gu_addr), "m"(current->tss.ex.count),		   \
-		  "r"(__gu_ex_count), "r"(__gu_ex_count+1),		   \
-		  "0"(__gu_err), "1"(__gu_val)				   \
-		: "$28")
-
-#define __get_user_32							   \
-	__asm__("/* Inline __get_user_32 */\n\t"			   \
-		"br $28,1f\n\t"		/* set up exception address */	   \
-		"br 2f\n"		/* exception! */		   \
-		"1:\t"							   \
-		"stq %5,%3\n\t"		/* store inc'ed exception count */ \
-		"ldl %1,%2\n\t"		/* actual data load */		   \
-		"stq %4,%3\n\t"		/* restore exception count */	   \
-		"clr %0\n"		/* no exception: error = 0 */	   \
-		"2:\t/* End __get_user_32 */"				   \
-		: "=r"(__gu_err), "=r"(__gu_val)			   \
-		: "m"(*__gu_addr), "m"(current->tss.ex.count),		   \
-		  "r"(__gu_ex_count), "r"(__gu_ex_count+1),		   \
-		  "0"(__gu_err), "1"(__gu_val)				   \
-		: "$28")
-
-#define __get_user_16							   \
-	__asm__("/* Inline __get_user_16 */\n\t"			   \
-		"br $28,1f\n\t"		/* set up exception address */	   \
-		"br 2f\n"		/* exception! */		   \
-		"1:\t"							   \
-		"stq %6,%4\n\t"		/* store inc'ed exception count */ \
-		"ldq_u %1,%2\n\t"	/* actual data load */		   \
-		"stq %5,%4\n\t"		/* restore exception count */	   \
-		"clr %0\n\t"		/* no exception: error = 0 */	   \
-		"extwl %1,%3,%1\n"	/* extract the short */		   \
-		"2:\t/* End __get_user_16 */"				   \
-		: "=r"(__gu_err), "=r"(__gu_val)			   \
-		: "m"(*__gu_addr), "r"(__gu_addr),			   \
-		  "m"(current->tss.ex.count), "r"(__gu_ex_count),	   \
-		  "r"(__gu_ex_count+1), "0"(__gu_err), "1"(__gu_val)	   \
-		: "$28")
-
-#define __get_user_8							   \
-	__asm__("/* Inline __get_user_8 */\n\t"				   \
-		"br $28,1f\n\t"		/* set up exception address */	   \
-		"br 2f\n"		/* exception! */		   \
-		"1:\t"							   \
-		"stq %6,%4\n\t"		/* store inc'ed exception count */ \
-		"ldq_u %1,%2\n\t"	/* actual data load */		   \
-		"stq %5,%4\n\t"		/* restore exception count */	   \
-		"clr %0\n\t"		/* no exception: error = 0 */	   \
-		"extbl %1,%3,%1\n"	/* extract the byte */		   \
-		"2:\t/* End __get_user_8 */"				   \
-		: "=r"(__gu_err), "=r"(__gu_val)			   \
-		: "m"(*__gu_addr), "r"(__gu_addr),			   \
-		  "m"(current->tss.ex.count), "r"(__gu_ex_count),	   \
-		  "r"(__gu_ex_count+1), "0"(__gu_err), "1"(__gu_val)	   \
-		: "$28")
-
-extern void __put_user_unknown(void);
-
-#define __put_user(x,ptr,size,mask)				\
-({								\
-	long __pu_err = -EFAULT;				\
-	__typeof__(*(ptr)) *__pu_addr = (ptr);			\
-        __typeof__(*(ptr)) __pu_val = (x);			\
-	if (__access_ok((long)__pu_addr,size,mask)) {		\
-		long __pu_ex_count = current->tss.ex.count;	\
-		switch (size) {					\
-		case 1: __put_user_8; break;			\
-		case 2: __put_user_16; break;			\
-		case 4: __put_user_32; break;			\
-		case 8: __put_user_64; break;			\
-		default: __put_user_unknown(); break;		\
-		}						\
-	}							\
-	__pu_err;						\
-})
-
-#define __put_user_64							   \
-	__asm__("/* Inline __put_user_64 */\n\t"			   \
-		"br $28,1f\n\t"		/* set up exception address */	   \
-		"br 2f\n"		/* exception! */		   \
-		"1:\t"							   \
-		"stq %5,%3\n\t"		/* store inc'ed exception count */ \
-		"stq %2,%1\n\t"		/* actual data store */		   \
-		"stq %4,%3\n\t"		/* restore exception count */	   \
-		"clr %0\n"		/* no exception: error = 0 */	   \
-		"2:\t/* End __put_user_64 */"				   \
-		: "=r"(__pu_err), "=m"(*__pu_addr)			   \
-		: "r"(__pu_val), "m"(current->tss.ex.count),		   \
-		  "r"(__pu_ex_count), "r"(__pu_ex_count+1),		   \
-		  "0"(__pu_err)						   \
-		: "$28")
-
-#define __put_user_32							   \
-	__asm__("/* Inline __put_user_32 */\n\t"			   \
-		"br $28,1f\n\t"		/* set up exception address */	   \
-		"br 2f\n"		/* exception! */		   \
-		"1:\t"							   \
-		"stq %5,%3\n\t"		/* store inc'ed exception count */ \
-		"stl %2,%1\n\t"		/* actual data store */		   \
-		"stq %4,%3\n\t"		/* restore exception count */	   \
-		"clr %0\n"		/* no exception: error = 0 */	   \
-		"2:\t/* End __put_user_32 */"				   \
-		: "=r"(__pu_err), "=m"(*__pu_addr)			   \
-		: "r"(__pu_val), "m"(current->tss.ex.count),		   \
-		  "r"(__pu_ex_count), "r"(__pu_ex_count+1),		   \
-		  "0"(__pu_err)						   \
-		: "$28")
-
-#define __put_user_16							   \
-	__asm__("/* Inline __put_user_16 */\n\t"			   \
-		"br $28,1f\n\t"		/* set up exception address */	   \
-		"lda %0,%7\n\t"		/* exception! error = -EFAULT */   \
-		"br 2f\n"						   \
-		"1:\t"							   \
-		"stq %6,%4\n\t"		/* store inc'ed exception count */ \
-		"ldq_u %0,%1\n\t"	/* masked data store */		   \
-		"inswl %2,%3,%2\n\t"					   \
-		"mskwl %0,%3,%0\n\t"					   \
-		"or %0,%2,%2\n\t"					   \
-		"stq_u %2,%1\n\t"					   \
-		"stq %5,%4\n\t"		/* restore exception count */	   \
-		"clr %0\n"		/* no exception: error = 0 */	   \
-		"2:\t/* End __put_user_16 */"				   \
-		: "=r"(__pu_err), "=m"(*__pu_addr), "=r"(__pu_val)	   \
-		: "r"(__pu_addr), "m"(current->tss.ex.count),		   \
-		  "r"(__pu_ex_count), "r"(__pu_ex_count+1), "i"(-EFAULT),  \
-		  "2"(__pu_val)						   \
-		: "$28")
-
-#define __put_user_8							   \
-	__asm__("/* Inline __put_user_8 */\n\t"				   \
-		"br $28,1f\n\t"		/* set up exception address */	   \
-		"lda %0,%7\n\t"		/* exception! error = -EFAULT */   \
-		"br 2f\n"						   \
-		"1:\t"							   \
-		"stq %6,%4\n\t"		/* store inc'ed exception count */ \
-		"ldq_u %0,%1\n\t"	/* masked data store */		   \
-		"insbl %2,%3,%2\n\t"					   \
-		"mskbl %0,%3,%0\n\t"					   \
-		"or %0,%2,%2\n\t"					   \
-		"stq_u %2,%1\n\t"					   \
-		"stq %5,%4\n\t"		/* restore exception count */	   \
-		"clr %0\n"		/* no exception: error = 0 */	   \
-		"2:\t/* End __put_user_8 */"				   \
-		: "=r"(__pu_err), "=m"(*__pu_addr), "=r"(__pu_val)	   \
-		: "r"(__pu_addr), "m"(current->tss.ex.count),		   \
-		  "r"(__pu_ex_count), "r"(__pu_ex_count+1), "i"(-EFAULT),  \
-		  "2"(__pu_val)						   \
-		: "$28")
-
-
-extern void __clear_user(void);
-
-#define clear_user(to,n)						\
-({									\
-	register void * __cl_to __asm__("$6") = (to);			\
-	register long __cl_len __asm__("$0") = (n);			\
-	if (__access_ok(((long)__cl_to),__cl_len,__access_mask)) {	\
-		register void * __cl_ex __asm__("$7");			\
-		__cl_ex = &current->tss.ex;				\
-		__asm__ __volatile__(					\
-			"jsr $28,(%2),__clear_user"			\
-			: "=r"(__cl_len), "=r"(__cl_to)			\
-			: "r"(__clear_user), "r"(__cl_ex),		\
-			  "0"(__cl_len), "1"(__cl_to)			\
-			: "$1","$2","$3","$4","$5","$28","memory");	\
-	}								\
-	__cl_len;							\
-})
-
-
-/* Returns: -EFAULT if exception before terminator, N if the entire
-   buffer filled, else strlen.  */
-
-struct exception_struct;
-extern long __strncpy_from_user(char *__to, const char *__from,
-				long __to_len, struct exception_struct *);
-
-#define strncpy_from_user(to,from,n)					      \
-({									      \
-	char * __sfu_to = (to);						      \
-	const char * __sfu_from = (from);				      \
-	long __sfu_len = (n), __sfu_ret = -EFAULT;			      \
-	if (__access_ok(((long)__sfu_from),__sfu_len,__access_mask)) {	      \
-		__sfu_ret = __strncpy_from_user(__sfu_to,__sfu_from,	      \
-						__sfu_len, &current->tss.ex); \
-	__sfu_ret;							      \
-})
-
-#endif /* _ASM_SEGMENT_H */
+#endif
diff -u --recursive --new-file v2.1.5/linux/include/asm-alpha/uaccess.h linux/include/asm-alpha/uaccess.h
--- v2.1.5/linux/include/asm-alpha/uaccess.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-alpha/uaccess.h	Tue Oct 29 14:10:51 1996
@@ -0,0 +1,348 @@
+#ifndef _ASM_SEGMENT_H
+#define _ASM_SEGMENT_H
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ */
+
+#define KERNEL_DS	0
+#define USER_DS		1
+
+#define VERIFY_READ	0
+#define VERIFY_WRITE	1
+
+#define get_fs()  (current->tss.flags & 0x1)
+#define set_fs(x) (current->tss.flags = (current->tss.flags & ~0x1) | ((x) & 0x1))
+
+static inline unsigned long get_ds(void)
+{
+	return 0;
+}
+
+/*
+ * Is a address valid? This does a straighforward calculation rather
+ * than tests.
+ *
+ * Address valid if:
+ *  - "addr" doesn't have any high-bits set
+ *  - AND "size" doesn't have any high-bits set
+ *  - AND "addr+size" doesn't have any high-bits set
+ *  - OR we are in kernel mode.
+ */
+#define __access_ok(addr,size,mask) \
+	(((mask)&((addr | size | (addr+size)) >> 42))==0)
+#define __access_mask (-(long)get_fs())
+
+#define access_ok(type,addr,size) \
+	__access_ok(((unsigned long)(addr)),(size),__access_mask)
+
+/*
+ * These are the main single-value transfer routines.  They automatically
+ * use the right size if we just have the right pointer type.
+ *
+ * As the alpha uses the same address space for kernel and user
+ * data, we can just do these as direct assignments.  (Of course, the
+ * exception handling means that it's no longer "just"...)
+ *
+ * Careful to not
+ * (a) re-use the arguments for side effects (sizeof/typeof is ok)
+ * (b) require any knowledge of processes at this stage
+ */
+#define put_user(x,ptr)	__put_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
+#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
+
+/*
+ * The "__xxx" versions do not do address space checking, useful when
+ * doing multiple accesses to the same area (the user has to do the
+ * checks by hand with "access_ok()")
+ */
+#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+
+#define copy_to_user(to,from,n)   __copy_tofrom_user((to),(from),(n),__cu_to)
+#define copy_from_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_from)
+
+/*
+ * Not pretty? What do you mean not "not pretty"?
+ */
+extern void __copy_user(void);
+
+#define __copy_tofrom_user(to,from,n,v)					    \
+({									    \
+	register void * __cu_to __asm__("$6") = (to);			    \
+	register const void * __cu_from __asm__("$7") = (from);		    \
+	register long __cu_len __asm__("$0") = (n);			    \
+	if (__access_ok(((long)(v)),__cu_len,__access_mask)) {		    \
+		register void * __cu_ex __asm__("$8");			    \
+		__cu_ex = &current->tss.ex;				    \
+		__asm__ __volatile__(					    \
+			"jsr $28,(%7),__copy_user"			    \
+			: "=r" (__cu_len), "=r" (__cu_from), "=r" (__cu_to) \
+			: "0" (__cu_len), "1" (__cu_from), "2" (__cu_to),   \
+			  "r" (__cu_ex), "r" (__copy_user)		    \
+			: "$1","$2","$3","$4","$5","$28","memory");	    \
+	}								    \
+	__cu_len;							    \
+})
+
+extern void __get_user_unknown(void);
+
+#define __get_user_nocheck(x,ptr,size)				\
+({								\
+	long __gu_err = -EFAULT, __gu_val = 0;			\
+	const __typeof__(*(ptr)) *__gu_addr = (ptr);		\
+	long __gu_ex_count = current->tss.ex.count;		\
+	switch (size) {						\
+	case 1: __get_user_8; break;				\
+	case 2: __get_user_16; break;				\
+	case 4: __get_user_32; break;				\
+	case 8: __get_user_64; break;				\
+	default: __get_user_unknown(); break;			\
+	}							\
+	(x) = (__typeof__(*(ptr))) __gu_val;			\
+	__gu_err;						\
+})
+
+#define __get_user_check(x,ptr,size,mask)			\
+({								\
+	long __gu_err = -EFAULT, __gu_val = 0;			\
+	const __typeof__(*(ptr)) *__gu_addr = (ptr);		\
+	if (__access_ok((long)__gu_addr,size,mask)) {		\
+		long __gu_ex_count = current->tss.ex.count;	\
+		switch (size) {					\
+		case 1: __get_user_8; break;			\
+		case 2: __get_user_16; break;			\
+		case 4: __get_user_32; break;			\
+		case 8: __get_user_64; break;			\
+		default: __get_user_unknown(); break;		\
+		}						\
+	}							\
+	(x) = (__typeof__(*(ptr))) __gu_val;			\
+	__gu_err;						\
+})
+
+#define __get_user_64							   \
+	__asm__("/* Inline __get_user_64 */\n\t"			   \
+		"br $28,1f\n\t"		/* set up exception address */	   \
+		"br 2f\n"		/* exception! */		   \
+		"1:\t"							   \
+		"stq %5,%3\n\t"		/* store inc'ed exception count */ \
+		"ldq %1,%2\n\t"		/* actual data load */		   \
+		"stq %4,%3\n\t"		/* restore exception count */	   \
+		"clr %0\n"		/* no exception: error = 0 */	   \
+		"2:\t/* End __get_user_64 */"				   \
+		: "=r"(__gu_err), "=r"(__gu_val)			   \
+		: "m"(*__gu_addr), "m"(current->tss.ex.count),		   \
+		  "r"(__gu_ex_count), "r"(__gu_ex_count+1),		   \
+		  "0"(__gu_err), "1"(__gu_val)				   \
+		: "$28")
+
+#define __get_user_32							   \
+	__asm__("/* Inline __get_user_32 */\n\t"			   \
+		"br $28,1f\n\t"		/* set up exception address */	   \
+		"br 2f\n"		/* exception! */		   \
+		"1:\t"							   \
+		"stq %5,%3\n\t"		/* store inc'ed exception count */ \
+		"ldl %1,%2\n\t"		/* actual data load */		   \
+		"stq %4,%3\n\t"		/* restore exception count */	   \
+		"clr %0\n"		/* no exception: error = 0 */	   \
+		"2:\t/* End __get_user_32 */"				   \
+		: "=r"(__gu_err), "=r"(__gu_val)			   \
+		: "m"(*__gu_addr), "m"(current->tss.ex.count),		   \
+		  "r"(__gu_ex_count), "r"(__gu_ex_count+1),		   \
+		  "0"(__gu_err), "1"(__gu_val)				   \
+		: "$28")
+
+#define __get_user_16							   \
+	__asm__("/* Inline __get_user_16 */\n\t"			   \
+		"br $28,1f\n\t"		/* set up exception address */	   \
+		"br 2f\n"		/* exception! */		   \
+		"1:\t"							   \
+		"stq %6,%4\n\t"		/* store inc'ed exception count */ \
+		"ldq_u %1,%2\n\t"	/* actual data load */		   \
+		"stq %5,%4\n\t"		/* restore exception count */	   \
+		"clr %0\n\t"		/* no exception: error = 0 */	   \
+		"extwl %1,%3,%1\n"	/* extract the short */		   \
+		"2:\t/* End __get_user_16 */"				   \
+		: "=r"(__gu_err), "=r"(__gu_val)			   \
+		: "m"(*__gu_addr), "r"(__gu_addr),			   \
+		  "m"(current->tss.ex.count), "r"(__gu_ex_count),	   \
+		  "r"(__gu_ex_count+1), "0"(__gu_err), "1"(__gu_val)	   \
+		: "$28")
+
+#define __get_user_8							   \
+	__asm__("/* Inline __get_user_8 */\n\t"				   \
+		"br $28,1f\n\t"		/* set up exception address */	   \
+		"br 2f\n"		/* exception! */		   \
+		"1:\t"							   \
+		"stq %6,%4\n\t"		/* store inc'ed exception count */ \
+		"ldq_u %1,%2\n\t"	/* actual data load */		   \
+		"stq %5,%4\n\t"		/* restore exception count */	   \
+		"clr %0\n\t"		/* no exception: error = 0 */	   \
+		"extbl %1,%3,%1\n"	/* extract the byte */		   \
+		"2:\t/* End __get_user_8 */"				   \
+		: "=r"(__gu_err), "=r"(__gu_val)			   \
+		: "m"(*__gu_addr), "r"(__gu_addr),			   \
+		  "m"(current->tss.ex.count), "r"(__gu_ex_count),	   \
+		  "r"(__gu_ex_count+1), "0"(__gu_err), "1"(__gu_val)	   \
+		: "$28")
+
+extern void __put_user_unknown(void);
+
+#define __put_user_nocheck(x,ptr,size)				\
+({								\
+	long __pu_err = -EFAULT;				\
+	__typeof__(*(ptr)) *__pu_addr = (ptr);			\
+        __typeof__(*(ptr)) __pu_val = (x);			\
+	long __pu_ex_count = current->tss.ex.count;		\
+	switch (size) {						\
+	case 1: __put_user_8; break;				\
+	case 2: __put_user_16; break;				\
+	case 4: __put_user_32; break;				\
+	case 8: __put_user_64; break;				\
+	default: __put_user_unknown(); break;			\
+	}							\
+	__pu_err;						\
+})
+
+#define __put_user_check(x,ptr,size,mask)			\
+({								\
+	long __pu_err = -EFAULT;				\
+	__typeof__(*(ptr)) *__pu_addr = (ptr);			\
+        __typeof__(*(ptr)) __pu_val = (x);			\
+	if (__access_ok((long)__pu_addr,size,mask)) {		\
+		long __pu_ex_count = current->tss.ex.count;	\
+		switch (size) {					\
+		case 1: __put_user_8; break;			\
+		case 2: __put_user_16; break;			\
+		case 4: __put_user_32; break;			\
+		case 8: __put_user_64; break;			\
+		default: __put_user_unknown(); break;		\
+		}						\
+	}							\
+	__pu_err;						\
+})
+
+#define __put_user_64							   \
+	__asm__("/* Inline __put_user_64 */\n\t"			   \
+		"br $28,1f\n\t"		/* set up exception address */	   \
+		"br 2f\n"		/* exception! */		   \
+		"1:\t"							   \
+		"stq %5,%3\n\t"		/* store inc'ed exception count */ \
+		"stq %2,%1\n\t"		/* actual data store */		   \
+		"stq %4,%3\n\t"		/* restore exception count */	   \
+		"clr %0\n"		/* no exception: error = 0 */	   \
+		"2:\t/* End __put_user_64 */"				   \
+		: "=r"(__pu_err), "=m"(*__pu_addr)			   \
+		: "r"(__pu_val), "m"(current->tss.ex.count),		   \
+		  "r"(__pu_ex_count), "r"(__pu_ex_count+1),		   \
+		  "0"(__pu_err)						   \
+		: "$28")
+
+#define __put_user_32							   \
+	__asm__("/* Inline __put_user_32 */\n\t"			   \
+		"br $28,1f\n\t"		/* set up exception address */	   \
+		"br 2f\n"		/* exception! */		   \
+		"1:\t"							   \
+		"stq %5,%3\n\t"		/* store inc'ed exception count */ \
+		"stl %2,%1\n\t"		/* actual data store */		   \
+		"stq %4,%3\n\t"		/* restore exception count */	   \
+		"clr %0\n"		/* no exception: error = 0 */	   \
+		"2:\t/* End __put_user_32 */"				   \
+		: "=r"(__pu_err), "=m"(*__pu_addr)			   \
+		: "r"(__pu_val), "m"(current->tss.ex.count),		   \
+		  "r"(__pu_ex_count), "r"(__pu_ex_count+1),		   \
+		  "0"(__pu_err)						   \
+		: "$28")
+
+#define __put_user_16							   \
+	__asm__("/* Inline __put_user_16 */\n\t"			   \
+		"br $28,1f\n\t"		/* set up exception address */	   \
+		"lda %0,%7\n\t"		/* exception! error = -EFAULT */   \
+		"br 2f\n"						   \
+		"1:\t"							   \
+		"stq %6,%4\n\t"		/* store inc'ed exception count */ \
+		"ldq_u %0,%1\n\t"	/* masked data store */		   \
+		"inswl %2,%3,%2\n\t"					   \
+		"mskwl %0,%3,%0\n\t"					   \
+		"or %0,%2,%2\n\t"					   \
+		"stq_u %2,%1\n\t"					   \
+		"stq %5,%4\n\t"		/* restore exception count */	   \
+		"clr %0\n"		/* no exception: error = 0 */	   \
+		"2:\t/* End __put_user_16 */"				   \
+		: "=r"(__pu_err), "=m"(*__pu_addr), "=r"(__pu_val)	   \
+		: "r"(__pu_addr), "m"(current->tss.ex.count),		   \
+		  "r"(__pu_ex_count), "r"(__pu_ex_count+1), "i"(-EFAULT),  \
+		  "2"(__pu_val)						   \
+		: "$28")
+
+#define __put_user_8							   \
+	__asm__("/* Inline __put_user_8 */\n\t"				   \
+		"br $28,1f\n\t"		/* set up exception address */	   \
+		"lda %0,%7\n\t"		/* exception! error = -EFAULT */   \
+		"br 2f\n"						   \
+		"1:\t"							   \
+		"stq %6,%4\n\t"		/* store inc'ed exception count */ \
+		"ldq_u %0,%1\n\t"	/* masked data store */		   \
+		"insbl %2,%3,%2\n\t"					   \
+		"mskbl %0,%3,%0\n\t"					   \
+		"or %0,%2,%2\n\t"					   \
+		"stq_u %2,%1\n\t"					   \
+		"stq %5,%4\n\t"		/* restore exception count */	   \
+		"clr %0\n"		/* no exception: error = 0 */	   \
+		"2:\t/* End __put_user_8 */"				   \
+		: "=r"(__pu_err), "=m"(*__pu_addr), "=r"(__pu_val)	   \
+		: "r"(__pu_addr), "m"(current->tss.ex.count),		   \
+		  "r"(__pu_ex_count), "r"(__pu_ex_count+1), "i"(-EFAULT),  \
+		  "2"(__pu_val)						   \
+		: "$28")
+
+
+extern void __clear_user(void);
+
+#define clear_user(to,n)						\
+({									\
+	register void * __cl_to __asm__("$6") = (to);			\
+	register long __cl_len __asm__("$0") = (n);			\
+	if (__access_ok(((long)__cl_to),__cl_len,__access_mask)) {	\
+		register void * __cl_ex __asm__("$7");			\
+		__cl_ex = &current->tss.ex;				\
+		__asm__ __volatile__(					\
+			"jsr $28,(%2),__clear_user"			\
+			: "=r"(__cl_len), "=r"(__cl_to)			\
+			: "r"(__clear_user), "r"(__cl_ex),		\
+			  "0"(__cl_len), "1"(__cl_to)			\
+			: "$1","$2","$3","$4","$5","$28","memory");	\
+	}								\
+	__cl_len;							\
+})
+
+
+/* Returns: -EFAULT if exception before terminator, N if the entire
+   buffer filled, else strlen.  */
+
+struct exception_struct;
+extern long __strncpy_from_user(char *__to, const char *__from,
+				long __to_len, struct exception_struct *);
+
+#define strncpy_from_user(to,from,n)					      \
+({									      \
+	char * __sfu_to = (to);						      \
+	const char * __sfu_from = (from);				      \
+	long __sfu_len = (n), __sfu_ret = -EFAULT;			      \
+	if (__access_ok(((long)__sfu_from),__sfu_len,__access_mask)) {	      \
+		__sfu_ret = __strncpy_from_user(__sfu_to,__sfu_from,	      \
+						__sfu_len, &current->tss.ex); \
+	__sfu_ret;							      \
+})
+
+extern inline int verify_area(int type, const void * addr, unsigned long size)
+{
+	return access_ok(type,addr,size)?0:-EFAULT;
+}
+
+#endif /* _ASM_SEGMENT_H */
diff -u --recursive --new-file v2.1.5/linux/include/asm-i386/elf.h linux/include/asm-i386/elf.h
--- v2.1.5/linux/include/asm-i386/elf.h	Sat Oct 19 10:07:32 1996
+++ linux/include/asm-i386/elf.h	Fri Oct 18 19:55:51 1996
@@ -6,6 +6,7 @@
  */
 
 #include <asm/ptrace.h>
+#include <asm/user.h>
 
 typedef unsigned long elf_greg_t;
 
diff -u --recursive --new-file v2.1.5/linux/include/asm-i386/segment.h linux/include/asm-i386/segment.h
--- v2.1.5/linux/include/asm-i386/segment.h	Sat Oct 19 10:07:32 1996
+++ linux/include/asm-i386/segment.h	Tue Oct 29 17:06:34 1996
@@ -7,217 +7,4 @@
 #define USER_CS		0x23
 #define USER_DS		0x2B
 
-#ifndef __ASSEMBLY__
-
-#include <linux/string.h>
-
-/*
- * The fs value determines whether argument validity checking should be
- * performed or not.  If get_fs() == USER_DS, checking is performed, with
- * get_fs() == KERNEL_DS, checking is bypassed.
- * 
- * For historical reasons, these macros are grossly misnamed.
- */
-      
-#define get_fs()	(current->tss.segment)
-#define set_fs(x)	(current->tss.segment = (x))
-#define get_ds()	(KERNEL_DS)
-
-#define __user_ok(addr,size) \
-((size <= 0xC0000000) && (addr <= 0xC0000000 - size))
-#define __kernel_ok \
-(get_fs() == KERNEL_DS)
-
-extern int __verify_write(const void *, unsigned long);
-
-#if CPU > 386
-#define __access_ok(type,addr,size) \
-(__kernel_ok || __user_ok(addr,size))
-#else
-#define __access_ok(type,addr,size) \
-(__kernel_ok || (__user_ok(addr,size) && \
-  ((type) == VERIFY_READ || wp_works_ok || __verify_write((void *)(addr),(size)))))
-#endif /* CPU */
-
-#define access_ok(type,addr,size) \
-__access_ok((type),(unsigned long)(addr),(size))
-
-/*
- * Uh, these should become the main single-value transfer routines..
- * They automatically use the right size if we just have the right
- * pointer type..
- *
- * This gets kind of ugly. We want to return _two_ values in "get_user()"
- * and yet we don't want to do any pointers, because that is too much
- * of a performance impact. Thus we have a few rather ugly macros here,
- * and hide all the uglyness from the user.
- */
-#define put_user(x,ptr) ({ \
-unsigned long __pu_addr = (unsigned long)(ptr); \
-__put_user((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
-
-#define get_user(x,ptr) ({ \
-unsigned long __gu_addr = (unsigned long)(ptr); \
-__get_user((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
-
-struct __large_struct { unsigned long buf[100]; };
-#define __m(x) (*(struct __large_struct *)(x))
-
-#define __put_user(x,addr,size) ({ \
-int __pu_ret = -EFAULT; \
-if (access_ok(VERIFY_WRITE,addr,size)) { \
-switch (size) { \
-case 1: __put_user_8(x,addr,__pu_ret); break; \
-case 2: __put_user_16(x,addr,__pu_ret); break; \
-case 4: __put_user_32(x,addr,__pu_ret); break; \
-default: __pu_ret = __put_user_bad(); break; \
-} } __pu_ret; })
-
-#define __put_user_asm(x,addr,ret,bwl,reg,rtype) \
-__asm__ __volatile__( \
-	"movl $1f,%0\n\t" \
-	"incl %3\n\t" \
-	"mov" #bwl " %" reg "1,%2\n\t" \
-	"xorl %0,%0\n\t" \
-	"decl %3\n1:" \
-:"=d" (ret) \
-:#rtype (x), "m" (__m(addr)),"m" (current->tss.ex.count), "0" (ret))
-
-#define __put_user_8(x,addr,ret) \
-__put_user_asm(x,addr,ret,b,"b","iq")
-#define __put_user_16(x,addr,ret) \
-__put_user_asm(x,addr,ret,w,"w","ir")
-#define __put_user_32(x,addr,ret) \
-__put_user_asm(x,addr,ret,l,"","ir")
-
-extern int __put_user_bad(void);
-
-#define __get_user(x,addr,size,type) ({ \
-int __gu_ret = -EFAULT; \
-unsigned long __gu_val = 0; \
-if (access_ok(VERIFY_WRITE,addr,size)) { \
-switch (size) { \
-case 1: __get_user_8(__gu_val,addr,__gu_ret); break; \
-case 2: __get_user_16(__gu_val,addr,__gu_ret); break; \
-case 4: __get_user_32(__gu_val,addr,__gu_ret); break; \
-default: __gu_ret = __get_user_bad(); break; \
-} } x = (type) __gu_val; __gu_ret; })
-
-#define __get_user_asm(x,addr,ret,bwl,reg,rtype) \
-__asm__ __volatile__( \
-	"movl $1f,%0\n\t" \
-	"incl %3\n\t" \
-	"mov" #bwl " %2,%" reg "1\n\t" \
-	"xorl %0,%0\n\t" \
-	"decl %3\n1:" \
-:"=d" (ret), #rtype (x) \
-:"m" (__m(addr)),"m" (current->tss.ex.count), "0" (ret), "1" (x))
-
-#define __get_user_8(x,addr,ret) \
-__get_user_asm(x,addr,ret,b,"b","=q")
-#define __get_user_16(x,addr,ret) \
-__get_user_asm(x,addr,ret,w,"w","=r")
-#define __get_user_32(x,addr,ret) \
-__get_user_asm(x,addr,ret,l,"","=r")
-
-extern int __get_user_bad(void);
-
-#define __copy_user(to,from,size) \
-__asm__ __volatile__( \
-	"movl $3f,%0\n\t" \
-	"incl %2\n\t" \
-	"rep; movsl\n\t" \
-	"testb $2,%b3\n\t" \
-	"je 1f\n\t" \
-	"movsw\n\t" \
-	"subb $2,%b3\n" \
-	"1:\t" \
-	"testb $1,%b3\n\t" \
-	"je 2f\n\t" \
-	"movsb\n\t" \
-	"decb %b3\n" \
-	"2:\t" \
-	"decl %2\n" \
-	"3:\tlea 0(%3,%1,4),%0" \
-	:"=d" (size) \
-	:"c" (size >> 2), "m" (current->tss.ex), "q" (size & 3), \
-	 "D" (to), "S" (from), "0" (size) \
-	:"cx","di","si","memory");
-
-#define copy_to_user(to,from,n) ({ \
-unsigned long __cu_to = (unsigned long) (to); \
-unsigned long __cu_size = (unsigned long) (n); \
-if (__cu_size && __access_ok(VERIFY_WRITE, __cu_to, __cu_size)) \
-__copy_user(__cu_to,from,__cu_size); \
-__cu_size; })
-
-#define copy_from_user(to,from,n) ({ \
-unsigned long __cu_from = (unsigned long) (from); \
-unsigned long __cu_size = (unsigned long) (n); \
-if (__cu_size && __access_ok(VERIFY_READ, __cu_from, __cu_size)) \
-__copy_user(to,__cu_from,__cu_size); \
-__cu_size; })
-
-#define __clear_user(addr,size) \
-__asm__ __volatile__( \
-	"movl $3f,%0\n\t" \
-	"incl %2\n\t" \
-	"rep; stosl\n\t" \
-	"testl $2,%3\n\t" \
-	"je 1f\n\t" \
-	"stosw\n\t" \
-	"subl $2,%3\n" \
-	"1:\t" \
-	"testl $1,%3\n\t" \
-	"je 2f\n\t" \
-	"stosb\n\t" \
-	"decl %3\n" \
-	"2:\t" \
-	"decl %2\n" \
-	"3:\tlea 0(%3,%1,4),%0" \
-	:"=d" (size) \
-	:"c" (size >> 2), "m" (current->tss.ex), "r" (size & 3), \
-	 "D" (addr), "0" (size), "a" (0) \
-	:"cx","di","memory");
-
-#define clear_user(addr,n) ({ \
-void * __cl_addr = (addr); \
-unsigned long __cl_size = (n); \
-if (__cl_size && __access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) \
-__clear_user(__cl_addr, __cl_size); \
-__cl_size; })
-
-#define __strncpy_from_user(dst,src,count,res) \
-__asm__ __volatile__( \
-	"cld\n\t" \
-	"movl $3f,%0\n\t" \
-	"incl %2\n" \
-	"1:\tdecl %1\n\t" \
-	"js 2f\n\t" \
-	"lodsb\n\t" \
-	"stosb\n\t" \
-	"testb %%al,%%al\n\t" \
-	"jne 1b\n" \
-	"2:\t" \
-	"incl %1\n\t" \
-	"xorl %0,%0\n\t" \
-	"decl %2\n" \
-	"3:" \
-	:"=d" (res), "=r" (count) \
-	:"m" (current->tss.ex), "1" (count), "S" (src),"D" (dst),"0" (res) \
-	:"si","di","ax","cx","memory")
-
-#define strncpy_from_user(dest,src,count) ({ \
-const void * __sc_src = (src); \
-unsigned long __sc_count = (count); \
-long __sc_res = -EFAULT; \
-if (__access_ok(VERIFY_READ, ((unsigned long)(__sc_src)), __sc_count)) { \
-	unsigned long __sc_residue = __sc_count; \
-	__strncpy_from_user(dest,__sc_src,__sc_count,__sc_res); \
-	if (!__sc_res) __sc_res = __sc_residue - __sc_count; \
-} __sc_res; })
-
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _ASM_SEGMENT_H */
+#endif
diff -u --recursive --new-file v2.1.5/linux/include/asm-i386/string-486.h linux/include/asm-i386/string-486.h
--- v2.1.5/linux/include/asm-i386/string-486.h	Sat Apr 20 13:12:23 1996
+++ linux/include/asm-i386/string-486.h	Mon Oct 28 15:02:57 1996
@@ -497,6 +497,7 @@
 	"std\n\t"
 	"rep\n\t"
 	"movsb\n\t"
+	"cld"
 	: /* no output */
 	:"c" (n), "S" (n-1+(const char *)src), "D" (n-1+(char *)tmp)
 	:"cx","si","di","memory");
diff -u --recursive --new-file v2.1.5/linux/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h
--- v2.1.5/linux/include/asm-i386/uaccess.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-i386/uaccess.h	Tue Oct 29 17:24:47 1996
@@ -0,0 +1,336 @@
+#ifndef __i386_UACCESS_H
+#define __i386_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+
+#include <asm/segment.h>
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ * 
+ * For historical reasons, these macros are grossly misnamed.
+ */
+      
+#define get_fs()	(current->tss.segment)
+#define set_fs(x)	(current->tss.segment = (x))
+#define get_ds()	(KERNEL_DS)
+
+#define __user_ok(addr,size) \
+((size <= 0xC0000000UL) && (addr <= 0xC0000000UL - size))
+#define __kernel_ok \
+(get_fs() == KERNEL_DS)
+
+extern int __verify_write(const void *, unsigned long);
+
+#if CPU > 386
+#define __access_ok(type,addr,size) \
+(__kernel_ok || __user_ok(addr,size))
+#else
+#define __access_ok(type,addr,size) \
+(__kernel_ok || (__user_ok(addr,size) && \
+  ((type) == VERIFY_READ || wp_works_ok || __verify_write((void *)(addr),(size)))))
+#endif /* CPU */
+
+#define access_ok(type,addr,size) \
+__access_ok((type),(unsigned long)(addr),(size))
+
+/*
+ * Uh, these should become the main single-value transfer routines..
+ * They automatically use the right size if we just have the right
+ * pointer type..
+ *
+ * This gets kind of ugly. We want to return _two_ values in "get_user()"
+ * and yet we don't want to do any pointers, because that is too much
+ * of a performance impact. Thus we have a few rather ugly macros here,
+ * and hide all the uglyness from the user.
+ *
+ * The "__xxx" versions of the user access functions are versions that
+ * do not verify the address space, that must have been done previously
+ * with a separate "access_ok()" call (this is used when we do multiple
+ * accesses to the same area of user memory).
+ */
+#define put_user(x,ptr) \
+__do_put_user((unsigned long)((__typeof__(*(ptr)))(x)),(ptr),(sizeof(*(ptr))))
+#define __put_user(x,ptr) \
+__do_put_user_nocheck((unsigned long)((__typeof__(*(ptr)))(x)),(ptr),(sizeof(*(ptr))))
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct *)(x))
+
+#define __put_user_asm(x,addr,ret,bwl,reg,rtype) \
+__asm__ __volatile__( \
+	"movl $1f,%0\n\t" \
+	"incl %3\n\t" \
+	"mov" #bwl " %" reg "1,%2\n\t" \
+	"xorl %0,%0\n\t" \
+	"decl %3\n1:" \
+:"=&d" (ret) \
+:#rtype (x), "m" (__m(addr)),"m" (current->tss.ex.count))
+
+extern int __put_user_bad(void);
+
+#define __put_user_size(x,ptr,size,retval) \
+switch (size) { \
+case 1: __put_user_asm(x,ptr,retval,b,"b","iq"); break; \
+case 2: __put_user_asm(x,ptr,retval,w,"w","ir"); break; \
+case 4: __put_user_asm(x,ptr,retval,l,"","ir"); break; \
+default: retval = __put_user_bad(); }
+
+static inline int __do_put_user(unsigned long x, void * ptr, int size)
+{
+	int retval = -EFAULT;
+	if (access_ok(VERIFY_WRITE, ptr, size))
+		__put_user_size(x,ptr,size,retval);
+	return retval;
+}
+
+#define __do_put_user_nocheck(x, ptr, size) \
+({ int retval; __put_user_size(x,ptr,size,retval); retval; })
+
+#define get_user(x,ptr) \
+__do_get_user((x),(unsigned long)(ptr),sizeof(*(ptr)),__typeof__(*(ptr)))
+
+#define __get_user(x,ptr) \
+__do_get_user_nocheck((x),(unsigned long)(ptr),sizeof(*(ptr)),__typeof__(*(ptr)))
+
+#define __do_get_user(x,ptr,size,type) ({ \
+unsigned long __gu_addr = ptr; \
+int __gu_ret = -EFAULT; \
+unsigned long __gu_val = 0; \
+if (access_ok(VERIFY_READ,__gu_addr,size)) { \
+switch (size) { \
+case 1: __do_get_user_8(__gu_val,__gu_addr,__gu_ret); break; \
+case 2: __do_get_user_16(__gu_val,__gu_addr,__gu_ret); break; \
+case 4: __do_get_user_32(__gu_val,__gu_addr,__gu_ret); break; \
+default: __gu_ret = __do_get_user_bad(); break; \
+} } x = (type) __gu_val; __gu_ret; })
+
+#define __do_get_user_nocheck(x,ptr,size,type) ({ \
+int __gu_ret; \
+unsigned long __gu_val; \
+switch (size) { \
+case 1: __do_get_user_8(__gu_val,ptr,__gu_ret); break; \
+case 2: __do_get_user_16(__gu_val,ptr,__gu_ret); break; \
+case 4: __do_get_user_32(__gu_val,ptr,__gu_ret); break; \
+default: __gu_ret = __do_get_user_bad(); __gu_val = 0; break; \
+} x = (type) __gu_val; __gu_ret; })
+
+#define __do_get_user_asm(x,addr,ret,bwl,reg,rtype) \
+__asm__ __volatile__( \
+	"movl $1f,%0\n\t" \
+	"incl %3\n\t" \
+	"mov" #bwl " %2,%" reg "1\n\t" \
+	"xorl %0,%0\n\t" \
+	"decl %3\n1:" \
+:"=&d" (ret), #rtype (x) \
+:"m" (__m(addr)),"m" (current->tss.ex.count))
+
+#define __do_get_user_8(x,addr,ret) \
+__do_get_user_asm(x,addr,ret,b,"b","=&q")
+#define __do_get_user_16(x,addr,ret) \
+__do_get_user_asm(x,addr,ret,w,"w","=&r")
+#define __do_get_user_32(x,addr,ret) \
+__do_get_user_asm(x,addr,ret,l,"","=&r")
+
+extern int __do_get_user_bad(void);
+
+#define __copy_user(to,from,size) \
+__asm__ __volatile__( \
+	"shrl $2,%1\n\t" \
+	"movl $3f,%0\n\t" \
+	"incl %3\n\t" \
+	"rep; movsl\n\t" \
+	"testl $2,%2\n\t" \
+	"je 1f\n\t" \
+	"movsw\n\t" \
+	"subl $2,%2\n" \
+	"1:\t" \
+	"testl $1,%2\n\t" \
+	"je 2f\n\t" \
+	"movsb\n\t" \
+	"decl %2\n" \
+	"2:\t" \
+	"decl %3\n" \
+	"3:\tlea 0(%2,%1,4),%0" \
+	:"=&d" (size) \
+	:"c" (size), "r" (size & 3), "m" (current->tss.ex), \
+	 "D" (to), "S" (from) \
+	:"cx","di","si","memory");
+
+static inline unsigned long __constant_copy_user(void * to, const void * from, unsigned long size)
+{
+	unsigned long result;
+
+	switch (size & 3) {
+	default:
+		__asm__ __volatile__(
+			"movl $1f,%0\n\t"
+			"incl %1\n\t"
+			"rep ; movsl\n\t"
+			"decl %1\n"
+			"1:\tlea 0(,%%ecx,4),%0"
+			:"=&d" (result)
+			:"m" (current->tss.ex),
+			 "S" (from),"D" (to),"c" (size/4)
+			:"cx","di","si","memory");
+		break;
+	case 1:
+		__asm__ __volatile__(
+			"movl $1f,%0\n\t"
+			"incl %3\n\t"
+			"rep ; movsl\n\t"
+			"movsb\n\t"
+			"decl %1\n\t"
+			"decl %3\n"
+			"1:\tlea 0(%1,%%ecx,4),%0"
+			:"=&d" (result)
+			:"ab" (1),"m" (current->tss.ex),
+			 "S" (from),"D" (to), "c" (size/4)
+			:"cx","di","si","memory");
+		break;
+	case 2:
+		__asm__ __volatile__(
+			"movl $1f,%0\n\t"
+			"incl %2\n\t"
+			"rep ; movsl\n\t"
+			"movsw\n\t"
+			"subl $2,%1\n\t"
+			"decl %2\n"
+			"1:\tlea 0(%1,%%ecx,4),%0"
+			:"=&d" (result)
+			:"ab" (2),"m" (current->tss.ex),
+			 "S" (from),"D" (to),"c" (size/4)
+			:"cx","di","si","memory");
+		break;
+	case 3:
+		__asm__ __volatile__(
+			"movl $1f,%0\n\t"
+			"incl %2\n\t"
+			"rep ; movsl\n\t"
+			"movsw\n\t"
+			"subl $2,%1\n\t"
+			"movsb\n\t"
+			"decl %1\n\t"
+			"decl %2\n"
+			"1:\tlea 0(%1,%%ecx,4),%0"
+			:"=&d" (result)
+			:"ab" (3),"m" (current->tss.ex),
+			 "S" (from),"D" (to),"c" (size/4)
+			:"cx","di","si","memory");
+		break;
+	}
+	return result;
+}
+
+static inline unsigned long __generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		__copy_user(to,from,n);
+	return n;
+}
+
+static inline unsigned long __constant_copy_to_user(void *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		n = __constant_copy_user(to,from,n);
+	return n;
+}
+
+static inline unsigned long __generic_copy_from_user(void *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_READ, from, n))
+		__copy_user(to,from,n);
+	return n;
+}
+
+static inline unsigned long __constant_copy_from_user(void *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_READ, from, n))
+		n = __constant_copy_user(to,from,n);
+	return n;
+}
+
+#define copy_to_user(to,from,n) \
+(__builtin_constant_p(n) ? \
+ __constant_copy_to_user((to),(from),(n)) : \
+ __generic_copy_to_user((to),(from),(n)))
+
+#define copy_from_user(to,from,n) \
+(__builtin_constant_p(n) ? \
+ __constant_copy_from_user((to),(from),(n)) : \
+ __generic_copy_from_user((to),(from),(n)))
+
+#define __clear_user(addr,size) \
+__asm__ __volatile__( \
+	"movl $3f,%0\n\t" \
+	"incl %2\n\t" \
+	"rep; stosl\n\t" \
+	"testl $2,%3\n\t" \
+	"je 1f\n\t" \
+	"stosw\n\t" \
+	"subl $2,%3\n" \
+	"1:\t" \
+	"testl $1,%3\n\t" \
+	"je 2f\n\t" \
+	"stosb\n\t" \
+	"decl %3\n" \
+	"2:\t" \
+	"decl %2\n" \
+	"3:\tlea 0(%3,%1,4),%0" \
+	:"=&d" (size) \
+	:"c" (size >> 2), "m" (current->tss.ex), "r" (size & 3), \
+	 "D" (addr), "a" (0) \
+	:"cx","di","memory");
+
+#define clear_user(addr,n) ({ \
+void * __cl_addr = (addr); \
+unsigned long __cl_size = (n); \
+if (__cl_size && __access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) \
+__clear_user(__cl_addr, __cl_size); \
+__cl_size; })
+
+#define __strncpy_from_user(dst,src,count,res) \
+__asm__ __volatile__( \
+	"cld\n\t" \
+	"movl $3f,%0\n\t" \
+	"incl %2\n" \
+	"1:\tdecl %1\n\t" \
+	"js 2f\n\t" \
+	"lodsb\n\t" \
+	"stosb\n\t" \
+	"testb %%al,%%al\n\t" \
+	"jne 1b\n" \
+	"2:\t" \
+	"incl %1\n\t" \
+	"xorl %0,%0\n\t" \
+	"decl %2\n" \
+	"3:" \
+	:"=&d" (res), "=r" (count) \
+	:"m" (current->tss.ex), "1" (count), "S" (src),"D" (dst) \
+	:"si","di","ax","memory")
+
+#define strncpy_from_user(dest,src,count) ({ \
+const void * __sc_src = (src); \
+unsigned long __sc_count = (count); \
+long __sc_res = -EFAULT; \
+if (__access_ok(VERIFY_READ, ((unsigned long)(__sc_src)), __sc_count)) { \
+	unsigned long __sc_residue = __sc_count; \
+	__strncpy_from_user(dest,__sc_src,__sc_count,__sc_res); \
+	if (!__sc_res) __sc_res = __sc_residue - __sc_count; \
+} __sc_res; })
+
+
+extern inline int verify_area(int type, const void * addr, unsigned long size)
+{
+	return access_ok(type,addr,size)?0:-EFAULT;
+}
+
+#endif /* __i386_UACCESS_H */
diff -u --recursive --new-file v2.1.5/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.1.5/linux/include/linux/fs.h	Wed Oct 16 10:48:29 1996
+++ linux/include/linux/fs.h	Tue Oct 29 17:24:34 1996
@@ -16,8 +16,6 @@
 #include <linux/kdev_t.h>
 #include <linux/ioctl.h>
 
-#include <asm/semaphore.h>
-
 /*
  * It's silly to have NR_OPEN bigger than NR_FILE, but I'll fix
  * that later. Anyway, now the file code is no longer dependent
@@ -123,6 +121,7 @@
 
 #ifdef __KERNEL__
 
+#include <asm/semaphore.h>
 #include <asm/bitops.h>
 
 extern void buffer_init(void);
diff -u --recursive --new-file v2.1.5/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.1.5/linux/include/linux/mm.h	Wed Oct 16 10:48:29 1996
+++ linux/include/linux/mm.h	Tue Oct 29 17:24:34 1996
@@ -14,15 +14,6 @@
 
 #include <asm/page.h>
 #include <asm/atomic.h>
-#include <asm/segment.h>
-
-#define VERIFY_READ 0
-#define VERIFY_WRITE 1
-
-extern inline int verify_area(int type, const void * addr, unsigned long size)
-{
-	return access_ok(type,addr,size)?0:-EFAULT;
-}
 
 /*
  * Linux kernel virtual memory manager primitives.
diff -u --recursive --new-file v2.1.5/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.1.5/linux/include/linux/proc_fs.h	Wed Oct  9 08:55:23 1996
+++ linux/include/linux/proc_fs.h	Tue Oct 29 17:24:44 1996
@@ -104,6 +104,7 @@
 	PROC_NET_IP_MASQ_APP,
 	PROC_NET_STRIP_STATUS,
 	PROC_NET_STRIP_TRACE,
+	PROC_NET_Z8530,
 	PROC_NET_LAST
 };
 
diff -u --recursive --new-file v2.1.5/linux/include/linux/raid0.h linux/include/linux/raid0.h
--- v2.1.5/linux/include/linux/raid0.h	Mon Feb 26 13:51:46 1996
+++ linux/include/linux/raid0.h	Tue Oct 29 15:20:24 1996
@@ -1,32 +1,3 @@
-
-#ifndef _RAID0_H
-#define _RAID0_H
-
-struct strip_zone
-{
-  int zone_offset;		/* Zone offset in md_dev */
-  int dev_offset;		/* Zone offset in real dev */
-  int size;			/* Zone size */
-  int nb_dev;			/* Number of devices attached to the zone */
-  struct real_dev *dev[MAX_REAL]; /* Devices attached to the zone */
-};
-
-struct raid0_hash
-{
-  struct strip_zone *zone0, *zone1;
-};
-
-struct raid0_data
-{
-  struct raid0_hash *hash_table; /* Dynamically allocated */
-  struct strip_zone *strip_zone; /* This one too */
-  int nr_strip_zones;
-  struct strip_zone *smallest;
-  int nr_zones;
-};
-
-#endif
-
 #ifndef _RAID0_H
 #define _RAID0_H
 
diff -u --recursive --new-file v2.1.5/linux/include/linux/scc.h linux/include/linux/scc.h
--- v2.1.5/linux/include/linux/scc.h	Fri Apr 12 09:49:46 1996
+++ linux/include/linux/scc.h	Tue Oct 29 15:33:39 1996
@@ -1,8 +1,10 @@
-/* $Id: scc.h,v 1.15 1995/11/16 20:19:26 jreuter Exp jreuter $ */
+/* $Id: scc.h,v 1.26 1996/10/09 16:35:56 jreuter Exp jreuter $ */
 
 #ifndef	_SCC_H
 #define	_SCC_H
 
+#include <linux/if_ether.h>
+
 /* selection of hardware types */
 
 #define PA0HZP		0x00	/* hardware type for PA0HZP SCC card and compatible */
@@ -16,30 +18,21 @@
 
 #define SCC_PARANOIA_CHECK	/* tell the user if something is going wrong */
 
-/* ioctl() commands */
-
-#define TIOCSCCCFG	0x2200		/* set hardware parameters */
-#define TIOCSCCINI	0x2201		/* init driver */
-#define TIOCCHANINI	0x2202		/* init channel */
-
-#define TIOCCHANMEM	0x2210		/* adjust buffer pools */
-
-#define TIOCGKISS	0x2282		/* get kiss parameter */
-#define TIOCSKISS	0x2283		/* set kiss parameter */
-
-#define TIOCSCCSTAT	0x2284		/* get scc status */
+/* DEV ioctl() commands */
 
+#define SIOCSCCRESERVED (SIOCDEVPRIVATE+0)
+#define SIOCSCCCFG	(SIOCDEVPRIVATE+1)
+#define SIOCSCCINI	(SIOCDEVPRIVATE+2)
+#define SIOCSCCCHANINI	(SIOCDEVPRIVATE+3)
+#define SIOCSCCSMEM	(SIOCDEVPRIVATE+4)
+#define SIOCSCCGKISS	(SIOCDEVPRIVATE+5)
+#define SIOCSCCSKISS	(SIOCDEVPRIVATE+6)
+#define SIOCSCCGSTAT	(SIOCDEVPRIVATE+7)
 
 /* magic number */
 
 #define SCC_MAGIC	0x8530		/* ;-) */
 
-/* KISS protocol flags */
-#define FEND	192
-#define FESC	219
-#define TFEND	220
-#define TFESC	221
-
 /* KISS state machine */
 
 #define	KISS_IDLE	0
@@ -67,12 +60,27 @@
 #define PARAM_WAIT      16
 #define PARAM_MAXDEFER	17
 #define PARAM_TX        18
-#define PARAM_SLIP	19
+#define PARAM_HWEVENT	31
 #define PARAM_RETURN	255	/* reset kiss mode */
 
+/* fulldup parameter */
+
+#define KISS_DUPLEX_HALF	0	/* normal CSMA operation */
+#define KISS_DUPLEX_FULL	1	/* fullduplex, key down trx after transmission */
+#define KISS_DUPLEX_LINK	2	/* fullduplex, key down trx after 'idletime' sec */
+#define KISS_DUPLEX_OPTIMA	3	/* fullduplex, let the protocol layer control the hw */
+
+/* misc. parameters */
+
 #define TIMER_OFF	65535U	/* to switch off timers */
 #define NO_SUCH_PARAM	65534U	/* param not implemented */
 
+/* HWEVENT parameter */
+
+#define HWEV_DCD_ON	0
+#define HWEV_DCD_OFF	1
+#define HWEV_ALL_SENT	2
+
 /* channel grouping */
 
 #define RXGROUP		0x100	/* if set, only tx when all channels clear */
@@ -91,21 +99,22 @@
 #define TXS_BUSY	1	/* waiting for permission to send / tailtime */
 #define TXS_ACTIVE	2	/* Transmitter on, sending data */
 #define TXS_NEWFRAME	3	/* reset CRC and send (next) frame */
+#define TXS_IDLE2	4	/* Transmitter on, no data pending */
+#define TXS_WAIT	5	/* Waiting for Mintime to expire */
+#define TXS_TIMEOUT	6	/* We had a transmission timeout */
 
 #define TX_ON		1	/* command for scc_key_trx() */
 #define TX_OFF		0	/* dto */
 
-/* Buffer management */
-
-#define BT_RECEIVE  1		/* buffer allocated by receive */
-#define BT_TRANSMIT 2		/* buffer allocated by transmit */
-
-#define NULLBUF  (struct mbuf *)0
-#define NULLBUFP (struct mbuf **)0
+/* Vector masks in RR2B */
 
+#define VECTOR_MASK	0x06
+#define TXINT		0x00
+#define EXINT		0x02
+#define RXINT		0x04
+#define SPINT		0x06
 
-typedef unsigned short io_port;	/* type definition for an 'io port address' */
-typedef unsigned short ioaddr;  /* old def */
+typedef unsigned long io_port;	/* type definition for an 'io port address' */
 
 #ifdef SCC_DELAY
 #define Inb(port)	inb_p(port)
@@ -115,42 +124,25 @@
 #define Outb(port, val)	outb(val, port)
 #endif
 
-/* some nasty macros (esp. Expired) */
+#define TIMER_OFF 65535U
 
-#define TIMER_STOPPED 65535U
-#define Running(k) (scc->k != TIMER_STOPPED)
-#define Expired(k) (scc->k != TIMER_STOPPED) && (!(scc->k) || (--(scc->k) == 0))
-#define Stop_Timer(k) scc->k = TIMER_STOPPED
-
-
-/* Basic message buffer structure */
-
-struct mbuf {
-	struct mbuf *next;	/* Link to next buffer */
-	struct mbuf *prev;	/* Link to previous buffer */
-	
-	int cnt;		/* Number of bytes stored in buffer */
-	unsigned char *rw_ptr;	/* read-write pointer */
-	unsigned char data[0];	/* anchor for allocated buffer */
-};
-	
 /* SCC channel control structure for KISS */
 
 struct scc_kiss {
 	unsigned char txdelay;		/* Transmit Delay 10 ms/cnt */
 	unsigned char persist;		/* Persistence (0-255) as a % */
 	unsigned char slottime;		/* Delay to wait on persistence hit */
-	unsigned char tailtime;		/* Delay after XMTR OFF */
+	unsigned char tailtime;		/* Delay after last byte written */
 	unsigned char fulldup;		/* Full Duplex mode 0=CSMA 1=DUP 2=ALWAYS KEYED */
 	unsigned char waittime;		/* Waittime before any transmit attempt */
 	unsigned int  maxkeyup;		/* Maximum time to transmit (seconds) */
-	unsigned char mintime;		/* Minimal offtime after MAXKEYUP timeout */
+	unsigned char mintime;		/* Minimal offtime after MAXKEYUP timeout (seconds) */
 	unsigned int  idletime;		/* Maximum idle time in ALWAYS KEYED mode (seconds) */
 	unsigned int  maxdefer;		/* Timer for CSMA channel busy limit */
 	unsigned char tx_inhibit;	/* Transmit is not allowed when set */	
-	unsigned char group;		/* group ID for AX.25 TX interlocking */
-	unsigned char not_slip;		/* set to zero: use SLIP instead of KISS */
-	unsigned char softdcd;		/* use DPLL instead of DCD pin for carrier detect */
+	unsigned char group;		/* Group ID for AX.25 TX interlocking */
+	unsigned char mode;		/* 'normal' or 'hwctrl' mode (unused) */
+	unsigned char softdcd;		/* Use DPLL instead of DCD pin for carrier detect */
 };
 
 
@@ -172,15 +164,9 @@
 	unsigned int tx_under;	/* Transmitter Underruns */
 
 	unsigned int tx_state;	/* Transmitter state */
-	
-	char tx_kiss_state;	/* state of the kiss interpreter */
-	char rx_kiss_state;	/* state of the kiss encoder */
-	
 	int tx_queued;		/* tx frames enqueued */
-	int rx_queued; 		/* rx frames enqueued */
-	
-	unsigned int rxbuffers;	/* allocated rx_buffers */
-	unsigned int txbuffers;	/* allocated tx_buffers */
+
+	unsigned int maxqueue;	/* allocated tx_buffers */
 	unsigned int bufsize;	/* used buffersize */
 };
 
@@ -191,13 +177,11 @@
 	char nrz;		/* NRZ instead of NRZI */	
 };
 
-struct ioctl_command {
+struct scc_kiss_cmd {
 	int  	 command;	/* one of the KISS-Commands defined above */
 	unsigned param;		/* KISS-Param */
 };
 
-/* currently unused */
-
 struct scc_hw_config {
 	io_port data_a;		/* data port channel A */
 	io_port ctrl_a;		/* control port channel A */
@@ -209,363 +193,57 @@
 	int	irq;		/* irq */
 	long	clock;		/* clock */
 	char	option;		/* command for function port */
-	
+
 	char brand;		/* hardware type */
 	char escc;		/* use ext. features of a 8580/85180/85280 */
 };
 
+/* (#) only one INTACK latch allowed. */
+
+
 struct scc_mem_config {
-	unsigned int rxbuffers;
-	unsigned int txbuffers;
+	unsigned int dummy;
 	unsigned int bufsize;
 };
 
-/* (#) only one INTACK latch allowed. */
-	
 
 /* SCC channel structure */
 
 struct scc_channel {
-	int magic;		/* magic word */
+	int magic;			/* magic word */
 	
-	int init;		/* channel exists? */
-	struct tty_struct *tty; /* link to tty control structure */
-	char tty_opened;	/* No. of open() calls... */
-	char throttled;		/* driver is throttled  */
-		
-	char brand;		/* manufacturer of the board */
-	long clock;		/* used clock */
+	int init;			/* channel exists? */
+
+	struct device *dev;		/* link to device control structure */
+	struct enet_statistics dev_stat;/* device statistics */
+
+	char brand;			/* manufacturer of the board */
+	long clock;			/* used clock */
 	
-	io_port ctrl;		/* I/O address of CONTROL register */
-	io_port	data;		/* I/O address of DATA register */
-	io_port special;	/* I/O address of special function port */
+	io_port ctrl;			/* I/O address of CONTROL register */
+	io_port	data;			/* I/O address of DATA register */
+	io_port special;		/* I/O address of special function port */
+	int irq;			/* Number of Interrupt */
 	
 	char option;
-	char enhanced;		/* Enhanced SCC support */
+	char enhanced;			/* Enhanced SCC support */
 
-	unsigned char wreg[16]; /* Copy of last written value in WRx */
-	unsigned char status;	/* Copy of R0 at last external interrupt */
+	unsigned char wreg[16]; 	/* Copy of last written value in WRx */
+	unsigned char status;		/* Copy of R0 at last external interrupt */
 
-        struct scc_kiss kiss;	/* control structure for KISS params */
-        struct scc_stat stat;	/* statistical information */
-        struct scc_modem modem; /* modem information */
-        
-        struct mbuf *rx_buffer_pool; /* free buffers for rx/tx frames are */
-        struct mbuf *tx_buffer_pool; /* linked in these ring chains */
+        struct scc_kiss kiss;		/* control structure for KISS params */
+        struct scc_stat stat;		/* statistical information */
+        struct scc_modem modem; 	/* modem information */
         
-        struct mbuf *rx_queue;	/* chain of received frames */
-        struct mbuf *tx_queue;	/* chain of frames due to transmit */
-        struct mbuf *rx_bp;	/* pointer to frame currently received */
-        struct mbuf *tx_bp;	/* pointer to frame currently transmitted */
-        
-        struct mbuf *kiss_decode_bp; /* frame we are receiving from tty */
-        struct mbuf *kiss_encode_bp; /* frame we are sending to tty */
-	
+        struct sk_buff *tx_next_buff;	/* next tx buffer */
+        struct sk_buff *rx_buff;	/* pointer to frame currently received */
+        struct sk_buff *tx_buff;	/* pointer to frame currently transmitted */
+
 	/* Timer */
-	
-	struct timer_list tx_t;	/* tx timer for this channel */
-	struct timer_list rx_t; /* rx timer */
 
-	/* rx timer counters */
-	
-	unsigned int t_dwait;	/* wait time (DWAIT) */
-	unsigned int t_slot;	/* channel sample frequency */
-	unsigned int t_txdel;	/* TX delay */
-	unsigned int t_tail;	/* tail time */
-	unsigned int t_maxk;	/* max. key up */
-	unsigned int t_min;	/* minimal key up */
-	unsigned int t_idle;	/* */
-	unsigned int t_mbusy;	/* time until defer if channel busy */	 	
+	struct timer_list tx_t;		/* tx timer for this channel */
+	struct timer_list tx_wdog;	/* tx watchdogs */
 };
 
-
-/* 8530 Serial Communications Controller Register definitions */
-#define	FLAG	0x7e
-
-/* Write Register 0 */
-#define	R0	0		/* Register selects */
-#define	R1	1
-#define	R2	2
-#define	R3	3
-#define	R4	4
-#define	R5	5
-#define	R6	6
-#define	R7	7
-#define	R8	8
-#define	R9	9
-#define	R10	10
-#define	R11	11
-#define	R12	12
-#define	R13	13
-#define	R14	14
-#define	R15	15
-
-#define	NULLCODE	0	/* Null Code */
-#define	POINT_HIGH	0x8	/* Select upper half of registers */
-#define	RES_EXT_INT	0x10	/* Reset Ext. Status Interrupts */
-#define	SEND_ABORT	0x18	/* HDLC Abort */
-#define	RES_RxINT_FC	0x20	/* Reset RxINT on First Character */
-#define	RES_Tx_P	0x28	/* Reset TxINT Pending */
-#define	ERR_RES		0x30	/* Error Reset */
-#define	RES_H_IUS	0x38	/* Reset highest IUS */
-
-#define	RES_Rx_CRC	0x40	/* Reset Rx CRC Checker */
-#define	RES_Tx_CRC	0x80	/* Reset Tx CRC Checker */
-#define	RES_EOM_L	0xC0	/* Reset EOM latch */
-
-/* Write Register 1 */
-
-#define	EXT_INT_ENAB	0x1	/* Ext Int Enable */
-#define	TxINT_ENAB	0x2	/* Tx Int Enable */
-#define	PAR_SPEC	0x4	/* Parity is special condition */
-
-#define	RxINT_DISAB	0	/* Rx Int Disable */
-#define	RxINT_FCERR	0x8	/* Rx Int on First Character Only or Error */
-#define	INT_ALL_Rx	0x10	/* Int on all Rx Characters or error */
-#define	INT_ERR_Rx	0x18	/* Int on error only */
-
-#define	WT_RDY_RT	0x20	/* Wait/Ready on R/T */
-#define	WT_FN_RDYFN	0x40	/* Wait/FN/Ready FN */
-#define	WT_RDY_ENAB	0x80	/* Wait/Ready Enable */
-
-/* Write Register 2 (Interrupt Vector) */
-
-/* Write Register 3 */
-
-#define	RxENABLE	0x1	/* Rx Enable */
-#define	SYNC_L_INH	0x2	/* Sync Character Load Inhibit */
-#define	ADD_SM		0x4	/* Address Search Mode (SDLC) */
-#define	RxCRC_ENAB	0x8	/* Rx CRC Enable */
-#define	ENT_HM		0x10	/* Enter Hunt Mode */
-#define	AUTO_ENAB	0x20	/* Auto Enables */
-#define	Rx5		0x0	/* Rx 5 Bits/Character */
-#define	Rx7		0x40	/* Rx 7 Bits/Character */
-#define	Rx6		0x80	/* Rx 6 Bits/Character */
-#define	Rx8		0xc0	/* Rx 8 Bits/Character */
-
-/* Write Register 4 */
-
-#define	PAR_ENA		0x1	/* Parity Enable */
-#define	PAR_EVEN	0x2	/* Parity Even/Odd* */
-
-#define	SYNC_ENAB	0	/* Sync Modes Enable */
-#define	SB1		0x4	/* 1 stop bit/char */
-#define	SB15		0x8	/* 1.5 stop bits/char */
-#define	SB2		0xc	/* 2 stop bits/char */
-
-#define	MONSYNC		0	/* 8 Bit Sync character */
-#define	BISYNC		0x10	/* 16 bit sync character */
-#define	SDLC		0x20	/* SDLC Mode (01111110 Sync Flag) */
-#define	EXTSYNC		0x30	/* External Sync Mode */
-
-#define	X1CLK		0x0	/* x1 clock mode */
-#define	X16CLK		0x40	/* x16 clock mode */
-#define	X32CLK		0x80	/* x32 clock mode */
-#define	X64CLK		0xC0	/* x64 clock mode */
-
-/* Write Register 5 */
-
-#define	TxCRC_ENAB	0x1	/* Tx CRC Enable */
-#define	RTS		0x2	/* RTS */
-#define	SDLC_CRC	0x4	/* SDLC/CRC-16 */
-#define	TxENAB		0x8	/* Tx Enable */
-#define	SND_BRK		0x10	/* Send Break */
-#define	Tx5		0x0	/* Tx 5 bits (or less)/character */
-#define	Tx7		0x20	/* Tx 7 bits/character */
-#define	Tx6		0x40	/* Tx 6 bits/character */
-#define	Tx8		0x60	/* Tx 8 bits/character */
-#define	DTR		0x80	/* DTR */
-
-/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
-
-/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
-
-/* Write Register 8 (transmit buffer) */
-
-/* Write Register 9 (Master interrupt control) */
-#define	VIS	1	/* Vector Includes Status */
-#define	NV	2	/* No Vector */
-#define	DLC	4	/* Disable Lower Chain */
-#define	MIE	8	/* Master Interrupt Enable */
-#define	STATHI	0x10	/* Status high */
-#define	NORESET	0	/* No reset on write to R9 */
-#define	CHRB	0x40	/* Reset channel B */
-#define	CHRA	0x80	/* Reset channel A */
-#define	FHWRES	0xc0	/* Force hardware reset */
-
-/* Write Register 10 (misc control bits) */
-#define	BIT6	1	/* 6 bit/8bit sync */
-#define	LOOPMODE 2	/* SDLC Loop mode */
-#define	ABUNDER	4	/* Abort/flag on SDLC xmit underrun */
-#define	MARKIDLE 8	/* Mark/flag on idle */
-#define	GAOP	0x10	/* Go active on poll */
-#define	NRZ	0	/* NRZ mode */
-#define	NRZI	0x20	/* NRZI mode */
-#define	FM1	0x40	/* FM1 (transition = 1) */
-#define	FM0	0x60	/* FM0 (transition = 0) */
-#define	CRCPS	0x80	/* CRC Preset I/O */
-
-/* Write Register 11 (Clock Mode control) */
-#define	TRxCXT	0	/* TRxC = Xtal output */
-#define	TRxCTC	1	/* TRxC = Transmit clock */
-#define	TRxCBR	2	/* TRxC = BR Generator Output */
-#define	TRxCDP	3	/* TRxC = DPLL output */
-#define	TRxCOI	4	/* TRxC O/I */
-#define	TCRTxCP	0	/* Transmit clock = RTxC pin */
-#define	TCTRxCP	8	/* Transmit clock = TRxC pin */
-#define	TCBR	0x10	/* Transmit clock = BR Generator output */
-#define	TCDPLL	0x18	/* Transmit clock = DPLL output */
-#define	RCRTxCP	0	/* Receive clock = RTxC pin */
-#define	RCTRxCP	0x20	/* Receive clock = TRxC pin */
-#define	RCBR	0x40	/* Receive clock = BR Generator output */
-#define	RCDPLL	0x60	/* Receive clock = DPLL output */
-#define	RTxCX	0x80	/* RTxC Xtal/No Xtal */
-
-/* Write Register 12 (lower byte of baud rate generator time constant) */
-
-/* Write Register 13 (upper byte of baud rate generator time constant) */
-
-/* Write Register 14 (Misc control bits) */
-#define	BRENABL	1	/* Baud rate generator enable */
-#define	BRSRC	2	/* Baud rate generator source */
-#define	DTRREQ	4	/* DTR/Request function */
-#define	AUTOECHO 8	/* Auto Echo */
-#define	LOOPBAK	0x10	/* Local loopback */
-#define	SEARCH	0x20	/* Enter search mode */
-#define	RMC	0x40	/* Reset missing clock */
-#define	DISDPLL	0x60	/* Disable DPLL */
-#define	SSBR	0x80	/* Set DPLL source = BR generator */
-#define	SSRTxC	0xa0	/* Set DPLL source = RTxC */
-#define	SFMM	0xc0	/* Set FM mode */
-#define	SNRZI	0xe0	/* Set NRZI mode */
-
-/* Write Register 15 (external/status interrupt control) */
-#define	ZCIE	2	/* Zero count IE */
-#define	DCDIE	8	/* DCD IE */
-#define	SYNCIE	0x10	/* Sync/hunt IE */
-#define	CTSIE	0x20	/* CTS IE */
-#define	TxUIE	0x40	/* Tx Underrun/EOM IE */
-#define	BRKIE	0x80	/* Break/Abort IE */
-
-
-/* Read Register 0 */
-#define	Rx_CH_AV	0x1	/* Rx Character Available */
-#define	ZCOUNT		0x2	/* Zero count */
-#define	Tx_BUF_EMP	0x4	/* Tx Buffer empty */
-#define	DCD		0x8	/* DCD */
-#define	SYNC_HUNT	0x10	/* Sync/hunt */
-#define	CTS		0x20	/* CTS */
-#define	TxEOM		0x40	/* Tx underrun */
-#define	BRK_ABRT	0x80	/* Break/Abort */
-
-/* Read Register 1 */
-#define	ALL_SNT		0x1	/* All sent */
-/* Residue Data for 8 Rx bits/char programmed */
-#define	RES3		0x8	/* 0/3 */
-#define	RES4		0x4	/* 0/4 */
-#define	RES5		0xc	/* 0/5 */
-#define	RES6		0x2	/* 0/6 */
-#define	RES7		0xa	/* 0/7 */
-#define	RES8		0x6	/* 0/8 */
-#define	RES18		0xe	/* 1/8 */
-#define	RES28		0x0	/* 2/8 */
-/* Special Rx Condition Interrupts */
-#define	PAR_ERR		0x10	/* Parity error */
-#define	Rx_OVR		0x20	/* Rx Overrun Error */
-#define	CRC_ERR		0x40	/* CRC/Framing Error */
-#define	END_FR		0x80	/* End of Frame (SDLC) */
-
-/* Read Register 2 (channel B only) - Interrupt vector */
-
-#define VECTOR_MASK	0x06
-
-#define TXINT   0x00
-#define EXINT   0x02
-#define RXINT   0x04
-#define SPINT   0x06
-
-
-/* Read Register 3 (interrupt pending register) ch a only */
-#define	CHBEXT	0x1		/* Channel B Ext/Stat IP */
-#define	CHBTxIP	0x2		/* Channel B Tx IP */
-#define	CHBRxIP	0x4		/* Channel B Rx IP */
-#define	CHAEXT	0x8		/* Channel A Ext/Stat IP */
-#define	CHATxIP	0x10		/* Channel A Tx IP */
-#define	CHARxIP	0x20		/* Channel A Rx IP */
-
-/* Read Register 8 (receive data register) */
-
-/* Read Register 10  (misc status bits) */
-#define	ONLOOP	2		/* On loop */
-#define	LOOPSEND 0x10		/* Loop sending */
-#define	CLK2MIS	0x40		/* Two clocks missing */
-#define	CLK1MIS	0x80		/* One clock missing */
-
-/* Read Register 12 (lower byte of baud rate generator constant) */
-
-/* Read Register 13 (upper byte of baud rate generator constant) */
-
-/* Read Register 15 (value of WR 15) */
-
-
-/* 8536 register definitions */
-
-#define CIO_MICR	0x00	/* Master interrupt control register */
-#define CIO_MCCR	0x01	/* Master configuration control register */
-#define CIO_CTMS1	0x1c	/* Counter/timer mode specification #1 */
-#define CIO_CTMS2	0x1d	/* Counter/timer mode specification #2 */
-#define CIO_CTMS3	0x1e	/* Counter/timer mode specification #3 */
-#define CIO_IVR 	0x04	/* Interrupt vector register */
-
-#define CIO_CSR1	0x0a	/* Command and status register CTC #1 */
-#define CIO_CSR2	0x0b	/* Command and status register CTC #2 */
-#define CIO_CSR3	0x0c	/* Command and status register CTC #3 */
-
-#define CIO_CT1MSB	0x16	/* CTC #1 Timer constant - MSB */
-#define CIO_CT1LSB	0x17	/* CTC #1 Timer constant - LSB */
-#define CIO_CT2MSB	0x18	/* CTC #2 Timer constant - MSB */
-#define CIO_CT2LSB	0x19	/* CTC #2 Timer constant - LSB */
-#define CIO_CT3MSB	0x1a	/* CTC #3 Timer constant - MSB */
-#define CIO_CT3LSB	0x1b	/* CTC #3 Timer constant - LSB */
-#define CIO_PDCA	0x23	/* Port A data direction control */
-#define CIO_PDCB	0x2b	/* Port B data direction control */
-
-#define CIO_GCB 	0x04	/* CTC Gate command bit */
-#define CIO_TCB 	0x02	/* CTC Trigger command bit */
-#define CIO_IE		0xc0	/* CTC Interrupt enable (set) */
-#define CIO_CIP 	0x20	/* CTC Clear interrupt pending */
-#define CIO_IP		0x20	/* CTC Interrupt pending */
-
-
-/* 8580/85180/85280 Enhanced SCC register definitions */
-
-/* Write Register 7' (SDLC/HDLC Programmable Enhancements) */
-#define AUTOTXF	0x01		/* Auto Tx Flag */
-#define AUTOEOM 0x02		/* Auto EOM Latch Reset */
-#define AUTORTS	0x04		/* Auto RTS */
-#define TXDNRZI 0x08		/* TxD Pulled High in SDLC NRZI mode */
-#define FASTDTR 0x10		/* Fast DTR/REQ Mode */
-#define CRCCBCR	0x20		/* CRC Check Bytes Completely Received */
-#define EXTRDEN	0x40		/* Extended Read Enabled */
-
-/* Write Register 15 (external/status interrupt control) */
-#define SHDLCE	1		/* SDLC/HDLC Enhancements Enable */
-#define FIFOE	4		/* FIFO Enable */
-
-/* Read Register 6 (frame status FIFO) */
-#define BCLSB	0xff		/* LSB of 14 bits count */
-
-/* Read Register 7 (frame status FIFO) */
-#define BCMSB	0x3f		/* MSB of 14 bits count */
-#define FDA	0x40		/* FIFO Data Available Status */
-#define FOY	0x80		/* FIFO Overflow Status */
-
-#endif	/* _SCC_H */
-
-/* global functions */
-
-#ifdef PREV_LINUX_1_3_33
-extern long scc_init(long kmem_start);
-#else
-extern int scc_init(void);
+int scc_init(void);
 #endif
diff -u --recursive --new-file v2.1.5/linux/include/linux/soundcard.h linux/include/linux/soundcard.h
--- v2.1.5/linux/include/linux/soundcard.h	Wed Oct  9 08:55:23 1996
+++ linux/include/linux/soundcard.h	Tue Oct 29 09:31:11 1996
@@ -24,9 +24,19 @@
  * SUCH DAMAGE.
  */
 
-#define SOUND_VERSION	350
-#define UNIX_SOUND_SYSTEM
 
+/*
+ * OSS interface version. With versions earlier than 3.6 this value is
+ * an integer with value less than 361. In versions 3.6 and later
+ * it's a six digit hexadecimal value. For example value
+ * of 0x030600 represents OSS version 3.6.0.
+ * Use ioctl(fd, OSS_GETVERSION, &int) to get the version number of
+ * the currently active driver.
+ */
+#define SOUND_VERSION	0x030700
+#define OPEN_SOUND_SYSTEM
+
+/* In Linux we need to be prepared for cross compiling */
 #include <linux/ioctl.h>
 
 /*
@@ -65,8 +75,19 @@
  * IOCTL Commands for /dev/sequencer
  */
 
-#ifndef _IOWR
-/*	@(#)ioctlp.h */
+#ifndef _SIOWR
+#if defined(_IOWR) && !defined(sun)
+/* Use already defined ioctl defines if they exist (except with Sun) */
+#define	SIOCPARM_MASK	IOCPARM_MASK
+#define	SIOC_VOID	IOC_VOID
+#define	SIOC_OUT	IOC_OUT
+#define	SIOC_IN		IOC_IN
+#define	SIOC_INOUT	IOC_INOUT
+#define	_SIO		_IO
+#define	_SIOR		_IOR
+#define	_SIOW		_IOW
+#define	_SIOWR		_IOWR
+#else
 
 /* Ioctl's have the command encoded in the lower word,
  * and the size of any in or out parameters in the upper
@@ -74,68 +95,73 @@
  * to encode the in/out status of the parameter; for now
  * we restrict parameters to at most 128 bytes.
  */
-/* #define	IOCTYPE		(0xff<<8) */
-#define	IOCPARM_MASK	0x7f		/* parameters must be < 128 bytes */
-#define	IOC_VOID	0x00000000	/* no parameters */
-#define	IOC_OUT		0x20000000	/* copy out parameters */
-#define	IOC_IN		0x40000000	/* copy in parameters */
-#define	IOC_INOUT	(IOC_IN|IOC_OUT)
+/* #define	SIOCTYPE		(0xff<<8) */
+#define	SIOCPARM_MASK	0x1fff		/* parameters must be < 8192 bytes */
+#define	SIOC_VOID	0x00000000	/* no parameters */
+#define	SIOC_OUT	0x20000000	/* copy out parameters */
+#define	SIOC_IN		0x40000000	/* copy in parameters */
+#define	SIOC_INOUT	(SIOC_IN|SIOC_OUT)
 /* the 0x20000000 is so we can distinguish new ioctl's from old */
-#define	_IO(x,y)	((int)(IOC_VOID|(x<<8)|y))
-#define	_IOR(x,y,t)	((int)(IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y))
-#define	_IOW(x,y,t)	((int)(IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y))
-/* this should be _IORW, but stdio got there first */
-#define	_IOWR(x,y,t)	((int)(IOC_INOUT|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y))
-#endif  /* !_IOWR */
-
-#define SNDCTL_SEQ_RESET		_IO  ('Q', 0)
-#define SNDCTL_SEQ_SYNC			_IO  ('Q', 1)
-#define SNDCTL_SYNTH_INFO		_IOWR('Q', 2, struct synth_info)
-#define SNDCTL_SEQ_CTRLRATE		_IOWR('Q', 3, int)	/* Set/get timer resolution (HZ) */
-#define SNDCTL_SEQ_GETOUTCOUNT		_IOR ('Q', 4, int)
-#define SNDCTL_SEQ_GETINCOUNT		_IOR ('Q', 5, int)
-#define SNDCTL_SEQ_PERCMODE		_IOW ('Q', 6, int)
-#define SNDCTL_FM_LOAD_INSTR		_IOW ('Q', 7, struct sbi_instrument)	/* Valid for FM only */
-#define SNDCTL_SEQ_TESTMIDI		_IOW ('Q', 8, int)
-#define SNDCTL_SEQ_RESETSAMPLES		_IOW ('Q', 9, int)
-#define SNDCTL_SEQ_NRSYNTHS		_IOR ('Q',10, int)
-#define SNDCTL_SEQ_NRMIDIS		_IOR ('Q',11, int)
-#define SNDCTL_MIDI_INFO		_IOWR('Q',12, struct midi_info)
-#define SNDCTL_SEQ_THRESHOLD		_IOW ('Q',13, int)
+#define	_SIO(x,y)	((int)(SIOC_VOID|(x<<8)|y))
+#define	_SIOR(x,y,t)	((int)(SIOC_OUT|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y))
+#define	_SIOW(x,y,t)	((int)(SIOC_IN|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y))
+/* this should be _SIORW, but stdio got there first */
+#define	_SIOWR(x,y,t)	((int)(SIOC_INOUT|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y))
+#  endif /* _IOWR */
+#endif  /* !_SIOWR */
+
+#define SNDCTL_SEQ_RESET		_SIO  ('Q', 0)
+#define SNDCTL_SEQ_SYNC			_SIO  ('Q', 1)
+#define SNDCTL_SYNTH_INFO		_SIOWR('Q', 2, struct synth_info)
+#define SNDCTL_SEQ_CTRLRATE		_SIOWR('Q', 3, int)	/* Set/get timer resolution (HZ) */
+#define SNDCTL_SEQ_GETOUTCOUNT		_SIOR ('Q', 4, int)
+#define SNDCTL_SEQ_GETINCOUNT		_SIOR ('Q', 5, int)
+#define SNDCTL_SEQ_PERCMODE		_SIOW ('Q', 6, int)
+#define SNDCTL_FM_LOAD_INSTR		_SIOW ('Q', 7, struct sbi_instrument)	/* Valid for FM only */
+#define SNDCTL_SEQ_TESTMIDI		_SIOW ('Q', 8, int)
+#define SNDCTL_SEQ_RESETSAMPLES		_SIOW ('Q', 9, int)
+#define SNDCTL_SEQ_NRSYNTHS		_SIOR ('Q',10, int)
+#define SNDCTL_SEQ_NRMIDIS		_SIOR ('Q',11, int)
+#define SNDCTL_MIDI_INFO		_SIOWR('Q',12, struct midi_info)
+#define SNDCTL_SEQ_THRESHOLD		_SIOW ('Q',13, int)
 #define SNDCTL_SEQ_TRESHOLD		SNDCTL_SEQ_THRESHOLD	/* there was once a typo */
-#define SNDCTL_SYNTH_MEMAVL		_IOWR('Q',14, int)	/* in=dev#, out=memsize */
-#define SNDCTL_FM_4OP_ENABLE		_IOW ('Q',15, int)	/* in=dev# */
-#define SNDCTL_PMGR_ACCESS		_IOWR('Q',16, struct patmgr_info)
-#define SNDCTL_SEQ_PANIC		_IO  ('Q',17)
-#define SNDCTL_SEQ_OUTOFBAND		_IOW ('Q',18, struct seq_event_rec)
+#define SNDCTL_SYNTH_MEMAVL		_SIOWR('Q',14, int)	/* in=dev#, out=memsize */
+#define SNDCTL_FM_4OP_ENABLE		_SIOW ('Q',15, int)	/* in=dev# */
+#define SNDCTL_PMGR_ACCESS		_SIOWR('Q',16, struct patmgr_info)
+#define SNDCTL_SEQ_PANIC		_SIO  ('Q',17)
+#define SNDCTL_SEQ_OUTOFBAND		_SIOW ('Q',18, struct seq_event_rec)
+#define SNDCTL_SEQ_GETTIME		_SIOR ('Q',19, int)
 
 	struct seq_event_rec {
 			unsigned char arr[8];
 		};
 
-#define SNDCTL_TMR_TIMEBASE		_IOWR('T', 1, int)
-#define SNDCTL_TMR_START		_IO  ('T', 2)
-#define SNDCTL_TMR_STOP			_IO  ('T', 3)
-#define SNDCTL_TMR_CONTINUE		_IO  ('T', 4)
-#define SNDCTL_TMR_TEMPO		_IOWR('T', 5, int)
-#define SNDCTL_TMR_SOURCE		_IOWR('T', 6, int)
+#define SNDCTL_TMR_TIMEBASE		_SIOWR('T', 1, int)
+#define SNDCTL_TMR_START		_SIO  ('T', 2)
+#define SNDCTL_TMR_STOP			_SIO  ('T', 3)
+#define SNDCTL_TMR_CONTINUE		_SIO  ('T', 4)
+#define SNDCTL_TMR_TEMPO		_SIOWR('T', 5, int)
+#define SNDCTL_TMR_SOURCE		_SIOWR('T', 6, int)
 #	define TMR_INTERNAL		0x00000001
 #	define TMR_EXTERNAL		0x00000002
 #		define TMR_MODE_MIDI	0x00000010
 #		define TMR_MODE_FSK	0x00000020
 #		define TMR_MODE_CLS	0x00000040
 #		define TMR_MODE_SMPTE	0x00000080
-#define SNDCTL_TMR_METRONOME		_IOW ('T', 7, int)
-#define SNDCTL_TMR_SELECT		_IOW ('T', 8, int)
+#define SNDCTL_TMR_METRONOME		_SIOW ('T', 7, int)
+#define SNDCTL_TMR_SELECT		_SIOW ('T', 8, int)
 
 /*
- *	Endian aware patch key generation algorithm.
+ * Some big endian/little endian handling macros
  */
 
-#if defined(_AIX) || defined(AIX)
+#if defined(_AIX) || defined(AIX) || defined(sparc) || defined(HPPA) || defined(PPC)
+/* Big endian machines */
 #  define _PATCHKEY(id) (0xfd00|id)
+#  define AFMT_S16_NE AFMT_S16_BE
 #else
 #  define _PATCHKEY(id) ((id<<8)|0xfd)
+#  define AFMT_S16_NE AFMT_S16_LE
 #endif
 
 /*
@@ -248,7 +274,7 @@
 #define		PS_MGR_OK		2	/* Patch manager supported */
 #define		PS_MANAGED		3	/* Patch manager running */
 
-#define SNDCTL_PMGR_IFACE		_IOWR('P', 1, struct patmgr_info)
+#define SNDCTL_PMGR_IFACE		_SIOWR('P', 1, struct patmgr_info)
 
 /*
  * The patmgr_info is a fixed size structure which is used for two
@@ -540,30 +566,30 @@
 		unsigned char data[30];
 	} mpu_command_rec;
 
-#define SNDCTL_MIDI_PRETIME		_IOWR('m', 0, int)
-#define SNDCTL_MIDI_MPUMODE		_IOWR('m', 1, int)
-#define SNDCTL_MIDI_MPUCMD		_IOWR('m', 2, mpu_command_rec)
+#define SNDCTL_MIDI_PRETIME		_SIOWR('m', 0, int)
+#define SNDCTL_MIDI_MPUMODE		_SIOWR('m', 1, int)
+#define SNDCTL_MIDI_MPUCMD		_SIOWR('m', 2, mpu_command_rec)
 
 /********************************************
  * IOCTL commands for /dev/dsp and /dev/audio
  */
 
-#define SNDCTL_DSP_RESET		_IO  ('P', 0)
-#define SNDCTL_DSP_SYNC			_IO  ('P', 1)
-#define SNDCTL_DSP_SPEED		_IOWR('P', 2, int)
-#define SNDCTL_DSP_STEREO		_IOWR('P', 3, int)
-#define SNDCTL_DSP_GETBLKSIZE		_IOWR('P', 4, int)
+#define SNDCTL_DSP_RESET		_SIO  ('P', 0)
+#define SNDCTL_DSP_SYNC			_SIO  ('P', 1)
+#define SNDCTL_DSP_SPEED		_SIOWR('P', 2, int)
+#define SNDCTL_DSP_STEREO		_SIOWR('P', 3, int)
+#define SNDCTL_DSP_GETBLKSIZE		_SIOWR('P', 4, int)
 #define SNDCTL_DSP_SAMPLESIZE		SNDCTL_DSP_SETFMT
-#define SNDCTL_DSP_CHANNELS		_IOWR('P', 6, int)
+#define SNDCTL_DSP_CHANNELS		_SIOWR('P', 6, int)
 #define SOUND_PCM_WRITE_CHANNELS	SNDCTL_DSP_CHANNELS
-#define SOUND_PCM_WRITE_FILTER		_IOWR('P', 7, int)
-#define SNDCTL_DSP_POST			_IO  ('P', 8)
-#define SNDCTL_DSP_SUBDIVIDE		_IOWR('P', 9, int)
-#define SNDCTL_DSP_SETFRAGMENT		_IOWR('P',10, int)
+#define SOUND_PCM_WRITE_FILTER		_SIOWR('P', 7, int)
+#define SNDCTL_DSP_POST			_SIO  ('P', 8)
+#define SNDCTL_DSP_SUBDIVIDE		_SIOWR('P', 9, int)
+#define SNDCTL_DSP_SETFRAGMENT		_SIOWR('P',10, int)
 
 /*	Audio data formats (Note! U8=8 and S16_LE=16 for compatibility) */
-#define SNDCTL_DSP_GETFMTS		_IOR ('P',11, int) /* Returns a mask */
-#define SNDCTL_DSP_SETFMT		_IOWR('P',5, int) /* Selects ONE fmt*/
+#define SNDCTL_DSP_GETFMTS		_SIOR ('P',11, int) /* Returns a mask */
+#define SNDCTL_DSP_SETFMT		_SIOWR('P',5, int) /* Selects ONE fmt*/
 #	define AFMT_QUERY		0x00000000	/* Return current fmt */
 #	define AFMT_MU_LAW		0x00000001
 #	define AFMT_A_LAW		0x00000002
@@ -588,10 +614,10 @@
 			/* Note! 'bytes' could be more than fragments*fragsize */
 		} audio_buf_info;
 
-#define SNDCTL_DSP_GETOSPACE		_IOR ('P',12, audio_buf_info)
-#define SNDCTL_DSP_GETISPACE		_IOR ('P',13, audio_buf_info)
-#define SNDCTL_DSP_NONBLOCK		_IO  ('P',14)
-#define SNDCTL_DSP_GETCAPS		_IOR ('P',15, int)
+#define SNDCTL_DSP_GETOSPACE		_SIOR ('P',12, audio_buf_info)
+#define SNDCTL_DSP_GETISPACE		_SIOR ('P',13, audio_buf_info)
+#define SNDCTL_DSP_NONBLOCK		_SIO  ('P',14)
+#define SNDCTL_DSP_GETCAPS		_SIOR ('P',15, int)
 #	define DSP_CAP_REVISION		0x000000ff	/* Bits for revision level (0 to 255) */
 #	define DSP_CAP_DUPLEX		0x00000100	/* Full duplex record/playback */
 #	define DSP_CAP_REALTIME		0x00000200	/* Real time capability */
@@ -605,8 +631,8 @@
 #	define DSP_CAP_TRIGGER		0x00001000	/* Supports SETTRIGGER */
 #	define DSP_CAP_MMAP		0x00002000	/* Supports mmap() */
 
-#define SNDCTL_DSP_GETTRIGGER		_IOR ('P',16, int)
-#define SNDCTL_DSP_SETTRIGGER		_IOW ('P',16, int)
+#define SNDCTL_DSP_GETTRIGGER		_SIOR ('P',16, int)
+#define SNDCTL_DSP_SETTRIGGER		_SIOW ('P',16, int)
 #	define PCM_ENABLE_INPUT		0x00000001
 #	define PCM_ENABLE_OUTPUT	0x00000002
 
@@ -616,22 +642,22 @@
 		int ptr;	/* Current DMA pointer value */
 	} count_info;
 
-#define SNDCTL_DSP_GETIPTR		_IOR ('P',17, count_info)
-#define SNDCTL_DSP_GETOPTR		_IOR ('P',18, count_info)
+#define SNDCTL_DSP_GETIPTR		_SIOR ('P',17, count_info)
+#define SNDCTL_DSP_GETOPTR		_SIOR ('P',18, count_info)
 
 typedef struct buffmem_desc {
 		unsigned *buffer;
 		int size;
 	} buffmem_desc;
-#define SNDCTL_DSP_MAPINBUF		_IOR ('P', 19, buffmem_desc)
-#define SNDCTL_DSP_MAPOUTBUF		_IOR ('P', 20, buffmem_desc)
-#define SNDCTL_DSP_SETSYNCRO		_IO  ('P', 21)
-#define SNDCTL_DSP_SETDUPLEX		_IO  ('P', 22)
-
-#define SOUND_PCM_READ_RATE		_IOR ('P', 2, int)
-#define SOUND_PCM_READ_CHANNELS		_IOR ('P', 6, int)
-#define SOUND_PCM_READ_BITS		_IOR ('P', 5, int)
-#define SOUND_PCM_READ_FILTER		_IOR ('P', 7, int)
+#define SNDCTL_DSP_MAPINBUF		_SIOR ('P', 19, buffmem_desc)
+#define SNDCTL_DSP_MAPOUTBUF		_SIOR ('P', 20, buffmem_desc)
+#define SNDCTL_DSP_SETSYNCRO		_SIO  ('P', 21)
+#define SNDCTL_DSP_SETDUPLEX		_SIO  ('P', 22)
+
+#define SOUND_PCM_READ_RATE		_SIOR ('P', 2, int)
+#define SOUND_PCM_READ_CHANNELS		_SIOR ('P', 6, int)
+#define SOUND_PCM_READ_BITS		_SIOR ('P', 5, int)
+#define SOUND_PCM_READ_FILTER		_SIOR ('P', 7, int)
 
 /* Some alias names */
 #define SOUND_PCM_WRITE_BITS		SNDCTL_DSP_SETFMT
@@ -685,16 +711,16 @@
 		unsigned char data[4000];
 	} copr_msg;
 
-#define SNDCTL_COPR_RESET             _IO  ('C',  0)
-#define SNDCTL_COPR_LOAD	      _IOWR('C',  1, copr_buffer)
-#define SNDCTL_COPR_RDATA	      _IOWR('C',  2, copr_debug_buf)
-#define SNDCTL_COPR_RCODE	      _IOWR('C',  3, copr_debug_buf)
-#define SNDCTL_COPR_WDATA	      _IOW ('C',  4, copr_debug_buf)
-#define SNDCTL_COPR_WCODE	      _IOW ('C',  5, copr_debug_buf)
-#define SNDCTL_COPR_RUN		      _IOWR('C',  6, copr_debug_buf)
-#define SNDCTL_COPR_HALT	      _IOWR('C',  7, copr_debug_buf)
-#define SNDCTL_COPR_SENDMSG	      _IOWR('C',  8, copr_msg)
-#define SNDCTL_COPR_RCVMSG	      _IOR ('C',  9, copr_msg)
+#define SNDCTL_COPR_RESET             _SIO  ('C',  0)
+#define SNDCTL_COPR_LOAD	      _SIOWR('C',  1, copr_buffer)
+#define SNDCTL_COPR_RDATA	      _SIOWR('C',  2, copr_debug_buf)
+#define SNDCTL_COPR_RCODE	      _SIOWR('C',  3, copr_debug_buf)
+#define SNDCTL_COPR_WDATA	      _SIOW ('C',  4, copr_debug_buf)
+#define SNDCTL_COPR_WCODE	      _SIOW ('C',  5, copr_debug_buf)
+#define SNDCTL_COPR_RUN		      _SIOWR('C',  6, copr_debug_buf)
+#define SNDCTL_COPR_HALT	      _SIOWR('C',  7, copr_debug_buf)
+#define SNDCTL_COPR_SENDMSG	      _SIOWR('C',  8, copr_msg)
+#define SNDCTL_COPR_RCVMSG	      _SIOR ('C',  9, copr_msg)
 
 /*********************************************
  * IOCTL commands for /dev/mixer
@@ -740,15 +766,15 @@
 #define SOUND_ONOFF_MAX		30
 
 /* Note!	Number 31 cannot be used since the sign bit is reserved */
-
+#define SOUND_MIXER_NONE	31
 
 /*
  * The following unsupported macros are no longer functional.
  * Use SOUND_MIXER_PRIVATE# macros in future.
  */
-#define SOUND_MIXER_ENHANCE	31
-#define SOUND_MIXER_MUTE	31
-#define SOUND_MIXER_LOUD	31
+#define SOUND_MIXER_ENHANCE	SOUND_MIXER_NONE
+#define SOUND_MIXER_MUTE	SOUND_MIXER_NONE
+#define SOUND_MIXER_LOUD	SOUND_MIXER_NONE
 
 
 #define SOUND_DEVICE_LABELS	{"Vol  ", "Bass ", "Trebl", "Synth", "Pcm  ", "Spkr ", "Line ", \
@@ -793,7 +819,7 @@
 #define SOUND_MASK_ENHANCE	(1 << SOUND_MIXER_ENHANCE)
 #define SOUND_MASK_LOUD		(1 << SOUND_MIXER_LOUD)
 
-#define MIXER_READ(dev)		_IOR('M', dev, int)
+#define MIXER_READ(dev)		_SIOR('M', dev, int)
 #define SOUND_MIXER_READ_VOLUME		MIXER_READ(SOUND_MIXER_VOLUME)
 #define SOUND_MIXER_READ_BASS		MIXER_READ(SOUND_MIXER_BASS)
 #define SOUND_MIXER_READ_TREBLE		MIXER_READ(SOUND_MIXER_TREBLE)
@@ -823,7 +849,7 @@
 #define SOUND_MIXER_READ_STEREODEVS	MIXER_READ(SOUND_MIXER_STEREODEVS)
 #define SOUND_MIXER_READ_CAPS		MIXER_READ(SOUND_MIXER_CAPS)
 
-#define MIXER_WRITE(dev)		_IOWR('M', dev, int)
+#define MIXER_WRITE(dev)		_SIOWR('M', dev, int)
 #define SOUND_MIXER_WRITE_VOLUME	MIXER_WRITE(SOUND_MIXER_VOLUME)
 #define SOUND_MIXER_WRITE_BASS		MIXER_WRITE(SOUND_MIXER_BASS)
 #define SOUND_MIXER_WRITE_TREBLE	MIXER_WRITE(SOUND_MIXER_TREBLE)
@@ -853,9 +879,18 @@
 {
   char id[16];
   char name[32];
+  int  modify_counter;
+  int fillers[10];
 } mixer_info;
 
-#define SOUND_MIXER_INFO		_IOR ('M', 101, mixer_info)
+typedef struct _old_mixer_info /* Obsolete */
+{
+  char id[16];
+  char name[32];
+} _old_mixer_info;
+
+#define SOUND_MIXER_INFO		_SIOR ('M', 101, mixer_info)
+#define SOUND_OLD_MIXER_INFO		_SIOR ('M', 101, _old_mixer_info)
 
 /*
  * A mechanism for accessing "proprietary" mixer features. This method
@@ -865,17 +900,42 @@
  */
 typedef unsigned char mixer_record[128];
 
-#define SOUND_MIXER_ACCESS		_IOWR('M', 102, mixer_record)
+#define SOUND_MIXER_ACCESS		_SIOWR('M', 102, mixer_record)
 
 /*
  * The SOUND_MIXER_PRIVATE# commands can be redefined by low level drivers.
  * These features can be used when accessing device specific features.
  */
-#define SOUND_MIXER_PRIVATE1		_IOWR('M', 111, int)
-#define SOUND_MIXER_PRIVATE2		_IOWR('M', 112, int)
-#define SOUND_MIXER_PRIVATE3		_IOWR('M', 113, int)
-#define SOUND_MIXER_PRIVATE4		_IOWR('M', 114, int)
-#define SOUND_MIXER_PRIVATE5		_IOWR('M', 115, int)
+#define SOUND_MIXER_PRIVATE1		_SIOWR('M', 111, int)
+#define SOUND_MIXER_PRIVATE2		_SIOWR('M', 112, int)
+#define SOUND_MIXER_PRIVATE3		_SIOWR('M', 113, int)
+#define SOUND_MIXER_PRIVATE4		_SIOWR('M', 114, int)
+#define SOUND_MIXER_PRIVATE5		_SIOWR('M', 115, int)
+
+/*
+ * SOUND_MIXER_GETLEVELS and SOUND_MIXER_SETLEVELS calls can be used
+ * for querying current mixer settings from the driver and for loading
+ * default volume settings _prior_ activating the mixer (loading
+ * doesn't affect current state of the mixer hardware). These calls
+ * are for internal use only.
+ */
+
+typedef struct mixer_vol_table {
+  int num;	/* Index to volume table */
+  char name[32];
+  int levels[32];
+} mixer_vol_table;
+
+#define SOUND_MIXER_GETLEVELS		_SIOWR('M', 116, mixer_vol_table)
+#define SOUND_MIXER_SETLEVELS		_SIOWR('M', 117, mixer_vol_table)
+
+/* 
+ * An ioctl for identifying the driver version. It will return value
+ * of the SOUND_VERSION macro used when compiling the driver.
+ * This call was introduced in OSS version 3.6 and it will not work
+ * with earlier versions (returns EINVAL).
+ */
+#define OSS_GETVERSION			_SIOR ('M', 118, int)
 
 /*
  * Level 2 event types for /dev/sequencer
diff -u --recursive --new-file v2.1.5/linux/include/linux/ultrasound.h linux/include/linux/ultrasound.h
--- v2.1.5/linux/include/linux/ultrasound.h	Sun Jun 30 11:43:41 1996
+++ linux/include/linux/ultrasound.h	Tue Oct 29 09:31:12 1996
@@ -8,7 +8,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
diff -u --recursive --new-file v2.1.5/linux/ipc/msg.c linux/ipc/msg.c
--- v2.1.5/linux/ipc/msg.c	Wed Oct 16 10:48:30 1996
+++ linux/ipc/msg.c	Mon Oct 28 14:21:41 1996
@@ -16,7 +16,7 @@
 #include <linux/kerneld.h>
 #include <linux/interrupt.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 extern int ipcperms (struct ipc_perm *ipcp, short msgflg);
 
diff -u --recursive --new-file v2.1.5/linux/ipc/sem.c linux/ipc/sem.c
--- v2.1.5/linux/ipc/sem.c	Wed Oct 16 10:48:30 1996
+++ linux/ipc/sem.c	Mon Oct 28 14:21:41 1996
@@ -32,13 +32,14 @@
  */
 
 #include <linux/errno.h>
-#include <asm/segment.h>
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/sem.h>
 #include <linux/ipc.h>
 #include <linux/stat.h>
 #include <linux/malloc.h>
+
+#include <asm/uaccess.h>
 
 extern int ipcperms (struct ipc_perm *ipcp, short semflg);
 static int newary (key_t, int, int);
diff -u --recursive --new-file v2.1.5/linux/ipc/shm.c linux/ipc/shm.c
--- v2.1.5/linux/ipc/shm.c	Wed Oct 16 10:48:30 1996
+++ linux/ipc/shm.c	Mon Oct 28 14:21:41 1996
@@ -14,7 +14,7 @@
 #include <linux/malloc.h>
 #include <linux/swap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 extern int ipcperms (struct ipc_perm *ipcp, short shmflg);
diff -u --recursive --new-file v2.1.5/linux/ipc/util.c linux/ipc/util.c
--- v2.1.5/linux/ipc/util.c	Wed Jan 17 07:32:09 1996
+++ linux/ipc/util.c	Mon Oct 28 14:21:41 1996
@@ -5,13 +5,14 @@
 
 #include <linux/config.h>
 #include <linux/errno.h>
-#include <asm/segment.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/stat.h>
+
+#include <asm/uaccess.h>
 
 #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
 
diff -u --recursive --new-file v2.1.5/linux/kernel/exit.c linux/kernel/exit.c
--- v2.1.5/linux/kernel/exit.c	Fri Jul  5 13:48:39 1996
+++ linux/kernel/exit.c	Mon Oct 28 14:21:41 1996
@@ -17,7 +17,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 extern void sem_exit (void);
diff -u --recursive --new-file v2.1.5/linux/kernel/fork.c linux/kernel/fork.c
--- v2.1.5/linux/kernel/fork.c	Wed Sep 25 12:51:59 1996
+++ linux/kernel/fork.c	Mon Oct 28 14:21:41 1996
@@ -21,9 +21,9 @@
 #include <linux/malloc.h>
 #include <linux/smp.h>
 
-#include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
+#include <asm/uaccess.h>
 
 int nr_tasks=1;
 int nr_running=1;
diff -u --recursive --new-file v2.1.5/linux/kernel/info.c linux/kernel/info.c
--- v2.1.5/linux/kernel/info.c	Wed Oct 16 10:48:30 1996
+++ linux/kernel/info.c	Mon Oct 28 14:21:41 1996
@@ -6,14 +6,14 @@
 
 /* This implements the sysinfo() system call */
 
-#include <asm/segment.h>
-
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/unistd.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
+
+#include <asm/uaccess.h>
 
 asmlinkage int sys_sysinfo(struct sysinfo *info)
 {
diff -u --recursive --new-file v2.1.5/linux/kernel/itimer.c linux/kernel/itimer.c
--- v2.1.5/linux/kernel/itimer.c	Wed Oct 16 10:48:30 1996
+++ linux/kernel/itimer.c	Mon Oct 28 14:21:41 1996
@@ -13,7 +13,7 @@
 #include <linux/time.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /*
  * change timeval to jiffies, trying to avoid the 
diff -u --recursive --new-file v2.1.5/linux/kernel/module.c linux/kernel/module.c
--- v2.1.5/linux/kernel/module.c	Wed Oct 16 10:48:30 1996
+++ linux/kernel/module.c	Mon Oct 28 14:21:41 1996
@@ -1,6 +1,5 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <asm/segment.h>
 #include <linux/mm.h>		/* defines GFP_KERNEL */
 #include <linux/string.h>
 #include <linux/module.h>
@@ -8,6 +7,8 @@
 #include <linux/malloc.h>
 #include <linux/vmalloc.h>
 #include <linux/config.h>
+
+#include <asm/uaccess.h>
 /*
  * Originally by Anonymous (as far as I know...)
  * Linux version by Bas Laarhoven <bas@vimec.nl>
diff -u --recursive --new-file v2.1.5/linux/kernel/panic.c linux/kernel/panic.c
--- v2.1.5/linux/kernel/panic.c	Fri Apr 12 09:49:47 1996
+++ linux/kernel/panic.c	Mon Oct 28 14:27:07 1996
@@ -59,7 +59,7 @@
 }
 
 /*
- * GCC 2.5.8 doesn't always optimize correctly; see include/asm/segment.h
+ * GCC 2.5.8 doesn't always optimize correctly; see include/asm/uaccess.h
  */
 
 int bad_user_access_length(void)
diff -u --recursive --new-file v2.1.5/linux/kernel/printk.c linux/kernel/printk.c
--- v2.1.5/linux/kernel/printk.c	Fri Jun  7 11:54:06 1996
+++ linux/kernel/printk.c	Mon Oct 28 14:21:41 1996
@@ -13,7 +13,6 @@
 
 #include <stdarg.h>
 
-#include <asm/segment.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
@@ -22,6 +21,8 @@
 #include <linux/mm.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
+
+#include <asm/uaccess.h>
 
 #define LOG_BUF_LEN	8192
 
diff -u --recursive --new-file v2.1.5/linux/kernel/sched.c linux/kernel/sched.c
--- v2.1.5/linux/kernel/sched.c	Wed Oct 16 10:48:30 1996
+++ linux/kernel/sched.c	Mon Oct 28 14:21:41 1996
@@ -31,7 +31,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 
diff -u --recursive --new-file v2.1.5/linux/kernel/signal.c linux/kernel/signal.c
--- v2.1.5/linux/kernel/signal.c	Wed Oct 16 10:48:30 1996
+++ linux/kernel/signal.c	Mon Oct 28 14:21:41 1996
@@ -13,7 +13,7 @@
 #include <linux/unistd.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define _S(nr) (1<<((nr)-1))
 
diff -u --recursive --new-file v2.1.5/linux/kernel/sys.c linux/kernel/sys.c
--- v2.1.5/linux/kernel/sys.c	Wed Oct 16 10:48:30 1996
+++ linux/kernel/sys.c	Mon Oct 28 16:27:31 1996
@@ -25,7 +25,7 @@
 #include <linux/apm_bios.h>
 #endif
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 /*
@@ -776,18 +776,7 @@
 asmlinkage int sys_uname(struct old_utsname * name)
 {
 	int error = -EFAULT;;
-	if (!name &&
-	    !copy_to_user(&name->sysname,&system_utsname.sysname,
-		sizeof (system_utsname.sysname)) &&
-	    !copy_to_user(&name->nodename,&system_utsname.nodename,
-		sizeof (system_utsname.nodename)) &&
-	    !copy_to_user(&name->release,&system_utsname.release,
-		sizeof (system_utsname.release)) &&
-	    !copy_to_user(&name->version,&system_utsname.version,
-		sizeof (system_utsname.version)) &&
-	    !copy_to_user(&name->machine,&system_utsname.machine,
-		sizeof (system_utsname.machine))
-	)
+	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
 		error = 0;
 	return error;
 }
diff -u --recursive --new-file v2.1.5/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.1.5/linux/kernel/sysctl.c	Wed Oct 16 10:48:30 1996
+++ linux/kernel/sysctl.c	Mon Oct 28 14:21:41 1996
@@ -17,11 +17,11 @@
 #include <linux/malloc.h>
 #include <linux/stat.h>
 #include <linux/ctype.h>
-#include <asm/bitops.h>
-#include <asm/segment.h>
-
 #include <linux/utsname.h>
 #include <linux/swapctl.h>
+
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
 
 /* External variables not in a header file. */
 extern int panic_timeout;
diff -u --recursive --new-file v2.1.5/linux/kernel/time.c linux/kernel/time.c
--- v2.1.5/linux/kernel/time.c	Wed Oct 16 10:48:30 1996
+++ linux/kernel/time.c	Mon Oct 28 18:02:58 1996
@@ -26,7 +26,7 @@
 #include <linux/mm.h>
 #include <linux/timex.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /* 
  * The timezone where the local system is located.  Used as a default by some
diff -u --recursive --new-file v2.1.5/linux/mm/filemap.c linux/mm/filemap.c
--- v2.1.5/linux/mm/filemap.c	Sat Oct 19 10:07:32 1996
+++ linux/mm/filemap.c	Mon Oct 28 14:21:41 1996
@@ -23,9 +23,9 @@
 #include <linux/pagemap.h>
 #include <linux/swap.h>
 
-#include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
+#include <asm/uaccess.h>
 
 /*
  * Shared mappings implemented 30.11.1994. It's not fully working yet,
diff -u --recursive --new-file v2.1.5/linux/mm/memory.c linux/mm/memory.c
--- v2.1.5/linux/mm/memory.c	Wed Oct 16 10:48:30 1996
+++ linux/mm/memory.c	Mon Oct 28 14:21:41 1996
@@ -46,7 +46,7 @@
 #include <linux/swap.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/string.h>
 
diff -u --recursive --new-file v2.1.5/linux/mm/mlock.c linux/mm/mlock.c
--- v2.1.5/linux/mm/mlock.c	Wed Oct 16 10:48:30 1996
+++ linux/mm/mlock.c	Mon Oct 28 14:21:41 1996
@@ -13,7 +13,7 @@
 #include <linux/string.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.5/linux/mm/mmap.c linux/mm/mmap.c
--- v2.1.5/linux/mm/mmap.c	Wed Oct 16 10:48:30 1996
+++ linux/mm/mmap.c	Mon Oct 28 14:21:41 1996
@@ -15,7 +15,7 @@
 #include <linux/pagemap.h>
 #include <linux/swap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.5/linux/mm/mprotect.c linux/mm/mprotect.c
--- v2.1.5/linux/mm/mprotect.c	Mon Sep  9 21:04:57 1996
+++ linux/mm/mprotect.c	Mon Oct 28 14:21:41 1996
@@ -13,7 +13,7 @@
 #include <linux/string.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.5/linux/mm/mremap.c linux/mm/mremap.c
--- v2.1.5/linux/mm/mremap.c	Mon Sep  9 21:04:57 1996
+++ linux/mm/mremap.c	Mon Oct 28 14:21:41 1996
@@ -15,7 +15,7 @@
 #include <linux/malloc.h>
 #include <linux/swap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.5/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.1.5/linux/mm/page_alloc.c	Wed Oct 16 10:48:30 1996
+++ linux/mm/page_alloc.c	Mon Oct 28 14:21:41 1996
@@ -20,7 +20,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for copy_to/from_user */
+#include <asm/uaccess.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.5/linux/mm/page_io.c linux/mm/page_io.c
--- v2.1.5/linux/mm/page_io.c	Wed Oct 16 10:48:30 1996
+++ linux/mm/page_io.c	Mon Oct 28 14:21:41 1996
@@ -23,7 +23,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for copy_to/from_user */
+#include <asm/uaccess.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.5/linux/mm/swap.c linux/mm/swap.c
--- v2.1.5/linux/mm/swap.c	Wed Oct 16 10:48:30 1996
+++ linux/mm/swap.c	Mon Oct 28 14:21:41 1996
@@ -26,7 +26,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for copy_to/from_user */
+#include <asm/uaccess.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.5/linux/mm/swap_state.c linux/mm/swap_state.c
--- v2.1.5/linux/mm/swap_state.c	Wed Oct 16 10:48:30 1996
+++ linux/mm/swap_state.c	Mon Oct 28 14:21:41 1996
@@ -19,7 +19,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for cop_to/from_user */
+#include <asm/uaccess.h> /* for cop_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.5/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.1.5/linux/mm/swapfile.c	Wed Oct 16 10:48:30 1996
+++ linux/mm/swapfile.c	Mon Oct 28 14:21:41 1996
@@ -21,7 +21,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for copy_to/from_user */
+#include <asm/uaccess.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.5/linux/mm/vmalloc.c linux/mm/vmalloc.c
--- v2.1.5/linux/mm/vmalloc.c	Wed Sep 25 14:33:57 1996
+++ linux/mm/vmalloc.c	Mon Oct 28 14:21:41 1996
@@ -7,7 +7,7 @@
 #include <linux/malloc.h>
 #include <linux/vmalloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 static struct vm_struct * vmlist = NULL;
diff -u --recursive --new-file v2.1.5/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.1.5/linux/mm/vmscan.c	Wed Oct 16 10:48:30 1996
+++ linux/mm/vmscan.c	Mon Oct 28 14:21:41 1996
@@ -23,7 +23,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for copy_to/from_user */
+#include <asm/uaccess.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.5/linux/net/802/tr.c linux/net/802/tr.c
--- v2.1.5/linux/net/802/tr.c	Mon Jul 31 09:46:27 1995
+++ linux/net/802/tr.c	Mon Oct 28 14:29:28 1996
@@ -1,4 +1,4 @@
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.5/linux/net/appletalk/aarp.c linux/net/appletalk/aarp.c
--- v2.1.5/linux/net/appletalk/aarp.c	Mon May 13 12:15:23 1996
+++ linux/net/appletalk/aarp.c	Mon Oct 28 14:29:28 1996
@@ -23,7 +23,7 @@
  *		Inside Appletalk (2nd Ed).
  */
  
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.1.5/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v2.1.5/linux/net/appletalk/ddp.c	Wed Oct 16 10:48:30 1996
+++ linux/net/appletalk/ddp.c	Mon Oct 28 22:19:15 1996
@@ -35,7 +35,7 @@
  
 #include <linux/config.h>
 #include <linux/module.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/types.h>
@@ -1024,10 +1024,9 @@
 	if(optval==NULL)
 		return(-EINVAL);
 
-	err=verify_area(VERIFY_READ,optval,sizeof(int));
-	if(err)
+	err = get_user(opt, (int *)optval);
+	if (err)
 		return err;
-	opt=get_fs_long((unsigned long *)optval);
 	
 	switch(level)
 	{
diff -u --recursive --new-file v2.1.5/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.1.5/linux/net/ax25/af_ax25.c	Wed Oct 16 10:48:31 1996
+++ linux/net/ax25/af_ax25.c	Mon Oct 28 14:29:28 1996
@@ -107,7 +107,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>	/* For TIOCINQ/OUTQ */
diff -u --recursive --new-file v2.1.5/linux/net/ax25/ax25_in.c linux/net/ax25/ax25_in.c
--- v2.1.5/linux/net/ax25/ax25_in.c	Wed Aug  7 08:41:57 1996
+++ linux/net/ax25/ax25_in.c	Mon Oct 28 14:29:28 1996
@@ -54,7 +54,7 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/ip.h>			/* For ip_rcv */
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.5/linux/net/ax25/ax25_out.c linux/net/ax25/ax25_out.c
--- v2.1.5/linux/net/ax25/ax25_out.c	Wed Aug  7 08:41:57 1996
+++ linux/net/ax25/ax25_out.c	Mon Oct 28 14:29:28 1996
@@ -48,7 +48,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.5/linux/net/ax25/ax25_route.c linux/net/ax25/ax25_route.c
--- v2.1.5/linux/net/ax25/ax25_route.c	Wed Oct 16 10:48:31 1996
+++ linux/net/ax25/ax25_route.c	Mon Oct 28 14:29:28 1996
@@ -58,7 +58,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.5/linux/net/ax25/ax25_subr.c linux/net/ax25/ax25_subr.c
--- v2.1.5/linux/net/ax25/ax25_subr.c	Wed Aug  7 08:41:57 1996
+++ linux/net/ax25/ax25_subr.c	Mon Oct 28 14:29:28 1996
@@ -51,7 +51,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.5/linux/net/ax25/ax25_timer.c linux/net/ax25/ax25_timer.c
--- v2.1.5/linux/net/ax25/ax25_timer.c	Wed Aug  7 08:41:57 1996
+++ linux/net/ax25/ax25_timer.c	Mon Oct 28 14:29:28 1996
@@ -38,7 +38,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.5/linux/net/bridge/br.c linux/net/bridge/br.c
--- v2.1.5/linux/net/bridge/br.c	Wed Oct 16 10:48:31 1996
+++ linux/net/bridge/br.c	Mon Oct 28 14:29:28 1996
@@ -36,7 +36,7 @@
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <net/br.h>
 
diff -u --recursive --new-file v2.1.5/linux/net/core/datagram.c linux/net/core/datagram.c
--- v2.1.5/linux/net/core/datagram.c	Wed Oct 16 10:48:31 1996
+++ linux/net/core/datagram.c	Mon Oct 28 14:29:28 1996
@@ -24,7 +24,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.1.5/linux/net/core/dev.c linux/net/core/dev.c
--- v2.1.5/linux/net/core/dev.c	Wed Oct 16 10:48:31 1996
+++ linux/net/core/dev.c	Tue Oct 29 15:33:39 1996
@@ -50,7 +50,7 @@
  *
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/config.h>
@@ -1366,6 +1366,7 @@
 extern int lance_init(void);
 extern int ni65_init(void);
 extern int pi_init(void);
+extern int scc_init(void);
 extern void sdla_setup(void);
 extern void dlci_setup(void);
 
@@ -1407,6 +1408,9 @@
 #if defined(CONFIG_PI)
 	pi_init();
 #endif	
+#if defined(CONFIG_SCC)
+	scc_init();
+#endif
 #if defined(CONFIG_PT)
 	pt_init();
 #endif
diff -u --recursive --new-file v2.1.5/linux/net/core/dev_mcast.c linux/net/core/dev_mcast.c
--- v2.1.5/linux/net/core/dev_mcast.c	Fri Nov 24 16:39:54 1995
+++ linux/net/core/dev_mcast.c	Mon Oct 28 14:29:28 1996
@@ -20,7 +20,7 @@
  *	2 of the License, or (at your option) any later version.
  */
  
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.1.5/linux/net/core/iovec.c linux/net/core/iovec.c
--- v2.1.5/linux/net/core/iovec.c	Wed Oct 16 10:48:31 1996
+++ linux/net/core/iovec.c	Mon Oct 28 14:29:28 1996
@@ -17,7 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/net.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 
 extern inline int min(int x, int y)
diff -u --recursive --new-file v2.1.5/linux/net/core/skbuff.c linux/net/core/skbuff.c
--- v2.1.5/linux/net/core/skbuff.c	Thu Jun  6 09:45:39 1996
+++ linux/net/core/skbuff.c	Mon Oct 28 14:29:29 1996
@@ -52,7 +52,7 @@
 #include <net/udp.h>
 #include <net/sock.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 /*
diff -u --recursive --new-file v2.1.5/linux/net/core/sock.c linux/net/core/sock.c
--- v2.1.5/linux/net/core/sock.c	Wed Oct 16 10:48:31 1996
+++ linux/net/core/sock.c	Mon Oct 28 14:29:29 1996
@@ -97,7 +97,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/inet.h>
diff -u --recursive --new-file v2.1.5/linux/net/ethernet/eth.c linux/net/ethernet/eth.c
--- v2.1.5/linux/net/ethernet/eth.c	Sat Aug  3 11:46:51 1996
+++ linux/net/ethernet/eth.c	Mon Oct 28 14:29:29 1996
@@ -36,7 +36,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  */
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.1.5/linux/net/ipv4/af_inet.c	Sat Oct 19 10:07:32 1996
+++ linux/net/ipv4/af_inet.c	Mon Oct 28 14:29:29 1996
@@ -75,7 +75,7 @@
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/inet.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.1.5/linux/net/ipv4/arp.c	Wed Oct 16 10:48:31 1996
+++ linux/net/ipv4/arp.c	Mon Oct 28 14:29:29 1996
@@ -113,7 +113,7 @@
 #endif
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <stdarg.h>
 
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.1.5/linux/net/ipv4/devinet.c	Tue May  7 15:22:30 1996
+++ linux/net/ipv4/devinet.c	Mon Oct 28 14:29:29 1996
@@ -17,7 +17,7 @@
 
 #include <linux/config.h>	/* For CONFIG_IP_CLASSLESS */
  
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.1.5/linux/net/ipv4/icmp.c	Sat Oct  5 16:58:36 1996
+++ linux/net/ipv4/icmp.c	Mon Oct 28 14:29:30 1996
@@ -256,7 +256,7 @@
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <net/checksum.h>
 
 #define min(a,b)	((a)<(b)?(a):(b))
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/igmp.c linux/net/ipv4/igmp.c
--- v2.1.5/linux/net/ipv4/igmp.c	Sat Aug 17 20:28:10 1996
+++ linux/net/ipv4/igmp.c	Mon Oct 28 14:29:30 1996
@@ -64,7 +64,7 @@
  */
 
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c
--- v2.1.5/linux/net/ipv4/ip_fragment.c	Wed Aug  7 14:00:08 1996
+++ linux/net/ipv4/ip_fragment.c	Sat Oct 19 10:08:12 1996
@@ -366,7 +366,7 @@
 		{
 			NETDEBUG(printk("Invalid fragment list: Fragment over size.\n"));
 			ip_free(qp);
-			frag_kfree_skb(skb,FREE_WRITE);
+			kfree_skb(skb,FREE_WRITE);
 			ip_statistics.IpReasmFails++;
 			return NULL;
 		}
@@ -466,6 +466,18 @@
 			return NULL;
 		}
 	}
+	
+	/*
+	 *	Attempt to construct an oversize packet.
+	 */
+	 
+	if(ntohs(iph->tot_len)+(int)offset>65535)
+	{
+		skb->sk = NULL;
+		frag_kfree_skb(skb, FREE_READ);
+		ip_statistics.IpReasmFails++;
+		return NULL;
+	}	
 
 	/*
 	 *	Determine the position of this fragment.
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- v2.1.5/linux/net/ipv4/ip_fw.c	Thu Oct 10 19:10:58 1996
+++ linux/net/ipv4/ip_fw.c	Mon Oct 28 14:29:30 1996
@@ -79,7 +79,7 @@
  */
 
 #include <linux/config.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -149,7 +149,9 @@
 
 static struct ip_fw **chains[] =
 	{&ip_fw_fwd_chain, &ip_fw_in_chain, &ip_fw_out_chain, &ip_acct_chain};
+#endif /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
 
+#ifdef CONFIG_IP_FIREWALL
 int ip_fw_fwd_policy=IP_FW_F_ACCEPT;
 int ip_fw_in_policy=IP_FW_F_ACCEPT;
 int ip_fw_out_policy=IP_FW_F_ACCEPT;
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c
--- v2.1.5/linux/net/ipv4/ip_input.c	Thu Jun  6 21:22:24 1996
+++ linux/net/ipv4/ip_input.c	Mon Oct 28 14:29:30 1996
@@ -117,7 +117,7 @@
  *		2 of the License, or (at your option) any later version.
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- v2.1.5/linux/net/ipv4/ip_output.c	Thu Oct 10 19:10:58 1996
+++ linux/net/ipv4/ip_output.c	Mon Oct 28 14:29:30 1996
@@ -28,7 +28,7 @@
  *					output firewall rules)
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/ip_sockglue.c linux/net/ipv4/ip_sockglue.c
--- v2.1.5/linux/net/ipv4/ip_sockglue.c	Wed Oct 16 10:48:31 1996
+++ linux/net/ipv4/ip_sockglue.c	Mon Oct 28 14:29:30 1996
@@ -34,7 +34,7 @@
 #include <linux/mroute.h>
 #include <net/route.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #ifdef CONFIG_IP_MULTICAST
 
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v2.1.5/linux/net/ipv4/ipmr.c	Wed Oct 16 10:48:31 1996
+++ linux/net/ipv4/ipmr.c	Mon Oct 28 14:29:30 1996
@@ -29,7 +29,7 @@
 
 #include <linux/config.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/packet.c linux/net/ipv4/packet.c
--- v2.1.5/linux/net/ipv4/packet.c	Mon May  6 12:26:17 1996
+++ linux/net/ipv4/packet.c	Mon Oct 28 14:29:30 1996
@@ -58,7 +58,7 @@
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /*
  *	We really ought to have a single public _inline_ min function!
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/protocol.c linux/net/ipv4/protocol.c
--- v2.1.5/linux/net/ipv4/protocol.c	Mon Sep 11 20:16:03 1995
+++ linux/net/ipv4/protocol.c	Mon Oct 28 14:29:30 1996
@@ -23,7 +23,7 @@
  *		2 of the License, or (at your option) any later version.
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/rarp.c linux/net/ipv4/rarp.c
--- v2.1.5/linux/net/ipv4/rarp.c	Wed Oct 16 10:48:31 1996
+++ linux/net/ipv4/rarp.c	Mon Oct 28 14:29:30 1996
@@ -47,7 +47,7 @@
 #include <linux/config.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <stdarg.h>
 #include <linux/inet.h>
 #include <linux/etherdevice.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/raw.c linux/net/ipv4/raw.c
--- v2.1.5/linux/net/ipv4/raw.c	Wed Oct 16 10:48:31 1996
+++ linux/net/ipv4/raw.c	Mon Oct 28 14:29:30 1996
@@ -39,7 +39,7 @@
  
 #include <linux/config.h> 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.1.5/linux/net/ipv4/route.c	Wed Oct 16 10:48:31 1996
+++ linux/net/ipv4/route.c	Mon Oct 28 14:29:30 1996
@@ -50,7 +50,7 @@
  */
 
 #include <linux/config.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.1.5/linux/net/ipv4/tcp.c	Wed Oct 16 10:48:32 1996
+++ linux/net/ipv4/tcp.c	Mon Oct 28 14:29:31 1996
@@ -433,7 +433,7 @@
 #include <net/icmp.h>
 #include <net/tcp.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 unsigned long seq_offset;
 struct tcp_mib	tcp_statistics;
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.1.5/linux/net/ipv4/udp.c	Wed Oct 16 10:48:32 1996
+++ linux/net/ipv4/udp.c	Mon Oct 28 14:29:31 1996
@@ -84,7 +84,7 @@
 */
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/fcntl.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipv4/utils.c linux/net/ipv4/utils.c
--- v2.1.5/linux/net/ipv4/utils.c	Tue Aug  1 10:02:49 1995
+++ linux/net/ipv4/utils.c	Mon Oct 28 14:29:31 1996
@@ -21,7 +21,7 @@
  *		2 of the License, or (at your option) any later version.
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.5/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v2.1.5/linux/net/ipx/af_ipx.c	Wed Oct 16 10:48:32 1996
+++ linux/net/ipx/af_ipx.c	Mon Oct 28 21:58:58 1996
@@ -77,7 +77,7 @@
 #include <linux/inet.h>
 #include <linux/route.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
@@ -1035,18 +1035,15 @@
 static int 
 ipxitf_ioctl_real(unsigned int cmd, void *arg)
 {
-	int err;
 	switch(cmd)
 	{
-		case SIOCSIFADDR:
-		{
+		case SIOCSIFADDR: {
 			struct ifreq ifr;
 			struct sockaddr_ipx *sipx;
 			ipx_interface_definition f;
-			err=verify_area(VERIFY_READ,arg,sizeof(ifr));
-			if(err)
-				return err;
-			copy_from_user(&ifr,arg,sizeof(ifr));
+
+			if (copy_from_user(&ifr,arg,sizeof(ifr)))
+				return -EFAULT;
 			sipx=(struct sockaddr_ipx *)&ifr.ifr_addr;
 			if(sipx->sipx_family!=AF_IPX)
 				return -EINVAL;
@@ -1060,16 +1057,14 @@
 			else
 				return ipxitf_create(&f);
 		}
-		case SIOCGIFADDR:
-		{
+		case SIOCGIFADDR: {
 			struct ifreq ifr;
 			struct sockaddr_ipx *sipx;
 			ipx_interface *ipxif;
 			struct device *dev;
-			err=verify_area(VERIFY_WRITE,arg,sizeof(ifr));
-			if(err)
-				return err;
-			copy_from_user(&ifr,arg,sizeof(ifr));
+
+			if (copy_from_user(&ifr,arg,sizeof(ifr)))
+				return -EFAULT;
 			sipx=(struct sockaddr_ipx *)&ifr.ifr_addr;
 			dev=dev_get(ifr.ifr_name);
 			if(!dev)
@@ -1080,19 +1075,24 @@
 			sipx->sipx_family=AF_IPX;
 			sipx->sipx_network=ipxif->if_netnum;
 			memcpy(sipx->sipx_node, ipxif->if_node, sizeof(sipx->sipx_node));
-			copy_to_user(arg,&ifr,sizeof(ifr));
+			if (copy_to_user(arg,&ifr,sizeof(ifr)))
+				return -EFAULT;
 			return 0;
 		}
-		case SIOCAIPXITFCRT:
-			err=verify_area(VERIFY_READ,arg,sizeof(char));
-			if(err)
+		case SIOCAIPXITFCRT: {
+			int err, val;
+			err = get_user(val, (unsigned char *) arg);
+			if (err)
 				return err;
-			return ipxcfg_set_auto_create(get_fs_byte(arg));
-		case SIOCAIPXPRISLT:
-			err=verify_area(VERIFY_READ,arg,sizeof(char));
-			if(err)
+			return ipxcfg_set_auto_create(val);
+		}
+		case SIOCAIPXPRISLT: {
+			int err, val;
+			err = get_user(val, (unsigned char *) arg);
+			if (err)
 				return err;
-			return ipxcfg_set_auto_select(get_fs_byte(arg));
+			return ipxcfg_set_auto_select(val);
+		}
 		default:
 			return -EINVAL;
 	}
@@ -1620,13 +1620,12 @@
 	
 	sk=(ipx_socket *)sock->data;
 	
-	if(optval==NULL)
+	if (optval==NULL)
 		return(-EINVAL);
 
-	err=verify_area(VERIFY_READ,optval,sizeof(int));
-	if(err)
+	err = get_user(opt, (unsigned int *)optval);
+	if (err)
 		return err;
-	opt=get_fs_long((unsigned long *)optval);
 	
 	switch(level)
 	{
diff -u --recursive --new-file v2.1.5/linux/net/netlink.c linux/net/netlink.c
--- v2.1.5/linux/net/netlink.c	Wed Oct 16 10:48:32 1996
+++ linux/net/netlink.c	Mon Oct 28 14:21:41 1996
@@ -27,7 +27,7 @@
 #include <net/netlink.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 static int (*netlink_handler[MAX_LINKS])(struct sk_buff *skb);
diff -u --recursive --new-file v2.1.5/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v2.1.5/linux/net/netrom/af_netrom.c	Wed Oct 16 10:48:32 1996
+++ linux/net/netrom/af_netrom.c	Mon Oct 28 14:29:31 1996
@@ -47,7 +47,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>	/* For TIOCINQ/OUTQ */
diff -u --recursive --new-file v2.1.5/linux/net/netrom/nr_dev.c linux/net/netrom/nr_dev.c
--- v2.1.5/linux/net/netrom/nr_dev.c	Mon May 13 12:15:24 1996
+++ linux/net/netrom/nr_dev.c	Mon Oct 28 14:29:32 1996
@@ -34,7 +34,7 @@
 #include <linux/if_ether.h>	/* For the statistics structure. */
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 #include <linux/inet.h>
diff -u --recursive --new-file v2.1.5/linux/net/netrom/nr_in.c linux/net/netrom/nr_in.c
--- v2.1.5/linux/net/netrom/nr_in.c	Mon May 13 12:15:24 1996
+++ linux/net/netrom/nr_in.c	Mon Oct 28 14:29:34 1996
@@ -43,7 +43,7 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/ip.h>			/* For ip_rcv */
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.5/linux/net/netrom/nr_out.c linux/net/netrom/nr_out.c
--- v2.1.5/linux/net/netrom/nr_out.c	Wed Aug  7 08:41:57 1996
+++ linux/net/netrom/nr_out.c	Mon Oct 28 14:29:34 1996
@@ -35,7 +35,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.5/linux/net/netrom/nr_route.c linux/net/netrom/nr_route.c
--- v2.1.5/linux/net/netrom/nr_route.c	Wed Oct 16 10:48:32 1996
+++ linux/net/netrom/nr_route.c	Mon Oct 28 14:29:35 1996
@@ -41,7 +41,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>	/* For TIOCINQ/OUTQ */
diff -u --recursive --new-file v2.1.5/linux/net/netrom/nr_subr.c linux/net/netrom/nr_subr.c
--- v2.1.5/linux/net/netrom/nr_subr.c	Mon May 13 12:15:24 1996
+++ linux/net/netrom/nr_subr.c	Mon Oct 28 14:29:35 1996
@@ -34,7 +34,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.5/linux/net/netrom/nr_timer.c linux/net/netrom/nr_timer.c
--- v2.1.5/linux/net/netrom/nr_timer.c	Fri Apr 12 09:49:51 1996
+++ linux/net/netrom/nr_timer.c	Mon Oct 28 14:29:35 1996
@@ -33,7 +33,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.1.5/linux/net/socket.c linux/net/socket.c
--- v2.1.5/linux/net/socket.c	Wed Oct 16 10:48:33 1996
+++ linux/net/socket.c	Mon Oct 28 14:21:41 1996
@@ -74,7 +74,7 @@
 #include <net/netlink.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #if defined(CONFIG_MODULES) && defined(CONFIG_NET)
 extern void export_net_symbols(void);
diff -u --recursive --new-file v2.1.5/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.1.5/linux/net/unix/af_unix.c	Wed Oct 16 10:48:33 1996
+++ linux/net/unix/af_unix.c	Mon Oct 28 14:29:35 1996
@@ -63,7 +63,7 @@
 #include <linux/in.h>
 #include <linux/fs.h>
 #include <linux/malloc.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <net/sock.h>
diff -u --recursive --new-file v2.1.5/linux/net/unix/garbage.c linux/net/unix/garbage.c
--- v2.1.5/linux/net/unix/garbage.c	Mon May 13 15:31:18 1996
+++ linux/net/unix/garbage.c	Mon Oct 28 14:29:35 1996
@@ -49,7 +49,7 @@
 #include <linux/in.h>
 #include <linux/fs.h>
 #include <linux/malloc.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <net/sock.h>
diff -u --recursive --new-file v2.1.5/linux/scripts/Menuconfig linux/scripts/Menuconfig
--- v2.1.5/linux/scripts/Menuconfig	Mon Sep 16 13:07:00 1996
+++ linux/scripts/Menuconfig	Tue Oct 29 17:38:07 1996
@@ -860,11 +860,11 @@
 
 #
 # Load config options from a file.
-# Converts all "# OPTION is not set" lines to "OPTION=" lines
+# Converts all "# OPTION is not set" lines to "OPTION=n" lines
 #
 function load_config_file () {
 	awk '
-	  /# .* is not set.*/ { printf("%s=\n", $2) }
+	  /# .* is not set.*/ { printf("%s=n\n", $2) }
 	! /# .* is not set.*/ { print }
 	' $1 >.tmpconfig
 
@@ -1119,12 +1119,12 @@
 Please enter a hexadecimal value. \
 Use the <TAB> key to move from the input field to the buttons below it."
 
-backtitle="Linux Kernel Configuration"
-
 DIALOG="./scripts/lxdialog/lxdialog"
 
 kernel_version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}"
 
+backtitle="Linux Kernel v$kernel_version Configuration"
+
 trap "cleanup ; rm -f .menuconfig ; exit 1" 1 2 15
 
 
@@ -1146,7 +1146,7 @@
   echo "#"
   echo "# Using defaults found in" $DEFAULTS
   echo "#"
-  . $DEFAULTS
+  load_config_file $DEFAULTS
 else
   echo "#"
   echo "# No defaults found"
