diff -u --recursive --new-file v1.3.62/linux/CREDITS linux/CREDITS
--- v1.3.62/linux/CREDITS	Fri Feb  9 17:52:54 1996
+++ linux/CREDITS	Mon Feb 12 06:49:38 1996
@@ -366,6 +366,13 @@
 E: philipg@onsett.com
 D: Kernel / timekeeping stuff
 
+N: Danny ter Haar
+E: dth@cistron.nl
+D: /proc/procinfo, reboot on panic , kernel pre-patch tester ;)
+S: PObox 297
+S: 2400 AG, Alphen aan den Rijn
+S: The Netherlands
+
 N: Bruno Haible
 E: haible@ma2s2.mathematik.uni-karlsruhe.de
 D: Unified SysV FS based on Xenix FS (part of standard kernel since 0.99.15)
diff -u --recursive --new-file v1.3.62/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v1.3.62/linux/Documentation/Configure.help	Fri Feb  9 17:52:55 1996
+++ linux/Documentation/Configure.help	Tue Feb 13 10:30:24 1996
@@ -70,80 +70,138 @@
   Most normal users won't need the RAM disk functionality, and can thus say 
   N here.
 
-Normal (MFM/RLL) disk and IDE disk/cdrom support
-CONFIG_ST506   		           
-  This is the regular, non-SCSI harddisk support. Pretty much everyone
-  will want to say Y here, except if they configure a diskless machine
-  which mounts all files over the network using NFS (rare; if you are
-  planning to do this, have a look at the package
-  /pub/Linux/system/Linux-boot/netboot-nfs.tar.gz, available via ftp
-  (user: anonymous) from sunsite.unc.edu, extract with "tar xzvf
-  filename") or if they exclusively use SCSI drives and no IDE/ATAPI
-  CDROMs (ATAPI = AT Attachment Packet Interface is a new protocol
-  currently used for controlling CDROM and tape drives, similar to the
-  SCSI protocol. Some newer CDROM drives such as NEC 260 and MITSUMI
-  triple/quad speed drives use it, but most MITSUMI CDROM drives
-  don't).  Useful information about how to use large (>504MB) IDE
-  harddrives and how to work around a hardware bug in the CMD640 IDE
-  interface is contained in drivers/block/README.ide. To fine-tune
-  the parameters of your IDE drive for improved performance, you might
-  want to have a look at the hdparm package in
-  sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/
-	
-Use old (reliable) disk-only driver for primary i/f
-CONFIG_BLK_DEV_HD
-  As you might have guessed, there are now two drivers for IDE
-  harddrives around: the old one and the new improved one. The old one
-  is not any longer more reliable than the new one. The new driver can
-  also handle IDE/ATAPI CDROM and tape drives (ATAPI = AT Attachment Packet
-  Interface is a new protocol currently used for controlling CDROM and
-  tape drives, similar to the SCSI protocol. Some newer CDROM drives
-  such as NEC 260 and MITSUMI triple/quad speed drives use it, but
-  most MITSUMI CDROM drives don't). The old driver supports up to two
-  hard drives, while the new one can deal with any mix of up to eight
-  hard drives and IDE/ATAPI CDROMs, two per IDE interface. Using the
-  old driver makes sense if you have older MFM/RLL/ESDI drives, since
-  it is smaller and these drives don't benefit from the additional
-  features of the new driver. If you have more than one IDE interface
-  (=controller), you can use the old driver on the first and the new
-  one on the others, if you like.  In that case (or if you have just
-  one interface and don't want to use the new driver at all) you would
-  say Y here, thereby enlarging your kernel by about 4 kB. If you want
-  to use the new driver exclusively, say N and answer Y to the
-  following question(s). Useful information about how to use large
-  (>504MB) IDE harddrives is contained in drivers/block/README.ide. If
-  unsure, say N.
-
-Use new IDE driver for primary/secondary i/f 
+Enhanced IDE/MFM/RLL disk/cdrom/tape support
 CONFIG_BLK_DEV_IDE 
-  This will use the new and improved IDE driver for the specified IDE
-  interface (=controller).  You can use up to 8 IDE harddisks and
-  IDE/ATAPI CDROMs, 2 per interface. (ATAPI = AT Attachment Packet
-  Interface is a new protocol currently used for controlling CDROM and
-  tape drives, similar to the SCSI protocol. Some newer CDROM drives
-  such as NEC 260 and MITSUMI triple/quad speed drives use it, but
-  most MITSUMI CDROM drives don't.) If you have just one IDE harddisk
-  and no IDE/ATAPI CDROM drive and you intend to use the old IDE
-  driver on the primary interface, say N here. Everybody else says
-  Y. This driver enlarges your kernel by about 8kB. Useful information
-  about how to use large (>504MB) IDE harddrives and how to use more
-  than 2 IDE interfaces is contained in drivers/block/README.ide.
+  This will use the full-featured IDE driver to control up to four IDE
+  interfaces, for a combination of up to eight IDE disk/cdrom/tape drives.
+  Useful information about large (>540MB) IDE disks, soundcard IDE ports,
+  and other topics, is all contained in drivers/block/README.ide.
+  If you have one or more IDE drives, say Y here.
+  If your system has no IDE drives, or if memory requirements are really tight,
+  you could say N here, and select the Old harddisk driver instead to save
+  about 13kB of memory in the kernel.  
+  To fine-tune IDE drive/interface parameters for improved performance,
+  look for the hdparm package at
+  sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/
 
-Include support for IDE/ATAPI CDROMs
+Old harddisk (MFM/RLL/IDE) driver
+CONFIG_BLK_DEV_HD_ONLY
+  There are two drivers for MFM/RLL/IDE disks.  Most people use the
+  newer enhanced driver, but the old one is still around for two reasons.
+  Some older systems have strange timing problems and seem to work only
+  with the old driver (which itself does not work with some newer systems).
+  The other reason is that the old driver is smaller, since it lacks the
+  enhanced functionality of the new one.  This makes it a good choice
+  for systems with very tight memory restrictions, or for systems with
+  only older MFM/RLL/ESDI drives.  Choosing the old driver can save 13kB
+  or so of kernel memory.  If you are unsure, then just choose the
+  Enhanced IDE/MFM/RLL driver instead of this one.
+
+Use old disk-only driver on primary interface
+CONFIG_BLK_DEV_HD_IDE
+  There are two drivers for MFM/RLL/IDE disks.  Most people use just the
+  new enhanced driver by itself.  This option installs the old harddisk
+  driver to control the primary IDE/disk interface in the system,
+  leaving the new enhanced IDE driver take care of only the 2nd/3rd/4th
+  IDE interfaces.  Choosing this option may be useful for older systems
+  which have MFM/RLL/ESDI controller+drives at the primary port address
+  (0x1f0), along with IDE drives at the secondary/3rd/4th port addresses.
+  Normally, just say N here.
+  
+Include IDE/ATAPI CDROM support
 CONFIG_BLK_DEV_IDECD
-  If you have a CDROM drive using the ATAPI protocol, say Y. (ATAPI =
-  AT Attachment Packet Interface is a new protocol currently used for
-  controlling CDROM and tape drives, similar to the SCSI protocol and
-  derived from IDE=ATA. Some newer CDROM drives such as NEC 260 and
-  MITSUMI triple/quad speed drives use it, but most MITSUMI CDROM
-  drives don't.) If this is your only CDROM drive, you can say N to
-  all other CDROM options appearing later, but make sure to say Y to
-  the ISO9660 filesystem and read the CDROM-HOWTO, available via ftp
-  (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note
-  that older version of the linux boot loader lilo cannot properly
-  deal with IDE/ATAPI CDROMs; install lilo 16 or higher, available
+  If you have a CDROM drive using the ATAPI protocol, say Y.
+  ATAPI is a new protocol used by IDE CDROM and TAPE drives,
+  similar to the SCSI protocol.  Most new CDROM drives use ATAPI,
+  including the NEC-260, Mitsumi FX400, Sony 55E, and just about 
+  all non-SCSI double(2X), quad(4X), and six(6X) speed drives.
+  At boot time, the TAPE drive will be identified along with other IDE devices,
+  as "hdb" or "hdc", or something similar.
+  If this is your only CDROM drive, you can say N to all other CDROM options,
+  but be sure to say Y to the ISO9660 filesystem.  Read the CDROM-HOWTO,
+  available via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO.
+  Note that older versions of lilo (the linux boot loader) cannot properly
+  deal with IDE/ATAPI CDROMs, so install lilo-16 or higher, available
   from sunsite.unc.edu:/pub/Linux/system/Linux-boot/lilo.
 
+Include IDE/ATAPI TAPE support
+CONFIG_BLK_DEV_IDETAPE
+  If you have an IDE tape drive using the ATAPI protocol, say Y.
+  ATAPI is a new protocol used by IDE TAPE and ATAPI drives,
+  similar to the SCSI protocol.  At boot time, the TAPE drive will
+  be identified along with other IDE devices, as "hdb" or "hdc",
+  or something similar.  Be sure to consult the drivers/block/ide-tape.c
+  and README.ide files for usage information.
+
+CMD640 chipset bugfix/support
+CONFIG_BLK_DEV_CMD640
+  The CMD-Technologies CMD640 chip is used on many common 486 and Pentium
+  motherboards, usually in combination with a "Neptune" or "SiS" chipset.
+  Unfortunately, it has a number of rather nasty design flaws that can cause
+  severe data corruption under many common conditions.  Say Y here to include
+  code which tries to automatically detect and correct the problems under Linux.
+  This also provides support for the enhanced features of the CMD640,
+  for improved support/operation under linux, including access to the secondary
+  IDE ports in some systems.  This driver will work automatically in PCI
+  based systems (most new systems have PCI slots).  But if your system uses
+  VESA local bus (VLB) instead of PCI, you must also supply a kernel boot
+  parameter to enable the CMD640 bugfix/support:  "ide0=cmd640_vlb"
+  The CMD640 chip is also used on add-in cards by Acculogic,
+  and on the "CSA-6400E PCI to IDE controller" that some people have.
+
+RZ1000 chipset bugfix/support
+CONFIG_BLK_DEV_RZ1000
+  The PC-Technologies RZ1000 chip is used on many common 486 and Pentium
+  motherboards, usually along with the "Neptune" chipset.  Unfortunately,
+  it has a rather nasty design flaw that can cause severe data corruption
+  under many conditions.  Say Y here to include code which automatically
+  detects and corrects the problem under Linux.  This may slow disk throughput
+  by a few percent, but at least things will operate 100% reliably.
+
+Other IDE chipset support
+CONFIG_IDE_CHIPSETS
+  Say Y here if you want to include enhanced support for various
+  IDE interface chipsets used on motherboards and add-on cards.
+  This enhanced support may be necessary for linux to be able to access
+  the 3rd/4th drives in some systems.  It may also enable setting of
+  higher speed I/O rates to improve system performance with these chipsets.
+  Most of these also require special kernel boot parameters to actually
+  turn on the support at runtime.
+
+DTC-2278 chipset support
+CONFIG_BLK_DEV_DTC2278
+  This driver is enabled at runtime using the "ide0=dtc2278" kernel
+  boot parameter.  It enables support for the secondary IDE interface
+  of the DTC-2278 card, and permits faster I/O speeds to be set as well.
+  See the README.ide and dtc2278.c files for more info.
+
+Holtek HT6560B chipset support
+CONFIG_BLK_DEV_HT6560B
+  This driver is enabled at runtime using the "ide0=ht6560b" kernel
+  boot parameter.  It enables support for the secondary IDE interface
+  of the Holtek card, and permits faster I/O speeds to be set as well.
+  See the README.ide and ht6560b.c files for more info.
+
+QDI QD6580 chipset support
+CONFIG_BLK_DEV_QD6580
+  This driver is enabled at runtime using the "ide0=qd6580" kernel
+  boot parameter.  It permits faster I/O speeds to be set.
+  See the README.ide and qd6580.c files for more info.
+
+UMC 8672 chipset support
+CONFIG_BLK_DEV_UMC8672
+  This driver is enabled at runtime using the "ide0=umc8672" kernel
+  boot parameter.  It enables support for the secondary IDE interface
+  of the UMC-8672, and permits faster I/O speeds to be set as well.
+  See the README.ide and umc8672.c files for more info.
+
+ALI M1439/M1445 chipset support
+CONFIG_BLK_DEV_ALI14XX
+  This driver is enabled at runtime using the "ide0=ali14xx" kernel
+  boot parameter.  It enables support for the secondary IDE interface
+  of the chipset, and permits faster I/O speeds to be set as well.
+  See the README.ide and ali14xx.c files for more info.
+
 XT harddisk support
 CONFIG_BLK_DEV_XD
   Very old 8 bit hard disk controllers used in the IBM XT
@@ -278,15 +336,16 @@
   certain BIOSes if your computer uses a PCI bussystem. This is
   recommended; say Y.
 
-PCI Triton IDE Bus Master DMA support
+Intel 430FX (Triton) chipset DMA support
 CONFIG_BLK_DEV_TRITON
+  This option is valid only if PCI BIOS support was also selected earlier.
   If your PCI system uses an IDE harddrive (as opposed to SCSI, say)
-  and includes the Intel PCI Triton chipset (82371FB), you will want
-  to enable this option to improve performance. Read the comments at
-  the beginning of drivers/block/triton.c. The hdparm utility can be
-  gotten via ftp (user: anonymous) from
-  sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/. It's safe to
-  say Y.
+  and includes the Intel 430FX PCI Triton chipset, you will want
+  to enable this option to allow use of bus-mastering DMA data transfers.
+  Read the comments at the beginning of drivers/block/triton.c.
+  The hdparm utility can be obtained via ftp (user: anonymous)
+  from sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/.
+  It is safe to say Y.
 
 System V IPC
 CONFIG_SYSVIPC
@@ -1885,9 +1944,36 @@
 CONFIG_OPTCD
   If this is your CDROM drive, say Y here.
 
-Sanyo H94A CDROM support
+Sanyo CDR-H94A CDROM support
 CONFIG_SJCD
-  If this is your CDROM drive, say Y here.
+  If this is your CDROM drive, say Y here. Command line option
+  (or 'append=' option in /etc/lilo.conf) is:
+                sjcd=<port>
+  Here 'port' is the base i/o address used by the drive. It defaults
+  to port=0x340.
+
+Soft configurable cdrom interface card support
+CONFIG_CDI_INIT
+  If you want to include boot-time intialisation of any cdrom
+  interface card that is software configurable, say Y here.
+  Currently only the ISP16/MAD16/Mozart cards are supported.
+
+ISP16/MAD16/Mozart soft configurable cdrom interface support
+CONFIG_ISP16_CDI
+  If you want any of these cdrom interface cards based on the
+  OPTi 82C928 or 82C929 chips get detected and possibly configured
+  at boot time, please say Y. Boot time command line options (or
+  'append=' options in /etc/lilo.conf) are:
+                isp16=<port>,<irq>,<dma>,<drive_type>
+  Here 'port','irq' and 'dma' are the base i/o address, irq number
+  and dma line assumed to be used by the attached cdrom drive. 'drive_type'
+  is the type of cdrom drive or its emulation mode. Valid values for
+  drive_type include: Sanyo, Panasonic (same as Sanyo), Sony and Mitsumi.
+  Default values are: port=0x340, irq=0, dma=0, drive_type=Sanyo.
+  The command line
+                isp16=noisp16
+  will skip detection and configuration after all.
+  N.B. options are case sensitive.
 
 Quota support
 CONFIG_QUOTA
diff -u --recursive --new-file v1.3.62/linux/Documentation/cdrom/isp16 linux/Documentation/cdrom/isp16
--- v1.3.62/linux/Documentation/cdrom/isp16	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/cdrom/isp16	Tue Feb 13 10:30:24 1996
@@ -0,0 +1,100 @@
+ -- Documentation/cdrom/isp16
+
+Docs by Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
+
+This is the README for version 0.6 of the cdrom interface on an
+ISP16, MAD16 or Mozart sound card.
+
+The detection and configuration of this interface used to be included
+in both the sjcd and optcd cdrom driver. Drives supported by these
+drivers came packed with Media Magic's multi media kit, which also
+included the ISP16 card. The idea (thanks Leo Spiekman)
+to move it from thes drivers into a separate module and moreover, not to
+rely on the MAD16 sound driver, are as follows:
+-duplication of code in the kernel is a waste of resources and should
+ be avoided;
+-however, kernels and notably those included with Linux distributions
+ (cf Slackware 3.0 included version 0.5 of the isp16 configuration
+ code included in the drivers) don't always come with sound support
+ included. Especially when they already include a bunch of cdrom drivers.
+ Hence, the cdrom interface should be configurable _independently_ of
+ sound support.
+
+The ISP16, MAD16 and Mozart sound cards have an OPTi 82C928 or an
+OPTi 82C929 chip.  The interface on these cards should work with
+any cdrom attached to the card, which is 'electrically' compatible
+with Sanyo/Panasonic, Sony or Mitsumi non-ide drives. However, the
+command sets for any propriatary drives may differ
+(and hence may not be supported in the kernel) from these four types.
+For a fact I know the interface works and the way of configuration
+as described in this documentation works in combination with the
+sjcd (in Sanyo/Panasonic compatibility mode) cdrom drivers
+(probably with the optcd (in Sony compatibility mode) as well).
+If you have such an OPTi based sound card and you want to use the
+cdrom interface with a cdrom drive supported by any of the other cdrom
+drivers, it will probably work. Please let me know any experience you
+might have).
+I understand that cards based on the OPTi 82C929 chips may be configured
+(hardware jumpers that is) as an IDE interface. Initialisation of such a
+card in this mode is not supported (yet?).
+
+The suggestion to configure the ISP16 etc. sound card by booting DOS and 
+do a warm reboot to boot Linux somehow doesn't work, at least not
+on my machine (IPC P90), with the OPTi 82C928 based card.
+
+Booting the kernel through the boot manager LILO allows the use
+of some command line options on the 'LILO boot:' prompt. At boot time
+press Alt or Shift while the LILO prompt is written on the screen and enter
+any kernel options. Alternatively these options may be used in
+the apropriate section in /etc/lilo.conf. Adding 'append="<cmd_line_options>"'
+will do the trick as well.
+The syntax of 'cmd_line_options' is
+
+        isp16=[<port>[,<irq>[,<dma>]]][[,]<drive_type>]
+
+If there is no ISP16 or compatibles detected, there's probably no harm done.
+These options indicate the values that your cdrom drive has been (or will be)
+configured to use.
+Valid values for the base i/o address are:
+  port=0x340,0x320,0x330,0x360
+for the interrupt request number 
+  irq=0,3,5,7,9,10,11
+for the direct memory access line
+  dma=0,3,5,6,7
+and for the type of drive
+  drive_type=noisp16,Sanyo,Panasonic,Sony,Mitsumi.
+Note that these options are case sensitive.
+The values 0 for irq and dma indicate that they are not used, and
+the drive will be used in 'polling' mode. The values 5 and 7 for irq
+should be avoided in order to avoid any conflicts with optional
+sound card configuration.
+The syntax of the command line does not allow the specifiaction of
+irq when there's nothing specified for the base address and no
+specification of dma when there is no specification of irq.
+The value 'nosip16' for drive_type, which may be used as the first
+non-integer option value (e.g. 'isp16=noisp16'), makes sure that probing
+for and subsequent configuration of an ISP16-compatible card is skipped
+all together. This can be useful to overcome possible conflicts which
+may arise while the kernel is probing your hardware.
+The default values are
+  port=0x340
+  irq=0
+  dma=0
+  drive_type=Sanyo
+reflecting my own configuration. The defaults can be changed in
+the file ~/include/linux/ips16.h.
+
+The cdrom interface can be configured at run time by loading the
+initialisation driver as a module. In that case, the interface
+parameters can be set by giving appropriate values on the command
+line. Configuring the driver can then be done by the following
+command (assuming you have iso16.o installed in a proper place):
+
+  insmod isp16.o isp16_cdrom_base=<port> isp16_cdrom_irq=<irq> \
+    isp16_cdrom_dma=<dma> isp16_cdrom_type=<drive_type>
+
+where port, irq, dma and drive_type can have any of the values mentioned
+above.
+
+
+Have fun!
diff -u --recursive --new-file v1.3.62/linux/Documentation/cdrom/sjcd linux/Documentation/cdrom/sjcd
--- v1.3.62/linux/Documentation/cdrom/sjcd	Mon Oct 23 18:02:00 1995
+++ linux/Documentation/cdrom/sjcd	Tue Feb 13 10:30:24 1996
@@ -1,4 +1,4 @@
- -- README.sjcd
+ -- Documentation/cdrom/sjcd
 				80% of the work takes 20% of the time,
 				20% of the work takes 80% of the time...
 						(Murphy law)
@@ -6,57 +6,24 @@
 				Once started, training can not be stopped...
 						(StarWars)
 
-This is the README for the sjcd cdrom driver, version 1.5.
+This is the README for the sjcd cdrom driver, version 1.6.
 
 This file is meant as a tips & tricks edge for the usage of the SANYO CDR-H94A
 cdrom drive. It will grow as the questions arise. ;-)
-Since the drive often comes with an ISP16 soundcard, which can be used
-as cdrom interface, this is also the place for ISP16 related issues.
+For info on configuring the ISP16 sound card look at Documetation/cdrom/isp16.
 
-The driver should work with any SoundBlaster/Panasonic style CDROM interface,
-including the "soft configurable" MediaMagic sound card.
-To make this sound card (and others like "Mozart") working, it has to get 
-"configured" by software.
-The suggestion to configure the ISP16 soundcard by booting DOS and 
-a warm reboot to boot Linux somehow doesn't work, at least not
-on Eric's machine (IPC P90), with the version of the ISP16
-card he has (there appear to be at least two versions: Eric's card with
-no jumpered IDE support and OPTi 82C928 chip, and Vadim's version
-with a jumper to enable IDE support, probably with a OPTi 82C929 chip).
-Therefore detection and configuration of the ISP16 interfaces is included
-in the driver.
-If we should support any other interfaces (which cannot be configured
-through DOS) or if there are any more ISP16 types, please let us
-know (maarel@marin.nl) and we'll see.
-
-Otherwise, you should boot DOS once (and by this, run the "configuration driver")
-and then switch to Linux by use of CTRL-ALT-DEL. Each use of the RESET
-button or the power switch makes this procedure necessary again.
-If no ISP16 is detected, there's no harm done; a card configured trough DOS
-may still work as expected.
-
-As of version 1.4 sound through the speakers is supported; only for MSS-mode 
-and no volume controle yet.
-
-PAUSE and STOP ioctl commands don't seem to work yet.
-
-ISP16 configuration routines reside at Vadim's server
-      ftp.rbrf.ru:/linux/mediamagic/
-and at Eberhard's mirror
-      ftp.gwdg.de:/pub/linux/cdrom/drivers/sanyo/
-
-Leo Spiekman's configuration routines for the ISP-16 card can get found at
-      dutette.et.tudelft.nl:/pub/linux/
-and at Eberhard's mirror
-      ftp.gwdg.de:/pub/linux/cdrom/drivers/optics/
-
-Eric van der Maarel's routines are included in sjcd.c.
-This, and any related stuff may be found by anonymous ftp at
-      ftp.gwdg.de:/pub/linux/cdrom/drivers/sanyo/
+The driver should work with any of the Panasonic, Sony or Mitsum style
+CDROM interface.
+The cdrom interface on Media Magic's soft configurable sound card ISP16,
+which used to be included in the driver, is now supported in a separate module.
+This initilisation module will probably also work with other interfaces
+based on an OPTi 82C928 or 82C929 chip (like MAD16 and Mozart): see the
+documentation Documentation/cdrom/isp16.
 
 The device major for sjcd is 18, and minor is 0. Create a block special
 file in your /dev directory (e.g., /dev/sjcd) with these numbers.
-(For those who don't know, being root and doing the following should do the trick:
+(For those who don't know, being root and doing the following should do
+the trick:
   mknod -m 644 /dev/sjcd b 18 0
 and mount the cdrom by /dev/sjcd).
 
@@ -64,17 +31,30 @@
   base address 0x340
   no irq
   no dma
-As of version 1.2, setting base address, irq and dma at boot time is supported
+(Acctulay the CDR-H94A doesn't know how to use irq and dma.)
+As of version 1.2, setting base address at boot time is supported
 through the use of command line options: type at the "boot:" prompt:
-  linux sjcd=<base address>,<irq>,<dma>
-(where your kernel is assumed to be called by saying "linux" to
-the boot manager).
+  linux sjcd=<base_address>
+(where you would use the kernel labeled "linux" in lilo's configuration
+file /etc/lilo.conf). You could also use 'append="sjcd=<configuration_info>"'
+in the appropriate section of /etc/lilo.conf
+If you're building a kernel yourself you can set your default base
+i/o address with SJCD_BASE_ADDR in include/linux/sjcd.h.
+
+The sjcd driver supports beng loaded as a module. The following
+command will set the base i/o address on the fly (assuming you
+have installed the module in an appropriate place).
+  insmod sjcd.o sjcd_base=<base_address>
 
-If something is wrong, e-mail to		vadim@rbrf.ru
+
+Have fun!
+
+If something is wrong, please email to		vadim@rbrf.ru
 					or 	vadim@ipsun.ras.ru
 					or	model@cecmow.enet.dec.com
+					or	H.T.M.v.d.Maarel@marin.nl
 
 It happens sometimes that Vadim is not reachable by mail. For these
-instances, Eric van der Maarel (maarel@marin.nl) will help, too.
+instances, Eric van der Maarel will help too.
 
 		Vadim V. Model, Eric van der Maarel, Eberhard Moenkeberg
diff -u --recursive --new-file v1.3.62/linux/Documentation/modules.txt linux/Documentation/modules.txt
--- v1.3.62/linux/Documentation/modules.txt	Mon Sep 25 12:26:20 1995
+++ linux/Documentation/modules.txt	Tue Feb 13 10:30:24 1996
@@ -51,6 +51,7 @@
 		gscd:      Goldstar GCDR-420
 		mcd, mcdx: Mitsumi LU005, FX001
 		optcd:     Optics Storage Dolphin 8000AT
+		sjcd:      Sanyo CDR-H94A
 		sbpcd:     Matsushita/Panasonic CR52x, CR56x, CD200,
 		           Longshine LCS-7260, TEAC CD-55A
 		sonycd535: Sony CDU-531/535, CDU-510/515
@@ -58,6 +59,7 @@
 	Some misc modules:
 		lp: line printer
 		binfmt_elf: elf loader
+		isp16: cdrom interface
 
 When you have made the kernel, you create the modules by doing:
 
diff -u --recursive --new-file v1.3.62/linux/Makefile linux/Makefile
--- v1.3.62/linux/Makefile	Sun Feb 11 15:32:43 1996
+++ linux/Makefile	Tue Feb 13 18:50:22 1996
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 62
+SUBLEVEL = 63
 
 ARCH = i386
 
diff -u --recursive --new-file v1.3.62/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v1.3.62/linux/arch/i386/defconfig	Fri Feb  9 17:52:57 1996
+++ linux/arch/i386/defconfig	Mon Feb 12 07:14:08 1996
@@ -27,21 +27,20 @@
 # CONFIG_M686 is not set
 
 #
-# Block devices
+# Floppy, IDE, and other block devices
 #
 CONFIG_BLK_DEV_FD=y
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_ST506=y
+CONFIG_BLK_DEV_IDE=y
 
 #
 # Please see drivers/block/README.ide for help/info on IDE drives
 #
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDE=y
+# CONFIG_BLK_DEV_HD_IDE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_RZ1000=y
 CONFIG_BLK_DEV_CMD640=y
+CONFIG_BLK_DEV_RZ1000=y
 # CONFIG_BLK_DEV_TRITON is not set
 # CONFIG_IDE_CHIPSETS is not set
 # CONFIG_BLK_DEV_XD is not set
diff -u --recursive --new-file v1.3.62/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v1.3.62/linux/arch/ppc/config.in	Fri Feb  9 17:52:58 1996
+++ linux/arch/ppc/config.in	Tue Feb 13 10:30:24 1996
@@ -245,7 +245,8 @@
   tristate 'Goldstar R420 CDROM support' CONFIG_GSCD n
   tristate 'Philips/LMS CM206 CDROM support' CONFIG_CM206 n
   tristate 'Experimental Optics Storage DOLPHIN 8000AT CDROM support' CONFIG_OPTCD n
-  bool 'Experimental Sanyo H94A CDROM support' CONFIG_SJCD n
+  tristate 'Sanyo CDR-H94A CDROM support' CONFIG_SJCD n
+  bool 'ISP16/MAD16/Mozart soft configurable cdrom interface support' CONFIG_ISP16_CDI n
 fi
 
 comment 'Filesystems'
diff -u --recursive --new-file v1.3.62/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v1.3.62/linux/drivers/block/Config.in	Fri Feb  9 17:52:58 1996
+++ linux/drivers/block/Config.in	Mon Feb 12 07:04:01 1996
@@ -2,37 +2,35 @@
 # Block device driver configuration
 #
 mainmenu_option next_comment
-comment 'Block devices'
+comment 'Floppy, IDE, and other block devices'
 
 tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD
 tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
-bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506
-if [ "$CONFIG_ST506" = "y" ]; then
-  comment 'Please see drivers/block/README.ide for help/info on IDE drives'
-  bool '   Use old disk-only driver for primary i/f' CONFIG_BLK_DEV_HD
-  if [ "$CONFIG_BLK_DEV_HD" = "y" ]; then
-    bool '   Include new IDE driver for secondary i/f support' CONFIG_BLK_DEV_IDE
-  else
-    bool '   Use new IDE driver for primary/secondary i/f' CONFIG_BLK_DEV_IDE
-  fi
-  if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
-    bool '   Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD
-    bool '   Include (ALPHA) IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE
+bool 'Enhanced IDE/MFM/RLL disk/cdrom/tape support' CONFIG_BLK_DEV_IDE
+comment 'Please see drivers/block/README.ide for help/info on IDE drives'
+if [ "$CONFIG_BLK_DEV_IDE" = "n" ]; then
+  bool 'Old harddisk (MFM/RLL/IDE) driver' CONFIG_BLK_DEV_HD_ONLY
+else
+  bool '   Use old disk-only driver on primary interface' CONFIG_BLK_DEV_HD_IDE
+  bool '   Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD
+  bool '   Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE
+  bool '   CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640
+  if [ "$CONFIG_PCI" = "y" ]; then
     bool '   RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000
-    bool '   CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640
-    if [ "$CONFIG_PCI" = "y" ]; then
-      bool '   TRITON chipset DMA support' CONFIG_BLK_DEV_TRITON
-    fi
-    bool '   Other IDE chipset support' CONFIG_IDE_CHIPSETS
-    if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
-      comment 'Note: most of these also require special kernel boot parameters'
-      bool '     DTC2278 chipset support' CONFIG_BLK_DEV_DTC2278
-      bool '     HT6560B chipset support' CONFIG_BLK_DEV_HT6560B
-      bool '     QD6580  chipset support' CONFIG_BLK_DEV_QD6580
-      bool '     UMC8672 chipset support' CONFIG_BLK_DEV_UMC8672
-      bool '     ALI14XX chipset support' CONFIG_BLK_DEV_ALI14XX
-    fi
+    bool '   Intel 430FX (Triton) chipset DMA support' CONFIG_BLK_DEV_TRITON
+  fi
+  bool '   Other IDE chipset support' CONFIG_IDE_CHIPSETS
+  if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
+    comment 'Note: most of these also require special kernel boot parameters'
+    bool '      DTC-2278        chipset support' CONFIG_BLK_DEV_DTC2278
+    bool '      Holtek HT6560B  chipset support' CONFIG_BLK_DEV_HT6560B
+    bool '      QDI QD6580      chipset support' CONFIG_BLK_DEV_QD6580
+    bool '      UMC 8672        chipset support' CONFIG_BLK_DEV_UMC8672
+    bool '      ALI M1439/M1445 chipset support' CONFIG_BLK_DEV_ALI14XX
   fi
+fi
+if [ "$CONFIG_BLK_DEV_HD_IDE" = "y" -o "$CONFIG_BLK_DEV_HD_ONLY" = "y" ]; then
+  define_bool CONFIG_BLK_DEV_HD y
 fi
 
 bool 'XT harddisk support' CONFIG_BLK_DEV_XD
diff -u --recursive --new-file v1.3.62/linux/drivers/block/README.ide linux/drivers/block/README.ide
--- v1.3.62/linux/drivers/block/README.ide	Fri Feb  9 17:52:58 1996
+++ linux/drivers/block/README.ide	Mon Feb 12 07:04:02 1996
@@ -58,6 +58,7 @@
 NEW!    - ide-cd.c now supports door locking and auto-loading.
 		- Also preliminary support for multisession
 		  and direct reads of audio data.
+NEW!	- the hdparm-2.6 package can be used to set PIO modes for some chipsets.
 
 For work in progress, see the comments in ide.c, ide-cd.c, and triton.c.
 
@@ -260,7 +261,7 @@
  "ide0=cmd640_vlb"	: *REQUIRED* for VLB cards with the CMD640 chip
 			  (not for PCI -- automatically detected)
  "ide0=qd6580"		: probe/support qd6580 interface
- "ide0=ali14xx"		: probe/support ali14xx chipsets (ALI M1439, M1443, M1445)
+ "ide0=ali14xx"		: probe/support ali14xx chipsets (ALI M1439/M1445)
  "ide0=umc8672"		: probe/support umc8672 chipsets
 
 Everything else is rejected with a "BAD OPTION" message.
@@ -427,6 +428,25 @@
 more generally compatible method of achieving the same results (DOS access
 to the entire disk).  However, if you must use DiskManager, it now works
 with Linux 1.3.x in most cases.  Let me know if you still have trouble.
+
+My recommendations to anyone who asks about NEW systems are:
+
+        - buy a motherboard that uses the Intel Triton chipset -- very common.
+        - use IDE for the first two drives, placing them on separate interfaces.
+	- place the IDE cdrom drive as slave on either interface.
+        - if additional disks are to be connected, consider your needs:
+                - fileserver?  Buy a SC200 SCSI adaptor for the next few drives.
+                - personal system?  Use IDE for the next two drives.
+                - still not enough?  Keep adding SC200 SCSI cards as needed.
+
+Most manufacturers make both IDE and SCSI-2 versions of each of their drives.
+The IDE ones are usually faster and cheaper, due to the higher data transfer
+speed of PIO mode4 (ATA2), 16.6MBytes/sec versus 10Mbytes/sec for SCSI-2.
+
+In particular, I recommend Quantum FireBalls as cheap and exceptionally fast.
+The new WD1.6GB models are also cheap screamers.
+
+For really high end systems, go for fast/wide 7200rpm SCSI.  But it'll cost ya!
 
 mlord@bnr.ca
 
diff -u --recursive --new-file v1.3.62/linux/drivers/block/ali14xx.c linux/drivers/block/ali14xx.c
--- v1.3.62/linux/drivers/block/ali14xx.c	Fri Feb  9 17:52:58 1996
+++ linux/drivers/block/ali14xx.c	Mon Feb 12 07:04:02 1996
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ali14xx.c       Version 0.01  Feb 06, 1996
+ *  linux/drivers/block/ali14xx.c       Version 0.03  Feb 09, 1996
  *
  *  Copyright (C) 1996  Linus Torvalds & author (see below)
  */
@@ -37,8 +37,21 @@
 #include <linux/hdreg.h>
 #include <asm/io.h>
 #include "ide.h"
+#include "ide_modes.h"
 
-#define ALI_14xx_BUS_SPEED	40	/* PCI / VLB bus speed */
+/*
+ * This should be set to the system's local bus (PCI or VLB) speed,
+ * e.g., 33 for a 486DX33 or 486DX2/66.  Legal values are anything
+ * from 25 to 50.  Setting this too *low* will make the EIDE
+ * controller unable to communicate with the disks.
+ *
+ * I suggest using a default of 50, since it should work ok with any
+ * system.  (Low values cause problems because it multiplies by bus speed
+ * to get cycles, and thus gets a too-small cycle count and tries to
+ * access the disks too fast.  I tried this once under DOS and it locked
+ * up the system.)	-- derekn@vw.ece.cmu.edu
+ */
+#define ALI_14xx_BUS_SPEED	50	/* PCI / VLB bus speed */
 
 /* port addresses for auto-detection */
 #define ALI_NUM_PORTS 4
@@ -112,11 +125,11 @@
 	struct hd_driveid *id = drive->id;
 	unsigned long flags;
 
-	if (pio == 255)  {	/* auto-tune */
-		pio = id->tPIO;
-		if ((id->field_valid & 0x02) && (id->eide_pio_modes & 0x01))
-			pio = 3;
-	}
+	if (pio == 255)
+		pio = ide_get_best_pio_mode(drive);
+	if (pio > 3)
+		pio = 3;
+
 	/* calculate timing, according to PIO mode */
 	time1 = timeTab[pio].time1;
 	time2 = timeTab[pio].time2;
diff -u --recursive --new-file v1.3.62/linux/drivers/block/cmd640.c linux/drivers/block/cmd640.c
--- v1.3.62/linux/drivers/block/cmd640.c	Fri Feb  9 17:53:00 1996
+++ linux/drivers/block/cmd640.c	Mon Feb 12 07:04:02 1996
@@ -56,6 +56,7 @@
 #include <linux/hdreg.h>
 #include <asm/io.h>
 #include "ide.h"
+#include "ide_modes.h"
 
 int cmd640_vlb = 0;
 
@@ -594,88 +595,10 @@
 	{ 50,	125,	383 },	/* PIO Mode 1 */
 	{ 30,	100,	240 },	/* PIO Mode 2 */
 	{ 30,	80,	180 },	/* PIO Mode 3 */
-	{ 25,	70,	125 },	/* PIO Mode 4 */
+	{ 25,	70,	125 },	/* PIO Mode 4  -- should be 120, not 125 */
 	{ 20,	50,	100 }	/* PIO Mode ? (nonstandard) */
 };
 
-/*
- * Black list. Some drives incorrectly report their maximal PIO modes, at least
- * in respect to CMD640. Here we keep info on some known drives.
- */
-
-static struct drive_pio_info {
-	const char	*name;
-	int		pio;
-} drive_pios[] = {
-/*	{ "Conner Peripherals 1275MB - CFS1275A", 4 }, */
-
-	{ "WDC AC2700",  3 },
-	{ "WDC AC2540",  3 },
-	{ "WDC AC2420",  3 },
-	{ "WDC AC2340",  3 },
-	{ "WDC AC2250",  0 },
-	{ "WDC AC2200",  0 },
-	{ "WDC AC2120",  0 },
-	{ "WDC AC2850",  3 },
-	{ "WDC AC1270",  3 },
-	{ "WDC AC1170",  3 },
-	{ "WDC AC1210",  1 },
-	{ "WDC AC280",   0 },
-/*	{ "WDC AC21000", 4 }, */
-	{ "WDC AC31000", 3 },
-/*	{ "WDC AC21200", 4 }, */
-	{ "WDC AC31200", 3 },
-/*	{ "WDC AC31600", 4 }, */
-
-	{ "Maxtor 7131 AT", 1 },
-	{ "Maxtor 7171 AT", 1 },
-	{ "Maxtor 7213 AT", 1 },
-	{ "Maxtor 7245 AT", 1 },
-	{ "Maxtor 7345 AT", 1 },
-	{ "Maxtor 7546 AT", 3 },
-	{ "Maxtor 7540 AV", 3 },
-
-	{ "SAMSUNG SHD-3121A", 1 },
-	{ "SAMSUNG SHD-3122A", 1 },
-	{ "SAMSUNG SHD-3172A", 1 },
-
-/*	{ "ST51080A", 4 },
- *	{ "ST51270A", 4 },
- *	{ "ST31220A", 4 },
- *	{ "ST31640A", 4 },
- *	{ "ST32140A", 4 },
- *	{ "ST3780A",  4 },
- */	{ "ST5660A",  3 },
-	{ "ST3660A",  3 },
-	{ "ST3630A",  3 },
-	{ "ST3655A",  3 },
-	{ "ST3391A",  3 },
-	{ "ST3390A",  1 },
-	{ "ST3600A",  1 },
-	{ "ST3290A",  0 },
-	{ "ST3144A",  0 },
-
-	{ "QUANTUM ELS127A", 0 },
-	{ "QUANTUM ELS170A", 0 },
-	{ "QUANTUM LPS240A", 0 },
-	{ "QUANTUM LPS210A", 3 },
-	{ "QUANTUM LPS270A", 3 },
-	{ "QUANTUM LPS365A", 3 },
-	{ "QUANTUM LPS540A", 3 },
-	{ "QUANTUM FIREBALL", 3 }, /* For models 540/640/1080/1280 */
-	{ NULL,	0 }
-};
-
-static int known_drive_pio(char* name) {
-	struct drive_pio_info* pi;
-
-	for (pi = drive_pios; pi->name != NULL; pi++) {
-		if (strmatch(pi->name, name) == 0)
-			return pi->pio;
-	}
-	return -1;
-}
-
 static void cmd640_timings_to_clocks(int mc_time, int av_time, int ds_time,
 				int clock_time, int drv_idx)
 {
@@ -764,7 +687,7 @@
 	drive_number = drive->select.b.unit;
 	clock_time = 1000/bus_speed;
 	id = drive->id;
-	if ((max_pio = known_drive_pio(id->model)) != -1) {
+	if ((max_pio = ide_scan_pio_blacklist(id->model)) != -1) {
 		ds_time = pio_timings[max_pio].ds_time;
 	} else {
 		max_pio = id->tPIO;
diff -u --recursive --new-file v1.3.62/linux/drivers/block/dtc2278.c linux/drivers/block/dtc2278.c
--- v1.3.62/linux/drivers/block/dtc2278.c	Fri Feb  9 17:53:00 1996
+++ linux/drivers/block/dtc2278.c	Mon Feb 12 07:04:02 1996
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/dtc2278.c       Version 0.01  Feb 06, 1996
+ *  linux/drivers/block/dtc2278.c       Version 0.02  Feb 10, 1996
  *
  *  Copyright (C) 1996  Linus Torvalds & author (see below)
  */
@@ -16,6 +16,12 @@
 #include <linux/hdreg.h>
 #include <asm/io.h>
 #include "ide.h"
+#include "ide_modes.h"
+
+/*
+ * Changing this #undef to #define may solve start up problems in some systems.
+ */
+#undef ALWAYS_SET_DTC2278_PIO_MODE
 
 /*
  * From: andy@cercle.cts.com (Dyan Wile)
@@ -27,9 +33,9 @@
  * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my
  * filesystem  corrupted with -u1, but under heavy disk load only :-)
  *
- * From: mlord@bnr.ca -- this chipset is now forced to use the "serialize" feature,
- * which hopefully will make it more reliable to use.. maybe it has the same bugs
- * as the CMD640B and RZ1000 ??
+ * This chipset is now forced to use the "serialize" feature,
+ * and irq-unmasking is disallowed.  If io_32bit is enabled,
+ * it must be done for BOTH drives on each interface.
  */
 
 static void sub22 (char b, char c)
@@ -50,24 +56,31 @@
 	}
 }
 
-static void tune_dtc2278 (ide_drive_t *drive, byte pio_mode)
+static void tune_dtc2278 (ide_drive_t *drive, byte pio)
 {
 	unsigned long flags;
 
-	if (pio_mode != 255) {	/* auto-tune not yet supported here */
-		if (pio_mode >= 3) {
-			save_flags(flags);
-			cli();
-			/*
-			 * This enables PIO mode4 (3?) on the first interface
-			 */
-			sub22(1,0xc3);
-			sub22(0,0xa0);
-			restore_flags(flags);
-		} else {
-			/* we don't know how to set it back again.. */
-		}
+	if (pio == 255)
+		pio = ide_get_best_pio_mode(drive);
+
+	if (pio >= 3) {
+		save_flags(flags);
+		cli();
+		/*
+		 * This enables PIO mode4 (3?) on the first interface
+		 */
+		sub22(1,0xc3);
+		sub22(0,0xa0);
+		restore_flags(flags);
+	} else {
+		/* we don't know how to set it back again.. */
 	}
+
+	/*
+	 * 32bit I/O has to be enabled for *both* drives at the same time.
+	 */
+	drive->io_32bit = 1;
+	HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1;
 }
 
 void init_dtc2278 (void)
@@ -83,10 +96,20 @@
 	inb(0x3f6);
 	outb_p(0x20,0xb4);
 	inb(0x3f6);
+#ifdef ALWAYS_SET_DTC2278_PIO_MODE
+	/*
+	 * This enables PIO mode4 (3?) on the first interface
+	 * and may solve start-up problems for some people.
+	 */
+	sub22(1,0xc3);
+	sub22(0,0xa0);
+#endif
 	restore_flags(flags);
 
 	ide_hwifs[0].serialized = 1;
 	ide_hwifs[0].chipset = ide_dtc2278;
 	ide_hwifs[1].chipset = ide_dtc2278;
 	ide_hwifs[0].tuneproc = &tune_dtc2278;
+	ide_hwifs[0].no_unmask = 1;
+	ide_hwifs[1].no_unmask = 1;
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/block/ht6560b.c linux/drivers/block/ht6560b.c
--- v1.3.62/linux/drivers/block/ht6560b.c	Fri Feb  9 17:53:00 1996
+++ linux/drivers/block/ht6560b.c	Mon Feb 12 07:04:02 1996
@@ -1,9 +1,55 @@
 /*
- *  linux/drivers/block/ht6580.c       Version 0.01  Feb 06, 1996
+ *  linux/drivers/block/ht6580.c       Version 0.03  Feb 09, 1996
  *
  *  Copyright (C) 1995-1996  Linus Torvalds & author (see below)
  */
 
+/*
+ *
+ *  Version 0.01        Initial version hacked out of ide.c
+ *
+ *  Version 0.02        Added support for PIO modes, auto-tune
+ *
+ *  Version 0.03        Some cleanups
+ *
+ * I reviewed some assembler sourcer listings of htide drivers and found
+ * out how they setup those cycle time interfacing values, as they at Holtek
+ * call them. IDESETUP.COM that is supplied with the drivers figures out
+ * optimal values and fetches those values to drivers. I found out that
+ * they use IDE_SELECT_REG to fetch timings to the ide board right after
+ * interface switching. After that it was quite easy to add code to
+ * ht6560b.c.
+ *
+ * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine
+ * for hda and hdc. But hdb needed higher values to work, so I guess
+ * that sometimes it is necessary to give higher value than IDESETUP
+ * gives.   [see cmd640.c for an extreme example of this. -ml]
+ *
+ * Perhaps I should explain something about these timing values:
+ * The higher nibble of value is the Recovery Time  (rt) and the lower nibble
+ * of the value is the Active Time  (at). Minimum value 2 is the fastest and
+ * the maximum value 15 is the slowest. Default values should be 15 for both.
+ * So 0x24 means 2 for rt and 4 for at. Each of the drives should have
+ * both values, and IDESETUP gives automatically rt=15 st=15 for cdroms or
+ * similar. If value is too small there will be all sorts of failures.
+ *
+ * Port 0x3e6 bit 0x20 sets these timings on/off. If 0x20 bit is set
+ * these timings are disabled.
+ *
+ * Mikko Ala-Fossi
+ *
+ * More notes:
+ *
+ * There's something still missing from the initialization code, though.
+ * If I have booted to dos sometime after power on, I can get smaller
+ * timing values working. Perhaps I could soft-ice the initialization.
+ *
+ * OS/2 driver seems to use some kind of DMA. But that code is really
+ * messy to me to found out how.
+ *
+ * -=- malafoss@snakemail.hut.fi -=- searching the marvels of universe -=-
+ */
+
 #undef REALLY_SLOW_IO           /* most systems can safely undef this */
 
 #include <linux/types.h>
@@ -16,6 +62,7 @@
 #include <linux/hdreg.h>
 #include <asm/io.h>
 #include "ide.h"
+#include "ide_modes.h"
 
 /*
  * This routine handles interface switching for the peculiar hardware design
@@ -31,33 +78,80 @@
  */
 
 /*
+ * The special i/o-port that HT-6560B uses to select interfaces:
+ */
+#define HT_SELECT_PORT     0x3e6
+
+/*
  * We don't know what all of the bits are for, but we *do* know about these:
- *	bit5 (0x20): "1" selects slower speed (?)
+ *	bit5 (0x20): "1" selects slower speed by disabling use of timing values
  *	bit0 (0x01): "1" selects second interface
  */
-static byte qd6560b_selects [2][MAX_DRIVES] = {{0x3c,0x3c}, {0x3d,0x3d}};
+static byte ht6560b_selects [2][MAX_DRIVES] = {{0x3c,0x3c}, {0x3d,0x3d}};
+
+/*
+ * VLB ht6560b Timing values:
+ *
+ * Timing byte consists of
+ *      High nibble:  Recovery Time  (rt)
+ *           The valid values range from 2 to 15. The default is 15.
+ *
+ *      Low nibble:   Active Time    (at)
+ *           The valid values range from 2 to 15. The default is 15.
+ *
+ * You can obtain optimized timing values by running Holtek IDESETUP.COM
+ * for DOS. DOS drivers get their timing values from command line, where
+ * the first value is the Recovery Time and the second value is the
+ * Active Time for each drive. Smaller value gives higher speed.
+ * In case of failures you should probably fall back to a higher value.
+ *
+ * Hopefully this example will make it clearer:
+ *
+ * DOS:    DEVICE=C:\bin\HTIDE\HTIDE.SYS /D0=2,4 /D1=4,5 /D2=10,10 /D3=15,15
+ * Linux:  byte ht6560b_timings [][] = {{0x24, 0x45}, {0xaa, 0xff}};
+ *
+ * Note: There are no ioctls to change these values directly,
+ * but settings can be approximated as PIO modes, using "hdparm":
+ *
+ * rc.local:  hdparm -p3 /dev/hda -p2 /dev/hdb -p1 /dev/hdc -p0 /dev/hdd
+ */
+
+static byte ht6560b_timings [2][MAX_DRIVES] = {{0xff,0xff}, {0xff,0xff}};
 
-static void qd6560b_selectproc (ide_drive_t *drive)	/* called from ide.c */
+static byte pio_to_timings[6] = {0xff, 0xaa, 0x45, 0x24, 0x13, 0x12};
+
+/*
+ * This routine is invoked from ide.c to prepare for access to a given drive.
+ */
+static void ht6560b_selectproc (ide_drive_t *drive)
 {
+	byte t;
+	unsigned long flags;
 	static byte current_select = 0;
-	byte drive_select = qd6560b_selects[HWIF(drive)->index][drive->select.b.unit];
-
-	if (drive_select != current_select) {
-		byte t;
-		unsigned long flags;
+	static byte current_timing = 0;
+	byte select = ht6560b_selects[HWIF(drive)->index][drive->select.b.unit];
+        byte timing = ht6560b_timings[HWIF(drive)->index][drive->select.b.unit];
+
+	if (select != current_select || timing != current_timing) {
+		current_select = select;
+		current_timing = timing;
 		save_flags (flags);
 		cli();
-		current_select = drive_select;
-		(void) inb(0x3e6);
-		(void) inb(0x3e6);
-		(void) inb(0x3e6);
+		(void) inb(HT_SELECT_PORT);
+		(void) inb(HT_SELECT_PORT);
+		(void) inb(HT_SELECT_PORT);
 		/*
 		 * Note: input bits are reversed to output bits!!
 		 */
-		t = inb(0x3e6) ^ 0x3f;
+		t = inb(HT_SELECT_PORT) ^ 0x3f;
 		t &= (~0x21);
 		t |= (current_select & 0x21);
-		outb(t,0x3e6);
+		outb(t, HT_SELECT_PORT);
+                /*
+                 * Set timing for this drive:
+                 */
+                outb (timing, IDE_SELECT_REG);
+                (void) inb (IDE_STATUS_REG);
 		restore_flags (flags);
 	}
 }
@@ -71,28 +165,29 @@
 	int i;
 
 	/* Autodetect ht6560b */
-	if ((orig_value=inb(0x3e6)) == 0xff)
+	if ((orig_value=inb(HT_SELECT_PORT)) == 0xff)
 		return 0;
 
 	for (i=3;i>0;i--) {
-		outb(0x00,0x3e6);
-		if (!( (~inb(0x3e6)) & 0x3f )) {
-			  outb(orig_value,0x3e6);
+		outb(0x00, HT_SELECT_PORT);
+		if (!( (~inb(HT_SELECT_PORT)) & 0x3f )) {
+			  outb(orig_value, HT_SELECT_PORT);
 			  return 0;
 		}
 	}
-	outb(0x00,0x3e6);
-	if ((~inb(0x3e6))& 0x3f) {
-		outb(orig_value,0x3e6);
+	outb(0x00, HT_SELECT_PORT);
+	if ((~inb(HT_SELECT_PORT))& 0x3f) {
+		outb(orig_value, HT_SELECT_PORT);
 		return 0;
 	}
-	/* 
+	/*
 	 * Ht6560b autodetected:
 	 *     reverse input bits to output bits
 	 *     initialize bit1 to 0
 	 */
-	outb((orig_value ^ 0x3f) & 0xfd,0x3e6);
-	printk("ht6560b: detected and initialized\n");
+	outb((orig_value ^ 0x3f) & 0xfd, HT_SELECT_PORT);
+
+	printk("\nht6560b: detected and initialized");
 	return 1;
 }
 
@@ -101,37 +196,37 @@
 	unsigned int hwif, unit;
 
 	if (pio == 255)  {	/* auto-tune */
-		if (drive->media != ide_disk) {
-			pio = 0; /* cdroms don't like our fast mode */
-		} else {
-			struct hd_driveid *id = drive->id;
-			pio = id->tPIO;
-			if ((id->field_valid & 0x02) && (id->eide_pio_modes & 0x01))
-				pio = 3;
-		}
+		if (drive->media != ide_disk)
+			pio = 0; /* some cdroms don't like fast modes (?) */
+		else
+			pio = ide_get_best_pio_mode (drive);
 	}
-	hwif = HWIF(drive)->index;
+	if (pio > 5)
+		pio = 5;
 	unit = drive->select.b.unit;
-	if (pio < 3)
-		qd6560b_selects[hwif][unit] |= 0x20;
+	hwif = HWIF(drive)->index;
+	ht6560b_timings[hwif][unit] = pio_to_timings[pio];
+	if (pio == 0)
+		ht6560b_selects[hwif][unit] |= 0x20;
 	else
-		qd6560b_selects[hwif][unit] &= ~0x20;
+		ht6560b_selects[hwif][unit] &= ~0x20;
 }
 
 void init_ht6560b (void)
 {
-	if (check_region(0x3e6,1)) {
+	if (check_region(HT_SELECT_PORT,1)) {
 		printk("\nht6560b: PORT 0x3e6 ALREADY IN USE\n");
 	} else {
 		if (try_to_init_ht6560b()) {
-			request_region(0x3e6, 1, "ht6560b");
+			request_region(HT_SELECT_PORT, 1, ide_hwifs[0].name);
 			ide_hwifs[0].chipset = ide_ht6560b;
 			ide_hwifs[1].chipset = ide_ht6560b;
-			ide_hwifs[0].selectproc = &qd6560b_selectproc;
-			ide_hwifs[1].selectproc = &qd6560b_selectproc;
+			ide_hwifs[0].selectproc = &ht6560b_selectproc;
+			ide_hwifs[1].selectproc = &ht6560b_selectproc;
 			ide_hwifs[0].tuneproc = &tune_ht6560b;
 			ide_hwifs[1].tuneproc = &tune_ht6560b;
 			ide_hwifs[0].serialized = 1;
-		}
+		} else
+			printk("ht6560b: not found\n");
 	}
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v1.3.62/linux/drivers/block/ide-cd.c	Sun Feb 11 15:32:44 1996
+++ linux/drivers/block/ide-cd.c	Mon Feb 12 07:04:02 1996
@@ -84,6 +84,8 @@
  *                       Add NO_DOOR_LOCKING configuration option.
  *                       Handle drive_cmd requests w/NULL args (for hdparm -t).
  *                       Work around sporadic Sony55e audio play problem.
+ * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix
+ *                        problem with "hde=cdrom" with no drive present.  -ml
  *
  * NOTE: Direct audio reads will only work on some types of drive.
  * So far, i've received reports of success for Sony and Toshiba drives.
@@ -2664,8 +2666,12 @@
   CDROM_CONFIG_FLAGS (drive)->no_doorlock = 0;
 #endif
 
-  CDROM_CONFIG_FLAGS (drive)->drq_interrupt =
-    ((drive->id->config & 0x0060) == 0x20);
+  if (drive->id != NULL) {
+    CDROM_CONFIG_FLAGS (drive)->drq_interrupt =
+      ((drive->id->config & 0x0060) == 0x20);
+  } else {
+    CDROM_CONFIG_FLAGS (drive)->drq_interrupt = 0;
+  }
 
 #if ! STANDARD_ATAPI
   CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 0;
@@ -2674,52 +2680,54 @@
   CDROM_CONFIG_FLAGS (drive)->playmsf_uses_bcd = 0;
   CDROM_CONFIG_FLAGS (drive)->vertos_lossage = 0;
 
-  /* Accommodate some broken drives... */
-  if (strcmp (drive->id->model, "CD220E") == 0 ||
-      strcmp (drive->id->model, "CD")     == 0)        /* Creative Labs */
-    CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-
-  else if (strcmp (drive->id->model, "TO-ICSLYAL") == 0 ||  /* Acer CD525E */
-           strcmp (drive->id->model, "OTI-SCYLLA") == 0)
-    CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-
-  /* I don't know who makes this.
-     Francesco Messineo <sidera@ccii.unipi.it> says this one's broken too. */
-  else if (strcmp (drive->id->model, "DCI-2S10") == 0)
-    CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
+  if (drive->id != NULL) {
+    /* Accommodate some broken drives... */
+    if (strcmp (drive->id->model, "CD220E") == 0 ||
+        strcmp (drive->id->model, "CD")     == 0)        /* Creative Labs */
+      CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
 
-  else if (strcmp (drive->id->model, "CDA26803I SE") == 0) /* Aztech */
-    {
+    else if (strcmp (drive->id->model, "TO-ICSLYAL") == 0 ||  /* Acer CD525E */
+             strcmp (drive->id->model, "OTI-SCYLLA") == 0)
       CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
 
-      /* This drive _also_ does not implement PLAYAUDIO12 correctly. */
-      CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
-    }
+    /* I don't know who makes this.
+       Francesco Messineo <sidera@ccii.unipi.it> says this one's broken too. */
+    else if (strcmp (drive->id->model, "DCI-2S10") == 0)
+      CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
 
-  /* Vertos 300.
-     There seem to be at least two different, incompatible versions
-     of this drive floating around.  Luckily, they appear to return their
-     id strings with different byte orderings. */
-  else if (strcmp (drive->id->model, "V003S0DS") == 0)
-    {
-      CDROM_CONFIG_FLAGS (drive)->vertos_lossage = 1;
-      CDROM_CONFIG_FLAGS (drive)->playmsf_uses_bcd = 1;
+    else if (strcmp (drive->id->model, "CDA26803I SE") == 0) /* Aztech */
+      {
+        CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
+
+        /* This drive _also_ does not implement PLAYAUDIO12 correctly. */
+        CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
+      }
+
+    /* Vertos 300.
+       There seem to be at least two different, incompatible versions
+       of this drive floating around.  Luckily, they appear to return their
+       id strings with different byte orderings. */
+    else if (strcmp (drive->id->model, "V003S0DS") == 0)
+      {
+        CDROM_CONFIG_FLAGS (drive)->vertos_lossage = 1;
+        CDROM_CONFIG_FLAGS (drive)->playmsf_uses_bcd = 1;
+        CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
+      }
+    else if (strcmp (drive->id->model, "0V300SSD") == 0 ||
+  	   strcmp (drive->id->model, "V003M0DP") == 0)
+      CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
+
+    /* Vertos 400. */
+    else if (strcmp (drive->id->model, "V004E0DT") == 0 ||
+  	   strcmp (drive->id->model, "0V400ETD") == 0)
       CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-    }
-  else if (strcmp (drive->id->model, "0V300SSD") == 0 ||
-	   strcmp (drive->id->model, "V003M0DP") == 0)
-    CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-
-  /* Vertos 400. */
-  else if (strcmp (drive->id->model, "V004E0DT") == 0 ||
-	   strcmp (drive->id->model, "0V400ETD") == 0)
-    CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
 
-  else if ( strcmp (drive->id->model, "CD-ROM CDU55D") == 0) /*sony cdu55d */
-    CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
+    else if ( strcmp (drive->id->model, "CD-ROM CDU55D") == 0) /*sony cdu55d */
+      CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
 
- else if (strcmp (drive->id->model, "CD-ROM CDU55E") == 0)
-	CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
+   else if (strcmp (drive->id->model, "CD-ROM CDU55E") == 0)
+  	CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
+  } /* drive-id != NULL */
 #endif  /* not STANDARD_ATAPI */
 
   drive->cdrom_info.toc               = NULL;
diff -u --recursive --new-file v1.3.62/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
--- v1.3.62/linux/drivers/block/ide-tape.c	Tue Jan 23 21:15:37 1996
+++ linux/drivers/block/ide-tape.c	Mon Feb 12 07:31:54 1996
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/block/ide-tape.c	Version 1.2 - ALPHA	Jan   1, 1996
+ * linux/drivers/block/ide-tape.c	Version 1.3 - ALPHA	Feb   9, 1996
  *
  * Copyright (C) 1995, 1996 Gadi Oxman <tgud@tochnapc2.technion.ac.il>
  *
@@ -53,6 +53,8 @@
  *		integral number of the tape's recommended data transfer unit
  *		(which is shown on initialization and can be received with
  *		 an ioctl).
+ *		As of version 1.3 of the driver, this is no longer as critical
+ *		as it used to be.
  *	3.	No buffering is performed by the user backup program.
  *
  * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive.
@@ -161,6 +163,23 @@
  *                       The recommended user block size is returned by
  *                        the MTIOCGET ioctl.
  *                       Additional minor changes.
+ * Ver 1.3   Feb  9  96  Fixed pipelined read mode bug which prevented the
+ *                        use of some block sizes during a restore procedure.
+ *                       The character device interface will now present a
+ *                        continuous view of the media - any mix of block sizes
+ *                        during a backup/restore procedure is supported. The
+ *                        driver will buffer the requests internally and
+ *                        convert them to the tape's recommended transfer
+ *                        unit, making performance almost independent of the
+ *                        chosen user block size.
+ *                       Some improvements in error recovery.
+ *                       By cooperating with triton.c, bus mastering DMA can
+ *                        now sometimes be used with IDE tape drives as well.
+ *                        Bus mastering DMA has the potential to dramatically
+ *                        reduce the CPU's overhead when accessing the device,
+ *                        and can be enabled by using hdparm -d1 on the tape's
+ *                        block device interface. For more info, read the
+ *                        comments in triton.c.
  *
  * We are currently in an *alpha* stage. The driver is not complete and not
  * much tested. I would strongly suggest to:
@@ -279,6 +298,7 @@
  *		sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
  */
 
+#include <linux/config.h>
 #include <linux/hdreg.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -351,11 +371,6 @@
  *	device interface.
  */
 
-#define IDETAPE_INQUIRY_IOCTL		0x0341
-#define	IDETAPE_LOCATE_IOCTL		0x0342
-
-#define IDETAPE_RESET_IOCTL		0x0350
-
 /*
  *	Special requests for our block device strategy routine.
  *
@@ -663,13 +678,22 @@
 typedef struct {
 	unsigned error_code	:7;	/* Current of deferred errors */
 	unsigned valid		:1;	/* The information field conforms to QIC-157C */
-	byte reserved_1;		/* Segment Number - Reserved */
+	unsigned reserved_1	:8;	/* Segment Number - Reserved */
 	unsigned sense_key	:4;	/* Sense Key */
 	unsigned reserved2_4	:1;	/* Reserved */
 	unsigned ili		:1;	/* Incorrect Length Indicator */
 	unsigned eom		:1;	/* End Of Medium */
-	unsigned filemark	:1;	/* Filemark */
-	unsigned long information;	/* Information - Command specific */
+	unsigned filemark 	:1;	/* Filemark */
+
+	/*
+	 *	We can't use a 32 bit variable, since it will be re-aligned
+	 *	by GCC, as we are not on a 32 bit boundary.
+	 */
+
+	byte information1;		/* MSB - Information - Command specific */
+	byte information2;
+	byte information3;
+	byte information4;		/* LSB */
 	byte asl;			/* Additional sense length (n-7) */
 	unsigned long command_specific; /* Additional command specific information */
 	byte asc;			/* Additional Sense Code */
@@ -679,6 +703,7 @@
 	unsigned sksv		:1;	/* Sense Key Specific informatio is valid */
 	byte sk_specific2;		/* Sense Key Specific */
 	byte sk_specific3;		/* Sense Key Specific */
+	byte pad [2];			/* Padding to 20 bytes */
 } idetape_request_sense_result_t;
 
 /*
@@ -817,13 +842,6 @@
 struct request *idetape_next_rq_storage (ide_drive_t *drive);
 
 /*
- *	idetape_end_request is used to finish servicing a request, and to
- *	insert a pending pipeline request into the main device queue.
- */
- 
-void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup);
-
-/*
  *	Various packet commands
  */
  
@@ -857,9 +875,7 @@
  */
 
 int idetape_chrdev_read (struct inode *inode, struct file *file, char *buf, int count);
-int idetape_chrdev_read_remainder (struct inode *inode, struct file *file, char *buf, int count);
 int idetape_chrdev_write (struct inode *inode, struct file *file, const char *buf, int count);
-int idetape_chrdev_write_remainder (struct inode *inode, struct file *file, const char *buf, int count);
 int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
 int idetape_chrdev_open (struct inode *inode, struct file *file);
 void idetape_chrdev_release (struct inode *inode,struct file *file);
@@ -927,6 +943,8 @@
 unsigned long idetape_swap_long (unsigned long temp);
 unsigned short idetape_swap_short (unsigned short temp);
 
+#define IDETAPE_MIN(a,b)	((a)<(b) ? (a):(b))
+
 /*
  *	Pipeline related functions
  */
@@ -939,7 +957,8 @@
 void idetape_add_stage_tail (ide_drive_t *drive,idetape_pipeline_stage_t *stage);
 void idetape_remove_stage_head (ide_drive_t *drive);
 void idetape_active_next_stage (ide_drive_t *drive);
-void idetape_empty_read_pipeline (ide_drive_t *drive);
+void idetape_wait_for_pipeline (ide_drive_t *drive);
+void idetape_discard_read_pipeline (ide_drive_t *drive);
 void idetape_empty_write_pipeline (ide_drive_t *drive);
 void idetape_insert_pipeline_into_queue (ide_drive_t *drive);
 
@@ -1223,6 +1242,7 @@
 	tape->error_in_pipeline_stage=0;
 	tape->request_status=0;
 	tape->chrdev_direction=idetape_direction_none;
+	tape->reset_issued=0;
 
 #if IDETAPE_PIPELINE
 	tape->max_number_of_stages=IDETAPE_MIN_PIPELINE_STAGES;
@@ -1240,16 +1260,22 @@
 	if (tape->data_buffer_size % IDETAPE_ALLOCATION_BLOCK)
 		allocation_length+=IDETAPE_ALLOCATION_BLOCK;
 	
+#if IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE
+	tape->data_buffer=tape->merge_buffer=NULL;
+#else
 	tape->data_buffer=kmalloc (allocation_length,GFP_KERNEL);
-	tape->temp_data_buffer=kmalloc (allocation_length,GFP_KERNEL);
-	if (tape->data_buffer == NULL || tape->temp_data_buffer == NULL) {
+	tape->merge_buffer=kmalloc (allocation_length,GFP_KERNEL);
+	if (tape->data_buffer == NULL || tape->merge_buffer == NULL) {
 		printk ("ide-tape: FATAL - Can not allocate 2 buffers of %d bytes each\n",allocation_length);
 		printk ("ide-tape: Aborting character device installation\n");
 		idetape_drive_already_found=0;
 		unregister_chrdev (idetape_chrdev.major,idetape_chrdev.name);
 		return;
 	}
+#endif /* IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE */
 
+	tape->merge_buffer_size=tape->merge_buffer_offset=0;
+	
 #if IDETAPE_ANTICIPATE_READ_WRITE_DSC
 
 	/*
@@ -1428,13 +1454,14 @@
 {
 	idetape_tape_t *tape;
 	idetape_bcount_reg_t bcount;
-        idetape_ireason_reg_t ireason;
+	idetape_ireason_reg_t ireason;
+	int dma_ok=0;
 
 	tape=&(drive->tape);
 	        
 #if IDETAPE_DEBUG_BUGS
 	if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
-		printk ("ide-tape: ide-tape.c bug - Two request sense in serial were issued\n");
+		printk ("ide-tape: possible ide-tape.c bug - Two request sense in serial were issued\n");
 	}
 #endif /* IDETAPE_DEBUG_BUGS */
 
@@ -1447,7 +1474,8 @@
 		/*
 		 *	We will "abort" retrying a packet command in case
 		 *	a legitimate error code was received (crossing a
-		 *	filemark, for example). We will not log those errors.
+		 *	filemark, or DMA error in the end of media, for
+		 *	example).
 		 */
 
 		if (!pc->abort) {
@@ -1478,10 +1506,21 @@
  */
  
 	pc->actually_transferred=0;					/* We haven't transferred any data yet */
+	pc->current_position=pc->buffer;	
 	bcount.all=pc->request_transfer;				/* Request to transfer the entire buffer at once */
 
-									/* Initialize the task file registers */
-	OUT_BYTE (0,IDETAPE_FEATURES_REG);				/* Use PIO data transger, No DMA */
+#ifdef CONFIG_BLK_DEV_TRITON
+	if (pc->dma_error) {
+		printk ("ide-tape: DMA disabled, reverting to PIO\n");
+		drive->using_dma=0;
+		pc->dma_error=0;
+	}
+	if (pc->request_transfer && pc->dma_recommended && drive->using_dma) {
+		dma_ok=!(HWIF(drive)->dmaproc(pc->writing ? ide_dma_write : ide_dma_read, drive));
+	}		
+#endif /* CONFIG_BLK_DEV_TRITON */
+
+	OUT_BYTE (dma_ok ? 1:0,IDETAPE_FEATURES_REG);			/* Use PIO/DMA */
 	OUT_BYTE (bcount.b.high,IDETAPE_BCOUNTH_REG);
 	OUT_BYTE (bcount.b.low,IDETAPE_BCOUNTL_REG);
 	OUT_BYTE (drive->select.all,IDETAPE_DRIVESEL_REG);
@@ -1498,17 +1537,24 @@
 		 *	here anyway.
 		 */
 		 
-		 printk ("ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
-		 return;
+		printk ("ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
+		return;
 	}
 	
 	ireason.all=IN_BYTE (IDETAPE_IREASON_REG);
 	if (!ireason.b.cod || ireason.b.io) {
 		printk ("ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n");
-		/* ??? */
+		ide_do_reset (drive);
+		return;		
 	}
 		
 	ide_output_data (drive,pc->c,12/4);			/* Send the actual packet */
+#ifdef CONFIG_BLK_DEV_TRITON
+	if ((pc->dma_in_progress=dma_ok)) {			/* Begin DMA, if necessary */
+		pc->dma_error=0;
+		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
+	}
+#endif /* CONFIG_BLK_DEV_TRITON */
 }
 
 /*
@@ -1527,10 +1573,27 @@
 	idetape_tape_t *tape=&(drive->tape);
 	idetape_status_reg_t status;
 	idetape_bcount_reg_t bcount;
-        idetape_ireason_reg_t ireason;
+	idetape_ireason_reg_t ireason;
 	idetape_packet_command_t *pc=tape->pc;
 	unsigned long temp;
 
+#ifdef CONFIG_BLK_DEV_TRITON
+	if (pc->dma_in_progress) {
+		if ((pc->dma_error=HWIF(drive)->dmaproc(ide_dma_status_bad, drive)))
+			/*
+			 *	We will currently correct the following in
+			 *	idetape_analyze_error.
+			 */
+			pc->actually_transferred=HWIF(drive)->dmaproc(ide_dma_transferred, drive);
+		else
+			pc->actually_transferred=pc->request_transfer;
+		(void) (HWIF(drive)->dmaproc(ide_dma_abort, drive));	/* End DMA */
+#if IDETAPE_DEBUG_LOG
+		printk ("ide-tape: DMA finished\n");
+#endif /* IDETAPE_DEBUG_LOG */
+	}
+#endif /* CONFIG_BLK_DEV_TRITON */
+
 	status.all=IN_BYTE (IDETAPE_STATUS_REG);		/* Clear the interrupt */
 
 #if IDETAPE_DEBUG_LOG
@@ -1542,10 +1605,11 @@
 		printk ("Packet command completed\n");
 		printk ("Total bytes transferred: %lu\n",pc->actually_transferred);
 #endif /* IDETAPE_DEBUG_LOG */
-		
+		pc->dma_in_progress=0;
+						
 		sti ();
 
-		if (status.b.check) {					/* Error detected */
+		if (status.b.check || pc->dma_error) {			/* Error detected */
 #if IDETAPE_DEBUG_LOG
 	/*
 	 *	Without debugging, we only log an error if we decided to
@@ -1553,6 +1617,12 @@
 	 */
 			printk ("ide-tape: %s: I/O error, ",drive->name);
 #endif /* IDETAPE_DEBUG_LOG */
+			if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
+				printk ("ide-tape: I/O error in request sense command\n");
+				ide_do_reset (drive);
+				return;
+			}			
+						
 			idetape_retry_pc (drive);			/* Retry operation */
 			return;
 		}
@@ -1572,19 +1642,30 @@
 			(*pc->callback)(drive);			/* Command finished - Call the callback function */
 		return;
 	}
-
+#ifdef CONFIG_BLK_DEV_TRITON
+	if (pc->dma_in_progress) {
+		pc->dma_in_progress=0;
+		printk ("ide-tape: The tape wants to issue more interrupts in DMA mode\n");
+		printk ("ide-tape: DMA disabled, reverting to PIO\n");
+		drive->using_dma=0;
+		ide_do_reset (drive);
+		return;
+	}
+#endif /* CONFIG_BLK_DEV_TRITON */
 	bcount.b.high=IN_BYTE (IDETAPE_BCOUNTH_REG);			/* Get the number of bytes to transfer */
 	bcount.b.low=IN_BYTE (IDETAPE_BCOUNTL_REG);			/* on this interrupt */
 	ireason.all=IN_BYTE (IDETAPE_IREASON_REG);			/* Read the interrupt reason register */
 
 	if (ireason.b.cod) {
 		printk ("ide-tape: CoD != 0 in idetape_pc_intr\n");
-		/* ??? */
+		ide_do_reset (drive);
+		return;
 	}
 	if (ireason.b.io != !(pc->writing)) {			/* Hopefully, we will never get here */
 		printk ("ide-tape: We wanted to %s, ",pc->writing ? "Write":"Read");
 		printk ("but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write");
-		/* ??? */		
+		ide_do_reset (drive);
+		return;
 	}
 	
 	if (!pc->writing) {					/* Reading - Check that we have enough space */
@@ -2058,24 +2139,19 @@
 void idetape_read_callback (ide_drive_t *drive)
 
 {
-	idetape_tape_t *tape;
-	struct request *rq;
+	idetape_tape_t *tape=&(drive->tape);
+	struct request *rq=HWGROUP(drive)->rq;
+	int blocks_read=tape->pc->actually_transferred/tape->tape_block_size;
 
-	tape=&(drive->tape);	
-	rq=HWGROUP(drive)->rq;
 #if IDETAPE_DEBUG_LOG	
 	printk ("ide-tape: Reached idetape_read_callback\n");
 #endif /* IDETAPE_DEBUG_LOG */
-	tape->block_address+=tape->pc->actually_transferred/tape->tape_block_size;
-	if (!tape->pc->error) {
-#if IDETAPE_DEBUG_LOG
-		printk ("Request completed\n");
-#endif /* IDETAPE_DEBUG_LOG */
-		rq->sector+=rq->current_nr_sectors;
-		rq->nr_sectors-=rq->current_nr_sectors;
-		rq->current_nr_sectors=0;
+
+	tape->block_address+=blocks_read;
+	rq->current_nr_sectors-=blocks_read;	
+
+	if (!tape->pc->error)
 		idetape_end_request (1,HWGROUP (drive));
-	}
 	else {
 		rq->errors=tape->pc->error;
 		switch (rq->errors) {
@@ -2091,25 +2167,21 @@
 void idetape_write_callback (ide_drive_t *drive)
 
 {
-	idetape_tape_t *tape;
-	struct request *rq;
-	
-	tape=&(drive->tape);
-	rq=HWGROUP(drive)->rq;
+	idetape_tape_t *tape=&(drive->tape);
+	struct request *rq=HWGROUP(drive)->rq;
+	int blocks_written=tape->pc->actually_transferred/tape->tape_block_size;
+		
 #if IDETAPE_DEBUG_LOG	
 	printk ("ide-tape: Reached idetape_write_callback\n");
 #endif /* IDETAPE_DEBUG_LOG */
-	tape->block_address+=tape->pc->actually_transferred/tape->tape_block_size;
-	if (!tape->pc->error) {
-#if IDETAPE_DEBUG_LOG
-		printk ("Request completed\n");
-#endif /* IDETAPE_DEBUG_LOG */
-		rq->sector+=rq->current_nr_sectors;
-		rq->nr_sectors-=rq->current_nr_sectors;
-		rq->current_nr_sectors=0;
+
+	tape->block_address+=blocks_written;
+	rq->current_nr_sectors-=blocks_written;
+
+	if (!tape->pc->error)
 		idetape_end_request (1,HWGROUP (drive));
-	}
 	else {
+		rq->errors=tape->pc->error;
 		idetape_end_request (0,HWGROUP (drive));
 	}
 	return;
@@ -2200,7 +2272,7 @@
 	pc->callback=&idetape_inquiry_callback;
 	pc->writing=0;
 	
-	idetape_zero_packet_command (pc);		
+	idetape_zero_packet_command (pc);
 	pc->c[0]=IDETAPE_INQUIRY_CMD;
 	pc->c[4]=255;
 }
@@ -2355,14 +2427,29 @@
 		if (result->filemark) {
 			pc->error=IDETAPE_RQ_ERROR_FILEMARK;
 			pc->abort=1;
-			return;
 		}
+	}
+
+	if (pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) {
 		if (result->sense_key == 8) {
 			pc->error=IDETAPE_RQ_ERROR_EOD;
 			pc->abort=1;
-			return;
 		}
 	}
+
+#if 1
+#ifdef CONFIG_BLK_DEV_TRITON
+
+	/*
+	 *	Correct pc->actually_transferred by asking the tape.
+	 */
+
+	if (pc->dma_error && pc->abort) {
+		unsigned long *long_ptr=(unsigned long *) &(result->information1);
+		pc->actually_transferred=pc->request_transfer-tape->tape_block_size*idetape_swap_long (*long_ptr);
+	}		
+#endif /* CONFIG_BLK_DEV_TRITON */
+#endif
 }
 
 void idetape_create_test_unit_ready_cmd (idetape_packet_command_t *pc)
@@ -2546,12 +2633,16 @@
 	pc->writing=0;
 
 	idetape_zero_packet_command (pc);
+
 	pc->c [0]=IDETAPE_READ_CMD;
 	pc->c [1]=1;
 	pc->c [4]=original.b.b1;
 	pc->c [3]=original.b.b2;
 	pc->c [2]=original.b.b3;
 
+	if (length)
+		pc->dma_recommended=1;
+
 	return;
 }
 
@@ -2616,12 +2707,16 @@
 	pc->writing=1;
 
 	idetape_zero_packet_command (pc);
+
 	pc->c [0]=IDETAPE_WRITE_CMD;
 	pc->c [1]=1;
 	pc->c [4]=original.b.b1;
 	pc->c [3]=original.b.b2;
 	pc->c [2]=original.b.b3;
 
+	if (length)
+		pc->dma_recommended=1;
+
 	return;
 }
 
@@ -2699,7 +2794,6 @@
 			unsigned int cmd, unsigned long arg)
 {
 	idetape_packet_command_t pc;
-	int retval;
 	
 	pc.buffer=pc.temp_buffer;
 	pc.buffer_size=IDETAPE_TEMP_BUFFER_SIZE;
@@ -2709,33 +2803,6 @@
 	printk ("ide-tape: Reached idetape_blkdev_ioctl\n");
 #endif /* IDETAPE_DEBUG_LOG */
 	switch (cmd) {
-		case IDETAPE_INQUIRY_IOCTL:
-#if IDETAPE_DEBUG_LOG
-			printk ("Adding INQUIRY packet command to the tail of the request queue\n");
-#endif /* IDETAPE_DEBUG_LOG */
-			idetape_create_inquiry_cmd (&pc);
-			pc.buffer=pc.temp_buffer;
-			pc.buffer_size=IDETAPE_TEMP_BUFFER_SIZE;
-			pc.current_position=pc.temp_buffer;
-			return (idetape_queue_pc_tail (drive,&pc));
-		case IDETAPE_LOCATE_IOCTL:
-#if IDETAPE_DEBUG_LOG
-			printk ("Adding LOCATE packet command to the tail of the request queue\n");
-#endif /* IDETAPE_DEBUG_LOG */
-			idetape_create_locate_cmd (&pc,arg,0);
-			retval=idetape_queue_pc_tail (drive,&pc);
-			if (retval!=0) return (retval);
-			
-			idetape_create_read_position_cmd (&pc);
-			pc.buffer=pc.temp_buffer;
-			pc.buffer_size=IDETAPE_TEMP_BUFFER_SIZE;
-			pc.current_position=pc.temp_buffer;
-			return (idetape_queue_pc_tail (drive,&pc));
-/*
-		case IDETAPE_RESET_IOCTL:
-			printk ("Resetting drive\n");
-			return (!ide_do_reset (drive));
-*/
 		default:
 			return -EIO;
 	}
@@ -2757,6 +2824,7 @@
 	idetape_tape_t *tape = &(drive->tape);
 	unsigned int major = HWIF(drive)->major;
 	struct blk_dev_struct *bdev = &blk_dev[major];
+	int error;
 
 #if IDETAPE_DEBUG_LOG
 	printk ("Reached idetape_end_request\n");
@@ -2766,7 +2834,8 @@
 
 	if (!rq->errors)				/* In case rq->errors is already set, */
 		rq->errors=!uptodate;			/* we won't change it. */
-	
+	error=rq->errors;
+		
 	if (tape->active_data_request == rq) {		/* The request was a pipelined data transfer request */
 
 		if (rq->cmd == IDETAPE_READ_REQUEST) {
@@ -2783,12 +2852,13 @@
 
 		if (rq->cmd == IDETAPE_WRITE_REQUEST) {
 			if (rq->errors)
-				tape->error_in_pipeline_stage=1;
+				tape->error_in_pipeline_stage=rq->errors;
 			idetape_remove_stage_head (drive);
 		}
 		
 		if (tape->next_stage == NULL) {
-			idetape_increase_max_pipeline_stages (drive);
+			if (!error)
+				idetape_increase_max_pipeline_stages (drive);
 			ide_end_drive_cmd (drive, 0, 0);
 			return;
 		}
@@ -2904,10 +2974,22 @@
 		 
 		 tape->postponed_rq = NULL;
 	}	
+
+	status.all=IN_BYTE (IDETAPE_STATUS_REG);
+
+	/*
+	 *	After a software reset, the status register is locked. We
+	 *	will ignore the DSC value for our very first packet command,
+	 *	which will restore DSC operation.
+	 */
+
+	if (tape->reset_issued) {
+		status.b.dsc=1;
+		tape->reset_issued=0;
+	}
 	
 	switch (rq->cmd) {
 		case IDETAPE_READ_REQUEST:
-			status.all=IN_BYTE (IDETAPE_STATUS_REG);
 			if (!status.b.dsc) {				/* Tape buffer not ready to accept r/w command */
 #if IDETAPE_DEBUG_LOG
 				printk ("ide-tape: DSC != 1 - Postponing read request\n");
@@ -2930,7 +3012,6 @@
 			return;
 		
 		case IDETAPE_WRITE_REQUEST:
-			status.all=IN_BYTE (IDETAPE_STATUS_REG);
 			if (!status.b.dsc) {				/* Tape buffer not ready to accept r/w command */
 #if IDETAPE_DEBUG_LOG
 				printk ("ide-tape: DSC != 1 - Postponing write request\n");
@@ -2959,7 +3040,6 @@
  *	but I have occasionally missed DSC on a media access command otherwise.
  *	??? Still have to figure it out ...
  */
-			status.all=IN_BYTE (IDETAPE_STATUS_REG);
 			if (!status.b.dsc) {				/* Tape buffers are still not ready */
 #if IDETAPE_DEBUG_LOG
 				printk ("ide-tape: DSC != 1 - Postponing packet command request\n");
@@ -3072,13 +3152,8 @@
 }
 
 /*
- *	idetape_queue_rw_tail is typically called from the character device
- *	interface to generate a read/write request for the block device interface
- *	and wait for it to be serviced. Note that cmd will be different than
- *	a buffer cache originated read/write request. This will be used
- *	in idetape_end_request.
- *
- *	Returns 0 on success or -EIO if an error occured.
+ *	idetape_queue_rw_tail generates a read/write request for the block
+ *	device interface and wait for it to be serviced.
  */
 
 int idetape_queue_rw_tail (ide_drive_t *drive,int cmd,int blocks,char *buffer)
@@ -3090,16 +3165,21 @@
 #if IDETAPE_DEBUG_LOG
 	printk ("idetape_queue_rw_tail: cmd=%d\n",cmd);
 #endif /* IDETAPE_DEBUG_LOG */
-	/* build up a special read request, and add it to the queue */
-	
+#if IDETAPE_DEBUG_BUGS
+	if (tape->active_data_request != NULL) {
+		printk ("ide-tape: bug: the pipeline is active in idetape_queue_rw_tail\n");
+		return (0);
+	}
+#endif /* IDETAPE_DEBUG_BUGS */	
+
 	ide_init_drive_cmd (&rq);
 	rq.buffer = buffer;
 	rq.cmd = cmd;
 	rq.sector = tape->block_address;
-	rq.nr_sectors = blocks;
-	rq.current_nr_sectors = blocks;
-	tape->active_data_request=NULL;	/* Non-pipelined mode */
-	return ide_do_drive_cmd (drive, &rq, ide_wait);
+	rq.nr_sectors = rq.current_nr_sectors = blocks;
+	(void) ide_do_drive_cmd (drive, &rq, ide_wait);
+
+	return (tape->tape_block_size*(blocks-rq.current_nr_sectors));
 }
 
 /*
@@ -3113,8 +3193,8 @@
 	idetape_tape_t *tape = &(drive->tape);
 	idetape_pipeline_stage_t *new_stage;
 	unsigned long flags;
-	struct request rq;
-	int errors;
+	struct request rq,*rq_ptr;
+	int bytes_read;
 	
 #if IDETAPE_DEBUG_LOG
 	printk ("Reached idetape_add_chrdev_read_request\n");
@@ -3123,8 +3203,7 @@
 	ide_init_drive_cmd (&rq);
 	rq.cmd = IDETAPE_READ_REQUEST;
 	rq.sector = tape->block_address;
-	rq.nr_sectors = blocks;
-	rq.current_nr_sectors = blocks;
+	rq.nr_sectors = rq.current_nr_sectors = blocks;
 
 	if (tape->current_number_of_stages < 0.5*tape->max_number_of_stages) {
 		new_stage=idetape_kmalloc_stage (drive);
@@ -3154,12 +3233,19 @@
 		idetape_wait_for_request (tape->active_data_request);
 	restore_flags (flags);
 
-	errors=tape->first_stage->rq.errors;
-	if (!errors)		
-		idetape_copy_buffer_from_stage (tape->first_stage,buffer);
-
-	idetape_remove_stage_head (drive);
-	return (errors ? -EIO:0);
+	rq_ptr=&(tape->first_stage->rq);
+	bytes_read=tape->tape_block_size*(rq_ptr->nr_sectors-rq_ptr->current_nr_sectors);
+	rq_ptr->nr_sectors=rq_ptr->current_nr_sectors=0;
+	idetape_copy_buffer_from_stage (tape->first_stage,buffer);
+	if (rq_ptr->errors != IDETAPE_RQ_ERROR_FILEMARK)
+		idetape_remove_stage_head (drive);
+#if IDETAPE_DEBUG_BUGS
+	if (bytes_read > blocks*tape->tape_block_size) {
+		printk ("ide-tape: bug: trying to return more bytes than requested\n");
+		bytes_read=blocks*tape->tape_block_size;
+	}
+#endif /* IDETAPE_DEBUG_BUGS */
+	return (bytes_read);
 }
 
 /*
@@ -3186,8 +3272,6 @@
 	printk ("Reached idetape_add_chrdev_write_request\n");
 #endif /* IDETAPE_DEBUG_LOG */
 	
-	if (tape->error_in_pipeline_stage)		/* Return a deferred error */
-		return (-EIO);
 	
 	new_stage=idetape_kmalloc_stage (drive);
 
@@ -3242,10 +3326,15 @@
 	if (tape->active_data_request == NULL && tape->current_number_of_stages >= 0.75*tape->max_number_of_stages)
 		idetape_insert_pipeline_into_queue (drive);		
 
-	return (0);		
+	if (tape->error_in_pipeline_stage) {		/* Return a deferred error */
+		tape->error_in_pipeline_stage=0;
+		return (-EIO);
+	}
+	
+	return (blocks);
 }
 
-void idetape_empty_read_pipeline (ide_drive_t *drive)
+void idetape_discard_read_pipeline (ide_drive_t *drive)
 
 {
 	idetape_tape_t *tape = &(drive->tape);
@@ -3253,11 +3342,14 @@
 
 #if IDETAPE_DEBUG_BUGS
 	if (tape->chrdev_direction != idetape_direction_read) {
-		printk ("ide-tape: bug: Trying to empty read pipeline, but we are not reading.\n");
+		printk ("ide-tape: bug: Trying to discard read pipeline, but we are not reading.\n");
 		return;
 	}
 #endif /* IDETAPE_DEBUG_BUGS */
 
+	tape->merge_buffer_size=tape->merge_buffer_offset=0;
+	tape->chrdev_direction=idetape_direction_none;
+	
 	if (tape->first_stage == NULL)
 		return;
 		
@@ -3277,23 +3369,23 @@
 #endif /* IDETAPE_PIPELINE */
 }
 
-
-void idetape_empty_write_pipeline (ide_drive_t *drive)
+/*
+ *	idetape_wait_for_pipeline will wait until all pending pipeline
+ *	requests are serviced. Typically called on device close.
+ */
+ 
+void idetape_wait_for_pipeline (ide_drive_t *drive)
 
 {
 	idetape_tape_t *tape = &(drive->tape);
 	unsigned long flags;
 
-#if IDETAPE_DEBUG_BUGS
-	if (tape->chrdev_direction != idetape_direction_write) {
-		printk ("ide-tape: bug: Trying to empty write pipeline, but we are not writing.\n");
-		return;
-	}
-#endif /* IDETAPE_DEBUG_BUGS */
-
 	if (tape->active_data_request == NULL)
 		idetape_insert_pipeline_into_queue (drive);		
 
+	if (tape->active_data_request == NULL)
+		return;
+
 	save_flags (flags);cli ();
 	if (tape->last_stage != NULL)
 		idetape_wait_for_request (&(tape->last_stage->rq));
@@ -3301,8 +3393,39 @@
 	else if (tape->active_data_request != NULL)
 		idetape_wait_for_request (tape->active_data_request);
 	restore_flags (flags);
+}
+
+void idetape_empty_write_pipeline (ide_drive_t *drive)
+
+{
+	idetape_tape_t *tape = &(drive->tape);
+	int blocks;
 	
+#if IDETAPE_DEBUG_BUGS
+	if (tape->chrdev_direction != idetape_direction_write) {
+		printk ("ide-tape: bug: Trying to empty write pipeline, but we are not writing.\n");
+		return;
+	}
+	if (tape->merge_buffer_size > tape->data_buffer_size) {
+		printk ("ide-tape: bug: merge_buffer too big\n");
+		tape->merge_buffer_size = tape->data_buffer_size;
+	}
+#endif /* IDETAPE_DEBUG_BUGS */
+
+	if (tape->merge_buffer_size) {
+		blocks=tape->merge_buffer_size/tape->tape_block_size;
+		if (tape->merge_buffer_size % tape->tape_block_size) {
+			blocks++;
+			memset (tape->merge_buffer+tape->merge_buffer_size,0,tape->data_buffer_size-tape->merge_buffer_size);
+		}
+		(void) idetape_add_chrdev_write_request (drive,blocks,tape->merge_buffer);
+		tape->merge_buffer_size=0;
+	}
+	
+	idetape_wait_for_pipeline (drive);
+
 	tape->error_in_pipeline_stage=0;
+	tape->chrdev_direction=idetape_direction_none;
 
 	/*
 	 *	On the next backup, perform the feedback loop again.
@@ -3316,7 +3439,6 @@
 #else
 	tape->max_number_of_stages=0;
 #endif /* IDETAPE_PIPELINE */
-
 #if IDETAPE_DEBUG_BUGS
 	if (tape->first_stage != NULL || tape->next_stage != NULL || tape->last_stage != NULL || tape->current_number_of_stages != 0) {
 		printk ("ide-tape: ide-tape pipeline bug\n");		
@@ -3324,7 +3446,6 @@
 #endif /* IDETAPE_DEBUG_BUGS */
 }
 
-
 /*
  *	idetape_zero_packet_command just zeros a packet command and
  *	sets the number of retries to 0, as we haven't retried it yet.
@@ -3339,6 +3460,8 @@
 		pc->c[i]=0;
 	pc->retries=0;
 	pc->abort=0;
+	pc->dma_recommended=0;
+	pc->dma_error=0;
 }
 
 /*
@@ -3494,27 +3617,20 @@
  *	Our character device read / write functions.
  *
  *	The tape is optimized to maximize throughput when it is transfering
- *	an integral number of the "continous transfer limit", which is
- *	a parameter of the specific tape (26 KB on my particular tape). The
- *	resulting increase in performance should be dramatical. In the
- *	character device read/write functions, we split the current
- *	request to units of the above size, and handle the remaining bytes
- *	in some other sub-functions.
- *
- *	In case the count number is not even an integral number of the tape
- *	block size (usually 512 or 1024 bytes), we will pad the transfer with
- *	zeroes (write) or read the entire block and return only the requested
- *	bytes (but the tape will be in the "wrong" position). Do not supply
- *	such a count value unless you are going to close the device right
- *	after this request.
+ *	an integral number of the "continuous transfer limit", which is
+ *	a parameter of the specific tape (26 KB on my particular tape).
  *
- *	Again, for best results use an integral number of the tape's parameter
+ *	For best results use an integral number of the tape's parameter
  *	(which is displayed in the driver installation stage and is returned
  *	 by the MTIOCGET ioctl).
- */
-
-/*
- *	Our character device read function.
+ *
+ *	As of version 1.3 of the driver, the character device provides an
+ *	abstract continuous view of the media - any mix of block sizes (even 1
+ *	byte) on the same backup/restore procedure is supported. The driver
+ *	will internally convert the requests to the recommended transfer unit,
+ *	so that an unmatch between the user's block size to the recommended
+ *	size will only result in a (slightly) increased driver overhead, but
+ *	will no longer hit performance.
  */
 
 int idetape_chrdev_read (struct inode *inode, struct file *file, char *buf, int count)
@@ -3522,9 +3638,8 @@
 {
 	ide_drive_t *drive=idetape_chrdev.drive;
 	idetape_tape_t *tape=&(drive->tape);
-	int blocks,remainder,retval;
-	char *buf_ptr;
-	unsigned long previous_block_address,actually_read;
+	char *buf_ptr=buf;
+	int bytes_read,temp,actually_read=0;
 
 #if IDETAPE_DEBUG_LOG
 	printk ("Reached idetape_chrdev_read\n");
@@ -3542,9 +3657,9 @@
 		 *	mode.
 		 */
 		 
-		retval=idetape_queue_rw_tail (drive,IDETAPE_READ_REQUEST,0,tape->temp_data_buffer);
-		if (retval)
-			return (retval);
+		bytes_read=idetape_queue_rw_tail (drive,IDETAPE_READ_REQUEST,0,tape->merge_buffer);
+		if (bytes_read < 0)
+			return (bytes_read);
 
 		tape->chrdev_direction=idetape_direction_read;
 	}
@@ -3552,97 +3667,55 @@
 	if (count==0)
 		return (0);
 
-	actually_read=0;
-	buf_ptr=buf;
-	blocks=count/tape->data_buffer_size;
-	remainder=count%tape->data_buffer_size;
-	
-	while (blocks) {
-		previous_block_address=tape->block_address;
-		retval=idetape_add_chrdev_read_request (drive,tape->capabilities.ctl,tape->temp_data_buffer);
-		if (tape->max_number_of_stages)
-			actually_read+=tape->data_buffer_size;
-		else
-			actually_read+=tape->tape_block_size*(tape->block_address-previous_block_address);
-
-		if (retval) {
-			if (tape->max_number_of_stages)
-				return (0);
-			else
-				return (actually_read);
+	if (tape->merge_buffer_size) {
+#if IDETAPE_DEBUG_BUGS
+		if (tape->merge_buffer_offset+tape->merge_buffer_size > tape->data_buffer_size) {
+			printk ("ide-tape: bug: merge buffer too big\n");
+			tape->merge_buffer_offset=0;tape->merge_buffer_size=tape->data_buffer_size-1;
 		}
-		memcpy_tofs (buf_ptr,tape->temp_data_buffer,tape->data_buffer_size);
-		buf_ptr+=tape->data_buffer_size;
-		blocks--;
+#endif /* IDETAPE_DEBUG_BUGS */
+		actually_read=IDETAPE_MIN (tape->merge_buffer_size,count);
+		memcpy_tofs (buf_ptr,tape->merge_buffer+tape->merge_buffer_offset,actually_read);
+		buf_ptr+=actually_read;tape->merge_buffer_size-=actually_read;
+		count-=actually_read;tape->merge_buffer_offset+=actually_read;
+	}
+
+	while (count >= tape->data_buffer_size) {
+		bytes_read=idetape_add_chrdev_read_request (drive,tape->capabilities.ctl,tape->merge_buffer);
+		if (bytes_read <= 0)
+			return (actually_read);
+		memcpy_tofs (buf_ptr,tape->merge_buffer,bytes_read);
+		buf_ptr+=bytes_read;count-=bytes_read;actually_read+=bytes_read;
+	}
+
+	if (count) {
+		bytes_read=idetape_add_chrdev_read_request (drive,tape->capabilities.ctl,tape->merge_buffer);
+		if (bytes_read <= 0)
+			return (actually_read);
+		temp=IDETAPE_MIN (count,bytes_read);
+		memcpy_tofs (buf_ptr,tape->merge_buffer,temp);
+		actually_read+=temp;
+		tape->merge_buffer_offset=temp;
+		tape->merge_buffer_size=bytes_read-temp;
 	}
-	if (remainder)
-		return (actually_read+idetape_chrdev_read_remainder (inode,file,buf_ptr,remainder));
-	else
-		return (actually_read);		
+	return (actually_read);
 }
  
-int idetape_chrdev_read_remainder (struct inode *inode, struct file *file, char *buf, int count)
+int idetape_chrdev_write (struct inode *inode, struct file *file, const char *buf, int count)
 
 {
 	ide_drive_t *drive=idetape_chrdev.drive;
 	idetape_tape_t *tape=&(drive->tape);
-	int blocks,remainder,retval;
-	unsigned long previous_block_address,actually_read;
-
-#if IDETAPE_DEBUG_LOG
-	printk ("Reached idetape_chrdev_read_remainder\n");
-#endif /* IDETAPE_DEBUG_LOG */
-
-	blocks=count/tape->tape_block_size;
-	remainder=count%tape->tape_block_size;
-	if (remainder) {
-#if IDETAPE_DEBUG_LOG
-	printk ("ide-tape: Padding read to block boundary\n");
-#endif /* IDETAPE_DEBUG_LOG */
-		blocks++;
-	}
-#if IDETAPE_DEBUG_LOG
-	printk ("Adding a READ request to the block device request queue\n");
-#endif /* IDETAPE_DEBUG_LOG */
-	previous_block_address=tape->block_address;
-	retval=idetape_add_chrdev_read_request (drive,blocks,tape->temp_data_buffer);
-	if (retval) {
-		if (tape->max_number_of_stages)
-			actually_read=0;
-		else
-			actually_read=tape->tape_block_size*(tape->block_address-previous_block_address);
-		if (actually_read > count)
-			actually_read=count;
-		if (actually_read != 0)
-			memcpy_tofs (buf,tape->temp_data_buffer,actually_read);
-		return (actually_read);
-	}
-#if IDETAPE_DEBUG_LOG
-	printk ("Copying %d bytes to the user space memory\n",count);
-#endif /* IDETAPE_DEBUG_LOG */
-	memcpy_tofs (buf,tape->temp_data_buffer,count);
-	return (count);
-}
-
-int idetape_chrdev_write (struct inode *inode, struct file *file, const char *buf, int count)
-
-{
-	ide_drive_t *drive;
-	idetape_tape_t *tape;
-	int blocks,remainder,retval;
-	const char *buf_ptr;
-	unsigned long previous_block_address,actually_written;
+	const char *buf_ptr=buf;
+	int retval,actually_written=0;
 
 #if IDETAPE_DEBUG_LOG
 	printk ("Reached idetape_chrdev_write\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
-	drive=idetape_chrdev.drive;
-	tape=&(drive->tape);
-
 	if (tape->chrdev_direction != idetape_direction_write) {	/* Initialize write operation */
 		if (tape->chrdev_direction == idetape_direction_read)
-			idetape_empty_read_pipeline (drive);
+			idetape_discard_read_pipeline (drive);
 
 		/*
 		 *	Issue a write 0 command to ensure that DSC handshake
@@ -3650,93 +3723,51 @@
 		 *	mode.
 		 */
 
-		retval=idetape_queue_rw_tail (drive,IDETAPE_WRITE_REQUEST,0,tape->temp_data_buffer);
-		if (retval)
+		retval=idetape_queue_rw_tail (drive,IDETAPE_WRITE_REQUEST,0,tape->merge_buffer);
+		if (retval < 0)
 			return (retval);		
-	
+
 		tape->chrdev_direction=idetape_direction_write;
 	}
 
 	if (count==0)
 		return (0);
 
-	actually_written=0;
-	buf_ptr=buf;
-	blocks=count/tape->data_buffer_size;
-	remainder=count%tape->data_buffer_size;
-
-	while (blocks) {
-		memcpy_fromfs (tape->temp_data_buffer,buf_ptr,tape->data_buffer_size);
-		buf_ptr+=tape->data_buffer_size;
-		previous_block_address=tape->block_address;
-		retval=idetape_add_chrdev_write_request (drive,tape->capabilities.ctl,tape->temp_data_buffer);
-		if (tape->max_number_of_stages)
-			actually_written+=tape->data_buffer_size;	/* Pipelined mode - Cheat :-) */
-		else
-			actually_written+=tape->tape_block_size*(tape->block_address-previous_block_address);
+	if (tape->merge_buffer_size) {
+#if IDETAPE_DEBUG_BUGS
+		if (tape->merge_buffer_size >= tape->data_buffer_size) {
+			printk ("ide-tape: bug: merge buffer too big\n");
+			tape->merge_buffer_size=0;
+		}
+#endif /* IDETAPE_DEBUG_BUGS */
 
-		if (retval) {
-			if (tape->max_number_of_stages)
-				return (0);
-			else
-				return (actually_written);
+		actually_written=IDETAPE_MIN (tape->data_buffer_size-tape->merge_buffer_size,count);
+		memcpy_fromfs (tape->merge_buffer+tape->merge_buffer_size,buf_ptr,actually_written);
+		buf_ptr+=actually_written;tape->merge_buffer_size+=actually_written;count-=actually_written;
+
+		if (tape->merge_buffer_size == tape->data_buffer_size) {
+			tape->merge_buffer_size=0;
+			retval=idetape_add_chrdev_write_request (drive,tape->capabilities.ctl,tape->merge_buffer);
+			if (retval <= 0)
+				return (retval);
 		}
-		blocks--;
 	}
-	if (remainder)
-		return (actually_written+idetape_chrdev_write_remainder (inode,file,buf_ptr,remainder));
-	else
-		return (actually_written);		
-}
-
-int idetape_chrdev_write_remainder (struct inode *inode, struct file *file, const char *buf, int count)
-
-{
-	ide_drive_t *drive;
-	idetape_tape_t *tape;
-	int blocks,remainder,retval;
-	char *ptr;
-	unsigned long previous_block_address,actually_written;
-
-#if IDETAPE_DEBUG_LOG
-	printk ("Reached idetape_chrdev_write_remainder\n");
-#endif /* IDETAPE_DEBUG_LOG */
-		
-	drive=idetape_chrdev.drive;
-	tape=&(drive->tape);
-
-	blocks=count/tape->tape_block_size;
-	remainder=count%tape->tape_block_size;
-	if (remainder)
-		blocks++;
-#if IDETAPE_DEBUG_LOG
-	printk ("Copying %d bytes from the user space memory\n",count);
-#endif /* IDETAPE_DEBUG_LOG */
 
-	memcpy_fromfs (tape->temp_data_buffer,buf,count);
-	if (remainder) {
-#if IDETAPE_DEBUG_LOG
-	printk ("ide-tape: Padding written data to block boundary\n");
-#endif /* IDETAPE_DEBUG_LOG */
-		ptr=tape->temp_data_buffer+(blocks-1)*tape->tape_block_size;
-		memset (ptr,0,remainder);
+	while (count >= tape->data_buffer_size) {
+		memcpy_fromfs (tape->merge_buffer,buf_ptr,tape->data_buffer_size);
+		buf_ptr+=tape->data_buffer_size;count-=tape->data_buffer_size;
+		retval=idetape_add_chrdev_write_request (drive,tape->capabilities.ctl,tape->merge_buffer);
+		actually_written+=tape->data_buffer_size;
+		if (retval <= 0)
+			return (retval);
 	}
-#if IDETAPE_DEBUG_LOG
-	printk ("Adding a WRITE request to the block device request queue\n");
-#endif /* IDETAPE_DEBUG_LOG */
 
-	previous_block_address=tape->block_address;
-	retval=idetape_add_chrdev_write_request (drive,blocks,tape->temp_data_buffer);
-	if (retval) {
-		if (tape->max_number_of_stages)
-			actually_written=0;
-		else
-			actually_written=tape->tape_block_size*(tape->block_address-previous_block_address);
-		if (actually_written > count)
-			actually_written=count;
-		return (actually_written);
+	if (count) {
+		actually_written+=count;
+		memcpy_fromfs (tape->merge_buffer,buf_ptr,count);
+		tape->merge_buffer_size+=count;
 	}
-	return (count);
+	return (actually_written);
 }
 
 /*
@@ -3788,14 +3819,10 @@
 	if (tape->chrdev_direction == idetape_direction_write) {
 		idetape_empty_write_pipeline (drive);
 		idetape_flush_tape_buffers (drive);
-		tape->chrdev_direction=idetape_direction_none;
 	}
 
-	if (tape->chrdev_direction == idetape_direction_read)
-		if (cmd != MTIOCTOP) {
-			idetape_empty_read_pipeline (drive);
-			tape->chrdev_direction=idetape_direction_none;
-		}
+	if (tape->chrdev_direction == idetape_direction_read && cmd != MTIOCTOP)
+		idetape_discard_read_pipeline (drive);
 	
 	pc.buffer=pc.temp_buffer;
 	pc.buffer_size=IDETAPE_TEMP_BUFFER_SIZE;
@@ -3904,6 +3931,8 @@
 		case MTFSFM:
 		case MTBSF:
 		case MTBSFM:
+			if (!mt_count)
+				return (0);
 			return (idetape_space_over_filemarks (drive,mt_op,mt_count));
 		default:
 			break;
@@ -3913,10 +3942,8 @@
 	 *	Empty the pipeline.
 	 */
 
-	if (tape->chrdev_direction == idetape_direction_read) {
-		idetape_empty_read_pipeline (drive);
-		tape->chrdev_direction=idetape_direction_none;
-	}
+	if (tape->chrdev_direction == idetape_direction_read)
+		idetape_discard_read_pipeline (drive);
 
 	switch (mt_op) {
 		case MTWEOF:
@@ -3976,7 +4003,8 @@
 		 *	We have a read-ahead buffer. Scan it for crossed
 		 *	filemarks.
 		 */
-		 
+
+		tape->merge_buffer_size=tape->merge_buffer_offset=0;
 		while (tape->first_stage != NULL) {
 			
 			/*
@@ -4003,7 +4031,7 @@
 			}
 			idetape_remove_stage_head (drive);
 		}
-		tape->chrdev_direction = idetape_direction_none;
+		idetape_discard_read_pipeline (drive);
 	}
 
 	/*
@@ -4049,10 +4077,10 @@
 int idetape_chrdev_open (struct inode *inode, struct file *filp)
 
 {
-	ide_drive_t *drive;
-	idetape_tape_t *tape;
+	ide_drive_t *drive=idetape_chrdev.drive;
+	idetape_tape_t *tape=&(drive->tape);
 	unsigned long flags;
-	unsigned int minor;
+	unsigned int minor=MINOR (inode->i_rdev),allocation_length;
 			
 	save_flags (flags);cli ();
 
@@ -4060,11 +4088,6 @@
 	printk ("Reached idetape_chrdev_open\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
-
-	drive=idetape_chrdev.drive;
-	tape=&(drive->tape);
-	minor=MINOR (inode->i_rdev);
-
 	if (minor!=0 && minor!=128) {		/* Currently supporting only one */
 		restore_flags (flags);		/* tape drive */
 		return (-ENXIO);
@@ -4078,6 +4101,26 @@
 	tape->busy=1;
 	restore_flags (flags);
 
+	allocation_length=tape->data_buffer_size;
+	if (tape->data_buffer_size % IDETAPE_ALLOCATION_BLOCK)
+		allocation_length+=IDETAPE_ALLOCATION_BLOCK;
+
+#if IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE
+	if (tape->data_buffer == NULL)
+		tape->data_buffer=kmalloc (allocation_length,GFP_KERNEL);
+	if (tape->data_buffer == NULL)
+		goto sorry;
+	if (tape->merge_buffer == NULL)
+		tape->merge_buffer=kmalloc (allocation_length,GFP_KERNEL);
+	if (tape->merge_buffer == NULL) {
+		kfree (tape->data_buffer);
+	sorry:
+		printk ("ide-tape: FATAL - Can not allocate continuous buffer of %d bytes\n",allocation_length);
+		tape->busy=0;
+		return (-EIO);
+	}
+#endif /* IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE */
+
 	if (!tape->block_address_valid) {
 		if (idetape_rewind_tape (drive)) {
 			printk ("ide-tape: Rewinding tape failed\n");
@@ -4096,10 +4139,9 @@
 void idetape_chrdev_release (struct inode *inode, struct file *filp)
 
 {
-	ide_drive_t *drive;
-	idetape_tape_t *tape;
-	
-	unsigned int minor;
+	ide_drive_t *drive=idetape_chrdev.drive;
+	idetape_tape_t *tape=&(drive->tape);
+	unsigned int minor=MINOR (inode->i_rdev);
 	idetape_packet_command_t pc;
 	unsigned long flags;
 			
@@ -4107,28 +4149,32 @@
 	printk ("Reached idetape_chrdev_release\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
-	drive=idetape_chrdev.drive;
-	tape=&(drive->tape);
-	minor=MINOR (inode->i_rdev);
-
 	if (tape->chrdev_direction == idetape_direction_write) {
 		idetape_empty_write_pipeline (drive);
-		tape->chrdev_direction = idetape_direction_none;
 		idetape_create_write_filemark_cmd (&pc,1);	/* Write a filemark */
-		if (idetape_queue_pc_tail (drive,&pc)) {
+		if (idetape_queue_pc_tail (drive,&pc))
 			printk ("ide-tape: Couldn't write a filemark\n");
-			/* ??? */
-		}
 	}
-
-	if (minor < 128) {
-		if (tape->chrdev_direction == idetape_direction_read)
-			idetape_empty_read_pipeline (drive);
-		if (idetape_rewind_tape (drive)) {
+	
+	if (tape->chrdev_direction == idetape_direction_read) {
+		if (minor < 128)
+			idetape_discard_read_pipeline (drive);
+		else
+			idetape_wait_for_pipeline (drive);
+	}
+	
+	if (minor < 128)
+		if (idetape_rewind_tape (drive))
 			printk ("ide-tape: Rewinding tape failed\n");
-			/* ??? */
-		}
+
+#if IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE
+	kfree (tape->data_buffer);
+	tape->data_buffer=NULL;
+	if (!tape->merge_buffer_size) {
+		kfree (tape->merge_buffer);
+		tape->merge_buffer=NULL;
 	}
+#endif /* IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE */
 
 	save_flags (flags);cli ();
 	tape->busy=0;
@@ -4307,7 +4353,7 @@
 
 /*
  *	idetape_copy_buffer_from_stage and idetape_copy_buffer_to_stage
- *	copy data from/to the small buffers into/from a continous buffer.
+ *	copy data from/to the small buffers into/from a continuous buffer.
  */
   
 void idetape_copy_buffer_from_stage (idetape_pipeline_stage_t *stage,char *buffer)
diff -u --recursive --new-file v1.3.62/linux/drivers/block/ide-tape.h linux/drivers/block/ide-tape.h
--- v1.3.62/linux/drivers/block/ide-tape.h	Thu Jan  4 21:54:54 1996
+++ linux/drivers/block/ide-tape.h	Mon Feb 12 07:04:02 1996
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/block/ide-tape.h	Version 1.2 - ALPHA	Jan   1, 1996
+ * linux/drivers/block/ide-tape.h	Version 1.3 - ALPHA	Feb   9, 1996
  *
  * Copyright (C) 1995, 1996 Gadi Oxman <tgud@tochnapc2.technion.ac.il>
  */
@@ -97,6 +97,20 @@
 #endif
 
 /*
+ *	ide-tape currently uses two continous buffers, each of the size of
+ *	one stage. By default, those buffers are allocated at initialization
+ *	time and never released, since dynamic allocation of pages bigger
+ *	than PAGE_SIZE may fail as memory becomes fragmented.
+ *
+ *	This results in about 100 KB memory usage when the tape is idle.
+ *	Setting IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE to 1 will let ide-tape
+ *	to dynamically allocate those buffers, resulting in about 20 KB idle
+ *	memory usage.
+ */
+ 
+#define	IDETAPE_MINIMIZE_IDLE_MEMORY_USAGE	0
+
+/*
  *	The following are used to debug the driver:
  *
  *	Setting IDETAPE_DEBUG_LOG to 1 will log driver flow control.
@@ -124,7 +138,7 @@
  *	Setting IDETAPE_MAX_PC_RETRIES to 0 will disable retries.
  */
 
-#define	IDETAPE_MAX_PC_RETRIES	2
+#define	IDETAPE_MAX_PC_RETRIES	3
 
 /*
  *	With each packet command, we allocate a buffer of
@@ -256,6 +270,9 @@
 	byte error;				/* Error code */
 	byte abort;				/* Set when an error is considered normal - We won't retry */
 	byte wait_for_dsc;			/* 1 When polling for DSC on a media access command */
+	byte dma_recommended;			/* 1 when we prefer to use DMA if possible */
+	byte dma_in_progress;			/* 1 while DMA in progress */
+	byte dma_error;				/* 1 when encountered problem during DMA */
 	unsigned long request_transfer;		/* Bytes to transfer */
 	unsigned long actually_transferred; 	/* Bytes actually transferred */
 	unsigned long buffer_size;		/* Size of our data buffer */
@@ -419,6 +436,14 @@
 	byte last_status;			/* Contents of the tape status register */
 						/* before the current request (saved for us */
 						/* by ide.c) */
+	/*
+	 *	After an ATAPI software reset, the status register will be
+	 *	locked, and thus we need to ignore it when checking DSC for
+	 *	the first time.
+	 */
+	 
+	byte reset_issued;
+
 	/* Position information */
 	
 	byte partition_num;			/* Currently not used */
@@ -456,8 +481,11 @@
 	struct request *active_data_request;	/* Pointer to the request which is waiting in the device request queue */
 	char *data_buffer;			/* The correspoding data buffer (for read/write requests) */
 	int data_buffer_size;			/* Data buffer size (chosen based on the tape's recommendation */
-	char *temp_data_buffer;			/* Temporary buffer for user <-> kernel space data transfer */
 
+	char *merge_buffer;			/* Temporary buffer for user <-> kernel space data transfer */
+	int merge_buffer_offset;
+	int merge_buffer_size;
+	
 	/*
 	 *	Pipeline parameters.
 	 *
diff -u --recursive --new-file v1.3.62/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v1.3.62/linux/drivers/block/ide.c	Fri Feb  9 17:53:01 1996
+++ linux/drivers/block/ide.c	Mon Feb 12 07:04:02 1996
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c	Version 5.27  Feb  8, 1996
+ *  linux/drivers/block/ide.c	Version 5.28  Feb 11, 1996
  *
  *  Copyright (C) 1994-1996  Linus Torvalds & authors (see below)
  */
@@ -200,6 +200,11 @@
  *			add  ali14xx support in ali14xx.c
  * Version 5.27		add [no]autotune parameters to help cmd640
  *			move rz1000  support to rz1000.c
+ * Version 5.28		#include "ide_modes.h"
+ *			fix disallow_unmask: now per-interface "no_unmask" bit
+ *			force io_32bit to be the same on drive pairs of dtc2278
+ *			improved IDE tape error handling, and tape DMA support
+ *			bugfix in ide_do_drive_cmd() for cdroms + serialize
  *
  *  Some additional driver compile-time options are in ide.h
  *
@@ -237,13 +242,13 @@
 #endif /* CONFIG_PCI */
 
 #include "ide.h"
+#include "ide_modes.h"
 
-static ide_hwgroup_t	*irq_to_hwgroup [16];
+static ide_hwgroup_t	*irq_to_hwgroup [NR_IRQS];
 static const byte	ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};
 
 static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168};
 static const byte	default_irqs[MAX_HWIFS]     = {14, 15, 11, 10};
-       int		ide_disallow_unmask = 0;	/* for buggy hardware */
 
 #if (DISK_RECOVERY_TIME > 0)
 /*
@@ -302,7 +307,7 @@
 		return;		/* already initialized */
 	magic_cookie = 0;
 
-	for (h = 0; h < 16; ++h)
+	for (h = 0; h < NR_IRQS; ++h)
 		 irq_to_hwgroup[h] = NULL;
 
 	/* bulk initialize hwif & drive info with zeros */
@@ -311,10 +316,10 @@
 		*--p = 0;
 	} while (p > (byte *) ide_hwifs);
 
+	/* fill in any non-zero initial values */
 	for (h = 0; h < MAX_HWIFS; ++h) {
 		ide_hwif_t *hwif = &ide_hwifs[h];
 
-		/* fill in any non-zero initial values */
 		hwif->index     = h;
 		hwif->noprobe	= (h > 1);
 		hwif->io_base	= default_io_base[h];
@@ -334,7 +339,6 @@
 		for (unit = 0; unit < MAX_DRIVES; ++unit) {
 			ide_drive_t *drive = &hwif->drives[unit];
 
-			/* fill in any non-zero initial values */
 			drive->select.all		= (unit<<4)|0xa0;
 			drive->hwif			= hwif;
 			drive->ctl			= 0x08;
@@ -349,7 +353,7 @@
 	}
 }
 
-#define VLB_SYNC 1
+#if SUPPORT_VLB_SYNC
 /*
  * Some localbus EIDE interfaces require a special access sequence
  * when using 32-bit I/O instructions to transfer data.  We call this
@@ -362,6 +366,7 @@
 	(void) inb (port);
 	(void) inb (port);
 }
+#endif /* SUPPORT_VLB_SYNC */
 
 /*
  * This is used for most PIO data transfers *from* the IDE interface
@@ -373,7 +378,7 @@
 	byte io_32bit = drive->io_32bit;
 
 	if (io_32bit) {
-#ifdef VLB_SYNC
+#if SUPPORT_VLB_SYNC
 		if (io_32bit & 2) {
 			cli();
 			do_vlb_sync(io_base+IDE_NSECTOR_OFFSET);
@@ -381,7 +386,7 @@
 			if (drive->unmask)
 				sti();
 		} else
-#endif /* VLB_SYNC */
+#endif /* SUPPORT_VLB_SYNC */
 			insl(data_reg, buffer, wcount);
 	} else
 		insw(data_reg, buffer, wcount<<1);
@@ -397,7 +402,7 @@
 	byte io_32bit = drive->io_32bit;
 
 	if (io_32bit) {
-#ifdef VLB_SYNC
+#if SUPPORT_VLB_SYNC
 		if (io_32bit & 2) {
 			cli();
 			do_vlb_sync(io_base+IDE_NSECTOR_OFFSET);
@@ -405,7 +410,7 @@
 			if (drive->unmask)
 				sti();
 		} else
-#endif /* VLB_SYNC */
+#endif /* SUPPORT_VLB_SYNC */
 			outsl(data_reg, buffer, wcount);
 	} else
 		outsw(data_reg, buffer, wcount<<1);
@@ -723,6 +728,10 @@
 void ide_do_reset (ide_drive_t *drive)
 {
 	do_reset1 (drive, 0);
+#ifdef CONFIG_BLK_DEV_IDETAPE
+	if (drive->media == ide_tape)
+		drive->tape.reset_issued=1;
+#endif /* CONFIG_BLK_DEV_IDETAPE */
 }
 
 /*
@@ -851,7 +860,8 @@
 	if ((rq = HWGROUP(drive)->rq) == NULL || drive == NULL)
 		return;
 	/* retry only "normal" I/O: */
-	if (rq->cmd != READ && rq->cmd != WRITE && drive->media != ide_cdrom) {
+	if (rq->cmd == IDE_DRIVE_CMD || (rq->cmd != READ && rq->cmd != WRITE && drive->media == ide_disk))
+	{
 		rq->errors = 1;
 		ide_end_drive_cmd(drive, stat, err);
 		return;
@@ -872,8 +882,16 @@
 	if (GET_STAT() & (BUSY_STAT|DRQ_STAT))
 		rq->errors |= ERROR_RESET;	/* Mmmm.. timing problem */
 
-	if (rq->errors >= ERROR_MAX)
-		ide_end_request(0, HWGROUP(drive));
+	if (rq->errors >= ERROR_MAX) {
+#ifdef CONFIG_BLK_DEV_IDETAPE
+		if (drive->media == ide_tape) {
+			rq->errors = 0;
+			idetape_end_request(0, HWGROUP(drive));
+		}
+		else
+#endif /* CONFIG_BLK_DEV_IDETAPE */
+ 		ide_end_request(0, HWGROUP(drive));
+	}
 	else {
 		if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
 			++rq->errors;
@@ -1347,6 +1365,12 @@
 #endif /* CONFIG_BLK_DEV_IDECD */
 #ifdef CONFIG_BLK_DEV_IDETAPE
 			case ide_tape:
+				if (rq->cmd == IDE_DRIVE_CMD) {
+					byte *args = (byte *) rq->buffer;
+					OUT_BYTE(args[2],IDE_FEATURE_REG);
+					ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
+					return;
+				}
 				idetape_do_request (drive, rq, block);
 				return;
 #endif /* CONFIG_BLK_DEV_IDETAPE */
@@ -1656,9 +1680,13 @@
 	if (cur_rq == NULL || action == ide_preempt) {
 		rq->next = cur_rq;
 		bdev->current_request = rq;
-		HWGROUP(drive)->rq = NULL;
-		if (action != ide_preempt)
+		if (action == ide_preempt) {
+			HWGROUP(drive)->rq = NULL;
+		} else
+		if (HWGROUP(drive)->rq == NULL) {  /* is this necessary (?) */
 			bdev->request_fn();
+			cli();
+		}
 	} else {
 		if (action == ide_wait || action == ide_end) {
 			while (cur_rq->next != NULL)	/* find end of list */
@@ -1667,7 +1695,7 @@
 		rq->next = cur_rq->next;
 		cur_rq->next = rq;
 	}
-	if (action == ide_wait)
+	if (action == ide_wait  && rq->rq_status != RQ_INACTIVE)
 		down(&sem);	/* wait for it to be serviced */
 	restore_flags(flags);
 	return rq->errors ? -EIO : 0;	/* return -EIO if errors */
@@ -1879,8 +1907,10 @@
 			return write_fs_long(arg, drive->bad_wstat == BAD_R_STAT);
 
 		case HDIO_SET_DMA:
-			if (drive->media != ide_disk)
+#ifdef CONFIG_BLK_DEV_IDECD
+			if (drive->media == ide_cdrom)
 				return -EPERM;
+#endif /* CONFIG_BLK_DEV_IDECD */
 			if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc)
 				return -EPERM;
 		case HDIO_SET_KEEPSETTINGS:
@@ -1907,7 +1937,7 @@
 					drive->keep_settings = arg;
 					break;
 				case HDIO_SET_UNMASKINTR:
-					if (arg && ide_disallow_unmask) {
+					if (arg && HWIF(drive)->no_unmask) {
 						restore_flags(flags);
 						return -EPERM;
 					}
@@ -1917,11 +1947,13 @@
 					drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
 					break;
 				case HDIO_SET_32BIT:
+					if (arg > (1 + (SUPPORT_VLB_SYNC<<1)))
+						return -EINVAL;
 					drive->io_32bit = arg;
-#ifndef VLB_SYNC
-					if (arg & 2)
-						printk("%s: VLB_SYNC not supported by this kernel\n", drive->name);
-#endif
+#ifdef CONFIG_BLK_DEV_DTC2278
+					if (HWIF(drive)->chipset == ide_dtc2278)
+						HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;
+#endif /* CONFIG_BLK_DEV_DTC2278 */
 					break;
 			}
 			restore_flags(flags);
@@ -1932,7 +1964,7 @@
 				return -EACCES;
 			if (MINOR(inode->i_rdev) & PARTN_MASK)
 				return -EINVAL;
-			if ((drive->id != NULL) && (arg > drive->id->max_multsect))
+			if (drive->id && arg > drive->id->max_multsect)
 				return -EINVAL;
 			save_flags(flags);
 			cli();
@@ -2093,15 +2125,19 @@
 #endif /* CONFIG_BLK_DEV_IDECD */
 			case 1:
 #ifdef CONFIG_BLK_DEV_IDETAPE
-				printk ("TAPE drive\n");
+				printk ("TAPE drive");
 				if (idetape_identify_device (drive,id)) {
 					drive->media = ide_tape;
 					drive->present = 1;
 					drive->removeable = 1;
+					if (HWIF(drive)->dmaproc != NULL &&
+					    !HWIF(drive)->dmaproc(ide_dma_check, drive))
+						printk(", DMA");
+					printk("\n");
 				}
 				else {
 					drive->present = 0;
-					printk ("ide-tape: The tape is not supported by this version of the driver\n");
+					printk ("\nide-tape: the tape is not supported by this version of the driver\n");
 				}
 				return;
 #else
@@ -2249,7 +2285,7 @@
 	if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
 		cli();			/* some systems need this */
 		do_identify(drive, cmd); /* drive returned ID */
-		if (drive->present && (drive->media == ide_disk || drive->media == ide_cdrom)) {
+		if (drive->present && drive->media != ide_tape) {
 			ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
 			if (tuneproc != NULL && drive->autotune == 1)
 				tuneproc(drive, 255);	/* auto-tune PIO mode */
diff -u --recursive --new-file v1.3.62/linux/drivers/block/ide.h linux/drivers/block/ide.h
--- v1.3.62/linux/drivers/block/ide.h	Fri Feb  9 17:53:01 1996
+++ linux/drivers/block/ide.h	Wed Feb 14 13:21:30 1996
@@ -25,6 +25,9 @@
 #undef REALLY_FAST_IO			/* define if ide ports are perfect */
 #define INITIAL_MULT_COUNT	0	/* off=0; on=2,4,8,16,32, etc.. */
 
+#ifndef SUPPORT_VLB_SYNC		/* 1 to support weird 32-bit chips */
+#define SUPPORT_VLB_SYNC	1	/* 0 to reduce kernel size */
+#endif
 #ifndef DISK_RECOVERY_TIME		/* off=0; on=access_delay_time */
 #define DISK_RECOVERY_TIME	0	/*  for hardware that needs it */
 #endif
@@ -347,7 +350,12 @@
  * Returns 1 if DMA read/write could not be started, in which case the caller
  * should either try again later, or revert to PIO for the current request.
  */
-typedef enum {ide_dma_read = 0, ide_dma_write = 1, ide_dma_abort = 2, ide_dma_check = 3} ide_dma_action_t;
+typedef enum {	ide_dma_read = 0,	ide_dma_write = 1,
+		ide_dma_abort = 2,	ide_dma_check = 3,
+		ide_dma_status_bad = 4,	ide_dma_transferred = 5,
+		ide_dma_begin = 6 }
+	ide_dma_action_t;
+
 typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
 
 
@@ -401,6 +409,7 @@
 	unsigned	noprobe : 1;	/* don't probe for this interface */
 	unsigned	present : 1;	/* this interface exists */
 	unsigned	serialized : 1;	/* valid only for ide_hwifs[0] */
+	unsigned	no_unmask : 1;	/* disallow setting unmask bits */
 #if (DISK_RECOVERY_TIME > 0)
 	unsigned long	last_time;	/* time when previous rq was done */
 #endif
@@ -615,6 +624,13 @@
  */
 
 void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long block);
+
+/*
+ *	idetape_end_request is used to finish servicing a request, and to
+ *	insert a pending pipeline request into the main device queue.
+ */
+ 
+void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup);
 
 /*
  *	Block device interface functions.
diff -u --recursive --new-file v1.3.62/linux/drivers/block/ide_modes.h linux/drivers/block/ide_modes.h
--- v1.3.62/linux/drivers/block/ide_modes.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/block/ide_modes.h	Mon Feb 12 07:04:02 1996
@@ -0,0 +1,142 @@
+#ifndef _IDE_MODES_H
+#define _IDE_MODES_H
+/*
+ *  linux/drivers/block/ide_modes.h
+ *
+ *  Copyright (C) 1996  Linus Torvalds, Igor Abramov, and Mark Lord
+ */
+
+/*
+ * Shared data/functions for determining best PIO mode for an IDE drive.
+ * Most of this stuff originally lived in cmd640.c, and changes to the
+ * ide_pio_blacklist[] table should be made with EXTREME CAUTION to avoid
+ * breaking the fragile cmd640.c support.
+ */
+
+#if defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS)
+
+#ifndef _IDE_C
+
+int ide_scan_pio_blacklist (char *model);
+unsigned int ide_get_best_pio_mode (ide_drive_t *drive);
+
+#else /* _IDE_C */
+
+/*
+ * Black list. Some drives incorrectly report their maximal PIO mode,
+ * at least in respect to CMD640. Here we keep info on some known drives.
+ */
+static struct ide_pio_info {
+	const char	*name;
+	int		pio;
+} ide_pio_blacklist [] = {
+/*	{ "Conner Peripherals 1275MB - CFS1275A", 4 }, */
+
+	{ "WDC AC2700",  3 },
+	{ "WDC AC2540",  3 },
+	{ "WDC AC2420",  3 },
+	{ "WDC AC2340",  3 },
+	{ "WDC AC2250",  0 },
+	{ "WDC AC2200",  0 },
+	{ "WDC AC2120",  0 },
+	{ "WDC AC2850",  3 },
+	{ "WDC AC1270",  3 },
+	{ "WDC AC1170",  3 },
+	{ "WDC AC1210",  1 },
+	{ "WDC AC280",   0 },
+/*	{ "WDC AC21000", 4 }, */
+	{ "WDC AC31000", 3 },
+/*	{ "WDC AC21200", 4 }, */
+	{ "WDC AC31200", 3 },
+/*	{ "WDC AC31600", 4 }, */
+
+	{ "Maxtor 7131 AT", 1 },
+	{ "Maxtor 7171 AT", 1 },
+	{ "Maxtor 7213 AT", 1 },
+	{ "Maxtor 7245 AT", 1 },
+	{ "Maxtor 7345 AT", 1 },
+	{ "Maxtor 7546 AT", 3 },
+	{ "Maxtor 7540 AV", 3 },
+
+	{ "SAMSUNG SHD-3121A", 1 },
+	{ "SAMSUNG SHD-3122A", 1 },
+	{ "SAMSUNG SHD-3172A", 1 },
+
+/*	{ "ST51080A", 4 },
+ *	{ "ST51270A", 4 },
+ *	{ "ST31220A", 4 },
+ *	{ "ST31640A", 4 },
+ *	{ "ST32140A", 4 },
+ *	{ "ST3780A",  4 },
+ */
+	{ "ST5660A",  3 },
+	{ "ST3660A",  3 },
+	{ "ST3630A",  3 },
+	{ "ST3655A",  3 },
+	{ "ST3391A",  3 },
+	{ "ST3390A",  1 },
+	{ "ST3600A",  1 },
+	{ "ST3290A",  0 },
+	{ "ST3144A",  0 },
+
+	{ "QUANTUM ELS127A", 0 },
+	{ "QUANTUM ELS170A", 0 },
+	{ "QUANTUM LPS240A", 0 },
+	{ "QUANTUM LPS210A", 3 },
+	{ "QUANTUM LPS270A", 3 },
+	{ "QUANTUM LPS365A", 3 },
+	{ "QUANTUM LPS540A", 3 },
+	{ "QUANTUM FIREBALL", 3 }, /* For models 540/640/1080/1280 */
+				   /* 1080A works fine in mode4 with triton */
+	{ NULL,	0 }
+};
+
+/*
+ * This routine searches the ide_pio_blacklist for an entry
+ * matching the start/whole of the supplied model name.
+ *
+ * Returns -1 if no match found.
+ * Otherwise returns the recommended PIO mode from ide_pio_blacklist[].
+ */
+int ide_scan_pio_blacklist (char *model)
+{
+	struct ide_pio_info *p;
+
+	for (p = ide_pio_blacklist; p->name != NULL; p++) {
+		if (strncmp(p->name, model, strlen(p->name)) == 0)
+			return p->pio;
+	}
+	return -1;
+}
+
+/*
+ * This routine returns the recommended PIO mode for a given drive,
+ * based on the drive->id information and the ide_pio_blacklist[].
+ * This is used by most chipset support modules when "auto-tuning".
+ */
+unsigned int ide_get_best_pio_mode (ide_drive_t *drive)
+{
+	unsigned int pio = 0;
+	struct hd_driveid *id = drive->id;
+
+	if (id != NULL) {
+		if (HWIF(drive)->chipset != ide_cmd640 && !strcmp("QUANTUM FIREBALL1080A", id->model))
+			pio = 4;
+		else
+			pio = ide_scan_pio_blacklist(id->model);
+		if (pio == -1) {
+			pio = (id->tPIO < 2) ? id->tPIO : 2;
+			if (id->field_valid & 2) {
+				byte modes = id->eide_pio_modes;
+				if      (modes & 4)	pio = 5;
+				else if (modes & 2)	pio = 4;
+				else if (modes & 1)	pio = 3;
+			}
+		}
+	}
+	return pio;
+}
+
+#endif /* _IDE_C */
+#endif /* defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) */
+#endif /* _IDE_MODES_H */
diff -u --recursive --new-file v1.3.62/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v1.3.62/linux/drivers/block/ll_rw_blk.c	Fri Jan 26 01:37:05 1996
+++ linux/drivers/block/ll_rw_blk.c	Wed Feb 14 11:26:09 1996
@@ -24,7 +24,12 @@
 /*
  * The request-struct contains all necessary data
  * to load a nr of sectors into memory
+ *
+ * NR_REQUEST is the number of entries in the request-queue.
+ * NOTE that writes may use only the low 2/3 of these: reads
+ * take precedence.
  */
+#define NR_REQUEST	16
 static struct request all_requests[NR_REQUEST];
 
 /*
@@ -37,34 +42,10 @@
 int read_ahead[MAX_BLKDEV] = {0, };
 
 /* blk_dev_struct is:
- *	do_request-address
- *	next-request
+ *	*request_fn
+ *	*current_request
  */
-struct blk_dev_struct blk_dev[MAX_BLKDEV] = {
-	{ NULL, NULL },		/* 0 no_dev */
-	{ NULL, NULL },		/* 1 dev mem */
-	{ NULL, NULL },		/* 2 dev fd */
-	{ NULL, NULL },		/* 3 dev ide0 or hd */
-	{ NULL, NULL },		/* 4 dev ttyx */
-	{ NULL, NULL },		/* 5 dev tty */
-	{ NULL, NULL },		/* 6 dev lp */
-	{ NULL, NULL },		/* 7 dev pipes */
-	{ NULL, NULL },		/* 8 dev sd */
-	{ NULL, NULL },		/* 9 dev st */
-	{ NULL, NULL },		/* 10 */
-	{ NULL, NULL },		/* 11 */
-	{ NULL, NULL },		/* 12 */
-	{ NULL, NULL },		/* 13 */
-	{ NULL, NULL },		/* 14 */
-	{ NULL, NULL },		/* 15 */
-	{ NULL, NULL },		/* 16 */
-	{ NULL, NULL },		/* 17 */
-	{ NULL, NULL },		/* 18 */
-	{ NULL, NULL },		/* 19 */
-	{ NULL, NULL },		/* 20 */
-	{ NULL, NULL },		/* 21 */
-	{ NULL, NULL }		/* 22 dev ide1 */
-};
+struct blk_dev_struct blk_dev[MAX_BLKDEV]; /* initialized by blk_dev_init() */
 
 /*
  * blk_size contains the size of all block-devices in units of 1024 byte
@@ -610,6 +591,12 @@
 int blk_dev_init(void)
 {
 	struct request * req;
+	struct blk_dev_struct *dev;
+
+	for (dev = blk_dev + MAX_BLKDEV; dev-- != blk_dev;) {
+		dev->request_fn      = NULL;
+		dev->current_request = NULL;
+	}
 
 	req = all_requests + NR_REQUEST;
 	while (--req >= all_requests) {
@@ -634,6 +621,9 @@
 #else
 	outb_p(0xc, 0x3f2);
 #endif
+#ifdef CONFIG_CDI_INIT
+	cdi_init();
+#endif CONFIG_CDI_INIT
 #ifdef CONFIG_CDU31A
 	cdu31a_init();
 #endif CONFIG_CDU31A
diff -u --recursive --new-file v1.3.62/linux/drivers/block/qd6580.c linux/drivers/block/qd6580.c
--- v1.3.62/linux/drivers/block/qd6580.c	Fri Feb  9 17:53:01 1996
+++ linux/drivers/block/qd6580.c	Mon Feb 12 07:04:03 1996
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/qd6580.c       Version 0.01  Feb 06, 1996
+ *  linux/drivers/block/qd6580.c       Version 0.02  Feb 09, 1996
  *
  *  Copyright (C) 1996  Linus Torvalds & author (see below)
  */
@@ -21,6 +21,7 @@
 #include <linux/hdreg.h>
 #include <asm/io.h>
 #include "ide.h"
+#include "ide_modes.h"
 
 /*
  * Register 0xb3 looks like:
@@ -43,19 +44,16 @@
 {
 	unsigned long flags;
 
-	if (pio == 255)  {	/* auto-tune */
-		struct hd_driveid *id = drive->id;
-		pio = id->tPIO;
-		if ((id->field_valid & 0x02) && (id->eide_pio_modes & 0x03))
-			pio = 3;
-	}
-	pio++;	/* is this correct? */
+	if (pio == 255)
+		pio = ide_get_best_pio_mode (drive);
+	if (pio > 3)
+		pio = 3;
 
 	save_flags(flags);
 	cli();
 	outb_p(0x8d,0xb0);
 	outb_p(0x0 ,0xb2);
-	outb_p((pio<<4)|0x0f,0xb3);
+	outb_p(((pio+1)<<4)|0x0f,0xb3);
 	inb(0x3f6);
 	restore_flags(flags);
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/block/rz1000.c linux/drivers/block/rz1000.c
--- v1.3.62/linux/drivers/block/rz1000.c	Fri Feb  9 17:53:01 1996
+++ linux/drivers/block/rz1000.c	Mon Feb 12 07:04:03 1996
@@ -45,8 +45,8 @@
 		if ((rc = pcibios_read_config_word(bus, fn, 0x40, &reg))
 		 || (rc =  pcibios_write_config_word(bus, fn, 0x40, reg & 0xdfff)))
 		{
-			extern int ide_disallow_unmask;
-			ide_disallow_unmask = 1;
+			ide_hwifs[0].no_unmask = 1;
+			ide_hwifs[1].no_unmask = 1;
 			ide_hwifs[0].serialized = 1;
 			ide_pci_access_error (rc);
 			printk("serialized, disabled unmasking\n");
diff -u --recursive --new-file v1.3.62/linux/drivers/block/triton.c linux/drivers/block/triton.c
--- v1.3.62/linux/drivers/block/triton.c	Fri Feb  9 17:53:01 1996
+++ linux/drivers/block/triton.c	Mon Feb 12 07:32:44 1996
@@ -95,6 +95,7 @@
  *
  * And, yes, Intel Zappa boards really *do* use the Triton IDE ports.
  */
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
@@ -116,7 +117,8 @@
  * of drives which do not support mword2 DMA but which are
  * known to work fine with this interface under Linux.
  */
-const char *good_dma_drives[] = {"Micropolis 2112A"};
+const char *good_dma_drives[] = {"Micropolis 2112A",
+				 "CONNER CTMA 4000"};
 
 /*
  * Our Physical Region Descriptor (PRD) table should be large enough
@@ -184,8 +186,13 @@
 		 * is always composed of two adjacent physical 4kB pages rather
 		 * than two possibly non-adjacent physical 4kB pages.
 		 */
-		if (bh == NULL) {  /* paging requests have (rq->bh == NULL) */
+		if (bh == NULL) {  /* paging and tape requests have (rq->bh == NULL) */
 			addr = virt_to_bus (rq->buffer);
+#ifdef CONFIG_BLK_DEV_IDETAPE
+			if (drive->media == ide_tape)
+				size = drive->tape.pc->request_transfer;
+			else
+#endif /* CONFIG_BLK_DEV_IDETAPE */	
 			size = rq->nr_sectors << 9;
 		} else {
 			/* group sequential buffers into one large buffer */
@@ -255,6 +262,10 @@
  * sector address using CHS or LBA.  All that remains is to prepare for DMA
  * and then issue the actual read/write DMA/PIO command to the drive.
  *
+ * For ATAPI devices, we just prepare for DMA and return. The caller should
+ * then issue the packet command to the drive and call us again with
+ * ide_dma_begin afterwards.
+ *
  * Returns 0 if all went well.
  * Returns 1 if DMA read/write could not be started, in which case
  * the caller should revert to PIO for the current request.
@@ -274,6 +285,17 @@
 			reading = 0;
 		case ide_dma_read:
 			break;
+		case ide_dma_status_bad:
+			return ((inb(dma_base+2) & 7) != 4);	/* verify good DMA status */
+		case ide_dma_transferred:
+#if 0
+			return (number of bytes actually transferred);
+#else
+			return (0);
+#endif
+		case ide_dma_begin:
+			outb(inb(dma_base)|1, dma_base);	/* begin DMA */
+			return 0;
 		default:
 			printk("triton_dmaproc: unsupported func: %d\n", func);
 			return 1;
@@ -283,6 +305,10 @@
 	outl(virt_to_bus (HWIF(drive)->dmatable), dma_base + 4); /* PRD table */
 	outb(reading, dma_base);			/* specify r/w */
 	outb(0x26, dma_base+2);				/* clear status bits */
+#ifdef CONFIG_BLK_DEV_IDEATAPI
+	if (drive->media != ide_disk)
+		return 0;
+#endif /* CONFIG_BLK_DEV_IDEATAPI */	
 	ide_set_handler(drive, &dma_intr, WAIT_CMD);	/* issue cmd to drive */
 	OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
 	outb(inb(dma_base)|1, dma_base);		/* begin DMA */
diff -u --recursive --new-file v1.3.62/linux/drivers/block/umc8672.c linux/drivers/block/umc8672.c
--- v1.3.62/linux/drivers/block/umc8672.c	Fri Feb  9 17:53:01 1996
+++ linux/drivers/block/umc8672.c	Mon Feb 12 07:04:03 1996
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/umc8672.c	Version 0.02  Feb 06, 1996
+ *  linux/drivers/block/umc8672.c	Version 0.03  Feb 09, 1996
  *
  *  Copyright (C) 1995-1996  Linus Torvalds & author (see below)
  */
@@ -15,6 +15,7 @@
  *			This will get cleaned up in a subsequent release.
  *
  *  Version 0.02	now configs/compiles separate from ide.c  -ml
+ *  Version 0.03	enhanced auto-tune, fix display bug
  */
 
 /*
@@ -46,10 +47,10 @@
 #include <linux/hdreg.h>
 #include <asm/io.h>
 #include "ide.h"
+#include "ide_modes.h"
 
 /*
- * The speeds will eventually become selectable using hdparm via ioctl's,
- * but for now they are coded here:
+ * Default speeds.  These can be changed with "auto-tune" and/or hdparm.
  */
 #define UMC_DRIVE0      1              /* DOS measured drive speeds */
 #define UMC_DRIVE1      1              /* 0 to 11 allowed */
@@ -57,7 +58,7 @@
 #define UMC_DRIVE3      1              /* In case of crash reduce speed */
 
 static byte current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
-static const byte pio_to_umc [5] = {0,3,6,10,11};	/* rough guesses */
+static const byte pio_to_umc [5] = {0,3,7,10,11};	/* rough guesses */
 
 /*       0    1    2    3    4    5    6    7    8    9    10   11      */
 static const byte speedtab [3][12] = {
@@ -103,23 +104,16 @@
 	restore_flags(flags);
 
 	printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n",
-		speeds[0], speeds[1], speeds[2], speeds[4]);
+		speeds[0], speeds[1], speeds[2], speeds[3]);
 }
 
 static void tune_umc (ide_drive_t *drive, byte pio)
 {
-	if (pio == 255)  {	/* auto-tune */
-		struct hd_driveid *id = drive->id;
-		pio = id->tPIO;
-		if (id->field_valid & 0x02) {
-			if (id->eide_pio_modes & 0x01)
-				pio = 3;
-			if (id->eide_pio_modes & 0x02)
-				pio = 4;
-		}
-	}
+	if (pio == 255)
+		pio = ide_get_best_pio_mode(drive);
 	if (pio > 4)
 		pio = 4;
+
 	current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
 	umc_set_speeds (current_speeds);
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/cdrom/Config.in linux/drivers/cdrom/Config.in
--- v1.3.62/linux/drivers/cdrom/Config.in	Sat Jan  6 19:10:39 1996
+++ linux/drivers/cdrom/Config.in	Tue Feb 13 10:30:25 1996
@@ -19,4 +19,8 @@
 tristate 'Goldstar R420 CDROM support' CONFIG_GSCD
 tristate 'Philips/LMS CM206 CDROM support' CONFIG_CM206
 tristate 'Optics Storage DOLPHIN 8000AT CDROM support' CONFIG_OPTCD
-tristate 'Sanyo H94A CDROM support' CONFIG_SJCD
+tristate 'Sanyo CDR-H94A CDROM support' CONFIG_SJCD
+bool 'Soft configurable cdrom interface card support' CONFIG_CDI_INIT
+if [ "$CONFIG_CDI_INIT" = "y" ]; then
+  tristate 'ISP16/MAD16/Mozart soft configurable cdrom interface support' CONFIG_ISP16_CDI
+fi
diff -u --recursive --new-file v1.3.62/linux/drivers/cdrom/Makefile linux/drivers/cdrom/Makefile
--- v1.3.62/linux/drivers/cdrom/Makefile	Mon Oct 23 18:02:04 1995
+++ linux/drivers/cdrom/Makefile	Tue Feb 13 10:30:25 1996
@@ -106,10 +106,24 @@
 
 ifeq ($(CONFIG_SJCD),y)
 L_OBJS += sjcd.o
-#else
-#  ifeq ($(CONFIG_SJCD),m)
-#  M_OBJS += sjcd.o
-#  endif
+else
+  ifeq ($(CONFIG_SJCD),m)
+  M_OBJS += sjcd.o
+  endif
 endif #CONFIG_SJCD
+
+ifeq ($(CONFIG_CDI_INIT),y)
+L_OBJS += cdi.o
+endif #CONFIG_CDI_INIT
+ifeq ($(CONFIG_ISP16_CDI),y)
+L_OBJS += isp16.o
+else
+#  ifeq ($(CONFIG_CDI_INIT),m)
+#  M_OBJS += cdi.o
+#  endif
+  ifeq ($(CONFIG_ISP16_CDI),m)
+  M_OBJS += isp16.o
+  endif
+endif #CONFIG_ISP16_CDI
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.62/linux/drivers/cdrom/cdi.c linux/drivers/cdrom/cdi.c
--- v1.3.62/linux/drivers/cdrom/cdi.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/cdrom/cdi.c	Tue Feb 13 10:30:25 1996
@@ -0,0 +1,49 @@
+/* -- cdi.c
+ *
+ *    Initialisation of software configurable cdrom interface 
+ *    cards goes here.
+ *
+ *    Copyright (c) 1996 Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
+ *
+ *    Version 0.1
+ *
+ *    History:
+ *    0.1 First release. Only support for ISP16/MAD16/Mozart.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/blk.h>  /* where the proto type of cdi_init() is */
+#ifdef CONFIG_ISP16_CDI
+#include <linux/isp16.h>
+#endif CONFIG_ISP16_CDI
+
+/*
+ *  Cdrom interface configuration.
+ */
+int
+cdi_init(void)
+{
+  int ret_val = -1;
+
+#ifdef CONFIG_ISP16_CDI
+  ret_val &= isp16_init();
+#endif CONFIG_ISP16_CDI
+
+  return(ret_val);
+}
+
diff -u --recursive --new-file v1.3.62/linux/drivers/cdrom/isp16.c linux/drivers/cdrom/isp16.c
--- v1.3.62/linux/drivers/cdrom/isp16.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/cdrom/isp16.c	Tue Feb 13 10:30:25 1996
@@ -0,0 +1,315 @@
+/* -- ISP16 cdrom detection and configuration
+ *
+ *    Copyright (c) 1995,1996 Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
+ *
+ *    Version 0.6
+ *
+ *    History:
+ *    0.5 First release.
+ *        Was included in the sjcd and optcd cdrom drivers.
+ *    0.6 First "stand-alone" version.
+ *        Removed sound configuration.
+ *        Added "module" support.
+ *
+ *    Detect cdrom interface on ISP16 sound card.
+ *    Configure cdrom interface.
+ *
+ *    Algorithm for the card with OPTi 82C928 taken
+ *    from the CDSETUP.SYS driver for MSDOS,
+ *    by OPTi Computers, version 2.03.
+ *    Algorithm for the card with OPTi 82C929 as communicated
+ *    to me by Vadim Model and Leo Spiekman.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#define ISP16_VERSION_MAJOR 0
+#define ISP16_VERSION_MINOR 6
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif  /* MODULE */
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/isp16.h>
+#include <asm/io.h>
+
+static short isp16_detect(void);
+static short isp16_c928__detect(void);
+static short isp16_c929__detect(void);
+static short isp16_cdi_config(int base, u_char drive_type, int irq, int dma);
+static short isp16_type; /* dependent on type of interface card */
+static u_char isp16_ctrl;
+static u_short isp16_enable_port;
+
+static int isp16_cdrom_base = ISP16_CDROM_IO_BASE;
+static int isp16_cdrom_irq = ISP16_CDROM_IRQ;
+static int isp16_cdrom_dma = ISP16_CDROM_DMA;
+static char *isp16_cdrom_type = ISP16_CDROM_TYPE;
+#ifdef MODULE
+int init_module(void);
+void cleanup_module(void);
+#endif
+
+#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
+#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
+
+
+void
+isp16_setup(char *str, int *ints)
+{
+  if ( ints[0] > 0 )
+    isp16_cdrom_base = ints[1];
+  if ( ints[0] > 1 )      
+    isp16_cdrom_irq = ints[2];
+  if ( ints[0] > 2 )      
+    isp16_cdrom_dma = ints[3];
+  if ( str )
+    isp16_cdrom_type = str;
+}
+
+/*
+ *  ISP16 initialisation.
+ *
+ */
+int
+isp16_init(void)
+{
+  u_char expected_drive;
+
+  printk("ISP16: configuration cdrom interface, version %d.%d.\n", ISP16_VERSION_MAJOR,
+    ISP16_VERSION_MINOR);
+
+  if ( !strcmp(isp16_cdrom_type, "noisp16") ) {
+    printk("ISP16: no cdrom interface configured.\n");
+    return(0);
+  }
+
+  if (check_region(ISP16_IO_BASE, ISP16_IO_SIZE)) {
+    printk("ISP16: i/o ports already in use.\n");
+    return(-EIO);
+  }
+
+  if ( (isp16_type=isp16_detect()) < 0 ) {
+    printk("ISP16: no cdrom interface found.\n");
+    return(-EIO);
+  }
+
+  printk("ISP16: cdrom interface (with OPTi 82C92%d chip) detected.\n",
+    (isp16_type==2) ? 9 : 8);
+
+  if ( !strcmp(isp16_cdrom_type, "Sanyo") )
+    expected_drive = (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0);
+  else if ( !strcmp(isp16_cdrom_type, "Sony") )
+    expected_drive = ISP16_SONY;
+  else if ( !strcmp(isp16_cdrom_type, "Panasonic") )
+    expected_drive = (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0);
+  else if ( !strcmp(isp16_cdrom_type, "Mitsumi") )
+    expected_drive = ISP16_MITSUMI;
+  else {
+    printk("ISP16: %s not supported by cdrom interface.\n", isp16_cdrom_type);
+    return(-EIO);
+  }
+
+  if ( isp16_cdi_config(isp16_cdrom_base, expected_drive,
+    isp16_cdrom_irq, isp16_cdrom_dma ) < 0) {
+    printk("ISP16: cdrom interface has not been properly configured.\n");
+    return(-EIO);
+  }
+  printk("ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d,"
+    " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq, isp16_cdrom_dma,
+    isp16_cdrom_type);
+  return(0);
+}
+
+static short
+isp16_detect(void)
+{
+
+  if ( isp16_c929__detect() >= 0 )
+    return(2);
+  else
+    return(isp16_c928__detect());
+}
+
+static short
+isp16_c928__detect(void)
+{
+  u_char ctrl;
+  u_char enable_cdrom;
+  u_char io;
+  short i = -1;
+
+  isp16_ctrl = ISP16_C928__CTRL;
+  isp16_enable_port = ISP16_C928__ENABLE_PORT;
+
+  /* read' and write' are a special read and write, respectively */
+
+  /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
+  ctrl = ISP16_IN( ISP16_CTRL_PORT ) & 0xFC;
+  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
+
+  /* read' 3,4 and 5-bit from the cdrom enable port */
+  enable_cdrom = ISP16_IN( ISP16_C928__ENABLE_PORT ) & 0x38;
+
+  if ( !(enable_cdrom & 0x20) ) {  /* 5-bit not set */
+    /* read' last 2 bits of ISP16_IO_SET_PORT */
+    io = ISP16_IN( ISP16_IO_SET_PORT ) & 0x03;
+    if ( ((io&0x01)<<1) == (io&0x02) ) {  /* bits are the same */
+      if ( io == 0 ) {  /* ...the same and 0 */
+        i = 0;
+        enable_cdrom |= 0x20;
+      }
+      else {  /* ...the same and 1 */  /* my card, first time 'round */
+        i = 1;
+        enable_cdrom |= 0x28;
+      }
+      ISP16_OUT( ISP16_C928__ENABLE_PORT, enable_cdrom );
+    }
+    else {  /* bits are not the same */
+      ISP16_OUT( ISP16_CTRL_PORT, ctrl );
+      return(i); /* -> not detected: possibly incorrect conclusion */
+    }
+  }
+  else if ( enable_cdrom == 0x20 )
+    i = 0;
+  else if ( enable_cdrom == 0x28 )  /* my card, already initialised */
+    i = 1;
+
+  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
+
+  return(i);
+}
+
+static short
+isp16_c929__detect(void)
+{
+  u_char ctrl;
+  u_char tmp;
+
+  isp16_ctrl = ISP16_C929__CTRL;
+  isp16_enable_port = ISP16_C929__ENABLE_PORT;
+
+  /* read' and write' are a special read and write, respectively */
+
+  /* read' ISP16_CTRL_PORT and save */
+  ctrl = ISP16_IN( ISP16_CTRL_PORT );
+
+  /* write' zero to the ctrl port and get response */
+  ISP16_OUT( ISP16_CTRL_PORT, 0 );
+  tmp = ISP16_IN( ISP16_CTRL_PORT );
+
+  if ( tmp != 2 )  /* isp16 with 82C929 not detected */
+    return(-1);
+
+  /* restore ctrl port value */
+  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
+  
+  return(2);
+}
+
+static short
+isp16_cdi_config(int base, u_char drive_type, int irq, int dma)
+{
+  u_char base_code;
+  u_char irq_code;
+  u_char dma_code;
+  u_char i;
+
+  if ( (drive_type == ISP16_MITSUMI) && (dma != 0) )
+    printk("ISP16: Mitsumi cdrom drive has no dma support.\n");
+
+  switch (base) {
+  case 0x340: base_code = ISP16_BASE_340; break;
+  case 0x330: base_code = ISP16_BASE_330; break;
+  case 0x360: base_code = ISP16_BASE_360; break;
+  case 0x320: base_code = ISP16_BASE_320; break;
+  default:
+    printk("ISP16: base address 0x%03X not supported by cdrom interface.\n",
+      base);
+    return(-1);
+  }
+  switch (irq) {
+  case 0: irq_code = ISP16_IRQ_X; break; /* disable irq */
+  case 5: irq_code = ISP16_IRQ_5;
+          printk("ISP16: irq 5 shouldn't be used by cdrom interface,"
+            " due to possible conflicts with the sound card.\n");
+          break;
+  case 7: irq_code = ISP16_IRQ_7;
+          printk("ISP16: irq 7 shouldn't be used by cdrom interface,"
+            " due to possible conflicts with the sound card.\n");
+          break;
+  case 3: irq_code = ISP16_IRQ_3; break;
+  case 9: irq_code = ISP16_IRQ_9; break;
+  case 10: irq_code = ISP16_IRQ_10; break;
+  case 11: irq_code = ISP16_IRQ_11; break;
+  default:
+    printk("ISP16: irq %d not supported by cdrom interface.\n", irq );
+    return(-1);
+  }
+  switch (dma) {
+  case 0: dma_code = ISP16_DMA_X; break;  /* disable dma */
+  case 1: printk("ISP16: dma 1 cannot be used by cdrom interface,"
+            " due to conflict with the sound card.\n");
+          return(-1); break;
+  case 3: dma_code = ISP16_DMA_3; break;
+  case 5: dma_code = ISP16_DMA_5; break;
+  case 6: dma_code = ISP16_DMA_6; break;
+  case 7: dma_code = ISP16_DMA_7; break;
+  default:
+    printk("ISP16: dma %d not supported by cdrom interface.\n", dma);
+    return(-1);
+  }
+
+  if ( drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
+    drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
+    drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
+    drive_type != ISP16_DRIVE_X ) {
+    printk("ISP16: drive type (code 0x%02X) not supported by cdrom"
+     " interface.\n", drive_type );
+    return(-1);
+  }
+
+  /* set type of interface */
+  i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK;  /* clear some bits */
+  ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type );
+
+  /* enable cdrom on interface with 82C929 chip */
+  if ( isp16_type > 1 )
+    ISP16_OUT( isp16_enable_port, ISP16_ENABLE_CDROM );
+
+  /* set base address, irq and dma */
+  i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;  /* keep some bits */
+  ISP16_OUT( ISP16_IO_SET_PORT, i|base_code|irq_code|dma_code );
+
+  return(0);
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+  return isp16_init();
+}
+
+void cleanup_module(void)
+{
+	release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
+	printk("ISP16: module released.\n");
+}
+#endif /* MODULE */
diff -u --recursive --new-file v1.3.62/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c
--- v1.3.62/linux/drivers/cdrom/optcd.c	Tue Jan 23 21:15:39 1996
+++ linux/drivers/cdrom/optcd.c	Tue Feb 13 10:30:25 1996
@@ -5,9 +5,7 @@
 
 
 	Based on Aztech CD268 CDROM driver by Werner Zimmermann and preworks
-	by Eberhard Moenkeberg (emoenke@gwdg.de). ISP16 detection and
-	configuration by Eric van der Maarel (maarel@marin.nl) and
-	Vadim Model (vadim@cecmow.enet.dec.com).
+	by Eberhard Moenkeberg (emoenke@gwdg.de). 
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -71,9 +69,6 @@
 #include <linux/cdrom.h>
 #include <linux/optcd.h>
 
-#ifdef PROBE_ISP16
-#include "optcd_isp16.h"	/* optional ISP16 detection/configuration */
-#endif
 
 /* Debug support */
 
@@ -1960,51 +1955,13 @@
 };
 
 
-/* Flag indicates if ISP16 detection and initialisation should be skipped */
-#define skip_isp16_init	noisp16		/* Needed for the modutils. */
-static int skip_isp16_init = 0;
-
 /* Get kernel parameter when used as a kernel driver */
 void optcd_setup(char *str, int *ints)
 {
 	if (ints[0] > 0)
 		optcd_port = ints[1];
-	if (!strcmp(str ,"noisp16"))
-		skip_isp16_init = 1;
 }
 
-
-#ifdef PROBE_ISP16
-/* If ISP16 I/O ports not already reserved, probe for an ISP16 interface card,
-   and enable SONY mode with no interrupts and no DMA.
-   (As far as I know, all Optics 8000 AT drives come with a SONY interface.
-   Interrupts and DMA are not supported).
-   Returns false only if ISP16 detected but couldn't be initialised. */
-static int probe_isp16(void)
-{
-	if (skip_isp16_init)
-		return 1;
-
-	if (check_region(ISP16_DRIVE_SET_PORT, 5))
-		return 1;
-
-	if (isp16_detect() < 0 ) {
-		printk( "No ISP16 cdrom interface found.\n" );
-		return 1;
-	}
-
-	isp16_sound_config();	/* Enable playing through speakers */
-
-	printk( "ISP16 cdrom interface detected.\n");
-	if (isp16_cdi_config(optcd_port, ISP16_SONY, 0, 0) < 0) {
-		printk( "ISP16 configure error.\n" );
-		return 0;
-	}
-	return 1;
-}
-#endif PROBE_ISP16
-
-
 /* Test for presence of drive and initialize it. Called at boot time
    or during module initialisation. */
 int optcd_init(void)
@@ -2020,11 +1977,6 @@
 			optcd_port);
 		return -EIO;
 	}
-
-#ifdef PROBE_ISP16
-	if (!probe_isp16())
-		return -EIO;
-#endif
 
 	if (!reset_drive()) {
 		printk("optcd: drive at 0x%x not ready\n", optcd_port);
diff -u --recursive --new-file v1.3.62/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c
--- v1.3.62/linux/drivers/cdrom/sjcd.c	Mon Nov 27 12:48:30 1995
+++ linux/drivers/cdrom/sjcd.c	Tue Feb 13 10:30:25 1996
@@ -1,23 +1,16 @@
 /* -- sjcd.c
  *
- *   Sanyo CD-ROM device driver implementation, Version 1.5
+ *   Sanyo CD-ROM device driver implementation, Version 1.6
  *   Copyright (C) 1995  Vadim V. Model
  *
  *   model@cecmow.enet.dec.com
  *   vadim@rbrf.ru
  *   vadim@ipsun.ras.ru
  *
- *   ISP16 detection and configuration.
- *   Copyright (C) 1995  Eric van der Maarel (maarel@marin.nl)
- *                   and Vadim Model (vadim@cecmow.enet.dec.com)
- *
  *
  *  This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de);
  *  it was developed under use of mcd.c from Martin Harriss, with help of
- *  Eric van der Maarel (maarel@marin.nl).
- *
- *  ISP16 detection and configuration by Eric van der Maarel (maarel@marin.nl).
- *  Sound configuration by Vadim V. Model (model@cecmow.enet.dec.com)
+ *  Eric van der Maarel (H.T.M.v.d.Maarel@marin.nl).
  *
  *  It is planned to include these routines into sbpcd.c later - to make
  *  a "mixed use" on one cable possible for all kinds of drives which use
@@ -48,10 +41,19 @@
  *  1.4 MSS Sound support!! Listen to a CD through the speakers.
  *  1.5 Module support and bugfixes.
  *      Tray locking.
+ *  1.6 Removed ISP16 code from this driver.
+ *      Allow only to set io base address on comand line: sjcd=<io_base>
+ *      Changes to Documentation/cdrom/sjcd
+ *      Added cleanup after any error in the initialisation.
  *
  */
 
+#define SJCD_VERSION_MAJOR 1
+#define SJCD_VERSION_MINOR 6
+
+#ifdef MODULE
 #include <linux/module.h>
+#endif /* MODULE */
 
 #include <linux/errno.h>
 #include <linux/sched.h>
@@ -72,65 +74,7 @@
 #include <linux/blk.h>
 #include <linux/sjcd.h>
 
-/* Some (Media)Magic */
-/* define types of drive the interface on an ISP16 card may be looking at */
-#define ISP16_DRIVE_X 0x00
-#define ISP16_SONY  0x02
-#define ISP16_PANASONIC0 0x02
-#define ISP16_SANYO0 0x02
-#define ISP16_MITSUMI  0x04
-#define ISP16_PANASONIC1 0x06
-#define ISP16_SANYO1 0x06
-#define ISP16_DRIVE_NOT_USED 0x08  /* not used */
-#define ISP16_DRIVE_SET_MASK 0xF1  /* don't change 0-bit or 4-7-bits*/
-/* ...for port */
-#define ISP16_DRIVE_SET_PORT 0xF8D
-/* set io parameters */
-#define ISP16_BASE_340  0x00
-#define ISP16_BASE_330  0x40
-#define ISP16_BASE_360  0x80
-#define ISP16_BASE_320  0xC0
-#define ISP16_IRQ_X  0x00
-#define ISP16_IRQ_5  0x04  /* shouldn't be used due to soundcard conflicts */
-#define ISP16_IRQ_7  0x08  /* shouldn't be used due to soundcard conflicts */
-#define ISP16_IRQ_3  0x0C
-#define ISP16_IRQ_9  0x10
-#define ISP16_IRQ_10  0x14
-#define ISP16_IRQ_11  0x18
-#define ISP16_DMA_X  0x03
-#define ISP16_DMA_3  0x00
-#define ISP16_DMA_5  0x00
-#define ISP16_DMA_6  0x01
-#define ISP16_DMA_7  0x02
-#define ISP16_IO_SET_MASK  0x20  /* don't change 5-bit */
-/* ...for port */
-#define ISP16_IO_SET_PORT  0xF8E
-/* enable the card */
-#define ISP16_C928__ENABLE_PORT  0xF90  /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__ENABLE_PORT  0xF91  /* ISP16 with OPTi 82C929 chip */
-#define ISP16_ENABLE_CDROM  0x80  /* seven bit */
-
-/* the magic stuff */
-#define ISP16_CTRL_PORT  0xF8F
-#define ISP16_C928__CTRL  0xE2  /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__CTRL  0xE3  /* ISP16 with OPTi 82C929 chip */
-
-static short isp16_detect(void);
-static short isp16_c928__detect(void);
-static short isp16_c929__detect(void);
-static short isp16_cdi_config( int base, u_char drive_type, int irq, int dma );
-static void isp16_sound_config( void );
-static short isp16_type; /* dependent on type of interface card */
-static u_char isp16_ctrl;
-static u_short isp16_enable_port;
-
 static int sjcd_present = 0;
-static u_char special_mask = 0;
-
-static unsigned char defaults[ 16 ] = {
-  0xA8, 0xA8, 0x18, 0x18, 0x18, 0x18, 0x8E, 0x8E,
-  0x03, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00
-};
 
 #define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */
 
@@ -161,9 +105,7 @@
 static int sjcd_audio_status;
 static struct sjcd_play_msf sjcd_playing;
 
-static int sjcd_port = SJCD_BASE_ADDR;
-static int sjcd_irq  = SJCD_INTR_NR;
-static int sjcd_dma  = SJCD_DMA_NR;
+static int sjcd_base = SJCD_BASE_ADDR;
 
 static struct wait_queue *sjcd_waitq = NULL;
 
@@ -207,18 +149,16 @@
 
 #define CLEAR_TIMER del_timer( &sjcd_delay_timer )
 
+static int sjcd_cleanup(void);
+
 /*
  * Set up device, i.e., use command line data to set
- * base address, irq and dma.
+ * base address.
  */
 void sjcd_setup( char *str, int *ints )
 {
    if (ints[0] > 0)
-      sjcd_port = ints[1];
-   if (ints[0] > 1)      
-      sjcd_irq = ints[2];
-   if (ints[0] > 2)      
-      sjcd_dma = ints[3];
+      sjcd_base = ints[1];
 }
 
 /*
@@ -253,7 +193,7 @@
  */
 static void sjcd_send_cmd( unsigned char cmd ){
 #if defined( SJCD_TRACE )
-  printk( "sjcd: send_cmd( 0x%x )\n", cmd );
+  printk( "SJCD: send_cmd( 0x%x )\n", cmd );
 #endif
   outb( cmd, SJCDPORT( 0 ) );
   sjcd_command_is_in_progress = 1;
@@ -266,7 +206,7 @@
  */
 static void sjcd_send_1_cmd( unsigned char cmd, unsigned char a ){
 #if defined( SJCD_TRACE )
-  printk( "sjcd: send_1_cmd( 0x%x, 0x%x )\n", cmd, a );
+  printk( "SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a );
 #endif
   outb( cmd, SJCDPORT( 0 ) );
   outb( a, SJCDPORT( 0 ) );
@@ -281,7 +221,7 @@
 static void sjcd_send_4_cmd( unsigned char cmd, unsigned char a,
 	    unsigned char b, unsigned char c, unsigned char d ){
 #if defined( SJCD_TRACE )
-  printk( "sjcd: send_4_cmd( 0x%x )\n", cmd );
+  printk( "SJCD: send_4_cmd( 0x%x )\n", cmd );
 #endif
   outb( cmd, SJCDPORT( 0 ) );
   outb( a, SJCDPORT( 0 ) );
@@ -298,7 +238,7 @@
  */
 static void sjcd_send_6_cmd( unsigned char cmd, struct sjcd_play_msf *pms ){
 #if defined( SJCD_TRACE )
-  printk( "sjcd: send_long_cmd( 0x%x )\n", cmd );
+  printk( "SJCD: send_long_cmd( 0x%x )\n", cmd );
 #endif
   outb( cmd, SJCDPORT( 0 ) );
   outb( pms->start.min,   SJCDPORT( 0 ) );
@@ -365,7 +305,7 @@
    */
   if( sjcd_media_is_changed ) sjcd_toc_uptodate = 0;
 #if defined( SJCD_TRACE )
-  printk( "sjcd: status %02x.%02x loaded.\n",
+  printk( "SJCD: status %02x.%02x loaded.\n",
 	 ( int )sjcd_completion_status, ( int )sjcd_completion_error );
 #endif
 }
@@ -429,7 +369,7 @@
   sleep_on( &sjcd_waitq );    
 #if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE )
   if( sjcd_status_timeout <= 0 )
-    printk( "sjcd: Error Wait For Status.\n" );
+    printk( "SJCD: Error Wait For Status.\n" );
 #endif
   return( sjcd_status_timeout );
 }
@@ -437,7 +377,7 @@
 static int sjcd_receive_status( void ){
   int i;
 #if defined( SJCD_TRACE )
-  printk( "sjcd: receive_status\n" );
+  printk( "SJCD: receive_status\n" );
 #endif
   /*
    * Wait a bit for status available.
@@ -445,10 +385,10 @@
   for( i = 200; i-- && ( sjcd_check_status() == 0 ); );
   if( i < 0 ){
 #if defined( SJCD_TRACE )
-    printk( "sjcd: long wait for status\n" );
+    printk( "SJCD: long wait for status\n" );
 #endif
     if( sjcd_wait_for_status() <= 0 )
-      printk( "sjcd: Timeout when read status.\n" );
+      printk( "SJCD: Timeout when read status.\n" );
     else i = 0;
   }
   return( i );
@@ -459,7 +399,7 @@
  */
 static void sjcd_get_status( void ){
 #if defined( SJCD_TRACE )
-  printk( "sjcd: get_status\n" );
+  printk( "SJCD: get_status\n" );
 #endif
   sjcd_send_cmd( SCMD_GET_STATUS );
   sjcd_receive_status();
@@ -470,10 +410,10 @@
  */
 static int sjcd_disk_change( kdev_t full_dev ){
 #if 0
-  printk( "sjcd_disk_change( 0x%x )\n", full_dev );
+  printk( "SJCD: sjcd_disk_change( 0x%x )\n", full_dev );
 #endif
   if( MINOR( full_dev ) > 0 ){
-    printk( "sjcd: request error: invalid device minor.\n" );
+    printk( "SJCD: request error: invalid device minor.\n" );
     return 0;
   }
   if( !sjcd_command_is_in_progress )
@@ -493,7 +433,7 @@
   struct sjcd_hw_disk_info info;
   int i;
 #if defined( SJCD_TRACE )
-  printk( "sjcd: update toc:\n" );
+  printk( "SJCD: update toc:\n" );
 #endif
   /*
    * check to see if we need to do anything
@@ -507,27 +447,27 @@
   sjcd_receive_status();
 
   if( !sjcd_status_valid ){
-    printk( "cannot load status.\n" );
+    printk( "SJCD: cannot load status.\n" );
     return( -1 );
   }
 
   if( !sjcd_media_is_available ){
-    printk( "no disk in drive\n" );
+    printk( "SJCD: no disk in drive\n" );
     return( -1 );
   }
 
   if( !sjcd_command_failed ){
     if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){
-      printk( "cannot load response about TOC start.\n" );
+      printk( "SJCD: cannot load response about TOC start.\n" );
       return( -1 );
     }
     sjcd_first_track_no = bcd2bin( info.un.track_no );
   } else {
-    printk( "get first failed\n" );
+    printk( "SJCD: get first failed\n" );
     return( -1 );
   }
 #if defined( SJCD_TRACE )
-  printk( "TOC start 0x%02x ", sjcd_first_track_no );
+  printk( "SJCD: TOC start 0x%02x ", sjcd_first_track_no );
 #endif
   /*
    * Get the TOC finish information.
@@ -536,27 +476,27 @@
   sjcd_receive_status();
 
   if( !sjcd_status_valid ){
-    printk( "cannot load status.\n" );
+    printk( "SJCD: cannot load status.\n" );
     return( -1 );
   }
 
   if( !sjcd_media_is_available ){
-    printk( "no disk in drive\n" );
+    printk( "SJCD: no disk in drive\n" );
     return( -1 );
   }
 
   if( !sjcd_command_failed ){
     if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){
-      printk( "cannot load response about TOC finish.\n" );
+      printk( "SJCD: cannot load response about TOC finish.\n" );
       return( -1 );
     }
     sjcd_last_track_no = bcd2bin( info.un.track_no );
   } else {
-    printk( "get last failed\n" );
+    printk( "SJCD: get last failed\n" );
     return( -1 );
   }
 #if defined( SJCD_TRACE )
-  printk( "TOC finish 0x%02x ", sjcd_last_track_no );
+  printk( "SJCD: TOC finish 0x%02x ", sjcd_last_track_no );
 #endif
   for( i = sjcd_first_track_no; i <= sjcd_last_track_no; i++ ){
     /*
@@ -566,23 +506,23 @@
     sjcd_receive_status();
 
     if( !sjcd_status_valid ){
-      printk( "cannot load status.\n" );
+      printk( "SJCD: cannot load status.\n" );
       return( -1 );
     }
 
     if( !sjcd_media_is_available ){
-      printk( "no disk in drive\n" );
+      printk( "SJCD: no disk in drive\n" );
       return( -1 );
     }
 
     if( !sjcd_command_failed ){
       if( sjcd_load_response( &sjcd_table_of_contents[ i ],
 			     sizeof( struct sjcd_hw_disk_info ) ) != 0 ){
-	printk( "cannot load info for %d track\n", i );
+	printk( "SJCD: cannot load info for %d track\n", i );
 	return( -1 );
       }
     } else {
-      printk( "get info %d failed\n", i );
+      printk( "SJCD: get info %d failed\n", i );
       return( -1 );
     }
   }
@@ -594,29 +534,29 @@
   sjcd_receive_status();
 
   if( !sjcd_status_valid ){
-    printk( "cannot load status.\n" );
+    printk( "SJCD: cannot load status.\n" );
     return( -1 );
   }
 
   if( !sjcd_media_is_available ){
-    printk( "no disk in drive\n" );
+    printk( "SJCD: no disk in drive\n" );
     return( -1 );
   }
 
   if( !sjcd_command_failed ){
     if( sjcd_load_response( &info, sizeof( info ) ) != 0 ){
-      printk( "cannot load response about disk size.\n" );
+      printk( "SJCD: cannot load response about disk size.\n" );
       return( -1 );
     }
     sjcd_disk_length.min = info.un.track_msf.min;
     sjcd_disk_length.sec = info.un.track_msf.sec;
     sjcd_disk_length.frame = info.un.track_msf.frame;
   } else {
-    printk( "get size failed\n" );
+    printk( "SJCD: get size failed\n" );
     return( 1 );
   }
 #if defined( SJCD_TRACE )
-  printk( "(%02x:%02x.%02x)\n", sjcd_disk_length.min,
+  printk( "SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min,
 	 sjcd_disk_length.sec, sjcd_disk_length.frame );
 #endif
   return( 0 );
@@ -628,7 +568,7 @@
 static int sjcd_get_q_info( struct sjcd_hw_qinfo *qp ){
   int s;
 #if defined( SJCD_TRACE )
-  printk( "sjcd: load sub q\n" );
+  printk( "SJCD: load sub q\n" );
 #endif
   sjcd_send_cmd( SCMD_GET_QINFO );
   s = sjcd_receive_status();
@@ -677,7 +617,7 @@
  */
 static int sjcd_tray_close( void ){
 #if defined( SJCD_TRACE )
-  printk( "sjcd: tray_close\n" );
+  printk( "SJCD: tray_close\n" );
 #endif
   sjcd_send_cmd( SCMD_CLOSE_TRAY );
   return( sjcd_receive_status() );
@@ -685,7 +625,7 @@
 
 static int sjcd_tray_lock( void ){
 #if defined( SJCD_TRACE )
-  printk( "sjcd: tray_lock\n" );
+  printk( "SJCD: tray_lock\n" );
 #endif
   sjcd_send_cmd( SCMD_LOCK_TRAY );
   return( sjcd_receive_status() );
@@ -693,7 +633,7 @@
 
 static int sjcd_tray_unlock( void ){
 #if defined( SJCD_TRACE )
-  printk( "sjcd: tray_unlock\n" );
+  printk( "SJCD: tray_unlock\n" );
 #endif
   sjcd_send_cmd( SCMD_UNLOCK_TRAY );
   return( sjcd_receive_status() );
@@ -701,7 +641,7 @@
 
 static int sjcd_tray_open( void ){
 #if defined( SJCD_TRACE )
-  printk( "sjcd: tray_open\n" );
+  printk( "SJCD: tray_open\n" );
 #endif
   sjcd_send_cmd( SCMD_EJECT_TRAY );
   return( sjcd_receive_status() );
@@ -713,7 +653,7 @@
 static int sjcd_ioctl( struct inode *ip, struct file *fp,
 		       unsigned int cmd, unsigned long arg ){
 #if defined( SJCD_TRACE )
-  printk( "sjcd:ioctl\n" );
+  printk( "SJCD:ioctl\n" );
 #endif
 
   if( ip == NULL ) return( -EINVAL );
@@ -725,14 +665,14 @@
   switch( cmd ){
   case CDROMSTART:{
 #if defined( SJCD_TRACE )
-    printk( "sjcd: ioctl: start\n" );
+    printk( "SJCD: ioctl: start\n" );
 #endif
     return( 0 );
   }
 
   case CDROMSTOP:{
 #if defined( SJCD_TRACE )
-    printk( "sjcd: ioctl: stop\n" );
+    printk( "SJCD: ioctl: stop\n" );
 #endif
     sjcd_send_cmd( SCMD_PAUSE );
     ( void )sjcd_receive_status();
@@ -743,7 +683,7 @@
   case CDROMPAUSE:{
     struct sjcd_hw_qinfo q_info;
 #if defined( SJCD_TRACE )
-    printk( "sjcd: ioctl: pause\n" );
+    printk( "SJCD: ioctl: pause\n" );
 #endif
     if( sjcd_audio_status == CDROM_AUDIO_PLAY ){
       sjcd_send_cmd( SCMD_PAUSE );
@@ -760,7 +700,7 @@
 
   case CDROMRESUME:{
 #if defined( SJCD_TRACE )
-    printk( "sjcd: ioctl: resume\n" );
+    printk( "SJCD: ioctl: resume\n" );
 #endif
     if( sjcd_audio_status == CDROM_AUDIO_PAUSED ){
       /*
@@ -779,7 +719,7 @@
   case CDROMPLAYTRKIND:{
     struct cdrom_ti ti; int s;
 #if defined( SJCD_TRACE )
-    printk( "sjcd: ioctl: playtrkind\n" );
+    printk( "SJCD: ioctl: playtrkind\n" );
 #endif
     if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( ti ) ) ) == 0 ){
       memcpy_fromfs( &ti, (void *)arg, sizeof( ti ) );
@@ -805,7 +745,7 @@
   case CDROMPLAYMSF:{
     struct cdrom_msf sjcd_msf; int s;
 #if defined( SJCD_TRACE )
-    printk( "sjcd: ioctl: playmsf\n" );
+    printk( "SJCD: ioctl: playmsf\n" );
 #endif
     if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( sjcd_msf ) ) ) == 0 ){
       if( sjcd_audio_status == CDROM_AUDIO_PLAY ){
@@ -834,7 +774,7 @@
   case CDROMREADTOCHDR:{
     struct cdrom_tochdr toc_header; int s;
 #if defined (SJCD_TRACE )
-    printk( "sjcd: ioctl: readtocheader\n" );
+    printk( "SJCD: ioctl: readtocheader\n" );
 #endif
     if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( toc_header ) ) ) == 0 ){
       toc_header.cdth_trk0 = sjcd_first_track_no;
@@ -847,7 +787,7 @@
   case CDROMREADTOCENTRY:{
     struct cdrom_tocentry toc_entry; int s;
 #if defined( SJCD_TRACE )
-    printk( "sjcd: ioctl: readtocentry\n" );
+    printk( "SJCD: ioctl: readtocentry\n" );
 #endif
     if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( toc_entry ) ) ) == 0 ){
       struct sjcd_hw_disk_info *tp;
@@ -882,7 +822,7 @@
   case CDROMSUBCHNL:{
     struct cdrom_subchnl subchnl; int s;
 #if defined( SJCD_TRACE )
-    printk( "sjcd: ioctl: subchnl\n" );
+    printk( "SJCD: ioctl: subchnl\n" );
 #endif
     if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( subchnl ) ) ) == 0 ){
       struct sjcd_hw_qinfo q_info;
@@ -919,7 +859,7 @@
   case CDROMVOLCTRL:{
     struct cdrom_volctrl vol_ctrl; int s;
 #if defined( SJCD_TRACE )
-    printk( "sjcd: ioctl: volctrl\n" );
+    printk( "SJCD: ioctl: volctrl\n" );
 #endif
     if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( vol_ctrl ) ) ) == 0 ){
       unsigned char dummy[ 4 ];
@@ -935,7 +875,7 @@
 
   case CDROMEJECT:{
 #if defined( SJCD_TRACE )
-    printk( "sjcd: ioctl: eject\n" );
+    printk( "SJCD: ioctl: eject\n" );
 #endif
     if( !sjcd_command_is_in_progress ){
       sjcd_tray_unlock();
@@ -949,7 +889,7 @@
   case 0xABCD:{
     int s;
 #if defined( SJCD_TRACE )
-    printk( "sjcd: ioctl: statistic\n" );
+    printk( "SJCD: ioctl: statistic\n" );
 #endif
     if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( statistic ) ) ) == 0 )
       memcpy_tofs( (void *)arg, &statistic, sizeof( statistic ) );
@@ -982,7 +922,7 @@
 
 static void sjcd_transfer( void ){
 #if defined( SJCD_TRACE )
-  printk( "sjcd: transfer:\n" );
+  printk( "SJCD: transfer:\n" );
 #endif
   if( CURRENT_IS_VALID ){
     while( CURRENT->nr_sectors ){
@@ -1001,7 +941,7 @@
 	if( nr_sectors > CURRENT->nr_sectors )
 	  nr_sectors = CURRENT->nr_sectors;
 #if defined( SJCD_TRACE )
-	printk( "copy out\n" );
+	printk( "SJCD: copy out\n" );
 #endif
 	memcpy( CURRENT->buffer, sjcd_buf + offs, nr_sectors * 512 );
 	CURRENT->nr_sectors -= nr_sectors;
@@ -1014,7 +954,7 @@
     }
   }
 #if defined( SJCD_TRACE )
-  printk( "sjcd: transfer: done\n" );
+  printk( "SJCD: transfer: done\n" );
 #endif
 }
 
@@ -1127,7 +1067,7 @@
 	msf.end.min = 0; msf.end.sec = 0;            
 	msf.end.frame = sjcd_read_count = SJCD_BUF_SIZ;
 #if defined( SJCD_TRACE )
-	printk( "---reading msf-address %x:%x:%x  %x:%x:%x\n",
+	printk( "SJCD: ---reading msf-address %x:%x:%x  %x:%x:%x\n",
 	       msf.start.min, msf.start.sec, msf.start.frame,
 	       msf.end.min,   msf.end.sec,   msf.end.frame );
 	printk( "sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n", \
@@ -1170,7 +1110,7 @@
 
       if( !sjcd_status_valid || sjcd_command_failed ){
 #if defined( SJCD_TRACE )
-	printk( "sjcd: read block %d failed, maybe audio disk? Giving up\n",
+	printk( "SJCD: read block %d failed, maybe audio disk? Giving up\n",
 	       sjcd_next_bn );
 #endif
 	if( CURRENT_IS_VALID ) end_request( 0 );
@@ -1305,12 +1245,12 @@
   }
 
   default:
-    printk( "sjcd_poll: invalid state %d\n", sjcd_transfer_state );
+    printk( "SJCD: poll: invalid state %d\n", sjcd_transfer_state );
     return;
   }
   
   if( --sjcd_transfer_timeout == 0 ){
-    printk( "sjcd: timeout in state %d\n", sjcd_transfer_state );
+    printk( "SJCD: timeout in state %d\n", sjcd_transfer_state );
     while( CURRENT_IS_VALID ) end_request( 0 );
     sjcd_send_cmd( SCMD_STOP );
     sjcd_transfer_state = SJCD_S_IDLE;
@@ -1326,7 +1266,7 @@
 
 static void do_sjcd_request( void ){
 #if defined( SJCD_TRACE )
-  printk( "sjcd: do_sjcd_request(%ld+%ld)\n",
+  printk( "SJCD: do_sjcd_request(%ld+%ld)\n",
 	 CURRENT->sector, CURRENT->nr_sectors );
 #endif
   sjcd_transfer_is_active = 1;
@@ -1344,7 +1284,7 @@
       if( sjcd_transfer_state == SJCD_S_IDLE ){
 	if( !sjcd_toc_uptodate ){
 	  if( sjcd_update_toc() < 0 ){
-	    printk( "sjcd: transfer: discard\n" );
+	    printk( "SJCD: transfer: discard\n" );
 	    while( CURRENT_IS_VALID ) end_request( 0 );
 	    break;
 	  }
@@ -1396,22 +1336,22 @@
       if( !sjcd_status_valid ) sjcd_get_status();
       if( !sjcd_status_valid ){
 #if defined( SJCD_DIAGNOSTIC )
-	printk( "sjcd: open: timed out when check status.\n" );
+	printk( "SJCD: open: timed out when check status.\n" );
 #endif
 	return( -EIO );
       } else if( !sjcd_media_is_available ){
 #if defined( SJCD_DIAGNOSTIC )
-	printk("sjcd: open: no disk in drive\n");
+	printk("SJCD: open: no disk in drive\n");
 #endif
 	if( !sjcd_door_closed ){
 	  sjcd_door_was_open = 1;
 #if defined( SJCD_TRACE )
-	  printk("sjcd: open: close the tray\n");
+	  printk("SJCD: open: close the tray\n");
 #endif
 	  s = sjcd_tray_close();
 	  if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){
 #if defined( SJCD_DIAGNOSTIC )
-	    printk("sjcd: open: tray close attempt failed\n");
+	    printk("SJCD: open: tray close attempt failed\n");
 #endif
 	    return( -EIO );
 	  }
@@ -1423,15 +1363,17 @@
     s = sjcd_tray_lock();
     if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){
 #if defined( SJCD_DIAGNOSTIC )
-      printk("sjcd: open: tray lock attempt failed\n");
+      printk("SJCD: open: tray lock attempt failed\n");
 #endif
       return( -EIO );
     }
 #if defined( SJCD_TRACE )
-    printk( "sjcd: open: done\n" );
+    printk( "SJCD: open: done\n" );
 #endif
   }
+#ifdef MODULE
   MOD_INC_USE_COUNT;
+#endif
   ++sjcd_open_count;
   return( 0 );
 }
@@ -1443,9 +1385,11 @@
   int s;
 
 #if defined( SJCD_TRACE )
-  printk( "sjcd: release\n" );
+  printk( "SJCD: release\n" );
 #endif
+#ifdef MODULE
   MOD_DEC_USE_COUNT;
+#endif
   if( --sjcd_open_count == 0 ){
     sjcd_invalidate_buffers();
     sync_dev( inode->i_rdev );
@@ -1453,14 +1397,14 @@
     s = sjcd_tray_unlock();
     if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){
 #if defined( SJCD_DIAGNOSTIC )
-      printk("sjcd: release: tray unlock attempt failed.\n");
+      printk("SJCD: release: tray unlock attempt failed.\n");
 #endif
     }
     if( sjcd_door_was_open ){
       s = sjcd_tray_open();
       if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){
 #if defined( SJCD_DIAGNOSTIC )
-	printk("sjcd: release: tray unload attempt failed.\n");
+	printk("SJCD: release: tray unload attempt failed.\n");
 #endif
       }
     }
@@ -1503,40 +1447,25 @@
 int sjcd_init( void ){
   int i;
 
-  if ( (isp16_type=isp16_detect()) < 0 )
-    printk( "No ISP16 cdrom interface found.\n" );
-  else {
-    u_char expected_drive;
-
-    printk( "ISP16 cdrom interface (with OPTi 82C92%s chip) detected.\n",
-      (isp16_type==2)?"9":"8" );
-
-    printk( "ISP16 sound configuration.\n" );
-    isp16_sound_config();
-
-    expected_drive = (isp16_type?ISP16_SANYO1:ISP16_SANYO0);
-
-    if ( isp16_cdi_config( sjcd_port, expected_drive, sjcd_irq, sjcd_dma ) < 0 ) {
-      printk( "ISP16 cdrom interface has not been properly configured.\n" );
-      return( -EIO );
-    }
-  }
+  printk("SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n", SJCD_VERSION_MAJOR,
+    SJCD_VERSION_MINOR);
 
 #if defined( SJCD_TRACE )
-  printk( "sjcd=0x%x,%d: ", sjcd_port, sjcd_irq );
+  printk("SJCD: sjcd=0x%x: ", sjcd_base);
 #endif  
 
   if( register_blkdev( MAJOR_NR, "sjcd", &sjcd_fops ) != 0 ){
-    printk( "Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR );
+    printk( "SJCD: Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR );
     return( -EIO );
   }
   
   blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST;
   read_ahead[ MAJOR_NR ] = 4;
   
-  if( check_region( sjcd_port, 4 ) ){
-    printk( "Init failed, I/O port (%X) is already in use\n",
-      sjcd_port );
+  if( check_region( sjcd_base, 4 ) ){
+    printk( "SJCD: Init failed, I/O port (%X) is already in use\n",
+      sjcd_base );
+    sjcd_cleanup();
     return( -EIO );
   }
   
@@ -1544,9 +1473,9 @@
    * Check for card. Since we are booting now, we can't use standard
    * wait algorithm.
    */
-  printk( "Sanyo: Resetting: " );
+  printk( "SJCD: Resetting: " );
   sjcd_send_cmd( SCMD_RESET );
-  for( i = 1000; i-- > 0 && !sjcd_status_valid; ){
+  for( i = 1000; i > 0 && !sjcd_status_valid; --i ){
     unsigned long timer;
 
     /*
@@ -1558,13 +1487,14 @@
   }
   if( i == 0 || sjcd_command_failed ){
     printk( " reset failed, no drive found.\n" );
+    sjcd_cleanup();
     return( -EIO );
   } else printk( "\n" );
 
   /*
    * Get and print out cdrom version.
    */
-  printk( "Sanyo: Getting version: " );
+  printk( "SJCD: Getting version: " );
   sjcd_send_cmd( SCMD_GET_VERSION );
   for( i = 1000; i > 0 && !sjcd_status_valid; --i ){
     unsigned long timer;
@@ -1578,6 +1508,7 @@
   }
   if( i == 0 || sjcd_command_failed ){
     printk( " get version failed, no drive found.\n" );
+    sjcd_cleanup();
     return( -EIO );
   }
 
@@ -1586,6 +1517,7 @@
 	     ( int )sjcd_version.minor );
   } else {
     printk( " read version failed, no drive found.\n" );
+    sjcd_cleanup();
     return( -EIO );
   }
 
@@ -1593,7 +1525,7 @@
    * Check and print out the tray state. (if it is needed?).
    */
   if( !sjcd_status_valid ){
-    printk( "Sanyo: Getting status: " );
+    printk( "SJCD: Getting status: " );
     sjcd_send_cmd( SCMD_GET_STATUS );
     for( i = 1000; i > 0 && !sjcd_status_valid; --i ){
       unsigned long timer;
@@ -1607,300 +1539,40 @@
     }
     if( i == 0 || sjcd_command_failed ){
       printk( " get status failed, no drive found.\n" );
+      sjcd_cleanup();
       return( -EIO );
     } else printk( "\n" );
   }
 
-  printk( "SANYO CDR-H94A: Status: port=0x%x, irq=%d, dma=%d.\n",
-	 sjcd_port, sjcd_irq, sjcd_dma );
+  printk("SJCD: Status: port=0x%x.\n", sjcd_base);
 
   sjcd_present++;
   return( 0 );
 }
 
-#ifdef MODULE
-
-int init_module(void)
+static int
+sjcd_cleanup(void)
 {
-	return sjcd_init();
-}
-
-void cleanup_module( void ){
-  if( ( unregister_blkdev( MAJOR_NR, "sjcd" ) == -EINVAL ) ){
-    printk( "sjcd: module: can not unregister device.\n" );
-  } else {
-    release_region( sjcd_port, 4 );
-    printk( "sjcd: module: removed.\n");
-  }
-}
-#endif
-
-/*
- * -- ISP16 detection and configuration
- *
- *    Copyright (c) 1995, Eric van der Maarel <maarel@marin.nl>
- *
- *    Version 0.5
- *
- *    Detect cdrom interface on ISP16 soundcard.
- *    Configure cdrom interface.
- *    Configure sound interface.
- *
- *    Algorithm for the card with OPTi 82C928 taken
- *    from the CDSETUP.SYS driver for MSDOS,
- *    by OPTi Computers, version 2.03.
- *    Algorithm for the card with OPTi 82C929 as communicated
- *    to me by Vadim Model and Leo Spiekman.
- *
- *    Use, modifification or redistribution of this software is
- *    allowed under the terms of the GPL.
- *
- */
-
-
-#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
-#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
-
-static short
-isp16_detect(void)
-{
-
-  if ( !( isp16_c929__detect() < 0 ) )
-    return(2);
+  if( (unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL) )
+    printk( "SJCD: cannot unregister device.\n" );
   else
-    return( isp16_c928__detect() );
-}
+    release_region( sjcd_base, 4 );
 
-static short
-isp16_c928__detect(void)
-{
-  u_char ctrl;
-  u_char enable_cdrom;
-  u_char io;
-  short i = -1;
-
-  isp16_ctrl = ISP16_C928__CTRL;
-  isp16_enable_port = ISP16_C928__ENABLE_PORT;
-
-  /* read' and write' are a special read and write, respectively */
-
-  /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
-  ctrl = ISP16_IN( ISP16_CTRL_PORT ) & 0xFC;
-  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
-
-  /* read' 3,4 and 5-bit from the cdrom enable port */
-  enable_cdrom = ISP16_IN( ISP16_C928__ENABLE_PORT ) & 0x38;
-
-  if ( !(enable_cdrom & 0x20) ) {  /* 5-bit not set */
-    /* read' last 2 bits of ISP16_IO_SET_PORT */
-    io = ISP16_IN( ISP16_IO_SET_PORT ) & 0x03;
-    if ( ((io&0x01)<<1) == (io&0x02) ) {  /* bits are the same */
-      if ( io == 0 ) {  /* ...the same and 0 */
-        i = 0;
-        enable_cdrom |= 0x20;
-      }
-      else {  /* ...the same and 1 */  /* my card, first time 'round */
-        i = 1;
-        enable_cdrom |= 0x28;
-      }
-      ISP16_OUT( ISP16_C928__ENABLE_PORT, enable_cdrom );
-    }
-    else {  /* bits are not the same */
-      ISP16_OUT( ISP16_CTRL_PORT, ctrl );
-      return(i); /* -> not detected: possibly incorrect conclusion */
-    }
-  }
-  else if ( enable_cdrom == 0x20 )
-    i = 0;
-  else if ( enable_cdrom == 0x28 )  /* my card, already initialised */
-    i = 1;
-
-  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
-
-  return(i);
+  return(0);
 }
 
-static short
-isp16_c929__detect(void)
-{
-  u_char ctrl;
-  u_char tmp;
-
-  isp16_ctrl = ISP16_C929__CTRL;
-  isp16_enable_port = ISP16_C929__ENABLE_PORT;
-
-  /* read' and write' are a special read and write, respectively */
-
-  /* read' ISP16_CTRL_PORT and save */
-  ctrl = ISP16_IN( ISP16_CTRL_PORT );
-
-  /* write' zero to the ctrl port and get response */
-  ISP16_OUT( ISP16_CTRL_PORT, 0 );
-  tmp = ISP16_IN( ISP16_CTRL_PORT );
-
-  if ( tmp != 2 )  /* isp16 with 82C929 not detected */
-    return(-1);
-
-  /* restore ctrl port value */
-  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
-  
-  return(2);
-}
+#ifdef MODULE
 
-static short
-isp16_cdi_config( int base, u_char drive_type, int irq, int dma )
+int init_module(void)
 {
-  u_char base_code;
-  u_char irq_code;
-  u_char dma_code;
-  u_char i;
-
-  if ( (drive_type == ISP16_MITSUMI) && (dma != 0) )
-    printk( "Mitsumi cdrom drive has no dma support.\n" );
-
-  switch (base) {
-  case 0x340: base_code = ISP16_BASE_340; break;
-  case 0x330: base_code = ISP16_BASE_330; break;
-  case 0x360: base_code = ISP16_BASE_360; break;
-  case 0x320: base_code = ISP16_BASE_320; break;
-  default:
-    printk( "Base address 0x%03X not supported by cdrom interface on ISP16.\n", base );
-    return(-1);
-  }
-  switch (irq) {
-  case 0: irq_code = ISP16_IRQ_X; break; /* disable irq */
-  case 5: irq_code = ISP16_IRQ_5;
-          printk( "Irq 5 shouldn't be used by cdrom interface on ISP16,"
-            " due to possible conflicts with the soundcard.\n");
-          break;
-  case 7: irq_code = ISP16_IRQ_7;
-          printk( "Irq 7 shouldn't be used by cdrom interface on ISP16,"
-            " due to possible conflicts with the soundcard.\n");
-          break;
-  case 3: irq_code = ISP16_IRQ_3; break;
-  case 9: irq_code = ISP16_IRQ_9; break;
-  case 10: irq_code = ISP16_IRQ_10; break;
-  case 11: irq_code = ISP16_IRQ_11; break;
-  default:
-    printk( "Irq %d not supported by cdrom interface on ISP16.\n", irq );
-    return(-1);
-  }
-  switch (dma) {
-  case 0: dma_code = ISP16_DMA_X; break;  /* disable dma */
-  case 1: printk( "Dma 1 cannot be used by cdrom interface on ISP16,"
-            " due to conflict with the soundcard.\n");
-          return(-1); break;
-  case 3: dma_code = ISP16_DMA_3; break;
-  case 5: dma_code = ISP16_DMA_5; break;
-  case 6: dma_code = ISP16_DMA_6; break;
-  case 7: dma_code = ISP16_DMA_7; break;
-  default:
-    printk( "Dma %d not supported by cdrom interface on ISP16.\n", dma );
-    return(-1);
-  }
-
-  if ( drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
-    drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
-    drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
-    drive_type != ISP16_DRIVE_X ) {
-    printk( "Drive type (code 0x%02X) not supported by cdrom"
-     " interface on ISP16.\n", drive_type );
-    return(-1);
-  }
-
-  /* set type of interface */
-  i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK;  /* clear some bits */
-  ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type );
-
-  /* enable cdrom on interface with 82C929 chip */
-  if ( isp16_type > 1 )
-    ISP16_OUT( isp16_enable_port, ISP16_ENABLE_CDROM );
-
-  /* set base address, irq and dma */
-  i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;  /* keep some bits */
-  ISP16_OUT( ISP16_IO_SET_PORT, i|base_code|irq_code|dma_code );
-
-  return(0);
+  return sjcd_init();
 }
 
-static void isp16_sound_config( void )
+void cleanup_module(void)
 {
-  int i;
-  u_char saved;
-
-  saved = ISP16_IN( 0xF8D ) & 0x8F;
-    
-  ISP16_OUT( 0xF8D, 0x40 );
-
-  /*
-   * Now we should wait for a while...
-   */
-  for( i = 16*1024; i--; );
-  
-  ISP16_OUT( 0xF8D, saved );
-
-  ISP16_OUT( 0xF91, 0x1B );
-
-  for( i = 5*64*1024; i != 0; i-- )
-    if( !( inb( 0x534 ) & 0x80 ) ) break;
-
-  if( i > 0 ) {
-    saved = ( inb( 0x534 ) & 0xE0 ) | 0x0A;
-    outb( saved, 0x534 );
-
-    special_mask = ( inb( 0x535 ) >> 4 ) & 0x08;
-
-    saved = ( inb( 0x534 ) & 0xE0 ) | 0x0C;
-    outb( saved, 0x534 );
-
-    switch( inb( 0x535 ) ) {
-      case 0x09:
-      case 0x0A:
-        special_mask |= 0x05;
-        break;
-      case 0x8A:
-        special_mask = 0x0F;
-        break;
-      default:
-        i = 0;
-    }
-  }
-  if ( i == 0 ) {
-    printk( "Strange MediaMagic, but\n" );
-  }
-  else {
-    printk( "Conf:" );
-    saved = inb( 0x534 ) & 0xE0;
-    for( i = 0; i < 16; i++ ) {
-      outb( 0x20 | ( u_char )i, 0x534 );
-      outb( defaults[i], 0x535 );
-    }
-    for ( i = 0; i < 16; i++ ) {
-      outb( 0x20 | ( u_char )i, 0x534 );
-      saved = inb( 0x535 );
-      printk( " %02X", saved );
-    }
-    printk( "\n" );
-  }
-
-  ISP16_OUT( 0xF91, 0xA0 | special_mask );
-
-  /*
-   * The following have no explaination yet.
-   */
-  ISP16_OUT( 0xF90, 0xA2 );
-  ISP16_OUT( 0xF92, 0x03 );
-
-  /*
-   * Turn general sound on and set total volume.
-   */
-  ISP16_OUT( 0xF93, 0x0A );
-
-/*
-  outb( 0x04, 0x224 );
-  saved = inb( 0x225 );
-  outb( 0x04, 0x224 );
-  outb( saved, 0x225 );
-*/
-
+  if ( sjcd_cleanup() )
+    printk( "SJCD: module: cannot be removed.\n" );
+  else
+    printk( "SJCD: module: removed.\n");
 }
+#endif
diff -u --recursive --new-file v1.3.62/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v1.3.62/linux/drivers/char/vt.c	Sun Feb 11 15:32:45 1996
+++ linux/drivers/char/vt.c	Mon Feb 12 06:25:34 1996
@@ -219,7 +219,9 @@
 	case KIOCSOUND:
 		if (!perm)
 			return -EPERM;
-		kd_mksound(1193180 / (unsigned int) arg, 0);
+		if (arg)
+			arg = 1193180 / arg;
+		kd_mksound(arg, 0);
 		return 0;
 
 	case KDMKTONE:
diff -u --recursive --new-file v1.3.62/linux/drivers/char/wd501p.h linux/drivers/char/wd501p.h
--- v1.3.62/linux/drivers/char/wd501p.h	Tue Jan 23 21:15:41 1996
+++ linux/drivers/char/wd501p.h	Tue Feb 13 10:47:12 1996
@@ -64,6 +64,11 @@
 #define FEATUREMAP2		(WDC_SR_PSUOVER|WDC_SR_PSUUNDR)
 #endif
 
+#ifdef CONFIG_SOFT_WATCHDOG
+#define FEATUREMAP1            0
+#define FEATUREMAP2            0
+#endif
+
 #ifndef FEATUREMAP1
 #error "Config option not set"
 #endif
diff -u --recursive --new-file v1.3.62/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v1.3.62/linux/drivers/net/3c59x.c	Sun Feb 11 15:32:45 1996
+++ linux/drivers/net/3c59x.c	Wed Feb 14 09:26:26 1996
@@ -14,11 +14,12 @@
 	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 */
 
-static char *version = "3c59x.c:v0.11 1/21/96 becker@cesdis.gsfc.nasa.gov\n";
+static char *version = "3c59x.c:v0.13 2/13/96 becker@cesdis.gsfc.nasa.gov\n";
 
 /* "Knobs" that turn on special features. */
-/* Use bus master transfers instead of programmed-I/O for the Tx process.
-   This is disabled by default! */
+/* Allow the use of bus master transfers instead of programmed-I/O for the
+   Tx process.  Bus master transfers are always disabled by default, but
+   iff this is set they may be turned on using 'options'. */
 #define VORTEX_BUS_MASTER
 
 /* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
@@ -45,6 +46,11 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
+#ifdef HAVE_SHARED_IRQ
+#define USE_SHARED_IRQ
+#include <linux/shared_irq.h>
+#endif
+
 /* The total size is twice that of the original EtherLinkIII series: the
    runtime register window, window 1, is now always mapped in. */
 #define VORTEX_TOTAL_SIZE 0x20
@@ -295,8 +301,8 @@
 	int cards_found = 0;
 
 	if (pcibios_present()) {
-		int pci_index;
-		for (pci_index = 0; pci_index < 8; pci_index++) {
+		static int pci_index = 0;
+		for (; pci_index < 8; pci_index++) {
 			unsigned char pci_bus, pci_device_fn, pci_irq_line, pci_latency;
 			unsigned int pci_ioaddr;
 			unsigned short pci_command;
@@ -340,8 +346,9 @@
 										  PCI_LATENCY_TIMER, 255);
 			}
 #endif  /* VORTEX_BUS_MASTER */
-			vortex_found_device(dev, pci_ioaddr, pci_irq_line,
-							   index, options[cards_found]);
+			vortex_found_device(dev, pci_ioaddr, pci_irq_line, index,
+								dev && dev->mem_start ? dev->mem_start
+								: options[cards_found]);
 			dev = 0;
 			cards_found++;
 		}
@@ -359,7 +366,8 @@
 				&& (inw(ioaddr + 0xC82) & 0xFFF0) != 0x5920)
 				continue;
 			vortex_found_device(dev, ioaddr, inw(ioaddr + 0xC88) >> 12,
-							   DEMON_INDEX, options[cards_found]);
+								DEMON_INDEX,  dev && dev->mem_start
+								? dev->mem_start : options[cards_found]);
 			dev = 0;
 			cards_found++;
 		}
@@ -389,7 +397,7 @@
 	vp->product_name = product_names[product_index];
 	vp->options = options;
 	if (options >= 0) {
-		vp->media_override = options & 7;
+		vp->media_override = ((options & 7) == 2)  ?  0  :  options & 7;
 		vp->full_duplex = (options & 8) ? 1 : 0;
 		vp->bus_master = (options & 16) ? 1 : 0;
 	} else {
@@ -414,7 +422,7 @@
 	vp->product_name = product_names[product_index];
 	vp->options = options;
 	if (options >= 0) {
-		vp->media_override = options & 7;
+		vp->media_override = ((options & 7) == 2)  ?  0  :  options & 7;
 		vp->full_duplex = (options & 8) ? 1 : 0;
 		vp->bus_master = (options & 16) ? 1 : 0;
 	} else {
@@ -534,12 +542,19 @@
 
 	outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
 
-	if (irq2dev_map[dev->irq] != NULL
-		|| (irq2dev_map[dev->irq] = dev) == NULL
-		|| dev->irq == 0
-		|| request_irq(dev->irq, &vortex_interrupt, 0, vp->product_name)) {
+#ifdef USE_SHARED_IRQ
+	i = request_shared_irq(dev->irq, &vortex_interrupt, dev, vp->product_name);
+	if (i)						/* Error */
+		return i;
+#else
+	if (dev->irq == 0  ||  irq2dev_map[dev->irq] != NULL)
+		return -EAGAIN;
+	irq2dev_map[dev->irq] = dev;
+	if (request_irq(dev->irq, &vortex_interrupt, 0, vp->product_name)) {
+		irq2dev_map[dev->irq] = NULL;
 		return -EAGAIN;
 	}
+#endif
 
 	if (vortex_debug > 1) {
 		EL3WINDOW(4);
@@ -571,7 +586,7 @@
 	inw(ioaddr + 10);
 	inw(ioaddr + 12);
 	/* New: On the Vortex we must also clear the BadSSD counter. */
-	EL3WINDOW(3);
+	EL3WINDOW(4);
 	inb(ioaddr + 12);
 
 	/* Switch to register set 7 for normal use. */
@@ -723,7 +738,11 @@
    after the Tx thread. */
 static void vortex_interrupt(int irq, struct pt_regs *regs)
 {
+#ifdef USE_SHARED_IRQ
+	struct device *dev = (struct device *)(irq == 0 ? regs : irq2dev_map[irq]);
+#else
 	struct device *dev = (struct device *)(irq2dev_map[irq]);
+#endif
 	struct vortex_private *lp;
 	int ioaddr, status;
 	int latency;
@@ -933,9 +952,13 @@
 		outw(inw(ioaddr + Wn4_Media) & ~Media_TP, ioaddr + Wn4_Media);
 	}
 
+#ifdef USE_SHARED_IRQ
+	free_shared_irq(dev->irq, dev);
+#else
 	free_irq(dev->irq);
 	/* Mmmm, we should diable all interrupt sources here. */
 	irq2dev_map[dev->irq] = 0;
+#endif
 
 	update_stats(ioaddr, dev);
 #ifdef MODULE
@@ -979,7 +1002,7 @@
 	vp->stats.tx_window_errors		+= inb(ioaddr + 4);
 	vp->stats.rx_fifo_errors		+= inb(ioaddr + 5);
 	vp->stats.tx_packets			+= inb(ioaddr + 6);
-	vp->stats.tx_packets			+= (inb(ioaddr + 9)&15) << 8;
+	vp->stats.tx_packets			+= (inb(ioaddr + 9)&0x30) << 4;
 	/* Rx packets	*/				inb(ioaddr + 7);   /* Must read to clear */
 	/* Tx deferrals */				inb(ioaddr + 8);
 	/* Don't bother with register 9, an extention of registers 6&7.
@@ -988,7 +1011,7 @@
 	inw(ioaddr + 10);	/* Total Rx and Tx octets. */
 	inw(ioaddr + 12);
 	/* New: On the Vortex we must also clear the BadSSD counter. */
-	EL3WINDOW(3);
+	EL3WINDOW(4);
 	inb(ioaddr + 12);
 
 	/* We change back to window 7 (not 1) with the Vortex. */
diff -u --recursive --new-file v1.3.62/linux/drivers/net/loopback.c linux/drivers/net/loopback.c
--- v1.3.62/linux/drivers/net/loopback.c	Fri Feb  9 17:53:01 1996
+++ linux/drivers/net/loopback.c	Mon Feb 12 14:22:53 1996
@@ -49,26 +49,18 @@
 
 #define LOOPBACK_MTU (PAGE_SIZE*7/8)
 
+/*
+ * The higher levels take care of making this non-reentrant (it's
+ * called with bh's disabled).
+ */
 static int loopback_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct enet_statistics *stats = (struct enet_statistics *)dev->priv;
-	unsigned long flags;
 	int unlock=1;
   
 	if (skb == NULL || dev == NULL) 
 		return(0);
 
-	save_flags(flags);
-	cli();
-	if (dev->tbusy != 0) 
-	{
-		restore_flags(flags);
-		stats->tx_errors++;
-		return(1);
-	}
-	dev->tbusy = 1;
-	restore_flags(flags);
-  
 	/*
 	 *	Optimise so buffers with skb->free=1 are not copied but
 	 *	instead are lobbed from tx queue to rx queue 
@@ -89,29 +81,21 @@
 	  	 *	Packet sent but looped back around. Cease to charge
 	  	 *	the socket for the frame.
 	  	 */
-		save_flags(flags);
-	  	cli();
 	  	skb->sk->wmem_alloc-=skb->truesize;
 	  	skb->sk->write_space(skb->sk);
-	  	restore_flags(flags);
 	}
 
 	skb->protocol=eth_type_trans(skb,dev);
 	skb->dev=dev;
-	save_flags(flags);
-	cli();
 #ifndef LOOPBACK_MUST_CHECKSUM
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 #endif
 	netif_rx(skb);
 	if(unlock)
 	  	skb_device_unlock(skb);
-	restore_flags(flags);
   
-	stats->tx_packets++;
 	stats->rx_packets++;
-
-	dev->tbusy = 0;
+	stats->tx_packets++;
 
 	return(0);
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v1.3.62/linux/drivers/net/slip.c	Fri Feb  9 17:53:02 1996
+++ linux/drivers/net/slip.c	Mon Feb 12 06:42:06 1996
@@ -76,6 +76,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
+#include <linux/if_slip.h>
 #include "slip.h"
 #ifdef CONFIG_INET
 #include <linux/ip.h>
diff -u --recursive --new-file v1.3.62/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c
--- v1.3.62/linux/drivers/scsi/NCR5380.c	Fri Feb  9 17:53:02 1996
+++ linux/drivers/scsi/NCR5380.c	Tue Feb 13 10:47:11 1996
@@ -68,8 +68,6 @@
  *      the high level code.
  */
 
-#include "g_NCR5380.h"
-
 #if (NDEBUG & NDEBUG_LISTS)
 #define LIST(x,y) {printk("LINE:%d   Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); }
 #define REMOVE(w,x,y,z) {printk("LINE:%d   Removing: %p->%p  %p->%p \n", __LINE__, (void*)(w), (void*)(x), (void*)(y), (void*)(z)); if ((x)==(y)) udelay(5); }
@@ -788,8 +786,10 @@
      * the base address.
      */
 
+#ifdef NCR53C400
     if (flags & FLAG_NCR53C400)
 	instance->NCR5380_instance_name += NCR53C400_address_adjust;
+#endif
 
     NCR5380_setup(instance);
 
@@ -839,9 +839,11 @@
     NCR5380_write(TARGET_COMMAND_REG, 0);
     NCR5380_write(SELECT_ENABLE_REG, 0);
 
+#ifdef NCR53C400
     if (hostdata->flags & FLAG_NCR53C400) {
 	NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
     }
+#endif
 
     /* 
      * Detect and correct bus wedge problems.
diff -u --recursive --new-file v1.3.62/linux/drivers/scsi/NCR53c406a.c linux/drivers/scsi/NCR53c406a.c
--- v1.3.62/linux/drivers/scsi/NCR53c406a.c	Wed Nov  8 07:11:33 1995
+++ linux/drivers/scsi/NCR53c406a.c	Wed Feb 14 09:24:21 1996
@@ -1,7 +1,7 @@
 /* 
  *  NCR53c406.c
  *  Low-level SCSI driver for NCR53c406a chip.
- *  Copyright (C) 1994, 1995 Normunds Saumanis (normunds@tech.swh.lv)
+ *  Copyright (C) 1994, 1995, 1996 Normunds Saumanis (normunds@fi.ibm.com)
  * 
  *  LILO command line usage: ncr53c406a=<PORTBASE>[,<IRQ>[,<FASTPIO>]]
  *  Specify IRQ = 0 for non-interrupt driven mode.
@@ -43,6 +43,8 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/bitops.h>
@@ -157,13 +159,13 @@
 /*----------------------------------------------------------------*/
 
 enum Phase {
-  idle,
-  data_out,
-  data_in,
-  command_ph,
-  status_ph,
-  message_out,
-  message_in
+    idle,
+    data_out,
+    data_in,
+    command_ph,
+    status_ph,
+    message_out,
+    message_in
 };
 
 /* Static function prototypes */
@@ -207,13 +209,17 @@
 static volatile int internal_done_errcode = 0;
 static char info_msg[256];
 
+struct proc_dir_entry proc_scsi_NCR53c406a = {
+    PROC_SCSI_NCR53C406A, 7, "NCR53c406a",
+    S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
 /* ================================================================= */
 
 /* possible BIOS locations */
 #if USE_BIOS
 static void *addresses[] = {
-  (void *)0xd8000,
-  (void *)0xc8000
+    (void *)0xd8000,
+    (void *)0xc8000
 };
 #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
 #endif USE_BIOS
@@ -229,13 +235,13 @@
 /* signatures for NCR 53c406a based controllers */
 #if USE_BIOS
 struct signature {
-  char *signature;
-  int  sig_offset;
-  int  sig_length;
+    char *signature;
+    int  sig_offset;
+    int  sig_length;
 } signatures[] = {
-  /*          1         2         3         4         5         6 */
-  /* 123456789012345678901234567890123456789012345678901234567890 */
-  { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82 },
+    /*          1         2         3         4         5         6 */
+    /* 123456789012345678901234567890123456789012345678901234567890 */
+    { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82 },
 };
 #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
 #endif USE_BIOS
@@ -287,60 +293,60 @@
 NCR53c406a_dma_setup (unsigned char *ptr, 
 		      unsigned int count, 
 		      unsigned char mode) {
-  unsigned limit;
-  unsigned long flags = 0;
-
-  VDEB(printk("dma: before count=%d   ", count));
-  if (dma_chan <=3) {
-    if (count > 65536)
-      count = 65536;
-    limit = 65536 - (((unsigned) ptr) & 0xFFFF);
-  } else {
-    if (count > (65536<<1)) 
-      count = (65536<<1);
-    limit = (65536<<1) - (((unsigned) ptr) & 0x1FFFF);
-  }
-  
-  if (count > limit) count = limit;
-  
-  VDEB(printk("after count=%d\n", count));
-  if ((count & 1) || (((unsigned) ptr) & 1))
-    panic ("NCR53c406a: attempted unaligned DMA transfer\n"); 
-
-  save_flags(flags);
-  cli();
-  disable_dma(dma_chan);
-  clear_dma_ff(dma_chan);
-  set_dma_addr(dma_chan, (long) ptr);
-  set_dma_count(dma_chan, count);
-  set_dma_mode(dma_chan, mode);
-  enable_dma(dma_chan);
-  restore_flags(flags);
-
-  return count;
+    unsigned limit;
+    unsigned long flags = 0;
+    
+    VDEB(printk("dma: before count=%d   ", count));
+    if (dma_chan <=3) {
+        if (count > 65536)
+            count = 65536;
+        limit = 65536 - (((unsigned) ptr) & 0xFFFF);
+    } else {
+        if (count > (65536<<1)) 
+            count = (65536<<1);
+        limit = (65536<<1) - (((unsigned) ptr) & 0x1FFFF);
+    }
+    
+    if (count > limit) count = limit;
+    
+    VDEB(printk("after count=%d\n", count));
+    if ((count & 1) || (((unsigned) ptr) & 1))
+        panic ("NCR53c406a: attempted unaligned DMA transfer\n"); 
+    
+    save_flags(flags);
+    cli();
+    disable_dma(dma_chan);
+    clear_dma_ff(dma_chan);
+    set_dma_addr(dma_chan, (long) ptr);
+    set_dma_count(dma_chan, count);
+    set_dma_mode(dma_chan, mode);
+    enable_dma(dma_chan);
+    restore_flags(flags);
+    
+    return count;
 }
-     
+
 static __inline__ int 
 NCR53c406a_dma_write(unsigned char *src, unsigned int count) {
-  return NCR53c406a_dma_setup (src, count, DMA_MODE_WRITE);
+    return NCR53c406a_dma_setup (src, count, DMA_MODE_WRITE);
 }
 
 static __inline__ int 
 NCR53c406a_dma_read(unsigned char *src, unsigned int count) {
-  return NCR53c406a_dma_setup (src, count, DMA_MODE_READ);
+    return NCR53c406a_dma_setup (src, count, DMA_MODE_READ);
 }
 
 static __inline__ int 
 NCR53c406a_dma_residual (void) {
-  register int tmp;
-  unsigned long flags = 0;
-  save_flags(flags);
-  cli();
-  clear_dma_ff(dma_chan);
-  tmp = get_dma_residue(dma_chan);
-  restore_flags(flags);
-
-  return tmp;
+    register int tmp;
+    unsigned long flags = 0;
+    save_flags(flags);
+    cli();
+    clear_dma_ff(dma_chan);
+    tmp = get_dma_residue(dma_chan);
+    restore_flags(flags);
+    
+    return tmp;
 }
 #endif USE_DMA
 
@@ -348,710 +354,702 @@
 static __inline__ int NCR53c406a_pio_read(unsigned char *request, 
 					  unsigned int reqlen) 
 {
-  int	i;
-  int	len;	/* current scsi fifo size */
-  unsigned long flags = 0;
-
-  REG1;
-  while (reqlen) {
-    i = inb(PIO_STATUS);
-/*    VDEB(printk("pio_status=%x\n", i)); */
-    if (i & 0x80) 
-      return 0;
-
-    switch( i & 0x1e ) {
-    default:
-    case 0x10:
-      len=0; break;
-    case 0x0:
-      len=1; break;
-    case 0x8:
-      len=42; break;
-    case 0xc:
-      len=84; break;
-    case 0xe:
-      len=128; break;
-    }
-
-    if ((i & 0x40) && len == 0) { /* fifo empty and interrupt occured */
-      return 0;
-    }
-
-    if (len) {
-      if( len > reqlen ) 
-	len = reqlen;
-
-      save_flags(flags);
-      cli();
-      if( fast_pio && len > 3 ) { 
-	insl(PIO_FIFO,request,len>>2); 
-	request += len & 0xfc; 
-	reqlen -= len & 0xfc; 
-      } 
-      else { 
-	while(len--) {
-	  *request++ = inb(PIO_FIFO);
-	  reqlen--;
-	}
-      }
-      restore_flags(flags);
+    int	i;
+    int	len;	/* current scsi fifo size */
+    unsigned long flags = 0;
+    
+    REG1;
+    while (reqlen) {
+        i = inb(PIO_STATUS);
+        /*    VDEB(printk("pio_status=%x\n", i)); */
+        if (i & 0x80) 
+            return 0;
+        
+        switch( i & 0x1e ) {
+        default:
+        case 0x10:
+            len=0; break;
+        case 0x0:
+            len=1; break;
+        case 0x8:
+            len=42; break;
+        case 0xc:
+            len=84; break;
+        case 0xe:
+            len=128; break;
+        }
+        
+        if ((i & 0x40) && len == 0) { /* fifo empty and interrupt occured */
+            return 0;
+        }
+        
+        if (len) {
+            if( len > reqlen ) 
+                len = reqlen;
+            
+            save_flags(flags);
+            cli();
+            if( fast_pio && len > 3 ) { 
+                insl(PIO_FIFO,request,len>>2); 
+                request += len & 0xfc; 
+                reqlen -= len & 0xfc; 
+            } 
+            else { 
+                while(len--) {
+                    *request++ = inb(PIO_FIFO);
+                    reqlen--;
+                }
+            }
+            restore_flags(flags);
+        }
     }
-  }
-  return 0;
+    return 0;
 }
 
 static __inline__ int NCR53c406a_pio_write(unsigned char *request,
 					   unsigned int reqlen) 
 {
-  int	i = 0;
-  int	len;	/* current scsi fifo size */
-  unsigned long flags = 0;
-
-  REG1;
-  while (reqlen && !(i&0x40)) {
-    i = inb(PIO_STATUS);
-/*    VDEB(printk("pio_status=%x\n", i)); */
-    if (i & 0x80)		/* error */
-      return 0;
-    
-    switch( i & 0x1e ) {
-    case 0x10:
-      len=128; break;
-    case 0x0:
-      len=84; break;
-    case 0x8:
-      len=42; break;
-    case 0xc:
-      len=1; break;
-    default:
-    case 0xe:
-      len=0; break;
-    }
-
-    if (len) {
-      if( len > reqlen ) 
-	len = reqlen;
-      
-      save_flags(flags);
-      cli();
-      if( fast_pio && len > 3 ) { 
-	outsl(PIO_FIFO,request,len>>2); 
-	request += len & 0xfc; 
-	reqlen -= len & 0xfc; 
-      } 
-      else { 
-	while(len--) {
-	  outb(*request++, PIO_FIFO);
-	  reqlen--;
-	}
-      }
-      restore_flags(flags);
+    int	i = 0;
+    int	len;	/* current scsi fifo size */
+    unsigned long flags = 0;
+    
+    REG1;
+    while (reqlen && !(i&0x40)) {
+        i = inb(PIO_STATUS);
+        /*    VDEB(printk("pio_status=%x\n", i)); */
+        if (i & 0x80)		/* error */
+            return 0;
+        
+        switch( i & 0x1e ) {
+        case 0x10:
+            len=128; break;
+        case 0x0:
+            len=84; break;
+        case 0x8:
+            len=42; break;
+        case 0xc:
+            len=1; break;
+        default:
+        case 0xe:
+            len=0; break;
+        }
+        
+        if (len) {
+            if( len > reqlen ) 
+                len = reqlen;
+            
+            save_flags(flags);
+            cli();
+            if( fast_pio && len > 3 ) { 
+                outsl(PIO_FIFO,request,len>>2); 
+                request += len & 0xfc; 
+                reqlen -= len & 0xfc; 
+            } 
+            else { 
+                while(len--) {
+                    outb(*request++, PIO_FIFO);
+                    reqlen--;
+                }
+            }
+            restore_flags(flags);
+        }
     }
-  }
-  return 0;
+    return 0;
 }
 #endif USE_PIO
 
 int 
 NCR53c406a_detect(Scsi_Host_Template * tpnt){
-  struct Scsi_Host *shpnt;
+    struct Scsi_Host *shpnt;
 #ifndef PORT_BASE
-  int i;
+    int i;
 #endif
-  
+    
 #if USE_BIOS
-  int ii, jj;
-  bios_base = 0;
-  /* look for a valid signature */
-  for( ii=0; ii < ADDRESS_COUNT && !bios_base; ii++)
-    for( jj=0; (jj < SIGNATURE_COUNT) && !bios_base; jj++)
-      if(!memcmp((void *) addresses[ii]+signatures[jj].sig_offset,
-		 (void *) signatures[jj].signature,
-		 (int) signatures[jj].sig_length))
-	bios_base=addresses[ii];
-
-  if(!bios_base){
-    printk("NCR53c406a: BIOS signature not found\n");
-    return 0;
-  }
-  
-  DEB(printk("NCR53c406a BIOS found at %X\n", (unsigned int) bios_base););
+    int ii, jj;
+    bios_base = 0;
+    /* look for a valid signature */
+    for( ii=0; ii < ADDRESS_COUNT && !bios_base; ii++)
+        for( jj=0; (jj < SIGNATURE_COUNT) && !bios_base; jj++)
+            if(!memcmp((void *) addresses[ii]+signatures[jj].sig_offset,
+                       (void *) signatures[jj].signature,
+                       (int) signatures[jj].sig_length))
+                bios_base=addresses[ii];
+    
+    if(!bios_base){
+        printk("NCR53c406a: BIOS signature not found\n");
+        return 0;
+    }
+    
+    DEB(printk("NCR53c406a BIOS found at %X\n", (unsigned int) bios_base););
 #endif USE_BIOS
     
 #ifdef PORT_BASE
-  if (check_region(port_base, 0x10)) /* ports already snatched */
-    port_base = 0;
-
+    if (check_region(port_base, 0x10)) /* ports already snatched */
+        port_base = 0;
+    
 #else  /* autodetect */
-  if (port_base) {		/* LILO override */
-    if (check_region(port_base, 0x10))
-      port_base = 0;
-  }
-  else {
-    for(i=0;  i<PORT_COUNT && !port_base; i++){
-      if(check_region(ports[i], 0x10)){
-	DEB(printk("NCR53c406a: port %x in use\n", ports[i]));
-      }
-      else {
-	VDEB(printk("NCR53c406a: port %x available\n", ports[i]));
-	outb(C5_IMG, ports[i] + 0x0d); /* reg set 1 */
-	if(   (inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7
-	   && (inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7
-	   && (inb(ports[i] + 0x0e) & 0xf8) == 0x58 ) {
-	  VDEB(printk("NCR53c406a: Sig register valid\n"));
-	  VDEB(printk("port_base=%x\n", port_base));
-	  port_base = ports[i];
-	}
-      }
+    if (port_base) {		/* LILO override */
+        if (check_region(port_base, 0x10))
+            port_base = 0;
+    }
+    else {
+        for(i=0;  i<PORT_COUNT && !port_base; i++){
+            if(check_region(ports[i], 0x10)){
+                DEB(printk("NCR53c406a: port %x in use\n", ports[i]));
+            }
+            else {
+                VDEB(printk("NCR53c406a: port %x available\n", ports[i]));
+                outb(C5_IMG, ports[i] + 0x0d); /* reg set 1 */
+                if(   (inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7
+                   && (inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7
+                   && (inb(ports[i] + 0x0e) & 0xf8) == 0x58 ) {
+                    VDEB(printk("NCR53c406a: Sig register valid\n"));
+                    VDEB(printk("port_base=%x\n", port_base));
+                    port_base = ports[i];
+                }
+            }
+        }
     }
-  }
 #endif PORT_BASE
-
-  if(!port_base){		/* no ports found */
-    printk("NCR53c406a: no available ports found\n");
-    return 0;
-  }
-
-  DEB(printk("NCR53c406a detected\n"));
-  
-  calc_port_addr();
-  chip_init();
-
+    
+    if(!port_base){		/* no ports found */
+        printk("NCR53c406a: no available ports found\n");
+        return 0;
+    }
+    
+    DEB(printk("NCR53c406a detected\n"));
+    
+    calc_port_addr();
+    chip_init();
+    
 #ifndef IRQ_LEV
-  if (irq_level < 0) {		/* LILO override if >= 0*/
-    irq_level=irq_probe();
-    if (irq_level < 0) {		/* Trouble */
-      printk("NCR53c406a: IRQ problem, irq_level=%d, giving up\n", irq_level);
-      return 0;
+    if (irq_level < 0) {		/* LILO override if >= 0*/
+        irq_level=irq_probe();
+        if (irq_level < 0) {		/* Trouble */
+            printk("NCR53c406a: IRQ problem, irq_level=%d, giving up\n", irq_level);
+            return 0;
+        }
     }
-  }
 #endif
-
-  DEB(printk("NCR53c406a: using port_base %x\n", port_base));
-  request_region(port_base, 0x10, "NCR53c406a");
-
-  if(irq_level > 0) {
-    if(request_irq(irq_level, NCR53c406a_intr, 0, "NCR53c406a")){
-      printk("NCR53c406a: unable to allocate IRQ %d\n", irq_level);
-      return 0;
+    
+    DEB(printk("NCR53c406a: using port_base %x\n", port_base));
+    request_region(port_base, 0x10, "NCR53c406a");
+    
+    if(irq_level > 0) {
+        if(request_irq(irq_level, NCR53c406a_intr, 0, "NCR53c406a")){
+            printk("NCR53c406a: unable to allocate IRQ %d\n", irq_level);
+            return 0;
+        }
+        tpnt->can_queue = 1;
+        DEB(printk("NCR53c406a: allocated IRQ %d\n", irq_level));
     }
-    tpnt->can_queue = 1;
-    DEB(printk("NCR53c406a: allocated IRQ %d\n", irq_level));
-  }
-  else if (irq_level == 0) {
-    tpnt->can_queue = 0;
-    DEB(printk("NCR53c406a: No interrupts detected\n"));
+    else if (irq_level == 0) {
+        tpnt->can_queue = 0;
+        DEB(printk("NCR53c406a: No interrupts detected\n"));
 #if USE_DMA
-    printk("NCR53c406a: No interrupts found and DMA mode defined. Giving up.\n");
-    return 0;
+        printk("NCR53c406a: No interrupts found and DMA mode defined. Giving up.\n");
+        return 0;
 #endif USE_DMA
-  }
-  else {
-    DEB(printk("NCR53c406a: Shouldn't get here!\n"));
-    return 0;
-  }
-
+    }
+    else {
+        DEB(printk("NCR53c406a: Shouldn't get here!\n"));
+        return 0;
+    }
+    
 #if USE_DMA
-  dma_chan = DMA_CHAN;
-  if(request_dma(dma_chan, "NCR53c406a") != 0){
-    printk("NCR53c406a: unable to allocate DMA channel %d\n", dma_chan);
-    return 0;
-  }
-
-  DEB(printk("Allocated DMA channel %d\n", dma_chan));
+    dma_chan = DMA_CHAN;
+    if(request_dma(dma_chan, "NCR53c406a") != 0){
+        printk("NCR53c406a: unable to allocate DMA channel %d\n", dma_chan);
+        return 0;
+    }
+    
+    DEB(printk("Allocated DMA channel %d\n", dma_chan));
 #endif USE_DMA 
-
-  tpnt->present = 1;
-
-  shpnt = scsi_register(tpnt, 0);
-  shpnt->irq = irq_level;
-  shpnt->io_port = port_base;
-  shpnt->n_io_port = 0x10;
+    
+    tpnt->present = 1;
+    tpnt->proc_dir = &proc_scsi_NCR53c406a;
+    
+    shpnt = scsi_register(tpnt, 0);
+    shpnt->irq = irq_level;
+    shpnt->io_port = port_base;
+    shpnt->n_io_port = 0x10;
 #if USE_DMA
-  shpnt->dma = dma_chan;
+    shpnt->dma = dma_chan;
 #endif
-
+    
 #if USE_DMA
-  sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, DMA channel %d.", port_base, irq_level, dma_chan);
+    sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, DMA channel %d.", 
+            port_base, irq_level, dma_chan);
 #else
-  sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, %s PIO mode.", port_base, irq_level, fast_pio ? "fast" : "slow");
+    sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, %s PIO mode.", 
+            port_base, irq_level, fast_pio ? "fast" : "slow");
 #endif
-
-  return (tpnt->present);
+    
+    return (tpnt->present);
 }
 
 /* called from init/main.c */
 void NCR53c406a_setup(char *str, int *ints)
 {
-  static size_t setup_idx = 0;
-  size_t i;
-  
-  DEB(printk("NCR53c406a: Setup called\n"););
-  
-  if (setup_idx >= PORT_COUNT - 1) {
-    printk("NCR53c406a: Setup called too many times.  Bad LILO params?\n");
-    return;
-  }
-  if (ints[0] < 1 || ints[0] > 3) {
-    printk("NCR53c406a: Malformed command line\n");
-    printk("NCR53c406a: Usage: ncr53c406a=<PORTBASE>[,<IRQ>[,<FASTPIO>]]\n");
-    return;
-  }
-  for (i = 0; i < PORT_COUNT && !port_base; i++)
-    if (ports[i] == ints[1]) {
-      port_base = ints[1];
-      DEB(printk("NCR53c406a: Specified port_base 0x%X\n", port_base);)
-    }
-  if (!port_base) {
-    printk("NCR53c406a: Invalid PORTBASE 0x%X specified\n", ints[1]);
-    return;
-  }
-  
-  if (ints[0] > 1) {
-    if (ints[2] == 0) {
-      irq_level = 0;
-      DEB(printk("NCR53c406a: Specified irq %d\n", irq_level);)
+    static size_t setup_idx = 0;
+    size_t i;
+    
+    DEB(printk("NCR53c406a: Setup called\n"););
+    
+    if (setup_idx >= PORT_COUNT - 1) {
+        printk("NCR53c406a: Setup called too many times.  Bad LILO params?\n");
+        return;
     }
-    else
-      for (i = 0; i < INTR_COUNT && irq_level < 0; i++)
-	if (intrs[i] == ints[2]) {
-	  irq_level = ints[2];
-	  DEB(printk("NCR53c406a: Specified irq %d\n", port_base);)
-	}
-    if (irq_level < 0)
-      printk("NCR53c406a: Invalid IRQ %d specified\n", ints[2]);
-  }
-
-  if (ints[0] > 2)
-    fast_pio = ints[3];
-
-  DEB(printk("NCR53c406a: port_base=0x%X, irq=%d, fast_pio=%d\n", port_base, irq_level, fast_pio);)
+    if (ints[0] < 1 || ints[0] > 3) {
+        printk("NCR53c406a: Malformed command line\n");
+        printk("NCR53c406a: Usage: ncr53c406a=<PORTBASE>[,<IRQ>[,<FASTPIO>]]\n");
+        return;
+    }
+    for (i = 0; i < PORT_COUNT && !port_base; i++)
+        if (ports[i] == ints[1]) {
+            port_base = ints[1];
+            DEB(printk("NCR53c406a: Specified port_base 0x%X\n", port_base);)
+        }
+    if (!port_base) {
+        printk("NCR53c406a: Invalid PORTBASE 0x%X specified\n", ints[1]);
+        return;
+    }
+    
+    if (ints[0] > 1) {
+        if (ints[2] == 0) {
+            irq_level = 0;
+            DEB(printk("NCR53c406a: Specified irq %d\n", irq_level);)
+        }
+        else
+            for (i = 0; i < INTR_COUNT && irq_level < 0; i++)
+                if (intrs[i] == ints[2]) {
+                    irq_level = ints[2];
+                    DEB(printk("NCR53c406a: Specified irq %d\n", port_base);)
+                }
+        if (irq_level < 0)
+            printk("NCR53c406a: Invalid IRQ %d specified\n", ints[2]);
+    }
+    
+    if (ints[0] > 2)
+        fast_pio = ints[3];
+    
+    DEB(printk("NCR53c406a: port_base=0x%X, irq=%d, fast_pio=%d\n", 
+               port_base, irq_level, fast_pio);)
 }
 
 const char* 
 NCR53c406a_info(struct Scsi_Host *SChost){
-  DEB(printk("NCR53c406a_info called\n"));
-  return (info_msg);
+    DEB(printk("NCR53c406a_info called\n"));
+    return (info_msg);
 }
 
 static void internal_done(Scsi_Cmnd *SCpnt) {
-  internal_done_errcode = SCpnt->result;
-  ++internal_done_flag;
+    internal_done_errcode = SCpnt->result;
+    ++internal_done_flag;
 }
 
 
 static void wait_intr() {
-  int i = jiffies + WATCHDOG;
-
-  while(i>jiffies && !(inb(STAT_REG)&0xe0)) /* wait for a pseudo-interrupt */
-    barrier();
-
-  if (i <= jiffies) {		/* Timed out */
-    rtrc(0);
-    current_SC->result = DID_TIME_OUT << 16;
-    current_SC->SCp.phase = idle;
-    current_SC->scsi_done(current_SC);
-    return;
-  }
-  
-  NCR53c406a_intr(0, NULL);
+    int i = jiffies + WATCHDOG;
+    
+    while(i>jiffies && !(inb(STAT_REG)&0xe0)) /* wait for a pseudo-interrupt */
+        barrier();
+    
+    if (i <= jiffies) {		/* Timed out */
+        rtrc(0);
+        current_SC->result = DID_TIME_OUT << 16;
+        current_SC->SCp.phase = idle;
+        current_SC->scsi_done(current_SC);
+        return;
+    }
+    
+    NCR53c406a_intr(0, NULL);
 }
 
 int NCR53c406a_command(Scsi_Cmnd *SCpnt){
-  DEB(printk("NCR53c406a_command called\n"));
-  NCR53c406a_queue(SCpnt, internal_done);
-  if(irq_level)
-    while (!internal_done_flag);
-  else				/* interrupts not supported */
-    while (!internal_done_flag)
-      wait_intr();
-  
-  internal_done_flag = 0;
-  return internal_done_errcode;
+    DEB(printk("NCR53c406a_command called\n"));
+    NCR53c406a_queue(SCpnt, internal_done);
+    if(irq_level)
+        while (!internal_done_flag);
+    else                        /* interrupts not supported */
+        while (!internal_done_flag)
+            wait_intr();
+    
+    internal_done_flag = 0;
+    return internal_done_errcode;
 }
 
 
 int 
 NCR53c406a_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)){
-  int i;
-  unsigned long flags = 0;
-
-  VDEB(printk("NCR53c406a_queue called\n"));
-  DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", 
-	 SCpnt->cmnd[0],
-	 SCpnt->cmd_len,
-	 SCpnt->target, 
-	 SCpnt->lun,  
-	 SCpnt->request_bufflen));
+    int i;
+    unsigned long flags = 0;
 
+    VDEB(printk("NCR53c406a_queue called\n"));
+    DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", 
+               SCpnt->cmnd[0],
+               SCpnt->cmd_len,
+               SCpnt->target, 
+               SCpnt->lun,  
+               SCpnt->request_bufflen));
+    
 #if 0
-  VDEB(for(i=0; i<SCpnt->cmd_len; i++)
-    printk("cmd[%d]=%02x  ", i, SCpnt->cmnd[i]));
-  VDEB(printk("\n"));
-#endif
-
-  current_SC = SCpnt;
-  current_SC->scsi_done = done;
-  current_SC->SCp.phase = command_ph;
-  current_SC->SCp.Status = 0;
-  current_SC->SCp.Message = 0;
-  
-  save_flags(flags);
-  cli();
-  REG0;
-  outb(SCpnt->target, DEST_ID);	/* set destination */
-  outb(FLUSH_FIFO, CMD_REG);	/* reset the fifos */
-  
-  for(i=0; i<SCpnt->cmd_len; i++){
-    outb(SCpnt->cmnd[i], SCSI_FIFO);
-  }
-  outb(SELECT_NO_ATN, CMD_REG);
-  restore_flags(flags);
-
-  rtrc(1);
-  return 0;
+    VDEB(for(i=0; i<SCpnt->cmd_len; i++)
+         printk("cmd[%d]=%02x  ", i, SCpnt->cmnd[i]));
+    VDEB(printk("\n"));
+#endif
+    
+    current_SC = SCpnt;
+    current_SC->scsi_done = done;
+    current_SC->SCp.phase = command_ph;
+    current_SC->SCp.Status = 0;
+    current_SC->SCp.Message = 0;
+    
+    save_flags(flags);
+    cli();
+    REG0;
+    outb(SCpnt->target, DEST_ID); /* set destination */
+    outb(FLUSH_FIFO, CMD_REG);	/* reset the fifos */
+    
+    for(i=0; i<SCpnt->cmd_len; i++){
+        outb(SCpnt->cmnd[i], SCSI_FIFO);
+    }
+    outb(SELECT_NO_ATN, CMD_REG);
+    restore_flags(flags);
+    
+    rtrc(1);
+    return 0;
 }
 
 int
 NCR53c406a_abort(Scsi_Cmnd *SCpnt){
-  DEB(printk("NCR53c406a_abort called\n"));
-  return SCSI_ABORT_SNOOZE;	/* Don't know how to abort */
+    DEB(printk("NCR53c406a_abort called\n"));
+    return SCSI_ABORT_SNOOZE;	/* Don't know how to abort */
 }
 
 int 
 NCR53c406a_reset(Scsi_Cmnd *SCpnt){
-  DEB(printk("NCR53c406a_reset called\n"));
-  outb(C4_IMG, CONFIG4); /* Select reg set 0 */
-  outb(CHIP_RESET, CMD_REG);
-  outb(SCSI_NOP, CMD_REG);	/* required after reset */
-  outb(SCSI_RESET, CMD_REG);
-  chip_init();
-
-  rtrc(2);
-  if (irq_level)
-    return SCSI_RESET_PENDING;	/* should get an interrupt */
-  else
-    return SCSI_RESET_WAKEUP;	/* won't get any interrupts */
+    DEB(printk("NCR53c406a_reset called\n"));
+    outb(C4_IMG, CONFIG4);      /* Select reg set 0 */
+    outb(CHIP_RESET, CMD_REG);
+    outb(SCSI_NOP, CMD_REG);	/* required after reset */
+    outb(SCSI_RESET, CMD_REG);
+    chip_init();
+    
+    rtrc(2);
+    if (irq_level)
+        return SCSI_RESET_PENDING; /* should get an interrupt */
+    else
+        return SCSI_RESET_WAKEUP; /* won't get any interrupts */
 }
 
 int 
 NCR53c406a_biosparm(Scsi_Disk *disk, kdev_t dev, int* info_array){
-  int size;
-
-  DEB(printk("NCR53c406a_biosparm called\n"));
-
-  size = disk->capacity;
-  info_array[0] = 64;   /* heads */
-  info_array[1] = 32;   /* sectors */
-  info_array[2] = size>>11;  /* cylinders */
-  if (info_array[2] > 1024) {	/* big disk */
-    info_array[0] = 255;
-    info_array[1] = 63;
-    info_array[2] = size / (255*63);
+    int size;
+    
+    DEB(printk("NCR53c406a_biosparm called\n"));
+    
+    size = disk->capacity;
+    info_array[0] = 64;         /* heads */
+    info_array[1] = 32;         /* sectors */
+    info_array[2] = size>>11;   /* cylinders */
+    if (info_array[2] > 1024) {	/* big disk */
+      info_array[0] = 255;
+      info_array[1] = 63;
+      info_array[2] = size / (255*63);
+    }
+    return 0;
   }
-  return 0;
-}
-
-static void
+     
+     static void
 NCR53c406a_intr(int unused, struct pt_regs *regs){
-  DEB(unsigned char fifo_size;)
-  DEB(unsigned char seq_reg;)
-  unsigned char status, int_reg;
-  unsigned long flags = 0;
+    DEB(unsigned char fifo_size;)
+    DEB(unsigned char seq_reg;)
+    unsigned char status, int_reg;
+    unsigned long flags = 0;
 #if USE_PIO
-  unsigned char pio_status; 
-  struct scatterlist *sglist;
-  unsigned int sgcount;
+    unsigned char pio_status; 
+    struct scatterlist *sglist;
+    unsigned int sgcount;
 #endif
-
-  VDEB(printk("NCR53c406a_intr called\n"));
-
-  save_flags(flags);
-  cli();
+    
+    VDEB(printk("NCR53c406a_intr called\n"));
+    
+    save_flags(flags);
+    cli();
 #if USE_PIO
-  REG1;
-  pio_status = inb(PIO_STATUS);
+    REG1;
+    pio_status = inb(PIO_STATUS);
 #endif
-  REG0;
-  status = inb(STAT_REG);
-  DEB(seq_reg = inb(SEQ_REG));
-  int_reg = inb(INT_REG);
-  DEB(fifo_size = inb(FIFO_FLAGS) & 0x1f);
-  restore_flags(flags);
-
+    REG0;
+    status = inb(STAT_REG);
+    DEB(seq_reg = inb(SEQ_REG));
+    int_reg = inb(INT_REG);
+    DEB(fifo_size = inb(FIFO_FLAGS) & 0x1f);
+    restore_flags(flags);
+    
 #if NCR53C406A_DEBUG
-  printk("status=%02x, seq_reg=%02x, int_reg=%02x, fifo_size=%02x", 
-	 status, seq_reg, int_reg, fifo_size);
+    printk("status=%02x, seq_reg=%02x, int_reg=%02x, fifo_size=%02x", 
+           status, seq_reg, int_reg, fifo_size);
 #if (USE_DMA)
-  printk("\n");
+    printk("\n");
 #else
-  printk(", pio=%02x\n", pio_status);
+    printk(", pio=%02x\n", pio_status);
 #endif USE_DMA
 #endif NCR53C406A_DEBUG
-
-  if(int_reg & 0x80){ /* SCSI reset intr */
-    rtrc(3);
-    DEB(printk("NCR53c406a: reset intr received\n"));
-    current_SC->SCp.phase = idle;
-    current_SC->result = DID_RESET << 16;
-    current_SC->scsi_done(current_SC);
-    return;
-  }
-
+    
+    if(int_reg & 0x80){         /* SCSI reset intr */
+        rtrc(3);
+        DEB(printk("NCR53c406a: reset intr received\n"));
+        current_SC->SCp.phase = idle;
+        current_SC->result = DID_RESET << 16;
+        current_SC->scsi_done(current_SC);
+        return;
+    }
+    
 #if USE_PIO
-  if(pio_status & 0x80) {
-    printk("NCR53C406A: Warning: PIO error!\n");
-    current_SC->SCp.phase = idle;
-    current_SC->result = DID_ERROR << 16;
-    current_SC->scsi_done(current_SC);
-    return;
-  }
+    if(pio_status & 0x80) {
+        printk("NCR53C406A: Warning: PIO error!\n");
+        current_SC->SCp.phase = idle;
+        current_SC->result = DID_ERROR << 16;
+        current_SC->scsi_done(current_SC);
+        return;
+    }
 #endif USE_PIO
-
-  if(status & 0x20) {		/* Parity error */
-    printk("NCR53c406a: Warning: parity error!\n");
-    current_SC->SCp.phase = idle;
-    current_SC->result = DID_PARITY << 16;
-    current_SC->scsi_done(current_SC);
-    return;
-  }
-
-  if(status & 0x40) {		/* Gross error */
-    printk("NCR53c406a: Warning: gross error!\n");
-    current_SC->SCp.phase = idle;
-    current_SC->result = DID_ERROR << 16;
-    current_SC->scsi_done(current_SC);
-    return;
-  }
-
-  if(int_reg & 0x20){		/* Disconnect */
-    DEB(printk("NCR53c406a: disconnect intr received\n"));
-    if(current_SC->SCp.phase != message_in){ /* Unexpected disconnect */
-      current_SC->result = DID_NO_CONNECT << 16;
-      }
-    else{  /* Command complete, return status and message */
-      current_SC->result = (current_SC->SCp.Status & 0xff) 
-	| ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16);
-    }
-  
-    rtrc(0);
-    current_SC->SCp.phase = idle;
-    current_SC->scsi_done( current_SC );
-    return;
-  }
-  
-  switch(status & 0x07){	/* scsi phase */
-  case 0x00:			/* DATA-OUT */
-    if(int_reg & 0x10){		/* Target requesting info transfer */
-      rtrc(5);
-      current_SC->SCp.phase = data_out;
-      VDEB(printk("NCR53c406a: Data-Out phase\n"));
-      outb(FLUSH_FIFO, CMD_REG);
-      LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */
+    
+    if(status & 0x20) {		/* Parity error */
+        printk("NCR53c406a: Warning: parity error!\n");
+        current_SC->SCp.phase = idle;
+        current_SC->result = DID_PARITY << 16;
+        current_SC->scsi_done(current_SC);
+        return;
+    }
+    
+    if(status & 0x40) {		/* Gross error */
+        printk("NCR53c406a: Warning: gross error!\n");
+        current_SC->SCp.phase = idle;
+        current_SC->result = DID_ERROR << 16;
+        current_SC->scsi_done(current_SC);
+        return;
+    }
+    
+    if(int_reg & 0x20){		/* Disconnect */
+        DEB(printk("NCR53c406a: disconnect intr received\n"));
+        if(current_SC->SCp.phase != message_in){ /* Unexpected disconnect */
+            current_SC->result = DID_NO_CONNECT << 16;
+        }
+        else{  /* Command complete, return status and message */
+            current_SC->result = (current_SC->SCp.Status & 0xff) 
+                | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16);
+        }
+        
+        rtrc(0);
+        current_SC->SCp.phase = idle;
+        current_SC->scsi_done( current_SC );
+        return;
+    }
+    
+    switch(status & 0x07){	/* scsi phase */
+    case 0x00:			/* DATA-OUT */
+        if(int_reg & 0x10){     /* Target requesting info transfer */
+            rtrc(5);
+            current_SC->SCp.phase = data_out;
+            VDEB(printk("NCR53c406a: Data-Out phase\n"));
+            outb(FLUSH_FIFO, CMD_REG);
+            LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */
 #if USE_DMA			/* No s/g support for DMA */
-      NCR53c406a_dma_write(current_SC->request_buffer, 
-			   current_SC->request_bufflen);
+            NCR53c406a_dma_write(current_SC->request_buffer, 
+                                 current_SC->request_bufflen);
 #endif USE_DMA
-      outb(TRANSFER_INFO | DMA_OP, CMD_REG); 
+            outb(TRANSFER_INFO | DMA_OP, CMD_REG); 
 #if USE_PIO
-      if (!current_SC->use_sg)	/* Don't use scatter-gather */
-	NCR53c406a_pio_write(current_SC->request_buffer, 
-			     current_SC->request_bufflen);
-      else {			/* use scatter-gather */
-	sgcount = current_SC->use_sg;
-	sglist = current_SC->request_buffer;
-	while( sgcount-- ) {
-	  NCR53c406a_pio_write(sglist->address, sglist->length);
-	  sglist++;
-	}
-      }
-      REG0;
+            if (!current_SC->use_sg) /* Don't use scatter-gather */
+                NCR53c406a_pio_write(current_SC->request_buffer, 
+                                     current_SC->request_bufflen);
+            else {              /* use scatter-gather */
+                sgcount = current_SC->use_sg;
+                sglist = current_SC->request_buffer;
+                while( sgcount-- ) {
+                    NCR53c406a_pio_write(sglist->address, sglist->length);
+                    sglist++;
+                }
+            }
+            REG0;
 #endif USE_PIO
-    }
-    break;
-      
-  case 0x01:			/* DATA-IN */
-    if(int_reg & 0x10){		/* Target requesting info transfer */
-      rtrc(6);
-      current_SC->SCp.phase = data_in;
-      VDEB(printk("NCR53c406a: Data-In phase\n"));
-      outb(FLUSH_FIFO, CMD_REG);
-      LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */
+        }
+        break;
+        
+    case 0x01:			/* DATA-IN */
+        if(int_reg & 0x10){     /* Target requesting info transfer */
+            rtrc(6);
+            current_SC->SCp.phase = data_in;
+            VDEB(printk("NCR53c406a: Data-In phase\n"));
+            outb(FLUSH_FIFO, CMD_REG);
+            LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */
 #if USE_DMA			/* No s/g support for DMA */
-      NCR53c406a_dma_read(current_SC->request_buffer, 
-			  current_SC->request_bufflen);
+            NCR53c406a_dma_read(current_SC->request_buffer, 
+                                current_SC->request_bufflen);
 #endif USE_DMA
-      outb(TRANSFER_INFO | DMA_OP, CMD_REG); 
+            outb(TRANSFER_INFO | DMA_OP, CMD_REG); 
 #if USE_PIO
-      if (!current_SC->use_sg)	/* Don't use scatter-gather */
-	NCR53c406a_pio_read(current_SC->request_buffer, 
-			    current_SC->request_bufflen);
-      else {			/* Use scatter-gather */
-	sgcount = current_SC->use_sg;
-	sglist = current_SC->request_buffer;
-	while( sgcount-- ) {
-	  NCR53c406a_pio_read(sglist->address, sglist->length);
-	  sglist++;
-	}
-      }
-      REG0;
+            if (!current_SC->use_sg) /* Don't use scatter-gather */
+                NCR53c406a_pio_read(current_SC->request_buffer, 
+                                    current_SC->request_bufflen);
+            else {              /* Use scatter-gather */
+                sgcount = current_SC->use_sg;
+                sglist = current_SC->request_buffer;
+                while( sgcount-- ) {
+                    NCR53c406a_pio_read(sglist->address, sglist->length);
+                    sglist++;
+                }
+            }
+            REG0;
 #endif USE_PIO
+        }
+        break;
+        
+    case 0x02:			/* COMMAND */
+        current_SC->SCp.phase = command_ph;
+        printk("NCR53c406a: Warning: Unknown interupt occured in command phase!\n");
+        break;
+        
+    case 0x03:			/* STATUS */
+        rtrc(7);
+        current_SC->SCp.phase = status_ph;
+        VDEB(printk("NCR53c406a: Status phase\n"));
+        outb(FLUSH_FIFO, CMD_REG);
+        outb(INIT_CMD_COMPLETE, CMD_REG);
+        break;
+        
+    case 0x04:			/* Reserved */
+    case 0x05:			/* Reserved */
+        printk("NCR53c406a: WARNING: Reserved phase!!!\n");
+        break;
+        
+    case 0x06:			/* MESSAGE-OUT */
+        DEB(printk("NCR53c406a: Message-Out phase\n"));
+        current_SC->SCp.phase = message_out;
+        outb(SET_ATN, CMD_REG);	/* Reject the message */
+        outb(MSG_ACCEPT, CMD_REG);
+        break;
+        
+    case 0x07:			/* MESSAGE-IN */
+        rtrc(4);
+        VDEB(printk("NCR53c406a: Message-In phase\n"));
+        current_SC->SCp.phase = message_in;
+        
+        current_SC->SCp.Status = inb(SCSI_FIFO);    
+        current_SC->SCp.Message = inb(SCSI_FIFO);
+        
+        VDEB(printk("SCSI FIFO size=%d\n", inb(FIFO_FLAGS) & 0x1f));
+        DEB(printk("Status = %02x  Message = %02x\n", 
+                   current_SC->SCp.Status, current_SC->SCp.Message));
+        
+        if(current_SC->SCp.Message == SAVE_POINTERS || 
+           current_SC->SCp.Message == DISCONNECT) {
+            outb(SET_ATN, CMD_REG); /* Reject message */
+            DEB(printk("Discarding SAVE_POINTERS message\n"));
+        }
+        outb(MSG_ACCEPT, CMD_REG);
+        break;
     }
-    break;
-    
-  case 0x02:			/* COMMAND */
-    current_SC->SCp.phase = command_ph;
-    printk("NCR53c406a: Warning: Unknown interupt occured in command phase!\n");
-    break;
-    
-  case 0x03:			/* STATUS */
-    rtrc(7);
-    current_SC->SCp.phase = status_ph;
-    VDEB(printk("NCR53c406a: Status phase\n"));
-#if 0
-#if VERBOSE_NCR53C406A_DEBUG
-    printk("request_buffer=");
-    for(i=0; i<current_SC->request_bufflen && i<256; i++)
-      printk("%02x ", *((unsigned char*)current_SC->request_buffer + i));
-    printk("\n");
-#if USE_DMA
-    printk("dma residue = %d\n", NCR53c406a_dma_residual());
-#endif USE_DMA
-#endif VERBOSE_NCR53C406A_DEBUG
-#endif
-    
-    outb(FLUSH_FIFO, CMD_REG);
-    outb(INIT_CMD_COMPLETE, CMD_REG);
-    break;
-    
-  case 0x04:			/* Reserved */
-  case 0x05:			/* Reserved */
-    printk("NCR53c406a: WARNING: Reserved phase!!!\n");
-    break;
-    
-  case 0x06:			/* MESSAGE-OUT */
-    DEB(printk("NCR53c406a: Message-Out phase\n"));
-    current_SC->SCp.phase = message_out;
-    outb(SET_ATN, CMD_REG);	/* Reject the message */
-    outb(MSG_ACCEPT, CMD_REG);
-    break;
-    
-  case 0x07:			/* MESSAGE-IN */
-    rtrc(4);
-    VDEB(printk("NCR53c406a: Message-In phase\n"));
-    current_SC->SCp.phase = message_in;
-    
-    current_SC->SCp.Status = inb(SCSI_FIFO);    
-    current_SC->SCp.Message = inb(SCSI_FIFO);
-    
-    VDEB(printk("SCSI FIFO size=%d\n", inb(FIFO_FLAGS) & 0x1f));
-    DEB(printk("Status = %02x  Message = %02x\n", 
-	       current_SC->SCp.Status, current_SC->SCp.Message));
-    
-    if(current_SC->SCp.Message == SAVE_POINTERS || 
-       current_SC->SCp.Message == DISCONNECT) {
-      outb(SET_ATN, CMD_REG);	/* Reject message */
-      DEB(printk("Discarding SAVE_POINTERS message\n"));
-    }
-    outb(MSG_ACCEPT, CMD_REG);
-    break;
-  }
 }
 
 #ifndef IRQ_LEV
 static int irq_probe()
 {
-  int irqs, irq;
-  int i;
-
-  inb(INT_REG);			/* clear the interrupt register */
-  sti();
-  irqs = probe_irq_on();
-
-  /* Invalid command will cause an interrupt */
-  REG0;
-  outb(0xff, CMD_REG);
-
-  /* Wait for the interrupt to occur */
-  i = jiffies + WATCHDOG;
-  while(i > jiffies && !(inb(STAT_REG) & 0x80))
-    barrier();
-  if (i <= jiffies) {		/* Timed out, must be hardware trouble */
-    probe_irq_off(irqs);
-    return -1;
-  }
-
-  irq = probe_irq_off(irqs);
-
-  /* Kick the chip */
-  outb(CHIP_RESET, CMD_REG);
-  outb(SCSI_NOP, CMD_REG);
-  chip_init();
-
-  return irq;
+    int irqs, irq;
+    int i;
+    
+    inb(INT_REG);               /* clear the interrupt register */
+    sti();
+    irqs = probe_irq_on();
+    
+    /* Invalid command will cause an interrupt */
+    REG0;
+    outb(0xff, CMD_REG);
+    
+    /* Wait for the interrupt to occur */
+    i = jiffies + WATCHDOG;
+    while(i > jiffies && !(inb(STAT_REG) & 0x80))
+        barrier();
+    if (i <= jiffies) {		/* Timed out, must be hardware trouble */
+        probe_irq_off(irqs);
+        return -1;
+    }
+    
+    irq = probe_irq_off(irqs);
+    
+    /* Kick the chip */
+    outb(CHIP_RESET, CMD_REG);
+    outb(SCSI_NOP, CMD_REG);
+    chip_init();
+    
+    return irq;
 }
 #endif IRQ_LEV
 
 static void chip_init()
 {
-  REG1;
+    REG1;
 #if USE_DMA
-  outb(0x00, PIO_STATUS);
+    outb(0x00, PIO_STATUS);
 #else  /* USE_PIO */
-  outb(0x01, PIO_STATUS);
+    outb(0x01, PIO_STATUS);
 #endif
-  outb(0x00, PIO_FLAG);
-  
-  outb(C4_IMG, CONFIG4);	/* REG0; */
-  outb(C3_IMG, CONFIG3);
-  outb(C2_IMG, CONFIG2);
-  outb(C1_IMG, CONFIG1);
-  
-  outb(0x05, CLKCONV);		/* clock conversion factor */
-  outb(0x9C, SRTIMOUT);		/* Selection timeout */
-  outb(0x05, SYNCPRD);		/* Synchronous transfer period */
-  outb(SYNC_MODE, SYNCOFF);		/* synchronous mode */  
+    outb(0x00, PIO_FLAG);
+    
+    outb(C4_IMG, CONFIG4);	/* REG0; */
+    outb(C3_IMG, CONFIG3);
+    outb(C2_IMG, CONFIG2);
+    outb(C1_IMG, CONFIG1);
+    
+    outb(0x05, CLKCONV);        /* clock conversion factor */
+    outb(0x9C, SRTIMOUT);       /* Selection timeout */
+    outb(0x05, SYNCPRD);        /* Synchronous transfer period */
+    outb(SYNC_MODE, SYNCOFF);   /* synchronous mode */  
 }
 
 void calc_port_addr()
 {
-/* Control Register Set 0 */
-TC_LSB		= (port_base+0x00);
-TC_MSB		= (port_base+0x01);
-SCSI_FIFO	= (port_base+0x02);
-CMD_REG		= (port_base+0x03);
-STAT_REG	= (port_base+0x04);
-DEST_ID		= (port_base+0x04);
-INT_REG		= (port_base+0x05);
-SRTIMOUT	= (port_base+0x05);
-SEQ_REG		= (port_base+0x06);
-SYNCPRD		= (port_base+0x06);
-FIFO_FLAGS	= (port_base+0x07);
-SYNCOFF		= (port_base+0x07);
-CONFIG1		= (port_base+0x08);
-CLKCONV		= (port_base+0x09);
-/* TESTREG		= (port_base+0x0A); */
-CONFIG2		= (port_base+0x0B);
-CONFIG3		= (port_base+0x0C);
-CONFIG4		= (port_base+0x0D);
-TC_HIGH		= (port_base+0x0E);
-/* FIFO_BOTTOM	= (port_base+0x0F); */
-
-/* Control Register Set 1 */
-/* JUMPER_SENSE	= (port_base+0x00);*/
-/* SRAM_PTR	= (port_base+0x01);*/
-/* SRAM_DATA	= (port_base+0x02);*/
-PIO_FIFO	= (port_base+0x04);
-/* PIO_FIFO1	= (port_base+0x05);*/
-/* PIO_FIFO2	= (port_base+0x06);*/
-/* PIO_FIFO3	= (port_base+0x07);*/
-PIO_STATUS	= (port_base+0x08);
-/* ATA_CMD		= (port_base+0x09);*/
-/* ATA_ERR		= (port_base+0x0A);*/
-PIO_FLAG	= (port_base+0x0B);
-CONFIG5		= (port_base+0x0D);
-/* SIGNATURE	= (port_base+0x0E);*/
-/* CONFIG6		= (port_base+0x0F);*/
+    /* Control Register Set 0 */
+    TC_LSB		= (port_base+0x00);
+    TC_MSB		= (port_base+0x01);
+    SCSI_FIFO		= (port_base+0x02);
+    CMD_REG		= (port_base+0x03);
+    STAT_REG		= (port_base+0x04);
+    DEST_ID		= (port_base+0x04);
+    INT_REG		= (port_base+0x05);
+    SRTIMOUT		= (port_base+0x05);
+    SEQ_REG		= (port_base+0x06);
+    SYNCPRD		= (port_base+0x06);
+    FIFO_FLAGS		= (port_base+0x07);
+    SYNCOFF		= (port_base+0x07);
+    CONFIG1		= (port_base+0x08);
+    CLKCONV		= (port_base+0x09);
+    /* TESTREG		= (port_base+0x0A); */
+    CONFIG2		= (port_base+0x0B);
+    CONFIG3		= (port_base+0x0C);
+    CONFIG4		= (port_base+0x0D);
+    TC_HIGH		= (port_base+0x0E);
+    /* FIFO_BOTTOM	= (port_base+0x0F); */
+    
+    /* Control Register Set 1 */
+    /* JUMPER_SENSE	= (port_base+0x00);*/
+    /* SRAM_PTR		= (port_base+0x01);*/
+    /* SRAM_DATA	= (port_base+0x02);*/
+    PIO_FIFO		= (port_base+0x04);
+    /* PIO_FIFO1	= (port_base+0x05);*/
+    /* PIO_FIFO2	= (port_base+0x06);*/
+    /* PIO_FIFO3	= (port_base+0x07);*/
+    PIO_STATUS		= (port_base+0x08);
+    /* ATA_CMD		= (port_base+0x09);*/
+    /* ATA_ERR		= (port_base+0x0A);*/
+    PIO_FLAG		= (port_base+0x0B);
+    CONFIG5		= (port_base+0x0D);
+    /* SIGNATURE	= (port_base+0x0E);*/
+    /* CONFIG6		= (port_base+0x0F);*/
 }
 
 #ifdef MODULE
@@ -1060,3 +1058,22 @@
 
 #include "scsi_module.c"
 #endif
+
+/*
+ * Overrides for Emacs so that we get a uniform tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v1.3.62/linux/drivers/scsi/NCR53c406a.h linux/drivers/scsi/NCR53c406a.h
--- v1.3.62/linux/drivers/scsi/NCR53c406a.h	Wed Sep 27 15:59:58 1995
+++ linux/drivers/scsi/NCR53c406a.h	Wed Feb 14 09:26:25 1996
@@ -28,7 +28,7 @@
 #define NCR53c406a { \
      NULL			/* next */, \
      NULL			/* usage count */, \
-     NULL			/* proc_dir */, \
+     &proc_scsi_NCR53c406a      /* proc_dir */, \
      NULL			/* proc_info */, \
      "NCR53c406a"		/* name */, \
      NCR53c406a_detect		/* detect */, \
@@ -49,6 +49,8 @@
      ENABLE_CLUSTERING \
 }
 
+extern struct proc_dir_entry proc_scsi_NCR53c406a;
+
 int NCR53c406a_detect(Scsi_Host_Template *);
 const char* NCR53c406a_info(struct Scsi_Host *);
 
@@ -59,4 +61,23 @@
 int NCR53c406a_biosparm(Disk *, kdev_t, int []);
 
 #endif /* _NCR53C406A_H */
+
+/*
+ * Overrides for Emacs so that we get a uniform tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/.objects linux/drivers/sound/.objects
--- v1.3.62/linux/drivers/sound/.objects	Tue Jan 23 21:15:44 1996
+++ linux/drivers/sound/.objects	Sat Feb 10 22:08:54 1996
@@ -76,10 +76,6 @@
 	OBJS := $(OBJS)  sequencer.o
 endif
 
-ifdef CONFIG_PNP
-	OBJS := $(OBJS)  sound_pnp.o
-endif
-
 ifdef CONFIG_SEQUENCER
 	OBJS := $(OBJS)  sound_timer.o
 endif
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/.version linux/drivers/sound/.version
--- v1.3.62/linux/drivers/sound/.version	Tue Jan 23 21:15:44 1996
+++ linux/drivers/sound/.version	Sat Feb 10 22:04:30 1996
@@ -1,2 +1,2 @@
-3.5-alpha8
+3.5-beta2
 0x030505
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/CHANGELOG linux/drivers/sound/CHANGELOG
--- v1.3.62/linux/drivers/sound/CHANGELOG	Tue Jan 23 21:15:44 1996
+++ linux/drivers/sound/CHANGELOG	Sat Feb 10 22:04:30 1996
@@ -1,5 +1,24 @@
-Changelog for version 3.5-alpha8
---------------------------------
+Changelog for version 3.5-beta2
+-------------------------------
+
+Since 3.5-beta1
+- Bugfixes.
+- Full duplex audio with MAD16+CS4231 may work now. The driver configures
+  SB DMA of MAD16 so that it doesn't conflict with codec's DMA channels.
+  The side effect is that all 8 bit DMA channels (0,1,3) are populated in duplex
+  mode.
+
+Since 3.5-alpha9
+- Bugfixes (mostly in Jazz16 and ESS1688/688 supports).
+- Temporarily disabled recording with ESS1688/688 since it causes crash.
+- Changed audio buffer partitioning algorithm so that it selects
+  smaller fragment size than earlier. This improves real time capabilities
+  of the driver and makes recording to disk to work better. Unfortunately
+  this change breaks some programs which assume that fragments cannot be
+  shorter than 4096 bytes.
+
+Since 3.5-alpha8
+- Bugfixes
 
 Since 3.5-alpha7
 - Linux kernel compatible configuration (_EXPERIMENTAL_). Enable
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/COPYING linux/drivers/sound/COPYING
--- v1.3.62/linux/drivers/sound/COPYING	Mon Jul 18 09:50:55 1994
+++ linux/drivers/sound/COPYING	Sat Feb 10 22:04:27 1996
@@ -1,25 +1,25 @@
 /*
- * Copyright by Hannu Savolainen 1993
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v1.3.62/linux/drivers/sound/Config.in	Tue Jan 23 21:15:44 1996
+++ linux/drivers/sound/Config.in	Sat Feb 10 22:04:30 1996
@@ -3,7 +3,7 @@
 #
 #--------
 # There is another confic script which is compatible with rest of
-# the kernel. It can be activated by running 'make script' in this
+# 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).
 #--------
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v1.3.62/linux/drivers/sound/Makefile	Tue Jan 23 21:15:44 1996
+++ linux/drivers/sound/Makefile	Sun Feb 11 19:10:28 1996
@@ -22,14 +22,12 @@
 	 gus_midi.o gus_vol.o patmgr.o sb_mixer.o sb16_dsp.o sb_midi.o \
 	 sb16_midi.o midi_synth.o uart6850.o sound_timer.o \
 	 sys_timer.o ics2101.o ad1848.o pss.o sscape.o trix.o aedsp16.o \
-	 mad16.o mad16_sb_midi.o cs4232.o maui.o sound_pnp.o
+	 mad16.o mad16_sb_midi.o cs4232.o maui.o
 endif
 
 
 build:
-	@echo Compiling modularized sound driver
 	@make sound.o
-	@echo Sound module compiled.
 
 install:	sound.o
 	cp sound.o $(MODULEDIR)
@@ -53,7 +51,7 @@
 #
 CC	= gcc
 HOSTCC	= gcc
-CFLAGS	= -D__KERNEL__ -DMODULE -DMODVERSIONS -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -m486
+CFLAGS	= -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -m486
 else
 include $(TOPDIR)/Rules.make
 endif
@@ -112,7 +110,7 @@
 #	@echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null
 	@echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h
 
-script: setup-$(TARGET_OS)
+mkscript: setup-$(TARGET_OS)
 	rm -f configure
 	$(HOSTCC) -o configure configure.c
 	./configure script > Config.in
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/Readme linux/drivers/sound/Readme
--- v1.3.62/linux/drivers/sound/Readme	Tue Jan 23 21:15:44 1996
+++ linux/drivers/sound/Readme	Sat Feb 10 22:04:28 1996
@@ -1,22 +1,27 @@
 
-VoxWare v3.5-alpha4 release notes
----------------------------------
+Version 3.5-beta2 release notes
+-------------------------------
 
 IMPORTANT! This version of the driver is compatible only with Linux versions
-	   1.3.58 and later. It may work with earlier ones as a loadable
+	   1.3.59 to 1.3.6x. It may work with few earlier ones as a loadable
 	   module but...
 
-	   Also this is an ALPHA test version which has not been tested
-	   with all cards. At least AEDSP16 support will not work. PAS16
-	   and PSS supports have not been tested. /dev/dsp and /dev/audio
- 	   playback with standard GUS sounds scrambled. 16 bit mode of
-	   SB16 doesn't work.
+	   This is a BETA test version. Most known bugs should have been fixed.
+	   However it's possible that there are still bugs. Please report them
+	   to me ASAP so that they can be fixed before Linux 1.4. But look
+	   at the web page (see below) before sending me a bug report. 
+
+	   Crashing with GUS should be fixed now.
+	   Recording is still disabled with ESS1688/688 cards since it
+	   causes a crash.
 
 Please read the SOUND-HOWTO (available from sunsite.unc.edu and other Linux ftp 
-sites). It contains much more information than this file.
+sites). It gives instructions about using sound with Linux. It's bit out of
+date but still very useful. Information about bug fixes and such things
+is available from the web page (see below).
 
 *****************************************************************
-* NEW! VoxWare home page is http://personal.eunet.fi/pp/voxware *
+* NEW! Driver's home page is http://personal.eunet.fi/pp/voxware*
 * The file Readme.cards contains card specific instructions     *
 * about configuring various cards.				*
 *****************************************************************
@@ -30,7 +35,7 @@
 
 I have got many patches from various persons during last year. Some of
 them are still on my mailbox and they should be included in versions
-after v3.0 (I will not add aditional features before v3.0 is ready).
+after v3.5 (I will not add aditional features before v3.5 is ready).
 
    ====================================================
 -  THIS VERSION ____REQUIRES____ Linux 1.3.58 OR LATER.
@@ -55,6 +60,8 @@
 Gravis Ultrasound (GUS)
 GUS MAX
 GUS with the 16 bit sampling daughtercard
+GUS ACE
+GUS PnP support should be available around May 1996.
 PAS16
 Windows Sound System compatible soundcards
 ECHO-PSS (cards based on the PSS architecture by Analog Devices.
@@ -63,7 +70,8 @@
 MediaTriX AudioTriX Pro (OPL4 and the optional effect daughtercard
 	require special initialization. There is a program (setfx) in
 	the snd-util-3.0.tar.gz package which does it).
-Ensoniq SoundScape (works but needs some improvements)
+Ensoniq SoundScape & SoundScape Elite
+Ensonig SoundScape PnP not supported yet (summer 1996?)
 MV Jazz16 based soundcards (ProSonic, 3D etc).
 SoundMan Wave
 Mozart (OAK OTI-601 interface chip) based soundcards.
@@ -72,19 +80,17 @@
 idea to configure MAD16 cards as Mozart ones. The MAD16 driver doesn't set
 up MPU401 which the Mozart one does.
 CS4232 based cards such as AcerMagic S23.
+ESS ES1688 based soundcards.
 
 
 In addition all Sound Blaster models and clones (up to AWE32) work if
-you want to use them.
+you want to use them. SB16/SB32/AWE32 PnP models don't work yet. See the web
+page for more info.
 
-The Emu synthesizer chip of AWE32 is not and will not be supported. The same is
+The Emu synthesizer chip of AWE32 will not be supported soon. The same is
 true with the ASP chip also. Creative Technology will not release detailed
 information about them so it's not possible to support them.
 
-If you want to get support for AWE32 or ASP, please contact Creative Labs.
-Ask _politely_ if they are going to support Linux. Maybe they change
-their policy if there is enough demand.
-
 ===========================================================================
 If your card is compatible with SB, MPU401 or Windows Sound System, it
 may work with the driver even if it's not listed in the above list. In this
@@ -109,7 +115,6 @@
 	Craig Metz	1/2 of the PAS16 Mixer and PCM support
 	Rob Hooft	Volume computation algorithm for the FM synth.
 	Mika Liljeberg	uLaw encoding and decoding routines
-	Andy Fingerhut	New ulaw conversion tables (ulaw.h)
 	Jeff Tranter	Linux SOUND HOWTO document
 	Greg Lee	Volume computation algorithm for the GUS and
 			lot's of valuable suggestions.
@@ -223,7 +228,7 @@
 ----------------------------------
 
 There appears to be some kind of conflict between the sound support
-(MV Jazz), mouse port and VoxWare. You could try to configure kernel
+(MV Jazz), mouse port and the sound driver. You could try to configure kernel
 with the C&T 82C710 mouse port support disabled.
 
 Hannu
@@ -232,7 +237,6 @@
 
 Hannu Savolainen
 hannu@voxware.pp.fi
-(or Hannu.Savolainen@cctap.carel.fi in case the above bounces)
 
 Snail mail:	Hannu Savolainen
 		Hiekkalaiturintie 3 A 8
@@ -245,4 +249,4 @@
 	get response, please check how your address is written in the message
 	header. I can't answer if I don't have a valid reply address.
 
-VoxWare home page is http://personal.eunet.fi/pp/voxware
+Sound driver's home page is http://personal.eunet.fi/pp/voxware
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/Readme.cards linux/drivers/sound/Readme.cards
--- v1.3.62/linux/drivers/sound/Readme.cards	Tue Jan 23 21:15:44 1996
+++ linux/drivers/sound/Readme.cards	Sat Feb 10 22:11:41 1996
@@ -1,4 +1,4 @@
-Configuring VoxWare 3.0 (for Linux) with some most common soundcards
+Configuring version 3.5 (for Linux) with some most common soundcards
 ====================================================================
 
 NOTE! This document may contain some error. Please inform me
@@ -7,10 +7,10 @@
 Read this before trying to configure the driver
 -----------------------------------------------
 
-There are currently many cards that work with VoxWare. Some of the cards
+There are currently many cards that work with this driver. Some of the cards
 have native support while the others work since they emulate some other
 cards (usually SB, MSS/WSS and/or MPU401). The following cards have native
-support in VoxWare. Detailed instructions for configuring these cards
+support in the driver. Detailed instructions for configuring these cards
 will be given later in this document.
 
 Pro Audio Spectrum 16 (PAS16) and compatibles:
@@ -18,7 +18,7 @@
 	Pro Audio Studio 16
 	Logitech Sound Man 16
 	NOTE! The original Pro Audio Spectrum as well as the PAS+ are not
-	      and will not be supported by VoxWare.
+	      and will not be supported by the driver.
 
 Media Vision Jazz16 based cards
 	Pro Sonic 16
@@ -33,7 +33,7 @@
 	NOTE!	The ASP chip and the EMU synth of the AWE32 is not supported 
 		since their manufacturer doesn't release information about
 		the card. However both the AB16ASP and the AWE32 work with
-		VoxWare just like a SB16. Also see the comment about some
+		the driver just like a SB16. Also see the comment about some
 		unsupported cards at the end of this file.
 	SB16 compatible cards by other manufacturers than Creative.
 		You have been fooled since there are no SB16 compatible
@@ -47,6 +47,7 @@
 	GUS + the 16 bit option
 	GUS MAX
 	GUS ACE (No MIDI port and audio recording)
+	GUS PnP (Partially supported)
 
 MPU-401	and compatibles
 	The driver works both with the full (intelligent mode) MPU-401
@@ -54,7 +55,7 @@
 	dumb MIDI ports. MPU-401 is currently the most common MIDI
 	interface. Most soundcards are compatible with it. However
 	don't enable MPU401 mode blindly. Many cards having native support
-	in VoxWare have their own MPU401 driver. Enabling the standard one
+	in the driver have their own MPU401 driver. Enabling the standard one
 	will cause a conflict with these cards. So look if your card is
 	in the list of supported cards before enabling MPU401.
 
@@ -69,16 +70,16 @@
 
 	Having a AD1848, CS4248 or CS4231 codec chip on the card is a good
 	sign. Even if the card is not MSS compatible, it could be easy to write
-	support for it to VoxWare. Note also that most MSS compatible cards
+	support for it. Note also that most MSS compatible cards
 	require special boot time initialization which may not be present
-	in VoxWare. Also some MSS compatible cards have native support in
-	VoxWare. Enabling the MSS support with these cards is likely to
+	in in the driver. Also some MSS compatible cards have native support.
+	Enabling the MSS support with these cards is likely to
 	cause a conflict. So check if your card is listed in this file before
 	enabling the MSS support.
 
 6850 UART MIDI
 	This UART chip is used in the MIDI interface of some (rare)
-	soundcards. It's supported by VoxWare in case you need it.
+	soundcards. It's supported by the driver in case you need it.
 
 Yamaha FM synthesizers (OPL2, OPL3 and OPL4)
 	Most soundcards have a FM synthesizer chip. The OPL2 is a 2
@@ -86,10 +87,10 @@
 	only in the cheapest (8 bit mono) cards. The OPL3 is a 4 operator 
 	FM chip which provides better sound quality and/or more available 
 	voices than the OPL2. The OPL4 is a new chip which has a OPL3 and
-	a wave table synthesizer packed on the same chip. VoxWare supports
+	a wave table synthesizer packed on the same chip. The driver supports
 	just the OPL3 mode directly. Most cards having a OPL4 (like
 	SM Wave and AudioTriX Pro) support the OPL4 mode using MPU401
-	emulation. Writing a native OPL4 support to VoxWare is difficult
+	emulation. Writing a native OPL4 support is difficult
 	since Yamaha doesn't give information about their sample ROM chip.
 
 	Enable the generic OPL2/OPL3 FM synthesizer support if your
@@ -104,7 +105,7 @@
 	There are several cards based on this architecture. The most known
 	ones are Orchid SW32 and Cardinal DSP16. 
 
-	VoxWare supports downloading DSP algorithms to these cards.
+	The driver supports downloading DSP algorithms to these cards.
 
 MediaTriX AudioTriX Pro
 	The ATP card is built around a CS4231 codec and a OPL4 synthesizer
@@ -129,14 +130,15 @@
 Audio Excell DSP16 
 	Support for this card is made by Riccardo Faccetti
 	(riccardo@cdc8g5.cdc.polimi.it). See aedsp16.c for more info.
+	(This driver is not functional in 3.5 versions of this driver).
 	
-Crystal CS4232 based cards such as AcerMagic S23
+Crystal CS4232 based cards such as AcerMagic S23 and many PC motherboards.
 	CS4232 is a PnP multimedia chip which contains a CS3231A codec,
 	SB and MPU401 emulations. There is support for OPL3 too.
 	(Unfortunately the MPU401 mode doesn't work).
 
 Turtle Beach Maui and Tropez
-	VoxWare supports sample, parch and program loading commands
+	This driver version supports sample, patch and program loading commands
 	described in the Maui/Tropez User's manual. There is no initialization
 	code for Maui so it must be initialized using DOS. Audio side of Tropez
 	is based on the MAD16 chip (see above).
@@ -145,7 +147,7 @@
 ----------------------------------
 
 Some of the earliest soundcards were jumper configurable. You have to
-configure VoxWare to configure VoxWare use I/O, IRQ and DMA settings
+configure the driver use I/O, IRQ and DMA settings
 that match the jumpers. Just few 8 bit cards are fully jumper 
 configurable (SB 1.x/2.x, SB Pro and clones).
 Some cards made by Aztech have an EEPROM which contains the 
@@ -157,14 +159,14 @@
 Latest cards are fully software configurable or they are PnP ISA
 compatible. There are no jumpers on the board.
 
-VoxWare handles software configurable cards automaticly. Just configure
+The driver handles software configurable cards automaticly. Just configure
 the driver to use I/O, IRQ and DMA settings which are known to work.
 You could usually use the same values than with DOS and/or Windows.
 Using different settings is possible but not recommended since it may cause
 some trouble (for example when warm booting from an OS to another or
 when installing new hardware to the machine).
 
-VoxWare sets the soft configurable parameters of the card automaticly
+Sound driver sets the soft configurable parameters of the card automaticly
 during boot. Usually you don't need to run any extra initialization
 programs when booting Linux but there are some exceptions. See the
 card specific instructions (below) for more info.
@@ -179,7 +181,7 @@
 
 The first thing to do is to look at the major IC chips on the card.
 Many of the latest soundcards are based on some standard chips. If you
-are lucky, all of them could be supported by VoxWare. The most common ones
+are lucky, all of them could be supported by the driver. The most common ones
 are the OPTi MAD16, Mozart, SoundScape (Ensoniq) and the PSS architectures
 listed above. Also look at the end of this file for list of unsupported
 cards and the ones which could be supported later.
@@ -194,20 +196,17 @@
 card to work by booting DOS before starting Linux (boot DOS, hit ctrl-alt-del
 and boot Linux without hard resetting the machine). In this method the
 DOS based driver initializes the hardware to use a known I/O, IRQ and DMA
-settings. If VoxWare is configured to use the same settings, everything should 
+settings. If sound driver is configured to use the same settings, everything should 
 work OK.
 
 
-Configuring VoxWare (with Linux)
-================================
+Configuring sound driver (with Linux)
+=====================================
 
-VoxWare sound driver is currently a part of Linux kernel distribution. The 
+Sound driver is currently a part of Linux kernel distribution. The 
 driver files are located in directory /usr/src/linux/drivers/sound. 
 
 ****************************************************************************
-*	VoxWare MUST BE CONFIGURED AND COMPILED WITH THE KERNEL. TRYING    *
-*	TO COMPILE IT ALONE WILL _NOT_ WORK.				   *
-*									   *
 *	ALWAYS USE THE SOUND DRIVER VERSION WHICH IS DISTRIBUTED WITH	   *
 *	THE KERNEL SOURCE PACKAGE YOU ARE USING. SOME ALPHA AND BETA TEST  *
 *	VERSIONS CAN BE INSTALLED FROM A SEPARATELY DISTRIBUTED PACKAGE	   *
@@ -322,7 +321,7 @@
 	  safe to answer 'y' in case you have the original Windows Sound 
 	  System card made by Microsoft or Aztech SG 16 Pro (or NX16 Pro).
 	  Also you may answer 'y' in case your card was not listed earlier
-	  in this file. For cards having native support in VoxWare, consult
+	  in this file. For cards having native support in the driver, consult
 	  the card specific instructions later in this file. Some drivers
 	  have their own MSS support and enabling this option wil cause a
 	  conflict.
@@ -338,7 +337,7 @@
 	  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),
-	  Reveal (some models) and Diamond (latest ones).
+	  Reveal (some models) and Diamond (some recent models).
   "Support for TB Maui"
 	- This is just an experimental extension to the MPU401 driver.
 	  Don't enable this option unless you are writing a .MOD
@@ -382,7 +381,7 @@
 
 This section gives additional instructions about configuring some cards.
 Please refer manual of your card for valid I/O, IRQ and DMA numbers. Using
-the same settings with DOS/Windows and VoxWare is recommended. Using
+the same settings with DOS/Windows and Linux is recommended. Using
 different values could cause some problems when switching between
 different operating systems.
 
@@ -497,6 +496,11 @@
 channel if it's a 16 bit one.
 
 
+GUS ACE works too but any attempt to record or to use the MIDI port
+will fail.
+
+GUS PnP (with RAM) is supported but it needs to be initialized using
+DOS before booting Linux. This may fail on machines having PnP BIOS.
 
 MPU401 and Windows Sound System
 -------------------------------
@@ -509,7 +513,7 @@
 most MSS compatible cards have it. However check that this is true
 before enabling OPL3.
 
-VoxWare supports more than one MPU401 compatible cards at the same time
+Sound driver supports more than one MPU401 compatible cards at the same time
 but the config program asks config info for just the first of them.
 Adding the second or third MPU interfaces must be done manually by
 editing sound/local.h (after running the config program). Add defines for
@@ -542,7 +546,7 @@
 partition containing the file with Linux. 
 
 It's possible to load your own DSP algorithms and run them with the card.
-Look at the directory sound/pss_test for more info (in the VoxWare-3.0.tar.gz)
+Look at the directory pss_test of snd-util-3.0.tar.gz for more info.§
 package.
 
 AudioTriX Pro
@@ -586,9 +590,9 @@
 becomes supported later. Currently the card's firmware doesn't contain
 support for it.
 
-With 3.0 of VoxWare you have to change your system to use /dev/dsp1 by default
-so execute: cd /dev;rm dsp;ln -s dsp1 dsp after you have installed VoxWare
-3.0 (first time).
+With 3.0 of the driver you have to change your system to use /dev/dsp1 by default
+so execute: cd /dev;rm dsp;ln -s dsp1 dsp after you have installed driver
+version 3.0 (or later) first time.
 
 The configuration program asks two DMA channels and two interrupts. One IRQ
 and one DMA is used by the MSS codec. The second IRQ is required for the
@@ -653,16 +657,21 @@
 to initialize it by using the MS-DOS SNDSETUP program.
 
 There are some other OPTi chips which may be used in soundcards such as
-82C930 and MAC32. These chips are not supported by VoxWare yet. Please
+82C930 and MAC32. These chips are not supported by the driver yet. Please
 contact me if you have a soundcard which uses these chips.
 
 Some MAD16 based cards may cause feedback, whistle or terrible noise if the
-line3 mixer channel is turned too high.
+line3 mixer channel is turned too high. This happens at least with Shuttle
+Sound System.
 
 If you have a MAD16 card which have an OPL4 (FM + Wave table) synthesizer
 chip (_not_ an OPL3), you have to apped line containing #define MAD16_OPL4
 to the file linux/dirvers/sound/local.h (after running make config).
 
+MAD16 cards having a CS4231 codec support full duplex mode. This mode
+can be enabled by configuring the card to use two DMA channels. Possible
+DMA channel pairs are: 0&1, 1&0 and 3&0.
+
 MV Jazz (ProSonic)
 ------------------
 
@@ -714,7 +723,7 @@
 an EEPROM chip for storing the configuration data. There is a microcontroller
 which initializes the card to match the EEPROM settigs when the machine
 is powered on. These cards actually behave just like they have jumpers
-for all of the settings. Configure VoxWare for MSS, MPU, SB/SB Pro  and OPL3 
+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
@@ -742,7 +751,7 @@
 
 The oldest (Sierra Aria based) soundcards made by Diamond are not supported
 (they may work if the card is initialized using DOS). The recent (LX?)
-models are based on the MAD16 chip which is supported by VoxWare.
+models are based on the MAD16 chip which is supported by the driver.
 
 Audio Excel DSP16
 -----------------
@@ -810,7 +819,7 @@
 products to public or at least their require signing a NDA.
 
 I have also made decicion to not accept code based on reverse engineering
-to VoxWare. There are three main reasons: First I don't want to break
+to the driver. There are three main reasons: First I don't want to break
 relationships to sound card manufacturers. The second reason is that
 maintaining and supporting a driver withoun any specs will be a pain. The
 third reason is that why shoud we help such companies in selling their
@@ -831,12 +840,12 @@
 you want to use Linux/Unix with their cards, please don't try to push
 me. It's a better idea to contact the manufacturer and explain that
 you want to use your card with Linux/Unix. You could also try to sell
-your card to somebody else and then buy a card that is supported by VoxWare.
+your card to somebody else and then buy a card that is supported by the driver.
 
 However it's possible that things change and a driver gets written
 for some of the banned cards. Please, don't send me messages asking if
 there is any plans to write a driver for the cards mentioned above. I 
-will put any news to the VoxWare www home page (see below).
+will put any news to sound driver's www home page (see below).
 
 There are some common audio chipsets that are not supported yet. For example
 Sierra Aria and IBM Mwave. It's possible that these architectures
@@ -850,5 +859,5 @@
 
 Hannu Savolainen
 hannu@voxware.pp.fi
-VoxWare www home page: http://personal.eunet.fi/pp/voxware
+Sound driver's www home page: http://personal.eunet.fi/pp/voxware
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/Readme.linux linux/drivers/sound/Readme.linux
--- v1.3.62/linux/drivers/sound/Readme.linux	Fri Oct 13 14:44:33 1995
+++ linux/drivers/sound/Readme.linux	Sat Feb 10 22:04:28 1996
@@ -215,8 +215,14 @@
 if [ -e /dev/mixer ]; then 
 	rm -f /dev/mixer 
 fi
+
+if [ -e /dev/mixer0 ]; then 
+	rm -f /dev/mixer0 
+fi
  
-mknod -m 666 /dev/mixer c 14 0
+mknod -m 666 /dev/mixer0 c 14 0
+ln -sf /dev/mixer0 /dev/mixer
+
 if [ -e /dev/mixer1 ]; then 
 	rm -f /dev/mixer1 
 fi
@@ -260,6 +266,7 @@
 		rm -f /dev/midi00
 	fi
 	mknod -m 666 /dev/midi00 c 14 2
+	ln -sf /dev/midi00 /dev/midi
 	
 	if [ -e /dev/midi01 ]; then
 		rm -f /dev/midi01
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/Readme.modules linux/drivers/sound/Readme.modules
--- v1.3.62/linux/drivers/sound/Readme.modules	Tue Jan 23 21:15:44 1996
+++ linux/drivers/sound/Readme.modules	Sat Feb 10 22:04:29 1996
@@ -1,7 +1,7 @@
 Building a loadable sound driver
 ================================
 
-Loadable module support in version 3.5 of VoxWare is mostly rewritten since
+Loadable module support in version 3.5 of the driver is mostly rewritten since
 the previous version (3.0.1). This means that some things have changed.
 
 To compile the sound driver as a loadable module you have to perform
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/Readme.v30 linux/drivers/sound/Readme.v30
--- v1.3.62/linux/drivers/sound/Readme.v30	Tue Jul 11 10:02:51 1995
+++ linux/drivers/sound/Readme.v30	Sat Feb 10 22:04:30 1996
@@ -1,5 +1,5 @@
-VoxWare v3.0
-------------
+Sound driver version v3.0 (and later)
+-------------------------------------
 
 All features of v2.90-2 should work as earlier. There could be some
 omissions but they are unintentional. I started this version thread
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
--- v1.3.62/linux/drivers/sound/ad1848.c	Tue Jan 23 21:15:45 1996
+++ linux/drivers/sound/ad1848.c	Sat Feb 10 22:04:34 1996
@@ -12,8 +12,10 @@
  *
  * CS4232 is a PnP audio chip which contains a CS4231A (and SB, MPU).
  * CS4232A is an improved version of CS4232.
- *
- * Copyright by Hannu Savolainen 1994, 1995
+ */
+
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -34,11 +36,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- * Modified:
- *  Riccardo Facchetti  24 Mar 1995
- *  - Added the Audio Excel DSP 16 initialization routine.
  */
+#include <linux/config.h>
+
 
 #define DEB(x)
 #define DEB1(x)
@@ -83,7 +83,7 @@
     volatile unsigned long timer_ticks;
     int             timer_running;
     int             irq_ok;
-    sound_os_info  *osp;
+    int            *osp;
   }
 
 ad1848_info;
@@ -98,13 +98,14 @@
 static char     mixer2codec[MAX_MIXER_DEV] =
 {0};
 
-static int      ad_format_mask[5 /*devc->mode */ ] =
+static int      ad_format_mask[6 /*devc->mode */ ] =
 {
   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	/* AD1845 */
+  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
 };
 
 static ad1848_info dev_info[MAX_AUDIO_DEV];
@@ -116,7 +117,7 @@
 
 static int      ad1848_open (int dev, int mode);
 static void     ad1848_close (int dev);
-static int      ad1848_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local);
+static int      ad1848_ioctl (int dev, unsigned int cmd, caddr_t arg, int local);
 static void     ad1848_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
 static void     ad1848_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
 static int      ad1848_prepare_for_IO (int dev, int bsize, int bcount);
@@ -461,7 +462,7 @@
 }
 
 static int
-ad1848_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
+ad1848_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 {
   ad1848_info    *devc;
 
@@ -781,7 +782,7 @@
 }
 
 static int
-ad1848_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
+ad1848_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
 
@@ -1126,7 +1127,7 @@
 }
 
 int
-ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
+ad1848_detect (int io_base, int *ad_flags, int *osp)
 {
 
   unsigned char   tmp;
@@ -1369,7 +1370,7 @@
 }
 
 void
-ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, sound_os_info * osp)
+ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, int *osp)
 {
   /*
      * NOTE! If irq < 0, there is another driver which has allocated the IRQ
@@ -1654,6 +1655,7 @@
 check_opl3 (int base, struct address_info *hw_config)
 {
 
+#ifdef CONFIG_YM3812
   if (check_region (base, 4))
     {
       printk ("\n\nopl3.c: I/O port %x already in use\n\n", base);
@@ -1665,6 +1667,7 @@
 
   opl3_init (0, base, hw_config->osp);
   request_region (base, 4, "OPL3/OPL2");
+#endif
 }
 
 int
@@ -1685,15 +1688,6 @@
       /* check_opl3(0x388, hw_config); */
       return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp);
     }
-
-#if defined(CONFIG_AEDSP16) && defined(AEDSP16_MSS)
-  /*
-     * Initialize Audio Excel DSP 16 to MSS: before any operation
-     * we must enable MSS I/O ports.
-   */
-
-  InitAEDSP16_MSS (hw_config);
-#endif
 
   /*
      * Check if the IO port returns valid signature. The original MS Sound
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/ad1848_mixer.h linux/drivers/sound/ad1848_mixer.h
--- v1.3.62/linux/drivers/sound/ad1848_mixer.h	Tue Jan 23 21:15:45 1996
+++ linux/drivers/sound/ad1848_mixer.h	Sat Feb 10 22:04:22 1996
@@ -2,9 +2,11 @@
  * sound/ad1848_mixer.h
  * 
  * Definitions for the mixer of AD1848 and compatible codecs.
- * 
- * Copyright by Hannu Savolainen 1994
- * 
+ */
+
+/*
+ * Copyright by Hannu Savolainen 1993-1996
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
  * met: 1. Redistributions of source code must retain the above copyright
@@ -12,7 +14,7 @@
  * Redistributions in binary form must reproduce the above copyright notice,
  * this list of conditions and the following disclaimer in the documentation
  * and/or other materials provided with the distribution.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -25,6 +27,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
+
 /*
  * The AD1848 codec has generic input lines called Line, Aux1 and Aux2.
  * Soundcard manufacturers have connected actual inputs (CD, synth, line,
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/adlib_card.c linux/drivers/sound/adlib_card.c
--- v1.3.62/linux/drivers/sound/adlib_card.c	Tue Jan 23 21:15:45 1996
+++ linux/drivers/sound/adlib_card.c	Sat Feb 10 22:04:34 1996
@@ -2,8 +2,10 @@
  * sound/adlib_card.c
  *
  * Detection routine for the AdLib card.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +26,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/aedsp16.c linux/drivers/sound/aedsp16.c
--- v1.3.62/linux/drivers/sound/aedsp16.c	Tue Jan 23 21:15:45 1996
+++ linux/drivers/sound/aedsp16.c	Sun Feb 11 18:34:35 1996
@@ -29,6 +29,7 @@
  * Include the main voxware header file. It include all the os/voxware/etc
  * headers needed by this source.
  */
+#include <linux/config.h>
 #include "sound_config.h"
 
 #ifndef AEDSP16_BASE
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/audio.c linux/drivers/sound/audio.c
--- v1.3.62/linux/drivers/sound/audio.c	Tue Jan 23 21:15:45 1996
+++ linux/drivers/sound/audio.c	Sat Feb 10 22:04:36 1996
@@ -2,8 +2,10 @@
  * sound/audio.c
  *
  * Device file manager for /dev/audio
- *
- * Copyright by Hannu Savolainen 1993
+ */
+
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +26,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -64,7 +67,7 @@
 	else
 	  fmt = AFMT_U8;	/* This is always supported */
 
-      audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) fmt, 1);
+      audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) fmt, 1);
     }
 
   if (local_conversion[dev])	/* This shadows the HW format */
@@ -103,7 +106,7 @@
 
   local_conversion[dev] = 0;
 
-  if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) bits, 1) != bits)
+  if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) bits, 1) != bits)
     {
       audio_release (dev, file);
       return -ENXIO;
@@ -181,7 +184,7 @@
 #endif
 
 int
-audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
+audio_write (int dev, struct fileinfo *file, const char *buf, int count)
 {
   int             c, p, l, buf_no, buf_ptr, buf_size;
   int             err;
@@ -267,7 +270,7 @@
 }
 
 int
-audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+audio_read (int dev, struct fileinfo *file, char *buf, int count)
 {
   int             c, p, l;
   char           *dmabuf;
@@ -330,7 +333,7 @@
 
 int
 audio_ioctl (int dev, struct fileinfo *file,
-	     unsigned int cmd, ioctl_arg arg)
+	     unsigned int cmd, caddr_t arg)
 {
 
   dev = dev >> 4;
@@ -376,7 +379,7 @@
 	{
 	  audio_buf_info  info;
 
-	  int             err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
+	  int             err = DMAbuf_ioctl (dev, cmd, (caddr_t) & info, 1);
 
 	  if (err < 0)
 	    return err;
@@ -394,7 +397,7 @@
 	  char           *dma_buf;
 	  int             buf_no, buf_ptr, buf_size;
 
-	  int             err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
+	  int             err = DMAbuf_ioctl (dev, cmd, (caddr_t) & info, 1);
 
 	  if (err < 0)
 	    return err;
@@ -457,15 +460,19 @@
   switch (sel_type)
     {
     case SEL_IN:
-      if (!(audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
-	return 0;		/* Not recording */
+      if (audio_mode[dev] & AM_WRITE && !(audio_devs[dev]->flags & DMA_DUPLEX))
+	{
+	  return 0;		/* Not recording */
+	}
 
       return DMAbuf_select (dev, file, sel_type, wait);
       break;
 
     case SEL_OUT:
-      if (!(audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
-	return 0;		/* Wrong direction */
+      if (audio_mode[dev] & AM_READ && !(audio_devs[dev]->flags & DMA_DUPLEX))
+	{
+	  return 0;		/* Wrong direction */
+	}
 
       if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
 	{
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/configure.c linux/drivers/sound/configure.c
--- v1.3.62/linux/drivers/sound/configure.c	Fri Feb  9 17:53:04 1996
+++ linux/drivers/sound/configure.c	Sat Feb 10 22:10:35 1996
@@ -1,8 +1,13 @@
+/*
+ *	 PnP support is not included in this driver version.
+ *       AEDSP16 will not work without significant changes.
+ */
 #define DISABLED_OPTIONS 	(B(OPT_PNP)|B(OPT_AEDSP16))
 /*
  * sound/configure.c  - Configuration program for the Linux Sound Driver
- *
- * Copyright by Hannu Savolainen 1993-1995
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -23,9 +28,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
 
+
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -662,7 +667,7 @@
 
   if (selected_options & B (OPT_PAS))
     {
-      fprintf (stderr, "\nEnable Joystick port on ProAudioSpectrum (n/y) ? ");
+      fprintf (stderr, "\nEnable Joystick port on ProAudioSpectrum (y/N) ? ");
       if (think_positively (0))
 	printf ("#define PAS_JOYSTICK_ENABLE\n");
 
@@ -671,7 +676,7 @@
 	       "There is a command line switch (was it :T?)\n"
 	       "in the DOS driver for PAS16 which solves this.\n"
 	       "Don't enable this feature unless you have problems!\n"
-	       "Do you have to use this switch with DOS (y/n) ?");
+	       "Do you have to use this switch with DOS (Y/n) ?");
       if (think_positively (0))
 	printf ("#define BROKEN_BUS_CLOCK\n");
     }
@@ -1111,7 +1116,7 @@
 
   if (access (oldconf, R_OK) == 0)
     {
-      fprintf (stderr, "Old configuration exists in %s. Use it (y/n) ? ",
+      fprintf (stderr, "Old configuration exists in %s. Use it (Y/n) ? ",
 	       oldconf);
       if (think_positively (1))
 	if (use_old_config (oldconf))
@@ -1149,7 +1154,7 @@
 		int             def_answ = hw_table[i].default_answ;
 
 		fprintf (stderr,
-			 def_answ ? "  %s (y/n) ? " : "  %s (n/y) ? ",
+			 def_answ ? "  %s (Y/n) ? " : "  %s (y/N) ? ",
 			 questions[i]);
 		if (think_positively (def_answ))
 		  if (hw_table[i].alias)
@@ -1172,7 +1177,7 @@
       fprintf (stderr, "Do you want support for the MV Jazz16 (ProSonic etc.) ? ");
       if (think_positively (0))
 	{
-	  fprintf (stderr, "Do you have SoundMan Wave (n/y) ? ");
+	  fprintf (stderr, "Do you have SoundMan Wave (y/N) ? ");
 
 	  if (think_positively (0))
 	    {
@@ -1184,7 +1189,7 @@
 		 "Logitech SoundMan Wave has a microcontroller which must be initialized\n"
 		 "before MIDI emulation works. This is possible only if the microcode\n"
 		 "file is compiled into the driver.\n"
-		 "Do you have access to the MIDI0001.BIN file (y/n) ? ");
+		 "Do you have access to the MIDI0001.BIN file (Y/n) ? ");
 	      if (think_positively (1))
 		{
 		  char            path[512];
@@ -1223,7 +1228,7 @@
 	       "\n"
 	       "DANGER! Read the above once again before answering 'y'\n"
 	       "Answer 'n' in case you are unsure what to do!\n");
-      fprintf (stderr, "Do you have a Logitech SoundMan Games (n/y) ? ");
+      fprintf (stderr, "Do you have a Logitech SoundMan Games (y/N) ? ");
       if (think_positively (0))
 	printf ("#define SM_GAMES\n");
     }
@@ -1272,7 +1277,7 @@
 	(stderr,
        "if you wish to emulate the soundblaster and you have a DSPxxx.LD.\n"
 	 "then you must include the LD in the kernel.\n"
-	 "Do you wish to include a LD (y/n) ? ");
+	 "Do you wish to include a LD (Y/n) ? ");
       if (think_positively (1))
 	{
 	  char            path[512];
@@ -1318,7 +1323,7 @@
 	       "modes of AudioTriX Pro will not work without\n"
 	       "this file!\n"
 	       "\n"
-	       "Do you want to include TRXPRO.HEX in your kernel (y/n) ? ");
+	       "Do you want to include TRXPRO.HEX in your kernel (Y/n) ? ");
 
       if (think_positively (1))
 	{
@@ -1377,7 +1382,7 @@
 
   if (!old_config_used)
     {
-      fprintf (stderr, "Save copy of this configuration to %s (y/n)", oldconf);
+      fprintf (stderr, "Save copy of this configuration to %s (Y/n)", oldconf);
       if (think_positively (1))
 	{
 	  char            cmd[200];
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/cs4232.c linux/drivers/sound/cs4232.c
--- v1.3.62/linux/drivers/sound/cs4232.c	Tue Jan 23 21:15:45 1996
+++ linux/drivers/sound/cs4232.c	Sat Feb 10 22:04:38 1996
@@ -7,8 +7,9 @@
  * interfaces. This is just a temporary driver until full PnP support
  * gets inplemented. Just the WSS codec, FM synth and the MIDI ports are
  * supported. Other interfaces are left uninitialized.
- *
- * Copyright by Hannu Savolainen 1995
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -29,8 +30,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -39,7 +41,13 @@
 #define KEY_PORT	0x279	/* Same as LPT1 status port */
 #define CSN_NUM		0x99	/* Just a random number */
 
-#define CS_OUT(a) 		outb( a,  KEY_PORT)
+static int     *osp;
+
+static void 
+CS_OUT (unsigned char a)
+{
+  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);}
 
@@ -55,6 +63,7 @@
 
   mpu_base = hw_config->io_base;
   mpu_irq = hw_config->irq;
+
   return 0;
 }
 
@@ -78,6 +87,8 @@
   int             i;
   int             base = hw_config->io_base, irq = hw_config->irq;
   int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
+
+  osp = hw_config->osp;
 
 /*
  * Verify that the I/O port range is free.
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c
--- v1.3.62/linux/drivers/sound/dev_table.c	Tue Jan 23 21:15:45 1996
+++ linux/drivers/sound/dev_table.c	Sat Feb 10 22:04:39 1996
@@ -2,8 +2,9 @@
  * sound/dev_table.c
  *
  * Device call tables.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #define _DEV_TABLE_C_
 #include "sound_config.h"
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h
--- v1.3.62/linux/drivers/sound/dev_table.h	Tue Jan 23 21:15:45 1996
+++ linux/drivers/sound/dev_table.h	Sat Feb 10 22:09:42 1996
@@ -2,31 +2,32 @@
  *	dev_table.h
  *
  *	Global definitions for device call tables
- * 
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
-*/
+ */
+#include <linux/config.h>
+
 
 #ifndef _DEV_TABLE_H_
 #define _DEV_TABLE_H_
@@ -134,7 +135,7 @@
 		char name[32];
 		int (*open) (void *devc, int sub_device);
 		void (*close) (void *devc, int sub_device);
-		int (*ioctl) (void *devc, unsigned int cmd, ioctl_arg arg, int local);
+		int (*ioctl) (void *devc, unsigned int cmd, caddr_t arg, int local);
 		void (*reset) (void *devc);
 
 		void *devc;		/* Driver specific info */
@@ -155,14 +156,14 @@
 			      int count, int intrflag, int dma_restart);
 	void (*start_input) (int dev, unsigned long buf, 
 			     int count, int intrflag, int dma_restart);
-	int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg, int local);
+	int (*ioctl) (int dev, unsigned int cmd, caddr_t arg, int local);
 	int (*prepare_for_input) (int dev, int bufsize, int nbufs);
 	int (*prepare_for_output) (int dev, int bufsize, int nbufs);
 	void (*reset) (int dev);
 	void (*halt_xfer) (int dev);
 	int (*local_qlen)(int dev);
         void (*copy_from_user)(int dev, char *localbuf, int localoffs,
-                               const snd_rw_buf *userbuf, int useroffs, int len);
+                               const char *userbuf, int useroffs, int len);
 	void (*halt_input) (int dev);
 	void (*halt_output) (int dev);
 	void (*trigger) (int dev, int bits);
@@ -178,7 +179,7 @@
 
 struct mixer_operations {
 	char name[32];
-	int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
+	int (*ioctl) (int dev, unsigned int cmd, caddr_t arg);
 };
 
 struct synth_operations {
@@ -189,13 +190,13 @@
 
 	int (*open) (int dev, int mode);
 	void (*close) (int dev);
-	int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
+	int (*ioctl) (int dev, unsigned int cmd, caddr_t arg);
 	int (*kill_note) (int dev, int voice, int note, int velocity);
 	int (*start_note) (int dev, int voice, int note, int velocity);
 	int (*set_instr) (int dev, int voice, int instr);
 	void (*reset) (int dev);
 	void (*hw_control) (int dev, unsigned char *event);
-	int (*load_patch) (int dev, int format, const snd_rw_buf *addr,
+	int (*load_patch) (int dev, int format, const char *addr,
 	     int offs, int count, int pmgr_flag);
 	void (*aftertouch) (int dev, int voice, int pressure);
 	void (*controller) (int dev, int voice, int ctrl_num, int value);
@@ -233,7 +234,7 @@
 		void (*outputintr)(int dev)
 		);
 	void (*close) (int dev);
-	int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
+	int (*ioctl) (int dev, unsigned int cmd, caddr_t arg);
 	int (*putc) (int dev, unsigned char data);
 	int (*start_read) (int dev);
 	int (*end_read) (int dev);
@@ -259,7 +260,7 @@
 	void (*close)(int dev);
 	int (*event)(int dev, unsigned char *ev);
 	unsigned long (*get_time)(int dev);
-	int (*ioctl) (int dev, unsigned int cmd, ioctl_arg arg);
+	int (*ioctl) (int dev, unsigned int cmd, caddr_t arg);
 	void (*arm_timer)(int dev, long time);
 };
 
@@ -341,9 +342,6 @@
 		{"TRXPRO", 0, SNDCARD_TRXPRO, "MediaTriX AudioTriX Pro",	attach_trix_wss, probe_trix_wss, unload_trix_wss},
 		{"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
-#ifdef CONFIG_PNP
-		{"AD1848", 0, 500, "PnP MSS",	attach_pnp_ad1848, probe_pnp_ad1848, unload_pnp_ad1848},
 #endif
 		{NULL, 0, 0,		"*?*",			NULL, NULL, NULL}
 	};
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c
--- v1.3.62/linux/drivers/sound/dmabuf.c	Tue Jan 23 21:15:45 1996
+++ linux/drivers/sound/dmabuf.c	Sun Feb 11 13:35:30 1996
@@ -2,8 +2,9 @@
  * sound/dmabuf.c
  *
  * The DMA buffer manager for digitized voice applications
- *
- * Copyright by Hannu Savolainen 1993, 1994, 1995
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -109,10 +111,20 @@
       if (bsz == dsp_dev->buffsize)
 	bsz /= 2;		/* Needs at least 2 buffers */
 
+/*
+ *    Split the computed fragment to smaller parts. After 3.5a9
+ *      the default subdivision is 4 which should give better
+ *      results when recording.
+ */
+
       if (dmap->subdivision == 0)	/* Not already set */
-	dmap->subdivision = 1;	/* Init to default value */
-      else
-	bsz /= dmap->subdivision;
+#ifdef V35A9_COMPATIBLE
+	dmap->subdivision = 1;	/* Init to the default value */
+#else
+	dmap->subdivision = 4;	/* Init to the default value */
+#endif
+
+      bsz /= dmap->subdivision;
 
       if (bsz < 16)
 	bsz = 16;		/* Just a sanity check */
@@ -170,7 +182,7 @@
 
   dmap->dma_mode = DMODE_NONE;
   dmap->mapping_flags = 0;
-  dmap->neutral_byte = 0x00;
+  dmap->neutral_byte = 0x80;
   dmap->cfrag = -1;
   dmap->closing = 0;
 }
@@ -270,9 +282,9 @@
   in_sleep_flag[dev].mode = WK_NONE;
   out_sleep_flag[dev].mode = WK_NONE;
 
-  audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, (ioctl_arg) 8, 1);
-  audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, (ioctl_arg) 1, 1);
-  audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, (ioctl_arg) DSP_DEFAULT_SPEED, 1);
+  audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, (caddr_t) 8, 1);
+  audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, (caddr_t) 1, 1);
+  audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_RATE, (caddr_t) DSP_DEFAULT_SPEED, 1);
 
   return 0;
 }
@@ -343,7 +355,7 @@
       cli ();
 
       while (!current_got_fatal_signal ()
-	     && audio_devs[dev]->dmap_out->qlen > 1)
+	     && audio_devs[dev]->dmap_out->qlen)
 	{
 
 	  {
@@ -352,7 +364,7 @@
 	    if (HZ)
 	      current_set_timeout (tl = jiffies + (HZ));
 	    else
-	      tl = 0xffffffff;
+	      tl = (unsigned long) -1;
 	    out_sleep_flag[dev].mode = WK_SLEEP;
 	    module_interruptible_sleep_on (&out_sleeper[dev]);
 	    if (!(out_sleep_flag[dev].mode & WK_WAKEUP))
@@ -389,7 +401,7 @@
 		if (HZ)
 		  current_set_timeout (tl = jiffies + (HZ));
 		else
-		  tl = 0xffffffff;
+		  tl = (unsigned long) -1;
 		out_sleep_flag[dev].mode = WK_SLEEP;
 		module_interruptible_sleep_on (&out_sleeper[dev]);
 		if (!(out_sleep_flag[dev].mode & WK_WAKEUP))
@@ -418,6 +430,10 @@
       && (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT))
     {
       dma_sync (dev);
+
+      memset (audio_devs[dev]->dmap_out->raw_buf,
+	      audio_devs[dev]->dmap_out->neutral_byte,
+	      audio_devs[dev]->dmap_out->bytes_in_use);
     }
 
   save_flags (flags);
@@ -494,15 +510,12 @@
 
   save_flags (flags);
   cli ();
-#ifdef ALLOW_BUFFER_MAPPING
   if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
     {
       printk ("Sound: Can't read from mmapped device (1)\n");
       return -EINVAL;
     }
-  else
-#endif
-  if (!dmap->qlen)
+  else if (!dmap->qlen)
     {
       int             timeout;
 
@@ -539,7 +552,7 @@
 	if (timeout)
 	  current_set_timeout (tl = jiffies + (timeout));
 	else
-	  tl = 0xffffffff;
+	  tl = (unsigned long) -1;
 	in_sleep_flag[dev].mode = WK_SLEEP;
 	module_interruptible_sleep_on (&in_sleeper[dev]);
 	if (!(in_sleep_flag[dev].mode & WK_WAKEUP))
@@ -577,15 +590,12 @@
 
   int             p = dmap->counts[dmap->qhead] + c;
 
-#ifdef ALLOW_BUFFER_MAPPING
   if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
     {
       printk ("Sound: Can't read from mmapped device (2)\n");
       return -EINVAL;
     }
-  else
-#endif
-  if (p >= dmap->fragment_size)
+  else if (p >= dmap->fragment_size)
     {				/* This buffer is completely empty */
       dmap->counts[dmap->qhead] = 0;
       if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
@@ -601,7 +611,7 @@
 }
 
 static int
-dma_subdivide (int dev, struct dma_buffparms *dmap, ioctl_arg arg, int fact)
+dma_subdivide (int dev, struct dma_buffparms *dmap, caddr_t arg, int fact)
 {
   if (fact == 0)
     {
@@ -626,7 +636,7 @@
 }
 
 static int
-dma_set_fragment (int dev, struct dma_buffparms *dmap, ioctl_arg arg, int fact)
+dma_set_fragment (int dev, struct dma_buffparms *dmap, caddr_t arg, int fact)
 {
   int             bytes, count;
 
@@ -700,7 +710,7 @@
 }
 
 int
-DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
+DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
   struct dma_buffparms *dmap_out = audio_devs[dev]->dmap_out;
   struct dma_buffparms *dmap_in = audio_devs[dev]->dmap_in;
@@ -770,10 +780,8 @@
 	  if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX)
 	    dmap = dmap_in;
 
-#ifdef ALLOW_BUFFER_MAPPING
 	  if (dmap->mapping_flags & DMA_MAP_MAPPED)
 	    return -EINVAL;
-#endif
 
 	  if (!(dmap->flags & DMA_ALLOC_DONE))
 	    reorganize_buffers (dev, dmap);
@@ -844,7 +852,6 @@
 	    activate_recording (dev, dmap_in);
 	  }
 
-#ifdef ALLOW_BUFFER_MAPPING
 	if ((changed & bits) & PCM_ENABLE_OUTPUT &&
 	    dmap_out->mapping_flags & DMA_MAP_MAPPED &&
 	    audio_devs[dev]->go)
@@ -855,7 +862,6 @@
 	    dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size;
 	    DMAbuf_start_output (dev, 0, dmap_out->fragment_size);
 	  }
-#endif
 
 	audio_devs[dev]->enable_bits = bits;
 	if (changed && audio_devs[dev]->trigger)
@@ -889,10 +895,8 @@
 	info.bytes += info.ptr;
 	memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 
-#ifdef ALLOW_BUFFER_MAPPING
 	if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
 	  audio_devs[dev]->dmap_in->qlen = 0;	/* Acknowledge interrupts */
-#endif
 	restore_flags (flags);
 	return 0;
       }
@@ -911,10 +915,8 @@
 	info.bytes += info.ptr;
 	memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 
-#ifdef ALLOW_BUFFER_MAPPING
 	if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
 	  audio_devs[dev]->dmap_out->qlen = 0;	/* Acknowledge interrupts */
-#endif
 	restore_flags (flags);
 	return 0;
       }
@@ -990,13 +992,11 @@
   int             abort, err = EIO;
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
 
-#ifdef ALLOW_BUFFER_MAPPING
   if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
     {
       printk ("Sound: Can't write to mmapped device (3)\n");
       return -EINVAL;
     }
-#endif
 
   if (dmap->dma_mode == DMODE_INPUT)	/* Direction change */
     {
@@ -1061,7 +1061,7 @@
 	if (timeout)
 	  current_set_timeout (tl = jiffies + (timeout));
 	else
-	  tl = 0xffffffff;
+	  tl = (unsigned long) -1;
 	out_sleep_flag[dev].mode = WK_SLEEP;
 	module_interruptible_sleep_on (&out_sleeper[dev]);
 	if (!(out_sleep_flag[dev].mode & WK_WAKEUP))
@@ -1094,6 +1094,11 @@
 
   *buf = dmap->raw_buf + dmap->qtail * dmap->fragment_size;
   *size = dmap->fragment_size;
+#if 1
+  memset (*buf,
+          dmap->neutral_byte,
+          *size);
+#endif
   dmap->counts[dmap->qtail] = 0;
 
   return dmap->qtail;
@@ -1138,7 +1143,6 @@
  * Bypass buffering if using mmaped access
  */
 
-#ifdef ALLOW_BUFFER_MAPPING
   if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
     {
       l = dmap->fragment_size;
@@ -1147,9 +1151,6 @@
       dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
     }
   else
-#else
-  if (dmap != NULL)
-#endif
     {
 
 
@@ -1281,18 +1282,16 @@
   unsigned long   flags;
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
 
-  int             p;
-
   dmap->byte_counter += dmap->counts[dmap->qhead];
 
 #ifdef OS_DMA_INTR
   sound_dma_intr (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);
 #endif
 
-#ifdef ALLOW_BUFFER_MAPPING
   if (dmap->mapping_flags & DMA_MAP_MAPPED)
     {
       /* mmapped access */
+      int             p;
 
       p = dmap->fragment_size * dmap->qhead;
       memset (dmap->raw_buf + p,
@@ -1316,9 +1315,7 @@
 	}
       dmap->flags |= DMA_ACTIVE;
     }
-  else
-#endif
-  if (event_type != 2)
+  else if (event_type != 2)
     {
       if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
 	{
@@ -1345,10 +1342,9 @@
 	      dmap->cfrag = -1;
 	      dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
 
-	      p = dmap->fragment_size * dmap->qhead;
-	      memset (dmap->raw_buf + p,
-		      dmap->neutral_byte,
-		      dmap->fragment_size);
+	      memset (audio_devs[dev]->dmap_out->raw_buf,
+		      audio_devs[dev]->dmap_out->neutral_byte,
+		      audio_devs[dev]->dmap_out->bytes_in_use);
 	    }
 	}
 
@@ -1392,7 +1388,6 @@
   sound_dma_intr (dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2);
 #endif
 
-#ifdef ALLOW_BUFFER_MAPPING
   if (dmap->mapping_flags & DMA_MAP_MAPPED)
     {
       dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
@@ -1411,9 +1406,7 @@
 
       dmap->flags |= DMA_ACTIVE;
     }
-  else
-#endif
-  if (dmap->qlen == (dmap->nbufs - 1))
+  else if (dmap->qlen == (dmap->nbufs - 1))
     {
       printk ("Sound: Recording overrun\n");
       dmap->underrun_count++;
@@ -1541,7 +1534,6 @@
     case SEL_IN:
       dmap = audio_devs[dev]->dmap_in;
 
-#ifdef ALLOW_BUFFER_MAPPING
       if (dmap->mapping_flags & DMA_MAP_MAPPED)
 	{
 	  if (dmap->qlen)
@@ -1554,7 +1546,6 @@
 	  restore_flags (flags);
 	  return 0;
 	}
-#endif
 
       if (dmap->dma_mode != DMODE_INPUT)
 	{
@@ -1587,7 +1578,6 @@
     case SEL_OUT:
       dmap = audio_devs[dev]->dmap_out;
 
-#ifdef ALLOW_BUFFER_MAPPING
       if (dmap->mapping_flags & DMA_MAP_MAPPED)
 	{
 	  if (dmap->qlen)
@@ -1600,7 +1590,6 @@
 	  restore_flags (flags);
 	  return 0;
 	}
-#endif
 
       if (dmap->dma_mode == DMODE_INPUT)
 	{
@@ -1674,7 +1663,7 @@
 }
 
 int
-DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
+DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
   return -EIO;
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/finetune.h linux/drivers/sound/finetune.h
--- v1.3.62/linux/drivers/sound/finetune.h	Mon Jul 18 09:50:55 1994
+++ linux/drivers/sound/finetune.h	Sat Feb 10 22:04:23 1996
@@ -1,29 +1,28 @@
 #ifdef SEQUENCER_C
 /*
- * Copyright by Hannu Savolainen 1993
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+
 
   unsigned short finetune_table[128] =
 	{
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/gus_card.c linux/drivers/sound/gus_card.c
--- v1.3.62/linux/drivers/sound/gus_card.c	Tue Jan 23 21:15:45 1996
+++ linux/drivers/sound/gus_card.c	Sat Feb 10 22:04:42 1996
@@ -2,8 +2,9 @@
  * sound/gus_card.c
  *
  * Detection routine for the Gravis Ultrasound.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -40,7 +42,7 @@
 extern int      gus_pcm_volume;
 extern int      have_gus_max;
 
-sound_os_info  *gus_osp;
+int            *gus_osp;
 
 long
 attach_gus_card (long mem_start, struct address_info *hw_config)
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/gus_midi.c linux/drivers/sound/gus_midi.c
--- v1.3.62/linux/drivers/sound/gus_midi.c	Tue Jan 23 21:15:45 1996
+++ linux/drivers/sound/gus_midi.c	Sat Feb 10 22:04:42 1996
@@ -2,8 +2,9 @@
  * sound/gus2_midi.c
  *
  * The low level driver for the GUS Midi Interface.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -44,9 +46,13 @@
 static volatile int qlen;
 static volatile unsigned char qhead, qtail;
 extern int      gus_base, gus_irq, gus_dma;
-extern sound_os_info *gus_osp;
+extern int     *gus_osp;
 
-#define GUS_MIDI_STATUS()	inb( u_MidiStatus)
+static int 
+GUS_MIDI_STATUS (void)
+{
+  return inb (u_MidiStatus);
+}
 
 static int
 gus_midi_open (int dev, int mode,
@@ -188,7 +194,7 @@
 }
 
 static int
-gus_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
+gus_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
   return -EINVAL;
 }
@@ -262,13 +268,14 @@
 void
 gus_midi_interrupt (int dummy)
 {
-  unsigned char   stat, data;
+  volatile unsigned char stat, data;
   unsigned long   flags;
+  int             timeout = 10;
 
   save_flags (flags);
   cli ();
 
-  while ((stat = GUS_MIDI_STATUS ()) & (MIDI_RCV_FULL | MIDI_XMIT_EMPTY))
+  while (timeout-- > 0 && (stat = GUS_MIDI_STATUS ()) & (MIDI_RCV_FULL | MIDI_XMIT_EMPTY))
     {
       if (stat & MIDI_RCV_FULL)
 	{
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/gus_vol.c linux/drivers/sound/gus_vol.c
--- v1.3.62/linux/drivers/sound/gus_vol.c	Tue Jan 23 21:15:46 1996
+++ linux/drivers/sound/gus_vol.c	Sat Feb 10 22:04:42 1996
@@ -1,8 +1,31 @@
 /*
  * gus_vol.c - Compute volume for GUS.
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
  *
- * Greg Lee 1993.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
+#include <linux/config.h>
+
 #include "sound_config.h"
 #ifdef CONFIG_GUS
 #include "gus_linearvol.h"
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c
--- v1.3.62/linux/drivers/sound/gus_wave.c	Tue Jan 23 21:15:46 1996
+++ linux/drivers/sound/gus_wave.c	Sat Feb 10 22:04:47 1996
@@ -2,8 +2,9 @@
  * sound/gus_wave.c
  *
  * Driver for the Gravis UltraSound wave table synth.
- *
- * Copyright by Hannu Savolainen 1993, 1994
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 #include <linux/ultrasound.h>
@@ -36,6 +38,8 @@
 #define MAX_SAMPLE	150
 #define MAX_PATCH	256
 
+#define NOT_SAMPLE	0xffff
+
 struct voice_info
   {
     unsigned long   orig_freq;
@@ -133,7 +137,7 @@
 static int      pcm_current_count;
 static int      pcm_current_intrflag;
 
-extern sound_os_info *gus_osp;
+extern int     *gus_osp;
 
 struct voice_info voices[32];
 
@@ -204,7 +208,7 @@
   free_sample = 0;
 
   for (i = 0; i < MAX_PATCH; i++)
-    patch_table[i] = -1;
+    patch_table[i] = NOT_SAMPLE;
 }
 
 void
@@ -889,7 +893,7 @@
 
 static int
 guswave_ioctl (int dev,
-	       unsigned int cmd, ioctl_arg arg)
+	       unsigned int cmd, caddr_t arg)
 {
 
   switch (cmd)
@@ -1222,7 +1226,7 @@
       return -EINVAL;
     }
 
-  if ((samplep = patch_table[patch]) == -1)
+  if ((samplep = patch_table[patch]) == NOT_SAMPLE)
     {
       return -EINVAL;
     }
@@ -1237,7 +1241,7 @@
 
   best_sample = samplep;
   best_delta = 1000000;
-  while (samplep >= 0 && sample == -1)
+  while (samplep != 0 && samplep != NOT_SAMPLE && sample == -1)
     {
       delta_freq = note_freq - samples[samplep].base_note;
       if (delta_freq < 0)
@@ -1251,9 +1255,7 @@
 	  note_freq <= samples[samplep].high_note)
 	sample = samplep;
       else
-	samplep = samples[samplep].key;		/*
-						   * Follow link
-						 */
+	samplep = samples[samplep].key;		/* Link to next sample */
     }
   if (sample == -1)
     sample = best_sample;
@@ -1505,14 +1507,14 @@
 }
 
 static int
-guswave_load_patch (int dev, int format, const snd_rw_buf * addr,
+guswave_load_patch (int dev, int format, const char *addr,
 		    int offs, int count, int pmgr_flag)
 {
   struct patch_info patch;
   int             instr;
   long            sizeof_patch;
 
-  unsigned long   blk_size, blk_end, left, src_offs, target;
+  unsigned long   blk_sz, blk_end, left, src_offs, target;
 
   sizeof_patch = (long) &patch.data[0] - (long) &patch;		/* Header size */
 
@@ -1638,21 +1640,21 @@
 
   while (left)			/* Not completely transferred yet */
     {
-      /* blk_size = audio_devs[gus_devnum]->buffsize; */
-      blk_size = audio_devs[gus_devnum]->dmap_out->bytes_in_use;
-      if (blk_size > left)
-	blk_size = left;
+      /* blk_sz = audio_devs[gus_devnum]->buffsize; */
+      blk_sz = audio_devs[gus_devnum]->dmap_out->bytes_in_use;
+      if (blk_sz > left)
+	blk_sz = left;
 
       /*
        * DMA cannot cross 256k bank boundaries. Check for that.
        */
-      blk_end = target + blk_size;
+      blk_end = target + blk_sz;
 
       if ((target >> 18) != (blk_end >> 18))
 	{			/* Split the block */
 
 	  blk_end &= ~(256 * 1024 - 1);
-	  blk_size = blk_end - target;
+	  blk_sz = blk_end - target;
 	}
 
       if (gus_no_dma)
@@ -1664,7 +1666,7 @@
 	  unsigned char   data;
 
 
-	  for (i = 0; i < blk_size; i++)
+	  for (i = 0; i < blk_sz; i++)
 	    {
 	      data = get_fs_byte (&((addr)[sizeof_patch + i]));
 	      if (patch.mode & WAVE_UNSIGNED)
@@ -1684,7 +1686,7 @@
 	   * OK, move now. First in and then out.
 	   */
 
-	  memcpy_fromfs (audio_devs[gus_devnum]->dmap_out->raw_buf, &((addr)[sizeof_patch + src_offs]), blk_size);
+	  memcpy_fromfs (audio_devs[gus_devnum]->dmap_out->raw_buf, &((addr)[sizeof_patch + src_offs]), blk_sz);
 
 	  save_flags (flags);
 	  cli ();
@@ -1692,7 +1694,7 @@
 	  gus_write8 (0x41, 0);	/* Disable GF1 DMA */
 	  DMAbuf_start_dma (gus_devnum,
 			    audio_devs[gus_devnum]->dmap_out->raw_buf_phys,
-			    blk_size, DMA_MODE_WRITE);
+			    blk_sz, DMA_MODE_WRITE);
 
 	  /*
 	   * Set the DRAM address for the wave data
@@ -1736,7 +1738,7 @@
 	    if (HZ)
 	      current_set_timeout (tl = jiffies + (HZ));
 	    else
-	      tl = 0xffffffff;
+	      tl = (unsigned long) -1;
 	    dram_sleep_flag.mode = WK_SLEEP;
 	    module_interruptible_sleep_on (&dram_sleeper);
 	    if (!(dram_sleep_flag.mode & WK_WAKEUP))
@@ -1755,9 +1757,9 @@
        * Now the next part
        */
 
-      left -= blk_size;
-      src_offs += blk_size;
-      target += blk_size;
+      left -= blk_sz;
+      src_offs += blk_sz;
+      target += blk_sz;
 
       gus_write8 (0x41, 0);	/* Stop DMA */
     }
@@ -1771,17 +1773,18 @@
 }
 
 static void
-guswave_hw_control (int dev, unsigned char *event)
+guswave_hw_control (int dev, unsigned char *event_rec)
 {
   int             voice, cmd;
   unsigned short  p1, p2;
-  unsigned long   plong, flags;
+  unsigned int    plong;
+  unsigned        flags;
 
-  cmd = event[2];
-  voice = event[3];
-  p1 = *(unsigned short *) &event[4];
-  p2 = *(unsigned short *) &event[6];
-  plong = *(unsigned long *) &event[4];
+  cmd = event_rec[2];
+  voice = event_rec[3];
+  p1 = *(unsigned short *) &event_rec[4];
+  p2 = *(unsigned short *) &event_rec[6];
+  plong = *(unsigned int *) &event_rec[4];
 
   if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) &&
       (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS))
@@ -1985,7 +1988,7 @@
 }
 
 static int
-gus_sampling_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
+gus_sampling_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
   switch (cmd)
     {
@@ -2425,7 +2428,7 @@
 
 static void
 gus_copy_from_user (int dev, char *localbuf, int localoffs,
-		    const snd_rw_buf * userbuf, int useroffs, int len)
+		    const char *userbuf, int useroffs, int len)
 {
   if (gus_sampling_channels == 1)
     {
@@ -2823,7 +2826,7 @@
 }
 
 int
-gus_default_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
+gus_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 {
 #define MIX_DEVS	(SOUND_MASK_MIC|SOUND_MASK_LINE| \
 			 SOUND_MASK_SYNTH|SOUND_MASK_PCM)
@@ -3098,7 +3101,24 @@
        */
     }
 
-  sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
+  if (hw_config->name)
+    {
+      strncpy (gus_info.name, hw_config->name, sizeof (gus_info.name));
+      gus_info.name[sizeof (gus_info.name) - 1] = 0;
+    }
+  else
+    sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
+
+
+  samples = (struct patch_info *) (sound_mem_blocks[sound_num_blocks] = kmalloc ((MAX_SAMPLE + 1) * sizeof (*samples), GFP_KERNEL));
+  if (sound_num_blocks < 1024)
+    sound_num_blocks++;;
+  if (samples == NULL)
+    {
+      printk ("GUS Error: Cant allocate memory for instrument tables\n");
+      return mem_start;
+    }
+
   conf_printf (gus_info.name, hw_config);
 
   if (num_synths >= MAX_SYNTH_DEV)
@@ -3111,11 +3131,6 @@
       gus_tmr_install (gus_base + 8);
 #endif
     }
-
-
-  samples = (struct patch_info *) (sound_mem_blocks[sound_num_blocks] = kmalloc ((MAX_SAMPLE + 1) * sizeof (*samples), GFP_KERNEL));
-  if (sound_num_blocks < 1024)
-    sound_num_blocks++;;
 
   reset_sample_memory ();
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/hex2hex.h linux/drivers/sound/hex2hex.h
--- v1.3.62/linux/drivers/sound/hex2hex.h	Mon Oct 23 18:02:14 1995
+++ linux/drivers/sound/hex2hex.h	Sat Feb 10 22:04:23 1996
@@ -9,30 +9,12 @@
 #define MAX_SIZE (256*1024)
 #define ABANDON(why) { \
 		fprintf(stderr, "%s: " why "\n", source); \
-		fclose(inf);fclose(outf);return 0; \
+		return 0; \
 		}
 
-int hex2hex(char *source, char *target, char *varline)
+int loadhex(FILE *inf, unsigned char *buf, char *source)
 {
-	FILE *inf, *outf;
-
-	int i,l, c;
-	unsigned char buf[MAX_SIZE];
-
-	if ((inf=fopen(source, "r"))==NULL)
-	{
-		perror(source);
-		return 0;
-	}
-
-	if ((outf=fopen(target, "w"))==NULL)
-	{
-		perror(target);
-		fclose(inf);
-		return 0;
-	}
-
-	l=0;
+	int l=0, c, i;
 
 	while ((c=getc(inf))!=EOF)
 	{
@@ -80,7 +62,40 @@
 		}
 	}
 
+	return l;
+}
+
+int hex2hex(char *source, char *target, char *varline)
+{
+	FILE *inf, *outf;
+
+	int i,l;
+	unsigned char buf[MAX_SIZE];
+
+	if ((inf=fopen(source, "r"))==NULL)
+	{
+		perror(source);
+		return 0;
+	}
+
+	if ((outf=fopen(target, "w"))==NULL)
+	{
+		perror(target);
+		fclose(inf);
+		return 0;
+	}
+
+	l=loadhex(inf, buf, source);
+	if (l<=0)
+        {
+           fclose(inf);
+	   fclose(outf);
+	   return l;
+	}
+
+
 	fprintf(outf, "/*\n *\t Computer generated file. Do not edit.\n */\n");
+        fprintf(outf, "static int %s_len = %d\n", l);
 	fprintf(outf, "static unsigned char %s[] = {\n", varline);
 
 	for (i=0;i<l;i++)
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/ics2101.c linux/drivers/sound/ics2101.c
--- v1.3.62/linux/drivers/sound/ics2101.c	Tue Jan 23 21:15:46 1996
+++ linux/drivers/sound/ics2101.c	Sat Feb 10 22:04:48 1996
@@ -2,8 +2,9 @@
  * sound/ics2101.c
  *
  * Driver for the ICS2101 mixer of GUS v3.7.
- *
- * Copyright by Hannu Savolainen 1994
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 #if defined(CONFIG_GUS)
@@ -37,7 +39,7 @@
 			 SOUND_MASK_SYNTH| \
   			 SOUND_MASK_CD | SOUND_MASK_VOLUME)
 
-extern sound_os_info *gus_osp;
+extern int     *gus_osp;
 extern int      gus_base;
 static int      volumes[ICS_MIXDEVS];
 static int      left_fix[ICS_MIXDEVS] =
@@ -130,7 +132,7 @@
 }
 
 static int
-ics2101_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
+ics2101_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 {
   if (((cmd >> 8) & 0xff) == 'M')
     {
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c
--- v1.3.62/linux/drivers/sound/mad16.c	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/mad16.c	Sat Feb 10 22:04:49 1996
@@ -1,4 +1,30 @@
 /*
+ * Copyright by Hannu Savolainen 1993-1996
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <linux/config.h>
+
+
+/*
  * sound/mad16.c
  *
  * Initialization code for OPTi MAD16 compatible audio chips. Including
@@ -45,29 +71,6 @@
  *      CD-ROM DMA (Mitsumi or IDE):    0x00=DMA5, 0x01=DMA6, 0x02=DMA7 or 0x03=disabled
  *
  *      For use with sbpcd, address 0x340, set MAD16_CDSEL to 0x03 or 0x23.
- *
- * Copyright by Hannu Savolainen 1995
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer. 2.
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
  */
 
 #include "sound_config.h"
@@ -100,7 +103,7 @@
 
 static int      board_type = C928;
 
-static sound_os_info *mad16_osp;
+static int     *mad16_osp;
 
 #ifndef DDB
 #define DDB(x)
@@ -424,6 +427,13 @@
 	  (dma == 3 && dma2 == 0))
 	{
 	  dma2_bit = 0x04;	/* Enable capture DMA */
+
+	  /* Change SB DMA so that it doesn't conflict with codec's DMAs */
+
+	  if (dma == 3)
+	    mad_write (MC3_PORT, (mad_read (MC3_PORT) & ~0x30) | 0x00);		/*DMA1 */
+	  else
+	    mad_write (MC3_PORT, (mad_read (MC3_PORT) & ~0x30) | 0x20);		/*DMA3 */
 	}
       else
 	{
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/mad16_sb_midi.c linux/drivers/sound/mad16_sb_midi.c
--- v1.3.62/linux/drivers/sound/mad16_sb_midi.c	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/mad16_sb_midi.c	Sat Feb 10 22:04:49 1996
@@ -2,8 +2,9 @@
  * sound/mad16_sb_midi.c
  *
  * The low level driver for MAD16 SoundBlaster-DS-chip-based MIDI.
- *
- * Copyright by Hannu Savolainen 1993, Aaron Ucko 1995
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,7 +25,11 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
+ */
+#include <linux/config.h>
+
+/*
+ * Modifications by Aaron Ucko 1995
  */
 
 #include "sound_config.h"
@@ -40,7 +45,7 @@
 static int      mad16_sb_irq = 0;
 static int      mad16_sb_dsp_ok = 0;
 static int      mad16_sb_dsp_attached = 0;
-static sound_os_info *midi_osp;
+static int     *midi_osp;
 
 int             mad16_sb_midi_mode = NORMAL_MIDI;
 int             mad16_sb_midi_busy = 0;
@@ -303,7 +308,7 @@
 }
 
 static int
-mad16_sb_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
+mad16_sb_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
   return -EPERM;
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/maui.c linux/drivers/sound/maui.c
--- v1.3.62/linux/drivers/sound/maui.c	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/maui.c	Sat Feb 10 22:04:49 1996
@@ -2,8 +2,9 @@
  * sound/maui.c
  *
  * The low level driver for Turtle Beach Maui and Tropez.
- *
- * Copyright by Hannu Savolainen 1995
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #define USE_SEQ_MACROS
 #define USE_SIMPLE_MACROS
@@ -37,7 +39,7 @@
 static int      maui_base = 0x330;
 
 static volatile int irq_ok = 0;
-static sound_os_info *maui_osp;
+static int     *maui_osp;
 
 #define HOST_DATA_PORT	(maui_base + 2)
 #define HOST_STAT_PORT	(maui_base + 3)
@@ -50,7 +52,7 @@
 #define STAT_RX_AVAIL	0x02
 #define STAT_RX_IENA	0x01
 
-static int      (*orig_load_patch) (int dev, int format, const snd_rw_buf * addr,
+static int      (*orig_load_patch) (int dev, int format, const char *addr,
 				 int offs, int count, int pmgr_flag) = NULL;
 
 static int
@@ -98,7 +100,7 @@
 
 
 int
-maui_load_patch (int dev, int format, const snd_rw_buf * addr,
+maui_load_patch (int dev, int format, const char *addr,
 		 int offs, int count, int pmgr_flag)
 {
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/midi_synth.c linux/drivers/sound/midi_synth.c
--- v1.3.62/linux/drivers/sound/midi_synth.c	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/midi_synth.c	Sat Feb 10 22:04:50 1996
@@ -2,8 +2,9 @@
  * sound/midi_synth.c
  *
  * High level midi sequencer manager for dumb MIDI interfaces.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #define USE_SEQ_MACROS
 #define USE_SIMPLE_MACROS
@@ -279,7 +281,7 @@
 
 int
 midi_synth_ioctl (int dev,
-		  unsigned int cmd, ioctl_arg arg)
+		  unsigned int cmd, caddr_t arg)
 {
   /*
    * int orig_dev = synth_devs[dev]->midi_dev;
@@ -498,7 +500,7 @@
 }
 
 int
-midi_synth_load_patch (int dev, int format, const snd_rw_buf * addr,
+midi_synth_load_patch (int dev, int format, const char *addr,
 		       int offs, int count, int pmgr_flag)
 {
   int             orig_dev = synth_devs[dev]->midi_dev;
@@ -576,7 +578,7 @@
 	  if (1)
 	    current_set_timeout (tl = jiffies + (1));
 	  else
-	    tl = 0xffffffff;
+	    tl = (unsigned long) -1;
 	  sysex_sleep_flag.mode = WK_SLEEP;
 	  module_interruptible_sleep_on (&sysex_sleeper);
 	  if (!(sysex_sleep_flag.mode & WK_WAKEUP))
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/midi_synth.h linux/drivers/sound/midi_synth.h
--- v1.3.62/linux/drivers/sound/midi_synth.h	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/midi_synth.h	Sat Feb 10 22:04:23 1996
@@ -1,5 +1,5 @@
 int midi_synth_ioctl (int dev,
-	    unsigned int cmd, ioctl_arg arg);
+	    unsigned int cmd, caddr_t arg);
 int midi_synth_kill_note (int dev, int channel, int note, int velocity);
 int midi_synth_set_instr (int dev, int channel, int instr_no);
 int midi_synth_start_note (int dev, int channel, int note, int volume);
@@ -7,7 +7,7 @@
 int midi_synth_open (int dev, int mode);
 void midi_synth_close (int dev);
 void midi_synth_hw_control (int dev, unsigned char *event);
-int midi_synth_load_patch (int dev, int format, const snd_rw_buf * addr,
+int midi_synth_load_patch (int dev, int format, const char * addr,
 		 int offs, int count, int pmgr_flag);
 void midi_synth_panning (int dev, int channel, int pressure);
 void midi_synth_aftertouch (int dev, int channel, int pressure);
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/midibuf.c linux/drivers/sound/midibuf.c
--- v1.3.62/linux/drivers/sound/midibuf.c	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/midibuf.c	Sat Feb 10 22:04:51 1996
@@ -2,8 +2,9 @@
  * sound/midibuf.c
  *
  * Device file manager for /dev/midi#
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -115,7 +117,7 @@
 	if (HZ / 10)
 	  current_set_timeout (tl = jiffies + (HZ / 10));
 	else
-	  tl = 0xffffffff;
+	  tl = (unsigned long) -1;
 	midi_sleep_flag[dev].mode = WK_SLEEP;
 	module_interruptible_sleep_on (&midi_sleeper[dev]);
 	if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
@@ -305,7 +307,7 @@
 	  if (0)
 	    current_set_timeout (tl = jiffies + (0));
 	  else
-	    tl = 0xffffffff;
+	    tl = (unsigned long) -1;
 	  midi_sleep_flag[dev].mode = WK_SLEEP;
 	  module_interruptible_sleep_on (&midi_sleeper[dev]);
 	  if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
@@ -337,7 +339,7 @@
 }
 
 int
-MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
+MIDIbuf_write (int dev, struct fileinfo *file, const char *buf, int count)
 {
   unsigned long   flags;
   int             c, n, i;
@@ -368,7 +370,7 @@
 	    if (0)
 	      current_set_timeout (tl = jiffies + (0));
 	    else
-	      tl = 0xffffffff;
+	      tl = (unsigned long) -1;
 	    midi_sleep_flag[dev].mode = WK_SLEEP;
 	    module_interruptible_sleep_on (&midi_sleeper[dev]);
 	    if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
@@ -405,7 +407,7 @@
 
 
 int
-MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+MIDIbuf_read (int dev, struct fileinfo *file, char *buf, int count)
 {
   int             n, c = 0;
   unsigned long   flags;
@@ -427,7 +429,7 @@
 	if (parms[dev].prech_timeout)
 	  current_set_timeout (tl = jiffies + (parms[dev].prech_timeout));
 	else
-	  tl = 0xffffffff;
+	  tl = (unsigned long) -1;
 	input_sleep_flag[dev].mode = WK_SLEEP;
 	module_interruptible_sleep_on (&input_sleeper[dev]);
 	if (!(input_sleep_flag[dev].mode & WK_WAKEUP))
@@ -467,7 +469,7 @@
 
 int
 MIDIbuf_ioctl (int dev, struct fileinfo *file,
-	       unsigned int cmd, ioctl_arg arg)
+	       unsigned int cmd, caddr_t arg)
 {
   int             val;
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/mpu401.c linux/drivers/sound/mpu401.c
--- v1.3.62/linux/drivers/sound/mpu401.c	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/mpu401.c	Sat Feb 10 22:04:53 1996
@@ -2,8 +2,9 @@
  * sound/mpu401.c
  *
  * The low level driver for Roland MPU-401 compatible Midi cards.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,11 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- * Modified:
- *  Riccardo Facchetti  24 Mar 1995
- *  - Added the Audio Excel DSP 16 initialization routine.
  */
+#include <linux/config.h>
+
 
 #define USE_SEQ_MACROS
 #define USE_SIMPLE_MACROS
@@ -82,20 +81,36 @@
     unsigned char   last_status;
     void            (*inputintr) (int dev, unsigned char data);
     int             shared_irq;
-    sound_os_info  *osp;
+    int            *osp;
   };
 
 #define	DATAPORT(base)   (base)
 #define	COMDPORT(base)   (base+1)
 #define	STATPORT(base)   (base+1)
 
-#define mpu401_status(devc)		inb( STATPORT(devc->base))
+static int 
+mpu401_status (struct mpu_config *devc)
+{
+  return inb (STATPORT (devc->base));
+}
 #define input_avail(devc)		(!(mpu401_status(devc)&INPUT_AVAIL))
 #define output_ready(devc)		(!(mpu401_status(devc)&OUTPUT_READY))
-#define write_command(devc, cmd)	outb( cmd,  COMDPORT(devc->base))
-#define read_data(devc)		inb( DATAPORT(devc->base))
+static void 
+write_command (struct mpu_config *devc, unsigned char cmd)
+{
+  outb (cmd, COMDPORT (devc->base));
+}
+static int 
+read_data (struct mpu_config *devc)
+{
+  return inb (DATAPORT (devc->base));
+}
 
-#define write_data(devc, byte)	outb( byte,  DATAPORT(devc->base))
+static void 
+write_data (struct mpu_config *devc, unsigned char byte)
+{
+  outb (byte, DATAPORT (devc->base));
+}
 
 #define	OUTPUT_READY	0x40
 #define	INPUT_AVAIL	0x80
@@ -619,11 +634,11 @@
     mpu401_input_loop (devc);
 
   /*
-   * Sometimes it takes about 30000 loops before the output becomes ready
+   * Sometimes it takes about 50000 loops before the output becomes ready
    * (After reset). Normally it takes just about 10 loops.
    */
 
-  timeout = 30000;
+  timeout = 50000;
 retry:
   if (timeout-- <= 0)
     {
@@ -641,19 +656,22 @@
     }
 
   write_command (devc, cmd->cmd);
+
   ok = 0;
   for (timeout = 50000; timeout > 0 && !ok; timeout--)
     if (input_avail (devc))
-      if (devc->opened && devc->mode == MODE_SYNTH)
-	{
-	  if (mpu_input_scanner (devc, read_data (devc)) == MPU_ACK)
-	    ok = 1;
-	}
-      else
-	{			/* Device is not currently open. Use simplier method */
-	  if (read_data (devc) == MPU_ACK)
-	    ok = 1;
-	}
+      {
+	if (devc->opened && devc->mode == MODE_SYNTH)
+	  {
+	    if (mpu_input_scanner (devc, read_data (devc)) == MPU_ACK)
+	      ok = 1;
+	  }
+	else
+	  {			/* Device is not currently open. Use simplier method */
+	    if (read_data (devc) == MPU_ACK)
+	      ok = 1;
+	  }
+      }
 
   if (!ok)
     {
@@ -769,7 +787,7 @@
 }
 
 static int
-mpu401_ioctl (int dev, unsigned cmd, ioctl_arg arg)
+mpu401_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
   struct mpu_config *devc;
 
@@ -827,7 +845,7 @@
 
 static int
 mpu_synth_ioctl (int dev,
-		 unsigned int cmd, ioctl_arg arg)
+		 unsigned int cmd, caddr_t arg)
 {
   int             midi_dev;
   struct mpu_config *devc;
@@ -998,23 +1016,35 @@
 mpu401_chk_version (struct mpu_config *devc)
 {
   int             tmp;
+  unsigned long   flags;
 
   devc->version = devc->revision = 0;
 
+  save_flags (flags);
+  cli ();
   if ((tmp = mpu_cmd (num_midis, 0xAC, 0)) < 0)
-    return;
+    {
+      restore_flags (flags);
+      return;
+    }
 
   if ((tmp & 0xf0) > 0x20)	/* Why it's larger than 2.x ??? */
-    return;
+    {
+      restore_flags (flags);
+      return;
+    }
 
   devc->version = tmp;
 
   if ((tmp = mpu_cmd (num_midis, 0xAD, 0)) < 0)
     {
       devc->version = 0;
+      restore_flags (flags);
       return;
     }
   devc->revision = tmp;
+
+  restore_flags (flags);
 }
 
 long
@@ -1064,6 +1094,7 @@
       if (!devc->shared_irq)
 	if (snd_set_irq_handler (devc->irq, mpuintr, "mpu401", devc->osp) < 0)
 	  {
+	    printk ("MPU401: Failed to allocate IRQ%d\n", devc->irq);
 	    return mem_start;
 	  }
 
@@ -1267,13 +1298,6 @@
   tmp_devc.opened = 0;
   tmp_devc.osp = hw_config->osp;
 
-#if defined(CONFIG_AEDSP16) && defined(AEDSP16_MPU401)
-  /*
-     * Initialize Audio Excel DSP 16 to MPU-401, before any operation.
-   */
-  InitAEDSP16_MPU401 (hw_config);
-#endif
-
   if (hw_config->always_detect)
     return 1;
 
@@ -1360,7 +1384,7 @@
 
   save_flags (flags);
   cli ();
-  next_event_time = 0xffffffff;
+  next_event_time = (unsigned long) -1;
   prev_event_time = 0;
   curr_ticks = curr_clocks = 0;
   restore_flags (flags);
@@ -1569,7 +1593,7 @@
 
 static int
 mpu_timer_ioctl (int dev,
-		 unsigned int command, ioctl_arg arg)
+		 unsigned int command, caddr_t arg)
 {
   int             midi_dev = sound_timer_devs[dev]->devlink;
 
@@ -1708,7 +1732,7 @@
 
   if (curr_ticks >= next_event_time)
     {
-      next_event_time = 0xffffffff;
+      next_event_time = (unsigned long) -1;
       sequencer_timer (0);
     }
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/opl3.c linux/drivers/sound/opl3.c
--- v1.3.62/linux/drivers/sound/opl3.c	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/opl3.c	Sat Feb 10 22:04:55 1996
@@ -2,8 +2,9 @@
  * sound/opl3.c
  *
  * A low level driver for Yamaha YM3812 and OPL-3 -chips
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 /*
  * Major improvements to the FM handling 30AUG92 by Rob Hooft,
@@ -74,7 +76,7 @@
     unsigned char   cmask;
 
     int             is_opl4;
-    sound_os_info  *osp;
+    int            *osp;
   }
 opl_devinfo;
 
@@ -121,7 +123,7 @@
 
 static int
 opl3_ioctl (int dev,
-	    unsigned int cmd, ioctl_arg arg)
+	    unsigned int cmd, caddr_t arg)
 {
   switch (cmd)
     {
@@ -167,7 +169,7 @@
 }
 
 int
-opl3_detect (int ioaddr, sound_os_info * osp)
+opl3_detect (int ioaddr, int *osp)
 {
   /*
    * This function returns 1 if the FM chicp is present at the given I/O port
@@ -876,7 +878,7 @@
 }
 
 static int
-opl3_load_patch (int dev, int format, const snd_rw_buf * addr,
+opl3_load_patch (int dev, int format, const char *addr,
 		 int offs, int count, int pmgr_flag)
 {
   struct sbi_instrument ins;
@@ -1171,7 +1173,7 @@
 };
 
 long
-opl3_init (long mem_start, int ioaddr, sound_os_info * osp)
+opl3_init (long mem_start, int ioaddr, int *osp)
 {
   int             i;
 
@@ -1191,7 +1193,7 @@
   devc->osp = osp;
 
   devc->nr_voice = 9;
-  strcpy (devc->fm_info.name, "OPL2-");
+  strcpy (devc->fm_info.name, "OPL2");
 
   devc->fm_info.device = 0;
   devc->fm_info.synth_type = SYNTH_TYPE_FM;
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/opl3.h linux/drivers/sound/opl3.h
--- v1.3.62/linux/drivers/sound/opl3.h	Fri Oct 13 14:44:34 1995
+++ linux/drivers/sound/opl3.h	Sat Feb 10 22:04:23 1996
@@ -1,29 +1,28 @@
 /*
  *	opl3.h	- Definitions of the OPL-3 registers
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
 
 /*
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/os.h linux/drivers/sound/os.h
--- v1.3.62/linux/drivers/sound/os.h	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/os.h	Sat Feb 10 22:04:27 1996
@@ -3,8 +3,6 @@
 #undef NO_INLINE_ASM
 #define SHORT_BANNERS
 
-#include <linux/config.h>
-
 #ifdef MODULE
 #define __NO_VERSION__
 #include <linux/module.h>
@@ -37,9 +35,6 @@
 
 #include <linux/soundcard.h>
 
-typedef char snd_rw_buf;
-typedef caddr_t ioctl_arg;
-
 #define FALSE	0
 #define TRUE	1
 
@@ -57,6 +52,5 @@
 extern caddr_t sound_mem_blocks[1024];
 extern int sound_num_blocks;
 
-typedef int sound_os_info;
-
 #undef PSEUDO_DMA_AUTOINIT
+#define ALLOW_BUFFER_MAPPING
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/pas2_card.c linux/drivers/sound/pas2_card.c
--- v1.3.62/linux/drivers/sound/pas2_card.c	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/pas2_card.c	Sat Feb 10 22:04:56 1996
@@ -3,8 +3,9 @@
  * sound/pas2_card.c
  *
  * Detection routine for the Pro Audio Spectrum cards.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -25,8 +26,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -44,7 +46,7 @@
 static int      pas_intr_mask = 0;
 static int      pas_irq = 0;
 
-sound_os_info  *pas_osp;
+int            *pas_osp;
 
 char            pas_model;
 static char    *pas_model_names[] =
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/pas2_midi.c linux/drivers/sound/pas2_midi.c
--- v1.3.62/linux/drivers/sound/pas2_midi.c	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/pas2_midi.c	Sat Feb 10 22:04:56 1996
@@ -2,8 +2,9 @@
  * sound/pas2_midi.c
  *
  * The low level driver for the PAS Midi Interface.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -215,7 +217,7 @@
 }
 
 static int
-pas_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
+pas_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
   return -EINVAL;
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/pas2_mixer.c linux/drivers/sound/pas2_mixer.c
--- v1.3.62/linux/drivers/sound/pas2_mixer.c	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/pas2_mixer.c	Sat Feb 10 22:04:57 1996
@@ -4,8 +4,9 @@
  * sound/pas2_mixer.c
  *
  * Mixer routines for the Pro Audio Spectrum cards.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -26,8 +27,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -39,7 +41,7 @@
 
 extern int      translat_code;
 extern char     pas_model;
-extern sound_os_info *pas_osp;
+extern int     *pas_osp;
 
 static int      rec_devices = (SOUND_MASK_MIC);		/* Default recording source */
 static int      mode_control = 0;
@@ -258,7 +260,7 @@
 }
 
 int
-pas_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
+pas_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 {
   TRACE (printk ("pas2_mixer.c: int pas_mixer_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/pas2_pcm.c linux/drivers/sound/pas2_pcm.c
--- v1.3.62/linux/drivers/sound/pas2_pcm.c	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/pas2_pcm.c	Sat Feb 10 22:04:58 1996
@@ -3,8 +3,9 @@
  * sound/pas2_pcm.c
  *
  * The low level driver for the Pro Audio Spectrum ADC/DAC.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -25,8 +26,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -53,6 +55,7 @@
 static unsigned char pcm_mode = PCM_NON;
 static unsigned long pcm_count = 0;
 static unsigned short pcm_bitsok = 8;	/* mask of OK bits */
+static int      pcm_busy = 0;
 static int      my_devnum = 0;
 
 int
@@ -66,11 +69,16 @@
   if (arg < 5000)
     arg = 5000;
 
-  foo = (1193180 + (arg / 2)) / arg;
-  arg = 1193180 / foo;
-
   if (pcm_channels & 2)
-    foo = foo >> 1;
+    {
+      foo = (596590 + (arg / 2)) / arg;
+      arg = 596590 / foo;
+    }
+  else
+    {
+      foo = (1193180 + (arg / 2)) / arg;
+      arg = 1193180 / foo;
+    }
 
   pcm_speed = arg;
 
@@ -152,7 +160,7 @@
 }
 
 static int
-pas_pcm_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
+pas_pcm_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
   TRACE (printk ("pas2_pcm.c: static int pas_pcm_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
 
@@ -230,9 +238,21 @@
 pas_pcm_open (int dev, int mode)
 {
   int             err;
+  unsigned long   flags;
 
   TRACE (printk ("pas2_pcm.c: static int pas_pcm_open(int mode = %X)\n", mode));
 
+  save_flags (flags);
+  cli ();
+  if (pcm_busy)
+    {
+      restore_flags (flags);
+      return -EBUSY;
+    }
+
+  pcm_busy = 1;
+  restore_flags (flags);
+
   if ((err = pas_set_intr (PAS_PCM_INTRBITS)) < 0)
     return err;
 
@@ -256,6 +276,7 @@
   pas_remove_intr (PAS_PCM_INTRBITS);
   pcm_mode = PCM_NON;
 
+  pcm_busy = 0;
   restore_flags (flags);
 }
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/patmgr.c linux/drivers/sound/patmgr.c
--- v1.3.62/linux/drivers/sound/patmgr.c	Tue Jan 23 21:15:47 1996
+++ linux/drivers/sound/patmgr.c	Sat Feb 10 22:04:58 1996
@@ -2,8 +2,9 @@
  * sound/patmgr.c
  *
  * The patch maneger interface for the /dev/sequencer
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #define PATMGR_C
 #include "sound_config.h"
@@ -91,7 +93,7 @@
 }
 
 int
-pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+pmgr_read (int dev, struct fileinfo *file, char *buf, int count)
 {
   unsigned long   flags;
   int             ok = 0;
@@ -133,7 +135,7 @@
 }
 
 int
-pmgr_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
+pmgr_write (int dev, struct fileinfo *file, const char *buf, int count)
 {
   unsigned long   flags;
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/pss.c linux/drivers/sound/pss.c
--- v1.3.62/linux/drivers/sound/pss.c	Tue Jan 23 21:15:48 1996
+++ linux/drivers/sound/pss.c	Sat Feb 10 22:05:01 1996
@@ -2,8 +2,9 @@
  * sound/pss.c
  *
  * The low level driver for the Personal Sound System (ECHO ESC614).
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -77,7 +79,7 @@
     int             base;
     int             irq;
     int             dma;
-    sound_os_info  *osp;
+    int            *osp;
   }
 
 pss_config;
@@ -489,7 +491,7 @@
 }
 
 static int
-pss_coproc_ioctl (void *dev_info, unsigned int cmd, ioctl_arg arg, int local)
+pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
 {
   /* printk("PSS coproc ioctl %x %x %d\n", cmd, arg, local); */
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/pss.h linux/drivers/sound/pss.h
--- v1.3.62/linux/drivers/sound/pss.h	Mon Jul 18 09:50:55 1994
+++ linux/drivers/sound/pss.h	Thu Jan  1 02:00:00 1970
@@ -1,371 +0,0 @@
-/******************************************************************************
-
-	def.h
-
-	Version 1.3	11/2/93
-
-	Copyright (c) 1993 Analog Devices Inc. All rights reserved
-
-******************************************************************************/
-/* Port offsets from base port for Sound Blaster DSP */
-#define DSP_PORT_CMSD0      0x00  /* C/MS music voice 1-6 data port, write only */
-#define DSP_PORT_CMSR0      0x01  /* C/MS music voice 1-6 register port, write only */
-#define DSP_PORT_CMSD1      0x02  /* C/MS music voice 7-12 data port, write only */
-#define DSP_PORT_CMSR1      0x03  /* C/MS music voice 7-12 register port, write only */
-
-#define DSP_PORT_STATUS     0x04  /* DSP Status bits, read only */
-#define DSP_PORT_CONTROL    0x04  /* DSP Control bits, write only */
-#define DSP_PORT_DATA_LSB   0x05  /* Read or write LSB of 16 bit data */
-
-
-#define DSP_PORT_RESET      0x06  /* DSP Reset, write only */
-#define DSP_PORT_07h        0x07  /* reserved port */
-
-#define DSP_PORT_FMD0       0x08  /* FM music data/status port, read/write  */
-#define DSP_PORT_FMR0       0x09  /* FM music data/status port, write only */
-
-#define DSP_PORT_RDDATA     0x0A  /* DSP Read data, read only reading signals DSP */
-#define DSP_PORT_0Bh        0x0B  /* reserved port */
-#define DSP_PORT_WRDATA     0x0C  /* DSP Write data or command, write */
-#define DSP_PORT_WRBUSY     0x0C  /* DSP Write buffer status (bit 7), read */
-#define DSP_PORT_0Dh        0x0D  /* reserved port */
-#define DSP_PORT_DATAAVAIL  0x0E  /* DSP Data available status (bit 7), read only */
-#define DSP_PORT_INTERFACE  0x0E  /* Sets DMA Channel and Interrupt, write only */
-#define DSP_PORT_0Fh        0x0F  /* reserved port (used on Pro cards) */
-
-#define ADDR_MASK   0x003f
-
-#define INT_MASK    0xffc7
-#define INT_3_BITS  0x0008
-#define INT_5_BITS  0x0010
-#define INT_7_BITS  0x0018
-#define INT_9_BITS  0x0020
-#define INT_10_BITS 0x0028
-#define INT_11_BITS 0x0030
-#define INT_12_BITS 0x0038
-
-#define GAME_BIT      0x0400
-#define GAME_BIT_MASK 0xfbff
-
-#define INT_TEST_BIT 0x0200
-#define INT_TEST_PASS 0x0100
-#define INT_TEST_BIT_MASK 0xFDFF
-
-#define DMA_MASK    0xfff8
-#define DMA_0_BITS  0x0001
-#define DMA_1_BITS  0x0002
-#define DMA_3_BITS  0x0003
-#define DMA_5_BITS  0x0004
-#define DMA_6_BITS  0x0005
-#define DMA_7_BITS  0x0006
-
-#define DMA_TEST_BIT  0x0080
-#define DMA_TEST_PASS 0x0040
-#define DMA_TEST_BIT_MASK 0xFF7F
-
-
-/* Echo DSP Flags */
-
-#define DSP_FLAG3     0x10
-#define DSP_FLAG2     0x08
-#define DSP_FLAG1     0x80
-#define DSP_FLAG0     0x40
-
-#define PSS_CONFIG    0x10
-#define PSS_WSS_CONFIG    0x12
-#define SB_CONFIG     0x14
-#define MIDI_CONFIG   0x18
-#define CD_CONFIG     0x16
-#define UART_CONFIG   0x1a
-
-#define PSS_DATA      0x00
-#define PSS_STATUS    0x02
-#define PSS_CONTROL   0x02
-#define PSS_ID_VERS   0x04
-
-#define PSS_FLAG3     0x0800
-#define PSS_FLAG2     0x0400
-#define PSS_FLAG1     0x1000
-#define PSS_FLAG0     0x0800
-
-/*_____ WSS defines */
-#define WSS_BASE_ADDRESS 0x530
-#define WSS_CONFIG       0x0
-#define WSS_VERSION      0x03
-#define WSS_SP0          0x04
-#define WSS_SP1          0x05
-#define WSS_SP2          0x06
-#define WSS_SP3          0x07
-
-/*_____ SoundPort register addresses */
-
-#define SP_LIN_SOURCE_CTRL   0x00
-#define SP_RIN_SOURCE_CTRL   0x01
-#define SP_LIN_GAIN_CTRL   0x10
-#define SP_RIN_GAIN_CTRL   0x11
-#define SP_LAUX1_CTRL      0x02
-#define SP_RAUX1_CTRL      0x03
-#define SP_LAUX2_CTRL      0x04
-#define SP_RAUX2_CTRL      0x05
-#define SP_LOUT_CTRL       0x06
-#define SP_ROUT_CTRL       0x07
-#define SP_CLK_FORMAT      0x48
-#define SP_INT_CONF        0x09
-#define SP_INT_CONF_MCE    0x49
-#define SP_PIN_CTRL        0x0a
-#define SP_TEST_INIT       0x0b
-#define SP_MISC_CTRL       0x0c
-#define SP_MIX_CTRL        0x0d
-#define SP_DMA_UCNT        0x0e
-#define SP_DMA_LCNT        0x0f
-
-/*_____ Gain constants  */
-
-#define GAIN_0      0x00
-#define GAIN_1_5    0x01
-#define GAIN_3      0x02
-#define GAIN_4_5    0x03
-#define GAIN_6      0x04
-#define GAIN_7_5    0x05
-#define GAIN_9      0x06
-#define GAIN_10_5   0x07
-#define GAIN_12     0x08
-#define GAIN_13_5   0x09
-#define GAIN_15     0x0a
-#define GAIN_16_5   0x0b
-#define GAIN_18     0x0c
-#define GAIN_19_5   0x0d
-#define GAIN_21     0x0e
-#define GAIN_22_5   0x0f
-#define MUTE       0XFFFF
-
-/*_____ Attenuation constants  */
-
-#define ATTEN_0      0x00
-#define ATTEN_1_5    0x01
-#define ATTEN_3      0x02
-#define ATTEN_4_5    0x03
-#define ATTEN_6      0x04
-#define ATTEN_7_5    0x05
-#define ATTEN_9      0x06
-#define ATTEN_10_5   0x07
-#define ATTEN_12     0x08
-#define ATTEN_13_5   0x09
-#define ATTEN_15     0x0a
-#define ATTEN_16_5   0x0b
-#define ATTEN_18     0x0c
-#define ATTEN_19_5   0x0d
-#define ATTEN_21     0x0e
-#define ATTEN_22_5   0x0f
-
-
-#define PSS_WRITE_EMPTY 0x8000
-
-#define CD_POL_MASK 0xFFBF
-#define CD_POL_BIT  0x0040
-
-
-
-/******************************************************************************
-
-	host.h
-
-	Version 1.2	9/27/93
-
-	Copyright (c) 1993 Analog Devices Inc. All rights reserved
-
-******************************************************************************/
-#define SB_WRITE_FULL    0x80
-#define SB_READ_FULL     0x80
-#define SB_WRITE_STATUS  0x0C
-#define SB_READ_STATUS   0x0E
-#define SB_READ_DATA     0x0A
-#define SB_WRITE_DATA    0x0C
-
-#define PSS_DATA_REG     0x00
-#define PSS_STATUS_REG   0x02
-#define PSS_WRITE_EMPTY  0x8000
-#define PSS_READ_FULL    0x4000
-
-/*_____ 1848 Sound Port bit defines */
-
-#define SP_IN_INIT            0x80
-#define MODE_CHANGE_ENABLE    0x40
-#define MODE_CHANGE_MASK      0xbf
-#define TRANSFER_DISABLE      0x20
-#define TRANSFER_DISABLE_MASK 0xdf
-#define ADDRESS_MASK          0xf0
-
-/*_____ Status bits */
-#define INTERRUPT_STATUS      0x01
-#define PLAYBACK_READY        0x02
-#define PLAYBACK_LEFT         0x04
-/*_____ pbright is not left */
-#define PLAYBACK_UPPER        0x08
-/*_____ bplower is not upper */
-
-#define SAMPLE_OVERRUN        0x10
-#define SAMPLE_UNDERRUN       0x10
-#define CAPTURE_READY         0x20
-#define CAPTURE_LEFT          0x40
-/*_____ cpright is not left */
-#define CAPTURE_UPPER         0x08
-/*_____ cplower is not upper */
-
-/*_____ Input & Output regs bits */
-#define LINE_INPUT            0x80
-#define AUX_INPUT             0x40
-#define MIC_INPUT             0x80
-#define MIXED_DAC_INPUT       0xC0
-#define INPUT_GAIN_MASK       0xf0
-#define INPUT_MIC_GAIN_ENABLE 0x20
-#define INPUT_MIC_GAIN_MASK   0xdf
-#define INPUT_SOURCE_MASK     0x3f
-#define AUX_INPUT_ATTEN_MASK  0xf0
-#define AUX_INPUT_MUTE        0x80
-#define AUX_INPUT_MUTE_MASK   0x7f
-#define OUTPUT_MUTE           0x80
-#define OUTPUT_MUTE_MASK      0x7f
-#define OUTPUT_ATTEN_MASK     0xc0
-
-/*_____ Clock and Data format reg bits */
-#define CLOCK_SELECT_MASK     0xfe
-#define CLOCK_XTAL2           0x01
-#define CLOCK_XTAL1           0x00
-#define CLOCK_FREQ_MASK       0xf1
-#define STEREO_MONO_MASK      0xef
-#define STEREO                0x10
-#define AUDIO_MONO            0x00
-#define LINEAR_COMP_MASK      0xdf
-#define LINEAR                0x00
-#define COMPANDED             0x20
-#define FORMAT_MASK           0xbf
-#define PCM                   0x00
-#define ULAW                  0x00
-#define TWOS_COMP             0x40
-#define ALAW                  0x40
-
-/*_____ Interface Configuration reg bits */
-#define PLAYBACK_ENABLE       0x01
-#define PLAYBACK_ENABLE_MASK  0xfe
-#define CAPTURE_ENABLE        0x02
-#define CAPTURE_ENABLE_MASK   0xfd
-#define SINGLE_DMA            0x04
-#define SINGLE_DMA_MASK       0xfb
-#define DUAL_DMA              0x00
-#define AUTO_CAL_ENABLE       0x08
-#define AUTO_CAL_DISABLE_MASK 0xf7
-#define PLAYBACK_PIO_ENABLE   0x40
-#define PLAYBACK_DMA_MASK     0xbf
-#define CAPTURE_PIO_ENABLE    0x80
-#define CAPTURE_DMA_MASK      0x7f
-
-/*_____ Pin control bits */
-#define INTERRUPT_ENABLE      0x02
-#define INTERRUPT_MASK        0xfd
-
-/*_____ Test and init reg bits */
-#define OVERRANGE_LEFT_MASK   0xfc
-#define OVERRANGE_RIGHT_MASK  0xf3
-#define DATA_REQUEST_STATUS   0x10
-#define AUTO_CAL_IN_PROG      0x20
-#define PLAYBACK_UNDERRUN     0x40
-#define CAPTURE_UNDERRUN      0x80
-
-/*_____ Miscellaneous Control reg bits */
-#define ID_MASK               0xf0
-
-/*_____ Digital Mix Control reg bits */
-#define DIGITAL_MIX1_MUTE_MASK 0xfe
-#define MIX_ATTEN_MASK         0x03
-
-/*_____ 1848 Sound Port reg defines */
-
-#define SP_LEFT_INPUT_CONTROL    0x0
-#define SP_RIGHT_INPUT_CONTROL   0x1
-#define SP_LEFT_AUX1_CONTROL     0x2
-#define SP_RIGHT_AUX1_CONTROL    0x3
-#define SP_LEFT_AUX2_CONTROL     0x4
-#define SP_RIGHT_AUX2_CONTROL    0x5
-#define SP_LEFT_OUTPUT_CONTROL   0x6
-#define SP_RIGHT_OUTPUT_CONTROL  0x7
-#define SP_CLOCK_DATA_FORMAT     0x8
-#define SP_INTERFACE_CONFIG      0x9
-#define SP_PIN_CONTROL           0xA
-#define SP_TEST_AND_INIT         0xB
-#define SP_MISC_INFO             0xC
-#define SP_DIGITAL_MIX           0xD
-#define SP_UPPER_BASE_COUNT      0xE
-#define SP_LOWER_BASE_COUNT      0xF
-
-#define HOST_SP_ADDR (0x534)
-#define HOST_SP_DATA (0x535)
-
-
-/******************************************************************************
-
-	phillips.h
-
-	Version 1.2	9/27/93
-
-	Copyright (c) 1993 Analog Devices Inc. All rights reserved
-
-******************************************************************************/
-/*_____ Phillips control SW defines */
-
-/*_____ Settings and ranges */
-#define VOLUME_MAX   6
-#define VOLUME_MIN (-64)
-#define VOLUME_RANGE 70
-#define VOLUME_STEP  2
-#define BASS_MAX    15
-#define BASS_MIN   (-12)
-#define BASS_STEP    2
-#define BASS_RANGE 27
-#define TREBLE_MAX  12
-#define TREBLE_MIN (-12)
-#define TREBLE_STEP  2
-#define TREBLE_RANGE 24
-
-#define VOLUME_CONSTANT 252
-#define BASS_CONSTANT   246
-#define TREBLE_CONSTANT 246
-
-/*_____ Software commands */
-#define SET_MASTER_COMMAND  0x0010
-#define MASTER_VOLUME_LEFT  0x0000
-#define MASTER_VOLUME_RIGHT 0x0100
-#define MASTER_BASS         0x0200
-#define MASTER_TREBLE       0x0300
-#define MASTER_SWITCH       0x0800
-
-#define STEREO_MODE  0x00ce
-#define PSEUDO_MODE  0x00d6
-#define SPATIAL_MODE 0x00de
-#define MONO_MODE    0x00c6
-
-
-#define PSS_STEREO           0x00ce
-#define PSS_PSEUDO           0x00d6
-#define PSS_SPATIAL          0x00de
-#define PSS_MONO             0x00c6
-
-#define PHILLIPS_VOL_MIN          -64
-#define PHILLIPS_VOL_MAX            6
-#define PHILLIPS_VOL_DELTA         70
-#define PHILLIPS_VOL_INITIAL      -20
-#define PHILLIPS_VOL_CONSTANT     252
-#define PHILLIPS_VOL_STEP           2
-#define PHILLIPS_BASS_MIN         -12
-#define PHILLIPS_BASS_MAX          15
-#define PHILLIPS_BASS_DELTA        27
-#define PHILLIPS_BASS_INITIAL       0
-#define PHILLIPS_BASS_CONSTANT    246
-#define PHILLIPS_BASS_STEP          2
-#define PHILLIPS_TREBLE_MIN       -12
-#define PHILLIPS_TREBLE_MAX        12
-#define PHILLIPS_TREBLE_DELTA      24
-#define PHILLIPS_TREBLE_INITIAL     0
-#define PHILLIPS_TREBLE_CONSTANT  246
-#define PHILLIPS_TREBLE_STEP        2
-
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sb16_dsp.c linux/drivers/sound/sb16_dsp.c
--- v1.3.62/linux/drivers/sound/sb16_dsp.c	Fri Jan 26 01:37:07 1996
+++ linux/drivers/sound/sb16_dsp.c	Sat Feb 10 22:05:02 1996
@@ -2,10 +2,9 @@
  * sound/sb16_dsp.c
  *
  * The low level driver for the SoundBlaster DSP chip.
- *
- * (C) 1993 J. Schubert (jsb@sth.ruhr-uni-bochum.de)
- *
- * based on SB-driver by (C) Hannu Savolainen
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -26,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #define DEB(x)
 #define DEB1(x)
@@ -41,7 +41,7 @@
 #if defined(CONFIG_SB) && defined(CONFIG_AUDIO)
 
 extern int      sbc_base;
-extern sound_os_info *sb_osp;
+extern int     *sb_osp;
 
 static int      sb16_dsp_ok = 0;
 static int      dsp_16bit = 0;
@@ -61,7 +61,7 @@
 static void     sb16_dsp_close (int dev);
 static void     sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
 static void     sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
-static int      sb16_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local);
+static int      sb16_dsp_ioctl (int dev, unsigned int cmd, caddr_t arg, int local);
 static int      sb16_dsp_prepare_for_input (int dev, int bsize, int bcount);
 static int      sb16_dsp_prepare_for_output (int dev, int bsize, int bcount);
 static void     sb16_dsp_reset (int dev);
@@ -151,7 +151,7 @@
 }
 
 static int
-sb16_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
+sb16_dsp_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
   switch (cmd)
     {
@@ -250,7 +250,7 @@
   save_flags (flags);
   cli ();
 
-  audio_devs[dev]->dmachan1 = dma8;
+  audio_devs[dev]->dmachan1 = audio_devs[dev]->dmachan2 = dma8;
 
   if (dma16 != dma8)
     sound_close_dma (dma16);
@@ -285,22 +285,6 @@
     cnt >>= 1;
   cnt--;
 
-#ifdef DEB_DMARES
-  printk ("output_block: %x %d %d\n", buf, count, intrflag);
-  if (intrflag)
-    {
-      int             pos, chan = audio_devs[dev]->dmachan;
-
-      save_flags (flags);
-      cli ();
-      clear_dma_ff (chan);
-      disable_dma (chan);
-      pos = get_dma_residue (chan);
-      enable_dma (chan);
-      restore_flags (flags);
-      printk ("dmapos=%d %x\n", pos, pos);
-    }
-#endif
   if (audio_devs[dev]->flags & DMA_AUTOMODE &&
       intrflag &&
       cnt == dsp_count)
@@ -354,22 +338,6 @@
     cnt >>= 1;
   cnt--;
 
-#ifdef DEB_DMARES
-  printk ("start_input: %x %d %d\n", buf, count, intrflag);
-  if (intrflag)
-    {
-      int             pos, chan = audio_devs[dev]->dmachan;
-
-      save_flags (flags);
-      cli ();
-      clear_dma_ff (chan);
-      disable_dma (chan);
-      pos = get_dma_residue (chan);
-      enable_dma (chan);
-      restore_flags (flags);
-      printk ("dmapos=%d %x\n", pos, pos);
-    }
-#endif
   if (audio_devs[dev]->flags & DMA_AUTOMODE &&
       intrflag &&
       cnt == dsp_count)
@@ -385,13 +353,14 @@
 
   if (dma_restart)
     {
-      sb_reset_dsp ();
+      sb16_dsp_halt (dev);
       DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
     }
 
   sb_dsp_command (0x42);
   sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff));
   sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff));
+
   sb_dsp_command ((unsigned char) (dsp_16bit ? 0xbe : 0xce));
   dsp_count = cnt;
   sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) +
@@ -407,22 +376,24 @@
 static int
 sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
 {
-  audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
+  audio_devs[my_dev]->dmachan1 =
+    audio_devs[my_dev]->dmachan2 =
+    dsp_16bit ? dma16 : dma8;
   dsp_count = 0;
   dsp_cleanup ();
   trigger_bits = 0;
-  sb_dsp_command (0xd4);
   return 0;
 }
 
 static int
 sb16_dsp_prepare_for_output (int dev, int bsize, int bcount)
 {
-  audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
+  audio_devs[my_dev]->dmachan1 =
+    audio_devs[my_dev]->dmachan2 =
+    dsp_16bit ? dma16 : dma8;
   dsp_count = 0;
   dsp_cleanup ();
   trigger_bits = 0;
-  sb_dsp_command (0xd4);
   return 0;
 }
 
@@ -432,19 +403,23 @@
   trigger_bits = bits;
 
   if (!bits)
-    sb_dsp_command (0xd0);	/* Halt DMA */
+    {
+      sb_dsp_command (0xd0);	/* Halt DMA */
+    }
   else if (bits & irq_mode)
     switch (irq_mode)
       {
       case IMODE_INPUT:
 	actually_start_input (my_dev, trg_buf, trg_bytes,
 			      trg_intrflag, trg_restart);
+
 	break;
 
       case IMODE_OUTPUT:
 	actually_output_block (my_dev, trg_buf, trg_bytes,
 			       trg_intrflag, trg_restart);
 	break;
+
       }
 }
 
@@ -526,7 +501,7 @@
   if (num_audiodevs < MAX_AUDIO_DEV)
     {
       audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations;
-      audio_devs[my_dev]->dmachan1 = dma8;
+      audio_devs[my_dev]->dmachan1 = audio_devs[my_dev]->dmachan2 = dma8;
       audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
 
       if (sound_alloc_dma (dma8, "SB16 (8bit)"))
@@ -560,6 +535,7 @@
   if (Jazz16_detected)
     {
       Jazz16_set_dma16 (hw_config->dma);
+      sb16_dsp_ok = 1;
       return 0;
     }
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sb16_midi.c linux/drivers/sound/sb16_midi.c
--- v1.3.62/linux/drivers/sound/sb16_midi.c	Tue Jan 23 21:15:48 1996
+++ linux/drivers/sound/sb16_midi.c	Sat Feb 10 22:05:02 1996
@@ -2,8 +2,9 @@
  * sound/sb16_midi.c
  *
  * The low level driver for the MPU-401 UART emulation of the SB16.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -37,14 +39,31 @@
 #define	COMDPORT   (sb16midi_base+1)
 #define	STATPORT   (sb16midi_base+1)
 
-extern sound_os_info *sb_osp;
+extern int     *sb_osp;
+static int      sb16midi_base = 0x330;
 
-#define sb16midi_status()		inb( STATPORT)
+static int 
+sb16midi_status (void)
+{
+  return inb (STATPORT);
+}
 #define input_avail()		(!(sb16midi_status()&INPUT_AVAIL))
 #define output_ready()		(!(sb16midi_status()&OUTPUT_READY))
-#define sb16midi_cmd(cmd)		outb( cmd,  COMDPORT)
-#define sb16midi_read()		inb( DATAPORT)
-#define sb16midi_write(byte)	outb( byte,  DATAPORT)
+static void 
+sb16midi_cmd (unsigned char cmd)
+{
+  outb (cmd, COMDPORT);
+}
+static int 
+sb16midi_read (void)
+{
+  return inb (DATAPORT);
+}
+static void 
+sb16midi_write (unsigned char byte)
+{
+  outb (byte, DATAPORT);
+}
 
 #define	OUTPUT_READY	0x40
 #define	INPUT_AVAIL	0x80
@@ -53,7 +72,6 @@
 #define	UART_MODE_ON	0x3F
 
 static int      sb16midi_opened = 0;
-static int      sb16midi_base = 0x330;
 static int      sb16midi_detected = 0;
 static int      my_dev;
 extern int      sbc_base;
@@ -168,7 +186,7 @@
 }
 
 static int
-sb16midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
+sb16midi_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
   return -EINVAL;
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v1.3.62/linux/drivers/sound/sb_card.c	Tue Jan 23 21:15:48 1996
+++ linux/drivers/sound/sb_card.c	Sat Feb 10 22:05:02 1996
@@ -2,8 +2,9 @@
  * sound/sb_card.c
  *
  * Detection routine for the SoundBlaster cards.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,11 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- * Modified:
- *  Riccardo Facchetti  24 Mar 1995
- *  - Added the Audio Excel DSP 16 initialization routine.
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -59,12 +58,6 @@
       return 0;
     }
 
-#if defined(CONFIG_AEDSP16) && defined(AEDSP16_SBPRO)
-  /*
-     * Initialize Audio Excel DSP 16 to SBPRO.
-   */
-  InitAEDSP16_SBPRO (hw_config);
-#endif
   return sb_dsp_detect (hw_config);
 }
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sb_dsp.c linux/drivers/sound/sb_dsp.c
--- v1.3.62/linux/drivers/sound/sb_dsp.c	Wed Feb  7 15:11:29 1996
+++ linux/drivers/sound/sb_dsp.c	Sat Feb 10 22:05:04 1996
@@ -2,8 +2,9 @@
  * sound/sb_dsp.c
  *
  * The low level driver for the SoundBlaster DSP chip (SB1.0 to 2.1, SB Pro).
- *
- * Copyright by Hannu Savolainen 1994
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,7 +25,10 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
+ */
+#include <linux/config.h>
+
+/*
  * Modified:
  *      Hunyue Yau      Jan 6 1994
  *      Added code to support Sound Galaxy NX Pro
@@ -102,9 +106,8 @@
 static int      dsp_speed (int);
 static int      dsp_set_stereo (int mode);
 static void     sb_dsp_reset (int dev);
-sound_os_info  *sb_osp = NULL;
-
-static void     ess_init (void);
+static void     dsp_get_vers (struct address_info *hw_config);
+int            *sb_osp = NULL;
 
 #if defined(CONFIG_MIDI) || defined(CONFIG_AUDIO)
 
@@ -478,7 +481,7 @@
 
   if (AudioDrive)
     {
-      int             c = 0x10000 - count;	/* ES1688 increments the count */
+      int             c = 0xffff - nr_bytes;	/* ES1688 increments the count */
 
       ess_write (0xa4, (unsigned char) (c & 0xff));
       ess_write (0xa5, (unsigned char) ((c >> 8) & 0xff));
@@ -525,6 +528,11 @@
 sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
 		    int restart_dma)
 {
+  if (sb_no_recording)
+    {
+      return;
+    }
+
   trg_buf = buf;
   trg_bytes = count;
   trg_intrflag = intrflag;
@@ -533,14 +541,14 @@
 }
 
 static void
-actually_start_input (int dev, unsigned long buf, int count, int intrflag,
+actually_start_input (int dev, unsigned long buf, int nr_bytes, int intrflag,
 		      int restart_dma)
 {
   unsigned long   flags;
+  int             count = nr_bytes;
 
   if (sb_no_recording)
     {
-      printk ("SB Error: This device doesn't support recording\n");
       return;
     }
 
@@ -563,7 +571,7 @@
 
   if (AudioDrive)
     {
-      int             c = 0x10000 - count;	/* ES1688 increments the count */
+      int             c = 0xffff - nr_bytes;	/* ES1688 increments the count */
 
       ess_write (0xa4, (unsigned char) (c & 0xff));
       ess_write (0xa5, (unsigned char) ((c >> 8) & 0xff));
@@ -641,6 +649,12 @@
 static int
 sb_dsp_prepare_for_input (int dev, int bsize, int bcount)
 {
+  if (sb_no_recording)
+    {
+      printk ("SB Error: This device doesn't support recording\n");
+      return 0;
+    }
+
   dsp_cleanup ();
   dsp_speaker (OFF);
 
@@ -651,7 +665,6 @@
       if (AudioDrive)
 	{
 
-	  /* ess_init(); */
 	  ess_write (0xb8, 0x0e);	/* Auto init DMA mode */
 	  ess_write (0xa8, (ess_read (0xa8) & ~0x04) |
 		     (2 - dsp_stereo));		/* Mono/stereo */
@@ -693,7 +706,9 @@
 	  /* Select correct dma channel
 	     * for 16/8 bit acccess
 	   */
-	  audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
+	  audio_devs[my_dev]->dmachan1 =
+	    audio_devs[my_dev]->dmachan2 =
+	    dsp_16bit ? dma16 : dma8;
 	  if (dsp_stereo)
 	    sb_dsp_command (dsp_16bit ? 0xac : 0xa8);
 	  else
@@ -718,7 +733,6 @@
       if (AudioDrive)
 	{
 
-	  /* ess_init(); */
 	  ess_write (0xb8, 4);	/* Auto init DMA mode */
 	  ess_write (0xa8, ess_read (0xa8) |
 		     (2 - dsp_stereo));		/* Mono/stereo */
@@ -763,7 +777,9 @@
 
 	  /* 16 bit specific instructions (Jazz16)
 	   */
-	  audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
+	  audio_devs[my_dev]->dmachan1 =
+	    audio_devs[my_dev]->dmachan2 =
+	    dsp_16bit ? dma16 : dma8;
 	  if (Jazz16_detected != 2)	/* SM Wave */
 	    sb_mixer_set_stereo (dsp_stereo);
 	  if (dsp_stereo)
@@ -828,7 +844,9 @@
 
   /* Allocate 8 bit dma
    */
-  audio_devs[my_dev]->dmachan1 = dma8;
+  audio_devs[my_dev]->dmachan1 =
+    audio_devs[my_dev]->dmachan2 =
+    dma8;
 
   /* Allocate 16 bit dma (jazz16)
    */
@@ -858,7 +876,9 @@
    */
   if (Jazz16_detected)
     {
-      audio_devs[my_dev]->dmachan1 = dma8;
+      audio_devs[my_dev]->dmachan1 =
+	audio_devs[my_dev]->dmachan2 =
+	dma8;
 
       if (dma16 != dma8)
 	sound_close_dma (dma16);
@@ -897,7 +917,7 @@
 }
 
 static int
-sb_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
+sb_dsp_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
   switch (cmd)
     {
@@ -1137,7 +1157,7 @@
   /*
      *  Make the OPL4 chip visible on the PC bus at 0x380.
      *
-     *  There is no need to enable this feature since VoxWare
+     *  There is no need to enable this feature since this driver
      *  doesn't support OPL4 yet. Also there is no RAM in SM Wave so
      *  enabling OPL4 is pretty useless.
    */
@@ -1205,7 +1225,16 @@
 				 */
   dma8 = dma16 = hw_config->dma;
 
-  if (!initialize_ProSonic16 ())
+  if (sb_reset_dsp ())
+    dsp_get_vers (hw_config);
+  else
+    sbc_major = 0;
+
+  if (sbc_major == 3 || sbc_major == 0)
+    if (initialize_ProSonic16 ())
+      return 1;
+
+  if (!sb_reset_dsp ())
     return 0;
 
   return 1;			/*
@@ -1239,12 +1268,15 @@
 #endif
 
 static void
-ess_init (void)			/* ESS1688 Initialization */
+ess_init (int ess_minor)	/* ESS1688 Initialization */
 {
   unsigned char   cfg, irq_bits = 0, dma_bits = 0;
 
   AudioDrive = 1;
-  midi_disabled = 1;
+  sb_no_recording = 1;		/* Temporary kludge */
+
+  if (ess_minor >= 8)		/* ESS1688 doesn't support SB MIDI */
+    midi_disabled = 1;
 
   sb_reset_dsp ();		/* Turn on extended mode */
 
@@ -1366,10 +1398,16 @@
 void
 Jazz16_midi_init (struct address_info *hw_config)
 {
+  extern void     smw_mixer_init (void);
+  extern void     sb_mixer_reset (void);
+
   mpu_base = hw_config->io_base;
   mpu_irq = hw_config->irq;
 
   initialize_ProSonic16 ();
+
+  smw_mixer_init ();
+  sb_mixer_reset ();
 }
 
 void
@@ -1377,6 +1415,17 @@
 {
   dma16 = dma;
 
+/* Allocate 16 bit dma (Jazz16)
+ */
+  if (dma16 != dma8)
+    {
+      if (sound_alloc_dma (dma16, "Jazz16 16 bit"))
+	{
+	  printk ("Jazz16: Can't allocate 16 bit DMA channel\n");
+	  Jazz16_detected = 0;
+	  return;
+	}
+    }
   initialize_ProSonic16 ();
 }
 
@@ -1504,7 +1553,7 @@
 		       "ESS ES1688 AudioDrive (rev %d)",
 		       ess_minor & 0x0f);
 	      sb_dsp_operations.format_mask |= AFMT_S16_LE;
-	      ess_init ();
+	      ess_init (ess_minor);
 	    }
 	}
       else
@@ -1532,20 +1581,9 @@
 
 	audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
 	dma8 = audio_devs[my_dev]->dmachan1 = hw_config->dma;
-	audio_devs[my_dev]->dmachan2 = -1;
+	dma16 = audio_devs[my_dev]->dmachan2 = hw_config->dma;
 	if (sound_alloc_dma (hw_config->dma, "SoundBlaster"))
 	  printk ("sb_dsp.c: Can't allocate DMA channel\n");
-
-	/* Allocate 16 bit dma (Jazz16)
-	 */
-	if (Jazz16_detected != 0)
-	  if (dma16 != dma8)
-	    {
-	      if (sound_alloc_dma (dma16, "Jazz16 16 bit"))
-		{
-		  printk ("Jazz16: Can't allocate 16 bit DMA channel\n");
-		}
-	    }
       }
     else
       printk ("SB: Too many DSP devices available\n");
@@ -1562,6 +1600,7 @@
 #endif
 
   sb_dsp_ok = 1;
+  sb_reset_dsp ();
   return mem_start;
 }
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sb_midi.c linux/drivers/sound/sb_midi.c
--- v1.3.62/linux/drivers/sound/sb_midi.c	Tue Jan 23 21:15:48 1996
+++ linux/drivers/sound/sb_midi.c	Sat Feb 10 22:05:05 1996
@@ -2,8 +2,9 @@
  * sound/sb_dsp.c
  *
  * The low level driver for the SoundBlaster DS chips.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -61,7 +63,7 @@
 int             input_opened = 0;
 static int      my_dev;
 
-extern sound_os_info *sb_osp;
+extern int     *sb_osp;
 
 void            (*midi_input_intr) (int dev, unsigned char data);
 
@@ -192,7 +194,7 @@
 }
 
 static int
-sb_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
+sb_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
   return -EPERM;
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sb_mixer.c linux/drivers/sound/sb_mixer.c
--- v1.3.62/linux/drivers/sound/sb_mixer.c	Tue Jan 23 21:15:48 1996
+++ linux/drivers/sound/sb_mixer.c	Sat Feb 10 22:05:06 1996
@@ -3,8 +3,9 @@
  * sound/sb_mixer.c
  *
  * The low level mixer driver for the SoundBlaster Pro and SB16 cards.
- *
- * Copyright by Hannu Savolainen 1994
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -25,7 +26,10 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
+ */
+#include <linux/config.h>
+
+/*
  * Modified:
  *      Hunyue Yau      Jan 6 1994
  *      Added code to support the Sound Galaxy NX Pro mixer.
@@ -43,7 +47,7 @@
 
 extern int      sbc_base;
 extern int      Jazz16_detected;
-extern sound_os_info *sb_osp;
+extern int     *sb_osp;
 extern int      AudioDrive;
 
 static int      mixer_initialized = 0;
@@ -223,7 +227,7 @@
   0x00				/* SOUND_MIXER_LINE3 */
 };
 
-static void
+void
 smw_mixer_init (void)
 {
   int             i;
@@ -441,7 +445,7 @@
 }
 
 static int
-sb_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
+sb_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 {
   if (((cmd >> 8) & 0xff) == 'M')
     {
@@ -499,7 +503,7 @@
   sb_mixer_ioctl
 };
 
-static void
+void
 sb_mixer_reset (void)
 {
   int             i;
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sb_mixer.h linux/drivers/sound/sb_mixer.h
--- v1.3.62/linux/drivers/sound/sb_mixer.h	Tue Jan 23 21:15:48 1996
+++ linux/drivers/sound/sb_mixer.h	Sat Feb 10 22:04:24 1996
@@ -2,9 +2,10 @@
  * sound/sb_mixer.h
  * 
  * Definitions for the SB Pro and SB16 mixers
- * 
- * Copyright by Hannu Savolainen 1993
- * 
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
  * met: 1. Redistributions of source code must retain the above copyright
@@ -12,7 +13,7 @@
  * Redistributions in binary form must reproduce the above copyright notice,
  * this list of conditions and the following disclaimer in the documentation
  * and/or other materials provided with the distribution.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,7 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
+ */
+
+/*
  * Modified:
  *	Hunyue Yau	Jan 6 1994
  *	Added defines for the Sound Galaxy NX Pro mixer.
@@ -213,6 +216,7 @@
   0x4040,			/* Line1 */
   0x4040,			/* Line2 */
   0x1515			/* Line3 */
+};
 
 #else  /* If the user selected just plain SB Pro */
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c
--- v1.3.62/linux/drivers/sound/sequencer.c	Tue Jan 23 21:15:48 1996
+++ linux/drivers/sound/sequencer.c	Sat Feb 10 22:05:08 1996
@@ -2,8 +2,9 @@
  * sound/sequencer.c
  *
  * The sequencer personality manager.
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #define SEQUENCER_C
 #include "sound_config.h"
@@ -99,7 +101,7 @@
 #endif
 
 int
-sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+sequencer_read (int dev, struct fileinfo *file, char *buf, int count)
 {
   int             c = count, p = 0;
   int             ev_len;
@@ -132,7 +134,7 @@
 	if (pre_event_timeout)
 	  current_set_timeout (tl = jiffies + (pre_event_timeout));
 	else
-	  tl = 0xffffffff;
+	  tl = (unsigned long) -1;
 	midi_sleep_flag.mode = WK_SLEEP;
 	module_interruptible_sleep_on (&midi_sleeper);
 	if (!(midi_sleep_flag.mode & WK_WAKEUP))
@@ -174,7 +176,7 @@
 }
 
 void
-seq_copy_to_input (unsigned char *event, int len)
+seq_copy_to_input (unsigned char *event_rec, int len)
 {
   unsigned long   flags;
 
@@ -192,7 +194,7 @@
 
   save_flags (flags);
   cli ();
-  memcpy (&iqueue[iqtail * IEV_SZ], event, len);
+  memcpy (&iqueue[iqtail * IEV_SZ], event_rec, len);
   iqlen++;
   iqtail = (iqtail + 1) % SEQ_MAX_QUEUE;
 
@@ -210,7 +212,7 @@
 sequencer_midi_input (int dev, unsigned char data)
 {
   unsigned int    tstamp;
-  unsigned char   event[4];
+  unsigned char   event_rec[4];
 
   if (data == 0xfe)		/* Ignore active sensing */
     return;
@@ -224,16 +226,16 @@
       prev_input_time = tstamp;
     }
 
-  event[0] = SEQ_MIDIPUTC;
-  event[1] = data;
-  event[2] = dev;
-  event[3] = 0;
+  event_rec[0] = SEQ_MIDIPUTC;
+  event_rec[1] = data;
+  event_rec[2] = dev;
+  event_rec[3] = 0;
 
-  seq_copy_to_input (event, 4);
+  seq_copy_to_input (event_rec, 4);
 }
 
 void
-seq_input_event (unsigned char *event, int len)
+seq_input_event (unsigned char *event_rec, int len)
 {
   unsigned long   this_time;
 
@@ -250,19 +252,19 @@
       tmp_event[1] = TMR_WAIT_ABS;
       tmp_event[2] = 0;
       tmp_event[3] = 0;
-      *(unsigned long *) &tmp_event[4] = this_time;
+      *(unsigned int *) &tmp_event[4] = this_time;
 
       seq_copy_to_input (tmp_event, 8);
       prev_input_time = this_time;
     }
 
-  seq_copy_to_input (event, len);
+  seq_copy_to_input (event_rec, len);
 }
 
 int
-sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
+sequencer_write (int dev, struct fileinfo *file, const char *buf, int count)
 {
-  unsigned char   event[EV_SZ], ev_code;
+  unsigned char   event_rec[EV_SZ], ev_code;
   int             p = 0, c, ev_size;
   int             err;
   int             mode = file->mode & O_ACCMODE;
@@ -281,21 +283,21 @@
 
   while (c >= 4)
     {
-      memcpy_fromfs ((char *) event, &((buf)[p]), 4);
-      ev_code = event[0];
+      memcpy_fromfs ((char *) event_rec, &((buf)[p]), 4);
+      ev_code = event_rec[0];
 
       if (ev_code == SEQ_FULLSIZE)
 	{
 	  int             err;
 
-	  dev = *(unsigned short *) &event[2];
+	  dev = *(unsigned short *) &event_rec[2];
 	  if (dev < 0 || dev >= max_synthdev)
 	    return -ENXIO;
 
 	  if (!(synth_open_mask & (1 << dev)))
 	    return -ENXIO;
 
-	  err = synth_devs[dev]->load_patch (dev, *(short *) &event[0], buf, p + 4, c, 0);
+	  err = synth_devs[dev]->load_patch (dev, *(short *) &event_rec[0], buf, p + 4, c, 0);
 	  if (err < 0)
 	    return err;
 
@@ -319,7 +321,7 @@
 	      return count - c;
 	    }
 
-	  memcpy_fromfs ((char *) &event[4], &((buf)[p + 4]), 4);
+	  memcpy_fromfs ((char *) &event_rec[4], &((buf)[p + 4]), 4);
 
 	}
       else
@@ -332,13 +334,13 @@
 	  ev_size = 4;
 	}
 
-      if (event[0] == SEQ_MIDIPUTC)
+      if (event_rec[0] == SEQ_MIDIPUTC)
 	{
 
-	  if (!midi_opened[event[2]])
+	  if (!midi_opened[event_rec[2]])
 	    {
 	      int             mode;
-	      int             dev = event[2];
+	      int             dev = event_rec[2];
 
 	      if (dev >= max_mididev)
 		{
@@ -361,8 +363,8 @@
 
 	}
 
-      if (!seq_queue (event, (file->flags & (O_NONBLOCK) ?
-			      1 : 0)))
+      if (!seq_queue (event_rec, (file->flags & (O_NONBLOCK) ?
+				  1 : 0)))
 	{
 	  int             processed = count - c;
 
@@ -464,7 +466,7 @@
       break;
 
     case SEQ_CONTROLLER:
-      synth_devs[dev]->controller (dev, q[3], q[4], *(short *) &q[5]);
+      synth_devs[dev]->controller (dev, q[3], q[4], (short) (q[5] | (q[6] << 8)));
       break;
 
     case SEQ_VOLMODE:
@@ -511,13 +513,13 @@
 }
 
 static void
-seq_chn_voice_event (unsigned char *event)
+seq_chn_voice_event (unsigned char *event_rec)
 {
-  unsigned char   dev = event[1];
-  unsigned char   cmd = event[2];
-  unsigned char   chn = event[3];
-  unsigned char   note = event[4];
-  unsigned char   parm = event[5];
+  unsigned char   dev = event_rec[1];
+  unsigned char   cmd = event_rec[2];
+  unsigned char   chn = event_rec[3];
+  unsigned char   note = event_rec[4];
+  unsigned char   parm = event_rec[5];
   int             voice = -1;
 
   if ((int) dev > max_synthdev)
@@ -593,15 +595,15 @@
 }
 
 static void
-seq_chn_common_event (unsigned char *event)
+seq_chn_common_event (unsigned char *event_rec)
 {
-  unsigned char   dev = event[1];
-  unsigned char   cmd = event[2];
-  unsigned char   chn = event[3];
-  unsigned char   p1 = event[4];
+  unsigned char   dev = event_rec[1];
+  unsigned char   cmd = event_rec[2];
+  unsigned char   chn = event_rec[3];
+  unsigned char   p1 = event_rec[4];
 
-  /* unsigned char   p2 = event[5]; */
-  unsigned short  w14 = *(short *) &event[6];
+  /* unsigned char   p2 = event_rec[5]; */
+  unsigned short  w14 = *(short *) &event_rec[6];
 
   if ((int) dev > max_synthdev)
     return;
@@ -691,16 +693,16 @@
 }
 
 static int
-seq_timing_event (unsigned char *event)
+seq_timing_event (unsigned char *event_rec)
 {
-  unsigned char   cmd = event[1];
-  unsigned int    parm = *(int *) &event[4];
+  unsigned char   cmd = event_rec[1];
+  unsigned int    parm = *(int *) &event_rec[4];
 
   if (seq_mode == SEQ_2)
     {
       int             ret;
 
-      if ((ret = tmr->event (tmr_no, event)) == TIMER_ARMED)
+      if ((ret = tmr->event (tmr_no, event_rec)) == TIMER_ARMED)
 	{
 	  if ((SEQ_MAX_QUEUE - qlen) >= output_treshold)
 	    {
@@ -779,7 +781,7 @@
 
     case TMR_ECHO:
       if (seq_mode == SEQ_2)
-	seq_copy_to_input (event, 8);
+	seq_copy_to_input (event_rec, 8);
       else
 	{
 	  parm = (parm << 8 | SEQ_ECHO);
@@ -794,10 +796,10 @@
 }
 
 static void
-seq_local_event (unsigned char *event)
+seq_local_event (unsigned char *event_rec)
 {
-  unsigned char   cmd = event[1];
-  unsigned int    parm = *((unsigned int *) &event[4]);
+  unsigned char   cmd = event_rec[1];
+  unsigned int    parm = *((unsigned int *) &event_rec[4]);
 
   switch (cmd)
     {
@@ -812,11 +814,11 @@
 }
 
 static void
-seq_sysex_message (unsigned char *event)
+seq_sysex_message (unsigned char *event_rec)
 {
-  int             dev = event[1];
+  int             dev = event_rec[1];
   int             i, l = 0;
-  unsigned char  *buf = &event[2];
+  unsigned char  *buf = &event_rec[2];
 
   if ((int) dev > max_synthdev)
     return;
@@ -844,7 +846,7 @@
      *   1 = Timer armed. Suspend playback until timer callback.
      *   2 = MIDI output buffer full. Restore queue and suspend until timer
    */
-  unsigned long  *delay;
+  unsigned int   *delay;
 
   switch (q[0])
     {
@@ -862,7 +864,7 @@
       break;
 
     case SEQ_WAIT:
-      delay = (unsigned long *) q;	/*
+      delay = (unsigned int *) q;	/*
 					 * Bytes 1 to 3 are containing the *
 					 * delay in jiffies
 					 */
@@ -1270,7 +1272,7 @@
 	    if (HZ / 10)
 	      current_set_timeout (tl = jiffies + (HZ / 10));
 	    else
-	      tl = 0xffffffff;
+	      tl = (unsigned long) -1;
 	    seq_sleep_flag.mode = WK_SLEEP;
 	    module_interruptible_sleep_on (&seq_sleeper);
 	    if (!(seq_sleep_flag.mode & WK_WAKEUP))
@@ -1370,7 +1372,7 @@
 	if (HZ)
 	  current_set_timeout (tl = jiffies + (HZ));
 	else
-	  tl = 0xffffffff;
+	  tl = (unsigned long) -1;
 	seq_sleep_flag.mode = WK_SLEEP;
 	module_interruptible_sleep_on (&seq_sleeper);
 	if (!(seq_sleep_flag.mode & WK_WAKEUP))
@@ -1415,7 +1417,7 @@
 	if (4)
 	  current_set_timeout (tl = jiffies + (4));
 	else
-	  tl = 0xffffffff;
+	  tl = (unsigned long) -1;
 	seq_sleep_flag.mode = WK_SLEEP;
 	module_interruptible_sleep_on (&seq_sleeper);
 	if (!(seq_sleep_flag.mode & WK_WAKEUP))
@@ -1538,7 +1540,7 @@
 
 int
 sequencer_ioctl (int dev, struct fileinfo *file,
-		 unsigned int cmd, ioctl_arg arg)
+		 unsigned int cmd, caddr_t arg)
 {
   int             midi_dev, orig_dev;
   int             mode = file->mode & O_ACCMODE;
@@ -1749,14 +1751,14 @@
 
     case SNDCTL_SEQ_OUTOFBAND:
       {
-	struct seq_event_rec event;
+	struct seq_event_rec event_rec;
 	unsigned long   flags;
 
-	memcpy_fromfs ((char *) &event, &(((char *) arg)[0]), sizeof (event));
+	memcpy_fromfs ((char *) &event_rec, &(((char *) arg)[0]), sizeof (event_rec));
 
 	save_flags (flags);
 	cli ();
-	play_event (event.arr);
+	play_event (event_rec.arr);
 	restore_flags (flags);
 
 	return 0;
@@ -2048,15 +2050,27 @@
 sequencer_init (long mem_start)
 {
 
-  sequencer_ok = 1;
 
   queue = (unsigned char *) (sound_mem_blocks[sound_num_blocks] = kmalloc (SEQ_MAX_QUEUE * EV_SZ, GFP_KERNEL));
   if (sound_num_blocks < 1024)
     sound_num_blocks++;;
+  if (queue == NULL)
+    {
+      printk ("Sound: Can't allocate memory for sequencer output queue\n");
+      return mem_start;
+    }
+
 
   iqueue = (unsigned char *) (sound_mem_blocks[sound_num_blocks] = kmalloc (SEQ_MAX_QUEUE * IEV_SZ, GFP_KERNEL));
   if (sound_num_blocks < 1024)
     sound_num_blocks++;;
+  if (queue == NULL)
+    {
+      printk ("Sound: Can't allocate memory for sequencer input queue\n");
+      return mem_start;
+    }
+
+  sequencer_ok = 1;
 
   return mem_start;
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sound_calls.h linux/drivers/sound/sound_calls.h
--- v1.3.62/linux/drivers/sound/sound_calls.h	Tue Jan 23 21:15:48 1996
+++ linux/drivers/sound/sound_calls.h	Sat Feb 10 22:04:25 1996
@@ -10,7 +10,7 @@
 int DMAbuf_rmchars(int dev, int buff_no, int c);
 int DMAbuf_start_output(int dev, int buff_no, int l);
 int DMAbuf_set_count(int dev, int buff_no, int l);
-int DMAbuf_ioctl(int dev, unsigned int cmd, ioctl_arg arg, int local);
+int DMAbuf_ioctl(int dev, unsigned int cmd, caddr_t arg, int local);
 long DMAbuf_init(long mem_start);
 int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode);
 int DMAbuf_open_dma (int dev);
@@ -25,12 +25,12 @@
  *	System calls for /dev/dsp and /dev/audio
  */
 
-int audio_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int audio_write (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count);
+int audio_read (int dev, struct fileinfo *file, char *buf, int count);
+int audio_write (int dev, struct fileinfo *file, const char *buf, int count);
 int audio_open (int dev, struct fileinfo *file);
 void audio_release (int dev, struct fileinfo *file);
 int audio_ioctl (int dev, struct fileinfo *file,
-	   unsigned int cmd, ioctl_arg arg);
+	   unsigned int cmd, caddr_t arg);
 int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
 long audio_init (long mem_start);
 
@@ -40,12 +40,12 @@
  *	System calls for the /dev/sequencer
  */
 
-int sequencer_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count);
+int sequencer_read (int dev, struct fileinfo *file, char *buf, int count);
+int sequencer_write (int dev, struct fileinfo *file, const char *buf, int count);
 int sequencer_open (int dev, struct fileinfo *file);
 void sequencer_release (int dev, struct fileinfo *file);
 int sequencer_ioctl (int dev, struct fileinfo *file,
-	   unsigned int cmd, ioctl_arg arg);
+	   unsigned int cmd, caddr_t arg);
 int sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
 long sequencer_init (long mem_start);
 void sequencer_timer(unsigned long dummy);
@@ -60,12 +60,12 @@
  *	System calls for the /dev/midi
  */
 
-int MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count);
+int MIDIbuf_read (int dev, struct fileinfo *file, char *buf, int count);
+int MIDIbuf_write (int dev, struct fileinfo *file, const char *buf, int count);
 int MIDIbuf_open (int dev, struct fileinfo *file);
 void MIDIbuf_release (int dev, struct fileinfo *file);
 int MIDIbuf_ioctl (int dev, struct fileinfo *file,
-	   unsigned int cmd, ioctl_arg arg);
+	   unsigned int cmd, caddr_t arg);
 int MIDIbuf_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
 void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count);
 long MIDIbuf_init(long mem_start);
@@ -79,11 +79,11 @@
 
 /*	From soundcard.c	*/
 void soundcard_init(void);
-void tenmicrosec(sound_os_info *osp);
+void tenmicrosec(int *osp);
 void request_sound_timer (int count);
 void sound_stop_timer(void);
 int snd_ioctl_return(int *addr, int value);
-int snd_set_irq_handler (int interrupt_level, void(*hndlr)(int, struct pt_regs *), char *name, sound_os_info *osp);
+int snd_set_irq_handler (int interrupt_level, void(*hndlr)(int, struct pt_regs *), char *name, int *osp);
 void snd_release_irq(int vect);
 void sound_dma_malloc(int dev);
 void sound_dma_free(int dev);
@@ -91,12 +91,12 @@
 void conf_printf2(char *name, int base, int irq, int dma, int dma2);
 
 /*	From sound_switch.c	*/
-int sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int sound_write_sw (int dev, struct fileinfo *file, const snd_rw_buf *buf, int count);
+int sound_read_sw (int dev, struct fileinfo *file, char *buf, int count);
+int sound_write_sw (int dev, struct fileinfo *file, const char *buf, int count);
 int sound_open_sw (int dev, struct fileinfo *file);
 void sound_release_sw (int dev, struct fileinfo *file);
 int sound_ioctl_sw (int dev, struct fileinfo *file,
-	     unsigned int cmd, ioctl_arg arg);
+	     unsigned int cmd, caddr_t arg);
 
 /*	From sb_dsp.c	*/
 int sb_dsp_detect (struct address_info *hw_config);
@@ -130,8 +130,8 @@
 int sb_mixer_init(int major_model);
 
 /*	From opl3.c	*/
-int opl3_detect (int ioaddr, sound_os_info *osp);
-long opl3_init(long mem_start, int ioaddr, sound_os_info *osp);
+int opl3_detect (int ioaddr, int *osp);
+long opl3_init(long mem_start, int ioaddr, int *osp);
 
 /*	From sb_card.c	*/
 long attach_sb_card(long mem_start, struct address_info *hw_config);
@@ -177,7 +177,7 @@
 void gus_write8(int reg, unsigned int data);
 void guswave_dma_irq(void);
 void gus_delay(void);
-int gus_default_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg);
+int gus_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg);
 void gus_timer_command (unsigned int addr, unsigned int val);
 
 /*	From gus_midi.c */
@@ -199,8 +199,8 @@
 /*	From patmgr.c */
 int pmgr_open(int dev);
 void pmgr_release(int dev);
-int pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count);
-int pmgr_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count);
+int pmgr_read (int dev, struct fileinfo *file, char * buf, int count);
+int pmgr_write (int dev, struct fileinfo *file, const char * buf, int count);
 int pmgr_access(int dev, struct patmgr_info *rec);
 int pmgr_inform(int dev, int event, unsigned long parm1, unsigned long parm2,
 				    unsigned long parm3, unsigned long parm4);
@@ -213,10 +213,10 @@
 void sound_timer_syncinterval(unsigned int new_usecs);
 
 /*	From ad1848.c */
-void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, sound_os_info *osp);
+void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, int *osp);
 void ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma);
 
-int ad1848_detect (int io_base, int *flags, sound_os_info *osp);
+int ad1848_detect (int io_base, int *flags, int *osp);
 #define AD_F_CS4231	0x0001	/* Returned if a CS4232 (or compatible) detected */
 #define AD_F_CS4248	0x0001	/* Returned if a CS4248 (or compatible) detected */
 
@@ -241,12 +241,12 @@
 int probe_ss_ms_sound (struct address_info *hw_config);
 long attach_ss_ms_sound(long mem_start, struct address_info * hw_config);
 
-int pss_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
-int pss_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
+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, ioctl_arg arg);
+	   unsigned int cmd, caddr_t arg);
 int pss_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
 long pss_init(long mem_start);
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sound_config.h linux/drivers/sound/sound_config.h
--- v1.3.62/linux/drivers/sound/sound_config.h	Tue Jan 23 21:15:48 1996
+++ linux/drivers/sound/sound_config.h	Sat Feb 10 22:04:25 1996
@@ -1,33 +1,32 @@
 /* sound_config.h
  *
  * A driver for Soundcards, misc configuration parameters.
- *
- * 
- * Copyright by Hannu Savolainen 1995
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
 
+
 #include "os.h"
 #include "local.h"
 #include "soundvers.h"
@@ -144,7 +143,7 @@
 	char *name;
 	int driver_use_1;	/* Driver defined field 1 */
 	int driver_use_2;	/* Driver defined field 2 */
-	sound_os_info *osp;	/* OS spesific info */
+	int *osp;	/* OS spesific info */
 	int card_subtype;	/* Driver spesific. Usually 0 */
 };
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sound_pnp.c linux/drivers/sound/sound_pnp.c
--- v1.3.62/linux/drivers/sound/sound_pnp.c	Tue Jan 23 21:15:48 1996
+++ linux/drivers/sound/sound_pnp.c	Thu Jan  1 02:00:00 1970
@@ -1,203 +0,0 @@
-/*
- * sound/sound_pnp.c
- *
- * PnP soundcard support (Linux spesific)
- *
- * Copyright by Hannu Savolainen 1995
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer. 2.
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-#include "sound_config.h"
-
-#if defined(CONFIG_PNP)
-
-#include <linux/pnp.h>
-
-static struct pnp_sounddev *pnp_devs[20] =
-{
-  NULL
-};
-
-static int      max_pnpdevs = 20;
-static int      nr_pnpdevs = 0;
-static int      pnp_sig = 0;
-
-void
-install_pnp_sounddrv (struct pnp_sounddev *drv)
-{
-  if (nr_pnpdevs < max_pnpdevs)
-    {
-      pnp_devs[nr_pnpdevs++] = drv;
-    }
-  else
-    printk ("Sound: More than 20 PnP drivers defined\n");
-}
-
-void
-cs4232_pnp (void *parm)
-{
-  struct pnp_dev *dev = (struct pnp_dev *) parm;
-  char           *name;
-
-  int             portmask = 0x00, irqmask = 0x01, dmamask = 0x03;
-  int             opl3_driver, wss_driver;
-
-  printk ("CS4232 driver waking up\n");
-
-  if (dev->card && dev->card->name)
-    name = dev->card->name;
-  else
-    name = "PnP WSS";
-
-  if ((wss_driver = sndtable_identify_card ("AD1848")))
-    portmask |= 0x01;		/* MSS */
-  else
-    printk ("Sound: MSS/WSS device detected but no driver enabled\n");
-
-  if ((opl3_driver = sndtable_identify_card ("OPL3")))
-    portmask |= 0x02;		/* OPL3 */
-  else
-    printk ("Sound: OPL3/4 device detected but no driver enabled\n");
-
-  printk ("WSS driver %d, OPL3 driver %d\n", wss_driver, opl3_driver);
-
-  if (!portmask)		/* No drivers available */
-    return;
-
-  if (!pnp_allocate_device (pnp_sig, dev, portmask, irqmask, dmamask, 0x00))
-    printk ("Device activation failed\n");
-  else
-    {
-      struct address_info hw_config;
-      int             wss_base, opl3_base;
-      int             irq;
-      int             dma1, dma2;
-
-      printk ("Device activation OK\n");
-      wss_base = pnp_get_port (dev, 0);
-      opl3_base = pnp_get_port (dev, 1);
-      irq = pnp_get_irq (dev, 0);
-      dma1 = pnp_get_dma (dev, 0);
-      dma2 = pnp_get_dma (dev, 1);
-
-      printk ("I/O0 %03x\n", wss_base);
-      printk ("I/O1 %03x\n", opl3_base);
-      printk ("IRQ %d\n", irq);
-      printk ("DMA0 %d\n", dma1);
-      printk ("DMA1 %d\n", dma2);
-
-      if (opl3_base && opl3_driver)
-	{
-	  hw_config.io_base = opl3_base;
-	  hw_config.irq = 0;
-	  hw_config.dma = -1;
-	  hw_config.dma2 = -1;
-	  hw_config.always_detect = 0;
-	  hw_config.name = "";
-	  hw_config.driver_use_1 = 0;
-	  hw_config.driver_use_2 = 0;
-	  hw_config.osp = NULL;
-	  hw_config.card_subtype = 0;
-
-	  if (sndtable_probe (opl3_driver, &hw_config))
-	    sndtable_init_card (opl3_driver, &hw_config);
-
-	}
-
-      if (wss_base && wss_driver)
-	{
-	  hw_config.io_base = wss_base;
-	  hw_config.irq = irq;
-	  hw_config.dma = dma1;
-	  hw_config.dma2 = (dma2 == NO_DMA) ? dma1 : dma2;
-	  hw_config.always_detect = 0;
-	  hw_config.name = name;
-	  hw_config.driver_use_1 = 0;
-	  hw_config.driver_use_2 = 0;
-	  hw_config.osp = NULL;
-	  hw_config.card_subtype = 0;
-
-	  if (sndtable_probe (wss_driver, &hw_config))
-	    sndtable_init_card (wss_driver, &hw_config);
-
-	}
-    }
-}
-
-static int
-pnp_activate (int id, struct pnp_dev *dev)
-{
-  int             i;
-
-  for (i = 0; i < nr_pnpdevs; i++)
-    if (pnp_devs[i]->id == id)
-      {
-
-	printk ("PnP dev: %08x, %s\n", id,
-		pnp_devid2asc (id));
-
-	pnp_devs[i]->setup ((void *) dev);
-	return 1;
-      }
-
-  return 0;
-}
-
-void
-sound_pnp_init (void)
-{
-  static struct pnp_sounddev cs4232_dev =
-  {PNP_DEVID ('C', 'S', 'C', 0x0000), cs4232_pnp, "CS4232"};
-
-  struct pnp_dev *dev;
-
-  install_pnp_sounddrv (&cs4232_dev);
-
-  dev = NULL;
-
-  if ((pnp_sig = pnp_connect ("sound")) == -1)
-    {
-      printk ("Sound: Can't connect to kernel PnP services.\n");
-      return;
-    }
-
-  while ((dev = pnp_get_next_device (pnp_sig, dev)) != NULL)
-    {
-      if (!pnp_activate (dev->key, dev))
-	{
-	  /* Scan all compatible devices */
-
-	  int             i;
-
-	  for (i = 0; i < dev->ncompat; i++)
-	    if (pnp_activate (dev->compat_keys[i], dev))
-	      break;
-	}
-    }
-}
-
-void
-sound_pnp_disconnect (void)
-{
-  pnp_disconnect (pnp_sig);
-}
-#endif
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sound_switch.c linux/drivers/sound/sound_switch.c
--- v1.3.62/linux/drivers/sound/sound_switch.c	Tue Jan 23 21:15:48 1996
+++ linux/drivers/sound/sound_switch.c	Sat Feb 10 22:05:09 1996
@@ -1,9 +1,10 @@
 /*
  * sound/sound_switch.c
  *
- * The system call switch
- *
- * Copyright by Hannu Savolainen 1993
+ * The system call switch handler
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -34,11 +36,7 @@
     int             usecount;
   };
 
-static int      in_use = 0;	/*
-
-
-				 * *  * * Total # of open device files
-				 * (excluding * * * minor 0)   */
+static int      in_use = 0;	/* Total # of open devices */
 
 /*
  * /dev/sndstatus -device
@@ -106,12 +104,12 @@
   status_ptr = 0;
 
 #ifdef SOUND_UNAME_A
-  put_status ("VoxWare Sound Driver:" SOUND_VERSION_STRING
+  put_status ("Sound Driver:" SOUND_VERSION_STRING
 	      " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY ",\n"
 	      SOUND_UNAME_A ")"
 	      "\n");
 #else
-  put_status ("VoxWare Sound Driver:" SOUND_VERSION_STRING
+  put_status ("Sound Driver:" SOUND_VERSION_STRING
 	      " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
 	      SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")"
 	      "\n");
@@ -301,7 +299,7 @@
 }
 
 static int
-read_status (snd_rw_buf * buf, int count)
+read_status (char *buf, int count)
 {
   /*
    * Return at most 'count' bytes from the status_buf.
@@ -323,7 +321,7 @@
 }
 
 int
-sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
+sound_read_sw (int dev, struct fileinfo *file, char *buf, int count)
 {
   DEB (printk ("sound_read_sw(dev=%d, count=%d)\n", dev, count));
 
@@ -361,7 +359,7 @@
 }
 
 int
-sound_write_sw (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
+sound_write_sw (int dev, struct fileinfo *file, const char *buf, int count)
 {
 
   DEB (printk ("sound_write_sw(dev=%d, count=%d)\n", dev, count));
@@ -506,7 +504,7 @@
 
 int
 sound_ioctl_sw (int dev, struct fileinfo *file,
-		unsigned int cmd, ioctl_arg arg)
+		unsigned int cmd, caddr_t arg)
 {
   DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sound_timer.c linux/drivers/sound/sound_timer.c
--- v1.3.62/linux/drivers/sound/sound_timer.c	Tue Jan 23 21:15:48 1996
+++ linux/drivers/sound/sound_timer.c	Sat Feb 10 22:05:10 1996
@@ -1,7 +1,8 @@
 /*
  * sound/sound_timer.c
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -22,8 +23,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #define SEQUENCER_C
 #include "sound_config.h"
@@ -98,7 +100,7 @@
   tmr_offs = 0;
   ticks_offs = 0;
   tmr_ctr = 0;
-  next_event_time = 0xffffffff;
+  next_event_time = (unsigned long) -1;
   prev_event_time = 0;
   curr_ticks = 0;
   restore_flags (flags);
@@ -112,7 +114,7 @@
 
   tmr_reset ();
   curr_tempo = 60;
-  curr_timebase = HZ;
+  curr_timebase = 100;
   opened = 1;
   reprogram_timer ();
 
@@ -202,7 +204,7 @@
 
 static int
 timer_ioctl (int dev,
-	     unsigned int cmd, ioctl_arg arg)
+	     unsigned int cmd, caddr_t arg)
 {
   switch (cmd)
     {
@@ -323,7 +325,7 @@
 
   if (curr_ticks >= next_event_time)
     {
-      next_event_time = 0xffffffff;
+      next_event_time = (unsigned long) -1;
       sequencer_timer (0);
     }
 }
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v1.3.62/linux/drivers/sound/soundcard.c	Tue Jan 23 21:15:49 1996
+++ linux/drivers/sound/soundcard.c	Sat Feb 10 22:09:56 1996
@@ -2,8 +2,9 @@
  * linux/kernel/chr_drv/sound/soundcard.c
  *
  * Soundcard driver for Linux
- *
- * Copyright by Hannu Savolainen 1993
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,20 +25,14 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- */
-/*
- * Created modular version by Peter Trattler (peter@sbox.tu-graz.ac.at)
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
 #include <linux/major.h>
 
-#ifdef CONFIG_PNP
-#include <linux/pnp.h>
-#endif
-
 static int      chrdev_registered = 0;
 
 static int      is_unloading = 0;
@@ -235,12 +230,11 @@
   return 0;
 }
 
-#ifdef ALLOW_BUFFER_MAPPING
 static int
 sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma)
 {
   int             dev, dev_class;
-  unsigned long   size, i;
+  unsigned long   size;
   struct dma_buffparms *dmap = NULL;
 
   dev = inode_get_rdev (inode);
@@ -324,7 +318,6 @@
 	  dmap->bytes_in_use);
   return 0;
 }
-#endif
 
 static struct file_operation_handle sound_fops =
 {
@@ -334,11 +327,7 @@
   NULL,				/* sound_readdir */
   sound_select,
   sound_ioctl,
-#ifdef ALLOW_BUFFER_MAPPING
   sound_mmap,
-#else
-  NULL,
-#endif
   sound_open,
   sound_release
 };
@@ -356,9 +345,6 @@
   sndtable_init (0);		/* Initialize call tables and
 				   * detect cards */
 
-#ifdef CONFIG_PNP
-  sound_pnp_init ();
-#endif
 
   if (sndtable_get_cardcount () == 0)
     return;			/* No cards detected */
@@ -383,7 +369,7 @@
 
 }
 
-static unsigned long irqs = 0;
+static unsigned int irqs = 0;
 
 #ifdef MODULE
 static void
@@ -481,16 +467,12 @@
 	    sound_free_dma (i);
 	  }
 
-#ifdef CONFIG_PNP
-      sound_pnp_disconnect ();
-#endif
-
     }
 }
 #endif
 
 void
-tenmicrosec (sound_os_info * osp)
+tenmicrosec (int *osp)
 {
   int             i;
 
@@ -499,7 +481,7 @@
 }
 
 int
-snd_set_irq_handler (int interrupt_level, void (*hndlr) (int, struct pt_regs *), char *name, sound_os_info * osp)
+snd_set_irq_handler (int interrupt_level, void (*hndlr) (int, struct pt_regs *), char *name, int *osp)
 {
   int             retcode;
 
@@ -629,9 +611,7 @@
   char           *start_addr, *end_addr;
   int             i, dma_pagesize;
 
-#ifdef ALLOW_BUFFER_MAPPING
   dmap->mapping_flags &= ~DMA_MAP_MAPPED;
-#endif
 
   if (dmap->raw_buf != NULL)
     return 0;			/* Already done */
@@ -721,10 +701,8 @@
   if (dmap->raw_buf == NULL)
     return;
 
-#ifdef ALLOW_BUFFER_MAPPING
   if (dmap->mapping_flags & DMA_MAP_MAPPED)
     return;			/* Don't free mmapped buffer. Will use it next time */
-#endif
 
   {
     int             sz, size, i;
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/soundvers.h linux/drivers/sound/soundvers.h
--- v1.3.62/linux/drivers/sound/soundvers.h	Tue Jan 23 21:15:49 1996
+++ linux/drivers/sound/soundvers.h	Sat Feb 10 22:04:26 1996
@@ -1,2 +1,2 @@
-#define SOUND_VERSION_STRING "3.5-alpha8-960109"
+#define SOUND_VERSION_STRING "3.5-beta2-960210"
 #define SOUND_INTERNAL_VERSION 0x030505
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c
--- v1.3.62/linux/drivers/sound/sscape.c	Tue Jan 23 21:15:49 1996
+++ linux/drivers/sound/sscape.c	Sat Feb 10 22:05:12 1996
@@ -2,8 +2,9 @@
  * sound/sscape.c
  *
  * Low level driver for Ensoniq Soundscape
- *
- * Copyright by Hannu Savolainen 1994
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -24,8 +25,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -94,7 +96,7 @@
     int             dma_allocated;
     int             my_audiodev;
     int             opened;
-    sound_os_info  *osp;
+    int            *osp;
   }
 
 sscape_info;
@@ -438,6 +440,7 @@
   unsigned long   flags;
   unsigned char   temp;
   int             done, timeout_val;
+  static int      already_done = 0;
 
   if (flag & CPF_FIRST)
     {
@@ -446,6 +449,13 @@
          * before continuing.
        */
 
+      if (already_done)
+	{
+	  printk ("Can't run 'ssinit' twice\n");
+	  return 0;
+	}
+      already_done = 1;
+
       save_flags (flags);
       cli ();
       if (devc->dma_allocated == 0)
@@ -497,7 +507,7 @@
 	if (1)
 	  current_set_timeout (tl = jiffies + (1));
 	else
-	  tl = 0xffffffff;
+	  tl = (unsigned long) -1;
 	sscape_sleep_flag.mode = WK_SLEEP;
 	module_interruptible_sleep_on (&sscape_sleeper);
 	if (!(sscape_sleep_flag.mode & WK_WAKEUP))
@@ -545,7 +555,7 @@
 	    if (1)
 	      current_set_timeout (tl = jiffies + (1));
 	    else
-	      tl = 0xffffffff;
+	      tl = (unsigned long) -1;
 	    sscape_sleep_flag.mode = WK_SLEEP;
 	    module_interruptible_sleep_on (&sscape_sleeper);
 	    if (!(sscape_sleep_flag.mode & WK_WAKEUP))
@@ -578,7 +588,7 @@
 	    if (1)
 	      current_set_timeout (tl = jiffies + (1));
 	    else
-	      tl = 0xffffffff;
+	      tl = (unsigned long) -1;
 	    sscape_sleep_flag.mode = WK_SLEEP;
 	    module_interruptible_sleep_on (&sscape_sleeper);
 	    if (!(sscape_sleep_flag.mode & WK_WAKEUP))
@@ -638,7 +648,7 @@
 }
 
 static int
-sscape_coproc_ioctl (void *dev_info, unsigned int cmd, ioctl_arg arg, int local)
+sscape_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
 {
 
   switch (cmd)
@@ -745,7 +755,7 @@
 }
 
 static int
-sscape_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
+sscape_audio_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
   sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/sys_timer.c linux/drivers/sound/sys_timer.c
--- v1.3.62/linux/drivers/sound/sys_timer.c	Tue Jan 23 21:15:49 1996
+++ linux/drivers/sound/sys_timer.c	Sat Feb 10 22:05:13 1996
@@ -2,9 +2,10 @@
  * sound/sys_timer.c
  *
  * The default timer for the Level 2 sequencer interface
- * Uses the (100HZ) timer of kernel.
- *
- * Copyright by Hannu Savolainen 1993
+ * Uses the (1/HZ sec) timer of kernel.
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -25,8 +26,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #define SEQUENCER_C
 #include "sound_config.h"
@@ -55,7 +57,7 @@
    *    (divide # of MIDI ticks/minute by # of system ticks/minute).
    */
 
-  return ((tmr_value * curr_tempo * curr_timebase) + (30 * HZ)) / (60 * HZ);
+  return ((tmr_value * curr_tempo * curr_timebase) + (30 * 100)) / (60 * HZ);
 }
 
 static void
@@ -77,7 +79,7 @@
 
 	  if (curr_ticks >= next_event_time)
 	    {
-	      next_event_time = 0xffffffff;
+	      next_event_time = (unsigned long) -1;
 	      sequencer_timer (0);
 	    }
 	}
@@ -94,7 +96,7 @@
   tmr_offs = 0;
   ticks_offs = 0;
   tmr_ctr = 0;
-  next_event_time = 0xffffffff;
+  next_event_time = (unsigned long) -1;
   prev_event_time = 0;
   curr_ticks = 0;
   restore_flags (flags);
@@ -108,7 +110,7 @@
 
   tmr_reset ();
   curr_tempo = 60;
-  curr_timebase = HZ;
+  curr_timebase = 100;
   opened = 1;
 
   ;
@@ -201,7 +203,7 @@
 
 static int
 def_tmr_ioctl (int dev,
-	       unsigned int cmd, ioctl_arg arg)
+	       unsigned int cmd, caddr_t arg)
 {
   switch (cmd)
     {
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/trix.c linux/drivers/sound/trix.c
--- v1.3.62/linux/drivers/sound/trix.c	Tue Jan 23 21:15:49 1996
+++ linux/drivers/sound/trix.c	Sat Feb 10 22:05:14 1996
@@ -3,8 +3,9 @@
  *
  * Low level driver for the MediaTriX AudioTriX Pro
  * (MT-0002-PC Control Chip)
- *
- * Copyright by Hannu Savolainen 1995
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -25,8 +26,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
+#include <linux/config.h>
+
 
 #include "sound_config.h"
 
@@ -34,6 +36,10 @@
 
 #ifdef INCLUDE_TRIX_BOOT
 #include "trix_boot.h"
+#else
+static unsigned char *trix_boot = NULL;
+static int      trix_boot_len = 0;
+
 #endif
 
 
@@ -41,7 +47,7 @@
 static int      sb_initialized = 0;
 static int      mpu_initialized = 0;
 
-static sound_os_info *trix_osp = NULL;
+static int     *trix_osp = NULL;
 
 static unsigned char
 trix_read (int addr)
@@ -60,8 +66,10 @@
 static void
 download_boot (int base)
 {
-#ifdef INCLUDE_TRIX_BOOT
-  int             i = 0, n = sizeof (trix_boot);
+  int             i = 0, n = trix_boot_len;
+
+  if (trix_boot_len == 0)
+    return;
 
   trix_write (0xf8, 0x00);	/* ??????? */
   outb (0x01, base + 6);	/* Clear the internal data pointer */
@@ -80,7 +88,6 @@
     outb (0x00, 0x391);
   outb (0x00, base + 6);	/* Reset */
   outb (0x50, 0x390);		/* ?????? */
-#endif
 
 }
 
@@ -104,8 +111,6 @@
       return 0;
     }
 
-  request_region (0x390, 2, "AudioTriX");
-
   kilroy_was_here = 1;
 
   /*
@@ -149,6 +154,8 @@
 int
 probe_trix_wss (struct address_info *hw_config)
 {
+  int             ret;
+
   /*
      * Check if the IO port returns valid signature. The original MS Sound
      * system returns 0x04 while some cards (AudioTriX Pro for example)
@@ -156,7 +163,7 @@
    */
   if (check_region (hw_config->io_base, 8))
     {
-      printk ("AudioTriX: MSS I/O port conflict\n");
+      printk ("AudioTriX: MSS I/O port conflict (%x)\n", hw_config->io_base);
       return 0;
     }
 
@@ -206,7 +213,12 @@
       return 0;
     }
 
-  return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp);
+  ret = ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp);
+
+  if (ret)
+    request_region (0x390, 2, "AudioTriX");
+
+  return ret;
 }
 
 long
@@ -282,9 +294,9 @@
   static char     irq_translate[] =
   {-1, -1, -1, 0, 1, 2, -1, 3};
 
-#ifndef INCLUDE_TRIX_BOOT
-  return 0;			/* No boot code -> no fun */
-#endif
+  if (trix_boot_len == 0)
+    return 0;			/* No boot code -> no fun */
+
   if (!kilroy_was_here)
     return 0;			/* AudioTriX Pro has not been detected earlier */
 
@@ -293,7 +305,7 @@
 
   if (check_region (hw_config->io_base, 16))
     {
-      printk ("AudioTriX: SB I/O port conflict\n");
+      printk ("AudioTriX: SB I/O port conflict (%x)\n", hw_config->io_base);
       return 0;
     }
 
@@ -374,7 +386,7 @@
 
   if (check_region (hw_config->io_base, 4))
     {
-      printk ("AudioTriX: MPU I/O port conflict\n");
+      printk ("AudioTriX: MPU I/O port conflict (%x)\n", hw_config->io_base);
       return 0;
     }
 
diff -u --recursive --new-file v1.3.62/linux/drivers/sound/uart6850.c linux/drivers/sound/uart6850.c
--- v1.3.62/linux/drivers/sound/uart6850.c	Tue Jan 23 21:15:49 1996
+++ linux/drivers/sound/uart6850.c	Sat Feb 10 22:05:14 1996
@@ -1,10 +1,8 @@
 /*
  * sound/uart6850.c
- *
- * Copyright by Hannu Savolainen 1993
- *
- * Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl:
- *      added 6850 support, used with COVOX SoundMaster II and custom cards.
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -25,40 +23,53 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
+ */
+#include <linux/config.h>
+
+/* Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl:
+ *      added 6850 support, used with COVOX SoundMaster II and custom cards.
  */
 
 #include "sound_config.h"
 
 #if defined(CONFIG_UART6850) && defined(CONFIG_MIDI)
 
-#define	DATAPORT   (uart6850_base)	/*
-					   * * * Midi6850 Data I/O Port on IBM
-					   *  */
-#define	COMDPORT   (uart6850_base+1)	/*
-					   * * * Midi6850 Command Port on IBM   */
-#define	STATPORT   (uart6850_base+1)	/*
-					   * * * Midi6850 Status Port on IBM   */
+static int      uart6850_base = 0x330;
+
+#define	DATAPORT   (uart6850_base)
+#define	COMDPORT   (uart6850_base+1)
+#define	STATPORT   (uart6850_base+1)
 
-#define uart6850_status()		inb( STATPORT)
+static int 
+uart6850_status (void)
+{
+  return inb (STATPORT);
+}
 #define input_avail()		(uart6850_status()&INPUT_AVAIL)
 #define output_ready()		(uart6850_status()&OUTPUT_READY)
-#define uart6850_cmd(cmd)	outb( cmd,  COMDPORT)
-#define uart6850_read()		inb( DATAPORT)
-#define uart6850_write(byte)	outb( byte,  DATAPORT)
-
-#define	OUTPUT_READY	0x02	/*
-				   * * * Mask for Data Read Ready Bit   */
-#define	INPUT_AVAIL	0x01	/*
-				   * * * Mask for Data Send Ready Bit   */
-
-#define	UART_RESET	0x95	/*
-				   * * * 6850 Total Reset Command   */
-#define	UART_MODE_ON	0x03	/*
-				   * * * 6850 Send/Receive UART Mode   */
+static void 
+uart6850_cmd (unsigned char cmd)
+{
+  outb (cmd, COMDPORT);
+}
+static int 
+uart6850_read (void)
+{
+  return inb (DATAPORT);
+}
+static void 
+uart6850_write (unsigned char byte)
+{
+  outb (byte, DATAPORT);
+}
+
+#define	OUTPUT_READY	0x02	/* Mask for data ready Bit */
+#define	INPUT_AVAIL	0x01	/* Mask for Data Send Ready Bit */
+
+#define	UART_RESET	0x95
+#define	UART_MODE_ON	0x03
 
 static int      uart6850_opened = 0;
-static int      uart6850_base = 0x330;
 static int      uart6850_irq;
 static int      uart6850_detected = 0;
 static int      my_dev;
@@ -67,7 +78,7 @@
 static void     (*midi_input_intr) (int dev, unsigned char data);
 static void     poll_uart6850 (unsigned long dummy);
 
-static sound_os_info *uart6850_osp;
+static int     *uart6850_osp;
 
 
 static struct timer_list uart6850_timer =
@@ -225,7 +236,7 @@
 }
 
 static int
-uart6850_ioctl (int dev, unsigned cmd, ioctl_arg arg)
+uart6850_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
   return -EINVAL;
 }
diff -u --recursive --new-file v1.3.62/linux/fs/dquot.c linux/fs/dquot.c
--- v1.3.62/linux/fs/dquot.c	Thu Dec 21 08:53:33 1995
+++ linux/fs/dquot.c	Mon Feb 12 06:45:30 1996
@@ -16,6 +16,9 @@
  * Version: $Id: dquot.c,v 5.6 1995/11/15 20:30:27 mvw Exp mvw $
  * 
  * Author:  Marco van Wieringen <mvw@mcs.ow.nl> <mvw@tnix.net>
+ * 
+ * Fixes:   Dmitry Gorodchanin <begemot@bgm.rosprint.net>, 11 Feb 96
+ *	    removed race conditions in dqput(), dqget() and iput(). 
  *
  * (C) Copyright 1994, 1995 Marco van Wieringen 
  *
@@ -678,6 +681,7 @@
 {
 	unsigned int id = 0;
 	short cnt;
+	struct dquot *tmp;
 
 	if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) {
 		for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -694,7 +698,16 @@
 						id = inode->i_gid;
 						break;
 				}
-				inode->i_dquot[cnt] = dqget(inode->i_dev, id, cnt);
+
+				tmp = dqget(inode->i_dev, id, cnt);
+				/* We may sleep in dqget(), so check it again.
+				 * 	Dmitry Gorodchanin 02/11/96
+				 */
+				if (inode->i_dquot[cnt] != NODQUOT) {
+					dqput(tmp);
+					continue;
+				} 
+				inode->i_dquot[cnt] = tmp;
 				inode->i_flags |= S_WRITE;
 			}
 		}
@@ -704,12 +717,17 @@
 void dquot_drop(struct inode *inode)
 {
 	short cnt;
+	struct dquot * tmp;
 
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (inode->i_dquot[cnt] == NODQUOT)
 			continue;
-		dqput(inode->i_dquot[cnt]);
+		/* We can sleep at dqput(). So we must do it this way.
+		 * 	Dmitry Gorodchanin 02/11/96
+		 */
+		tmp = inode->i_dquot[cnt];
 		inode->i_dquot[cnt] = NODQUOT;
+		dqput(tmp);
 	}
 	inode->i_flags &= ~S_WRITE;
 }
diff -u --recursive --new-file v1.3.62/linux/fs/inode.c linux/fs/inode.c
--- v1.3.62/linux/fs/inode.c	Wed Feb  7 15:11:31 1996
+++ linux/fs/inode.c	Mon Feb 12 06:45:30 1996
@@ -429,11 +429,19 @@
 		goto repeat;
 	}
 
-	inode->i_count--;
 	if (IS_WRITABLE(inode)) {
-		if (inode->i_sb && inode->i_sb->dq_op)
+		if (inode->i_sb && inode->i_sb->dq_op) {
+			/* Here we can sleep also. Let's do it again
+			 * Dmitry Gorodchanin 02/11/96 
+			 */
+			inode->i_lock = 1;
 			inode->i_sb->dq_op->drop(inode);
+			unlock_inode(inode);
+			goto repeat;
+		}
 	}
+	
+	inode->i_count--;
 
 	if (inode->i_mmap) {
 		printk("iput: inode %lu on device %s still has mappings.\n",
diff -u --recursive --new-file v1.3.62/linux/fs/msdos/msdosfs_syms.c linux/fs/msdos/msdosfs_syms.c
--- v1.3.62/linux/fs/msdos/msdosfs_syms.c	Fri Feb  9 17:53:06 1996
+++ linux/fs/msdos/msdosfs_syms.c	Tue Feb 13 10:47:12 1996
@@ -25,6 +25,8 @@
   	X(msdos_rmdir),
   	X(msdos_unlink),
   	X(msdos_unlink_umsdos),
+  	X(msdos_read_super),
+  	X(msdos_put_super), 
 #include <linux/symtab_end.h>
 };                                           
 
diff -u --recursive --new-file v1.3.62/linux/fs/proc/array.c linux/fs/proc/array.c
--- v1.3.62/linux/fs/proc/array.c	Sun Feb 11 15:32:46 1996
+++ linux/fs/proc/array.c	Mon Feb 12 06:45:30 1996
@@ -14,8 +14,8 @@
  *                      EVERY character on the current page.
  *                      <middelin@polyware.iaf.nl>
  *
- * Danny ter Haar    :	Some minor additions for cpuinfo
- *			<danny@ow.nl>
+ * Danny ter Haar    :	added cpuinfo 
+ *			<dth@cistron.nl>
  *
  * Alessandro Rubini :  profile extension.
  *                      <rubini@ipvvis.unipv.it>
diff -u --recursive --new-file v1.3.62/linux/include/linux/blk.h linux/include/linux/blk.h
--- v1.3.62/linux/include/linux/blk.h	Fri Jan 26 01:37:07 1996
+++ linux/include/linux/blk.h	Wed Feb 14 13:21:00 1996
@@ -6,13 +6,6 @@
 #include <linux/config.h>
 
 /*
- * NR_REQUEST is the number of entries in the request-queue.
- * NOTE that writes may use only the low 2/3 of these: reads
- * take precedence.
- */
-#define NR_REQUEST	64
-
-/*
  * This is used in the elevator algorithm.  We don't prioritise reads
  * over writes any more --- although reads are more time-critical than
  * writes, by treating them equally we increase filesystem throughput.
@@ -67,6 +60,9 @@
 #ifdef CONFIG_SJCD
 extern int sjcd_init(void);
 #endif CONFIG_SJCD
+#ifdef CONFIG_CDI_INIT
+extern int cdi_init(void);
+#endif CONFIG_CDI_INIT
 #ifdef CONFIG_BLK_DEV_HD
 extern int hd_init(void);
 #endif
diff -u --recursive --new-file v1.3.62/linux/include/linux/if_slip.h linux/include/linux/if_slip.h
--- v1.3.62/linux/include/linux/if_slip.h	Fri Feb  9 17:53:08 1996
+++ linux/include/linux/if_slip.h	Tue Feb 13 07:13:59 1996
@@ -20,7 +20,7 @@
  */
  
 #define SIOCSKEEPALIVE	(SIOCDEVPRIVATE)		/* Set keepalive timeout in sec */
-#define SIOCGKEEPALIVE	(SICODEVPRIVATE+1)		/* Get keepalive timeout */
+#define SIOCGKEEPALIVE	(SIOCDEVPRIVATE+1)		/* Get keepalive timeout */
 #define SIOCSOUTFILL	(SIOCDEVPRIVATE+2)		/* Set outfill timeout */
 #define	SIOCGOUTFILL	(SIOCDEVPRIVATE+3)		/* Get outfill timeout */
 
diff -u --recursive --new-file v1.3.62/linux/include/linux/isp16.h linux/include/linux/isp16.h
--- v1.3.62/linux/include/linux/isp16.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/isp16.h	Tue Feb 13 10:30:25 1996
@@ -0,0 +1,75 @@
+/* -- isp16.h
+ *
+ *  Header for detection and initialisation of cdrom interface (only) on
+ *  ISP16 (MAD16, Mozart) sound card.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/* These are the default values */
+#define ISP16_CDROM_TYPE "Sanyo"
+#define ISP16_CDROM_IO_BASE 0x340
+#define ISP16_CDROM_IRQ 0
+#define ISP16_CDROM_DMA 0
+
+/* Some (Media)Magic */
+/* define types of drive the interface on an ISP16 card may be looking at */
+#define ISP16_DRIVE_X 0x00
+#define ISP16_SONY  0x02
+#define ISP16_PANASONIC0 0x02
+#define ISP16_SANYO0 0x02
+#define ISP16_MITSUMI  0x04
+#define ISP16_PANASONIC1 0x06
+#define ISP16_SANYO1 0x06
+#define ISP16_DRIVE_NOT_USED 0x08  /* not used */
+#define ISP16_DRIVE_SET_MASK 0xF1  /* don't change 0-bit or 4-7-bits*/
+/* ...for port */
+#define ISP16_DRIVE_SET_PORT 0xF8D
+/* set io parameters */
+#define ISP16_BASE_340  0x00
+#define ISP16_BASE_330  0x40
+#define ISP16_BASE_360  0x80
+#define ISP16_BASE_320  0xC0
+#define ISP16_IRQ_X  0x00
+#define ISP16_IRQ_5  0x04  /* shouldn't be used to avoid sound card conflicts */
+#define ISP16_IRQ_7  0x08  /* shouldn't be used to avoid sound card conflicts */
+#define ISP16_IRQ_3  0x0C
+#define ISP16_IRQ_9  0x10
+#define ISP16_IRQ_10  0x14
+#define ISP16_IRQ_11  0x18
+#define ISP16_DMA_X  0x03
+#define ISP16_DMA_3  0x00
+#define ISP16_DMA_5  0x00
+#define ISP16_DMA_6  0x01
+#define ISP16_DMA_7  0x02
+#define ISP16_IO_SET_MASK  0x20  /* don't change 5-bit */
+/* ...for port */
+#define ISP16_IO_SET_PORT  0xF8E
+/* enable the card */
+#define ISP16_C928__ENABLE_PORT  0xF90  /* ISP16 with OPTi 82C928 chip */
+#define ISP16_C929__ENABLE_PORT  0xF91  /* ISP16 with OPTi 82C929 chip */
+#define ISP16_ENABLE_CDROM  0x80  /* seven bit */
+
+/* the magic stuff */
+#define ISP16_CTRL_PORT  0xF8F
+#define ISP16_C928__CTRL  0xE2  /* ISP16 with OPTi 82C928 chip */
+#define ISP16_C929__CTRL  0xE3  /* ISP16 with OPTi 82C929 chip */
+
+#define ISP16_IO_BASE 0xF8D
+#define ISP16_IO_SIZE 5  /* ports used from 0xF8D up to 0xF91 */
+
+void isp16_setup(char *str, int *ints);
+int isp16_init(void);
diff -u --recursive --new-file v1.3.62/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v1.3.62/linux/include/linux/proc_fs.h	Fri Feb  9 17:53:09 1996
+++ linux/include/linux/proc_fs.h	Wed Feb 14 09:26:25 1996
@@ -124,6 +124,7 @@
 	PROC_SCSI_EATA2X,
 	PROC_SCSI_AM53C974,
 	PROC_SCSI_SSC,
+	PROC_SCSI_NCR53C406A,
 	PROC_SCSI_SCSI_DEBUG,	
 	PROC_SCSI_NOT_PRESENT,
 	PROC_SCSI_FILE,                        /* I'm asuming here that we */
diff -u --recursive --new-file v1.3.62/linux/include/linux/sched.h linux/include/linux/sched.h
--- v1.3.62/linux/include/linux/sched.h	Sun Feb 11 15:32:46 1996
+++ linux/include/linux/sched.h	Wed Feb 14 07:33:28 1996
@@ -112,9 +112,14 @@
 
 asmlinkage void schedule(void);
 
+/* ??? */
 struct files_struct {
+	/* ??? */
 	int count;
+	/* bit mask to close fds on exec */
 	fd_set close_on_exec;
+	/* do we have at most NR_OPEN available fds? I assume fd i maps into
+ 	 * each open file */	
 	struct file * fd[NR_OPEN];
 };
 
@@ -187,10 +192,17 @@
 	unsigned long saved_kernel_stack;
 	unsigned long kernel_stack_page;
 	int exit_code, exit_signal;
+	/* ??? */
 	unsigned long personality;
 	int dumpable:1;
 	int did_exec:1;
-	int pid,pgrp,tty_old_pgrp,session,leader;
+	/* shouldn't this be pid_t? */
+	int pid;
+	int pgrp;
+	int tty_old_pgrp;
+	int session;
+	/* boolean value for session group leader */
+	int leader;
 	int	groups[NGROUPS];
 	/* 
 	 * pointers to (original) parent process, youngest child, younger sibling,
@@ -348,6 +360,20 @@
 extern int do_execve(char *, char **, char **, struct pt_regs *);
 extern int do_fork(unsigned long, unsigned long, struct pt_regs *);
 
+
+/* See if we have a valid user level fd.
+ * If it makes sense, return the file structure it references.
+ * Otherwise return NULL.
+ */
+extern inline struct file *file_from_fd(const unsigned int fd)
+{
+
+	if (fd >= NR_OPEN)
+		return NULL;
+	/* either valid or null */
+	return current->files->fd[fd];
+}
+	
 /*
  * The wait-queues are circular lists, and you have to be *very* sure
  * to keep them correct. Use only these two functions to add/remove
diff -u --recursive --new-file v1.3.62/linux/include/linux/sjcd.h linux/include/linux/sjcd.h
--- v1.3.62/linux/include/linux/sjcd.h	Mon Oct 16 18:38:24 1995
+++ linux/include/linux/sjcd.h	Tue Feb 13 10:30:25 1996
@@ -6,7 +6,7 @@
  *                                       vadim@rbrf.msk.su
  *                                       vadim@ipsun.ras.ru
  *                       Eric van der Maarel
- *                                       maarel@marin.nl
+ *                                       H.T.M.v.d.Maarel@marin.nl
  *
  *  This information is based on mcd.c from M. Harriss and sjcd102.lst from
  *  E. Moenkeberg.
@@ -57,7 +57,7 @@
  * Port access macro. Three ports are available: S-data port (command port),
  * status port (read only) and D-data port (read only).
  */
-#define SJCDPORT( x )       ( sjcd_port + ( x ) )
+#define SJCDPORT( x )       ( sjcd_base + ( x ) )
 #define SJCD_STATUS_PORT    SJCDPORT( 1 )
 #define SJCD_S_DATA_PORT    SJCDPORT( 0 )
 #define SJCD_COMMAND_PORT   SJCDPORT( 0 )
diff -u --recursive --new-file v1.3.62/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v1.3.62/linux/include/linux/skbuff.h	Fri Feb  9 17:53:10 1996
+++ linux/include/linux/skbuff.h	Wed Feb 14 13:20:12 1996
@@ -63,6 +63,8 @@
 		struct iphdr	*iph;
 		struct udphdr	*uh;
 		unsigned char	*raw;
+		/* for passing an fd in a unix domain socket */
+		struct file *filp;
 	} h;
   
 	union 
@@ -167,8 +169,10 @@
  */
 extern __inline__ struct sk_buff *skb_peek(struct sk_buff_head *list_)
 {
-	struct sk_buff *list = (struct sk_buff *)list_;
-	return (list->next != list)? list->next : NULL;
+	struct sk_buff *list = ((struct sk_buff *)list_)->next;
+	if (list == (struct sk_buff *)list_)
+		list = NULL;
+	return list;
 }
 
 /*
@@ -197,21 +201,32 @@
 
 /*
  *	Insert an sk_buff at the start of a list.
+ *
+ *	The "__skb_xxxx()" functions are the non-atomic ones that
+ *	can only be called with interrupts disabled.
  */
 
-extern __inline__ void skb_queue_head(struct sk_buff_head *list_,struct sk_buff *newsk)
+extern __inline__ void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+	struct sk_buff *prev, *next;
+
+	newsk->list = list;
+	list->qlen++;
+	prev = (struct sk_buff *)list;
+	next = prev->next;
+	newsk->next = next;
+	newsk->prev = prev;
+	next->prev = newsk;
+	prev->next = newsk;
+}
+
+extern __inline__ void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
 {
 	unsigned long flags;
-	struct sk_buff *list = (struct sk_buff *)list_;
 
 	save_flags(flags);
 	cli();
-	newsk->next = list->next;
-	newsk->prev = list;
-	newsk->next->prev = newsk;
-	newsk->prev->next = newsk;
-	newsk->list = list_;
-	list_->qlen++;
+	__skb_queue_head(list, newsk);
 	restore_flags(flags);
 }
 
@@ -219,78 +234,89 @@
  *	Insert an sk_buff at the end of a list.
  */
 
-extern __inline__ void skb_queue_tail(struct sk_buff_head *list_, struct sk_buff *newsk)
+extern __inline__ void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+	struct sk_buff *prev, *next;
+
+	newsk->list = list;
+	list->qlen++;
+	next = (struct sk_buff *)list;
+	prev = next->prev;
+	newsk->next = next;
+	newsk->prev = prev;
+	next->prev = newsk;
+	prev->next = newsk;
+}
+
+extern __inline__ void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
 {
 	unsigned long flags;
-	struct sk_buff *list = (struct sk_buff *)list_;
 
 	save_flags(flags);
 	cli();
-
-	newsk->next = list;
-	newsk->prev = list->prev;
-
-	newsk->next->prev = newsk;
-	newsk->prev->next = newsk;
-	newsk->list=list_;
-	list_->qlen++;
+	__skb_queue_tail(list, newsk);
 	restore_flags(flags);
 }
 
 /*
- *	Remove an sk_buff from a list. This routine is also interrupt safe
- *	so you can grab read and free buffers as another process adds them.
- *
- * 	Note we now do the ful list 
+ *	Remove an sk_buff from a list.
  */
 
-extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list_)
+extern __inline__ struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
 {
-	long flags;
-	struct sk_buff *result;
-	struct sk_buff *list = (struct sk_buff *)list_;
-
-	save_flags(flags);
-	cli();
-
-	result = list->next;
-	if (result == list) 
-	{
-		restore_flags(flags);
-		return NULL;
-	}
-	else
-	{
-		result->next->prev = list;
-		list->next = result->next;
+	struct sk_buff *next, *prev, *result;
 
+	prev = (struct sk_buff *) list;
+	next = prev->next;
+	result = NULL;
+	if (next != prev) {
+		result = next;
+		next = next->next;
+		list->qlen--;
+		next->prev = prev;
+		prev->next = next;
 		result->next = NULL;
 		result->prev = NULL;
+		result->list = NULL;
+	}
+	return result;
+}
 
-		list_->qlen--;
-		result->list=NULL;
-		restore_flags(flags);
+extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list)
+{
+	long flags;
+	struct sk_buff *result;
 
-		return result;
-	}
+	save_flags(flags);
+	cli();
+	result = __skb_dequeue(list);
+	restore_flags(flags);
+	return result;
 }
 
 /*
  *	Insert a packet before another one in a list.
  */
 
+extern __inline__ void __skb_insert(struct sk_buff *next, struct sk_buff *newsk)
+{
+	struct sk_buff * prev = next->prev;
+
+	newsk->next = next;
+	newsk->prev = prev;
+	next->prev = newsk;
+	prev->next = newsk;
+	newsk->list = next->list;
+	newsk->list->qlen++;
+}
+
 extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
 {
 	unsigned long flags;
 
 	save_flags(flags);
 	cli();
-	newsk->next = old;
-	newsk->prev = old->prev;
-	old->prev = newsk;
-	newsk->prev->next = newsk;
-	newsk->list = old->list;
-	newsk->list->qlen++;
+	__skb_insert(old, newsk);
 	restore_flags(flags);
 }
 
@@ -298,21 +324,43 @@
  *	Place a packet after a given packet in a list.
  */
 
+extern __inline__ void __skb_append(struct sk_buff *prev, struct sk_buff *newsk)
+{
+	struct sk_buff * next = prev->next;
+
+	newsk->next = next;
+	newsk->prev = prev;
+	next->prev = newsk;
+	prev->next = newsk;
+	newsk->list = prev->list;
+	newsk->list->qlen++;
+}
+
 extern __inline__ void skb_append(struct sk_buff *old, struct sk_buff *newsk)
 {
 	unsigned long flags;
 
 	save_flags(flags);
 	cli();
+	__skb_append(old, newsk);
+	restore_flags(flags);
+}
 
-	newsk->prev = old;
-	newsk->next = old->next;
-	newsk->next->prev = newsk;
-	old->next = newsk;
-	newsk->list = old->list;
-	newsk->list->qlen++;
+/*
+ * remove sk_buff from list. _Must_ be called atomically, and with
+ * the list known..
+ */
+extern __inline__ void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
+{
+	struct sk_buff * next, * prev;
 
-	restore_flags(flags);
+	list->qlen--;
+	next = skb->next;
+	prev = skb->prev;
+	skb->next = NULL;
+	skb->prev = NULL;
+	skb->list = NULL;
+	(next->prev = prev)->next = next;
 }
 
 /*
@@ -328,16 +376,8 @@
 
 	save_flags(flags);
 	cli();
-
 	if(skb->list)
-	{
-		skb->list->qlen--;
-		skb->next->prev = skb->prev;
-		skb->prev->next = skb->next;
-		skb->next = NULL;
-		skb->prev = NULL;
-		skb->list = NULL;
-	}
+		__skb_unlink(skb, skb->list);
 	restore_flags(flags);
 }
 
diff -u --recursive --new-file v1.3.62/linux/include/linux/soundcard.h linux/include/linux/soundcard.h
--- v1.3.62/linux/include/linux/soundcard.h	Tue Jan 23 21:15:54 1996
+++ linux/include/linux/soundcard.h	Sun Feb 11 18:12:31 1996
@@ -1,51 +1,29 @@
 #ifndef SOUNDCARD_H
 #define SOUNDCARD_H
 /*
- * Copyright by Hannu Savolainen 1993
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- * 
  */
 
- /* 
-  * If you make modifications to this file, please contact me before
-  * distributing the modified version. There is already enough 
-  * diversity in the world.
-  *
-  * Regards,
-  * Hannu Savolainen
-  * hannu@voxware.pp.fi
-  *
-  **********************************************************************
-  * PS.	The Hacker's Guide to VoxWare available from 
-  *     nic.funet.fi:pub/OS/Linux/ALPHA/sound. The file is
-  *	snd-sdk-doc-0.1.ps.gz (gzipped postscript). It contains
-  *	some useful information about programming with VoxWare.
-  *	(NOTE! The pub/OS/Linux/ALPHA/ directories are hidden. You have
-  *	to cd inside them before the files are accessible.)
-  **********************************************************************
-  */
-
 #define SOUND_VERSION	301
 #define VOXWARE
 
@@ -172,7 +150,7 @@
 		short device_no;	/* Synthesizer number */
 		short instr_no;		/* Midi pgm# */
 
-		unsigned long mode;
+		unsigned int mode;
 /*
  * The least significant byte has the same format than the GUS .PAT
  * files
@@ -191,8 +169,8 @@
 #define WAVE_SCALE	0x00040000	/* The scaling info is valid */
 /* Other bits must be zeroed */
 
-		long len;	/* Size of the wave data in bytes */
-		long loop_start, loop_end; /* Byte offsets from the beginning */
+		int len;	/* Size of the wave data in bytes */
+		int loop_start, loop_end; /* Byte offsets from the beginning */
 
 /* 
  * The base_freq and base_note fields are used when computing the
@@ -211,9 +189,9 @@
  */
 
 		unsigned int base_freq;
-		unsigned long base_note;
-		unsigned long high_note;
-		unsigned long low_note;
+		unsigned int base_note;
+		unsigned int high_note;
+		unsigned int low_note;
 		int panning;	/* -128=left, 127=right */
 		int detuning;
 
@@ -250,7 +228,7 @@
 #define SYSEX_PATCH	_PATCHKEY(0x05)
 #define MAUI_PATCH	_PATCHKEY(0x06)
 		short device_no;	/* Synthesizer number */
-		long len;	/* Size of the sysex data in bytes */
+		int len;	/* Size of the sysex data in bytes */
 		unsigned char data[1];	/* Sysex data starts here */
 	};
 
@@ -281,7 +259,7 @@
  */
 
 struct patmgr_info {	/* Note! size must be < 4k since kmalloc() is used */
-	  unsigned long key;	/* Don't worry. Reserved for communication
+	  unsigned int key;	/* Don't worry. Reserved for communication
 	  			   between the patch manager and the driver. */
 #define PM_K_EVENT		1 /* Event from the /dev/sequencer driver */
 #define PM_K_COMMAND		2 /* Request from a application */
@@ -315,14 +293,14 @@
  * Commands above 0xffff reserved for device specific use
  */
 
-	  long parm1;
-	  long parm2;
-	  long parm3;
+	  int parm1;
+	  int parm2;
+	  int parm3;
 
 	  union {
 		unsigned char data8[4000];
 		unsigned short data16[2000];
-		unsigned long data32[1000];
+		unsigned int data32[1000];
 		struct patch_info patch;
 	  } data;
 	};
@@ -526,7 +504,7 @@
 		int	nr_voices;
 		int	nr_drums;	/* Obsolete field */
 		int	instr_bank_size;
-		unsigned long	capabilities;	
+		unsigned int	capabilities;	
 #define SYNTH_CAP_PERCMODE		0x00000001 /* No longer used */
 #define SYNTH_CAP_OPL3			0x00000002 /* Set if OPL3 supported */
 #define SYNTH_CAP_INPUT			0x00000004 /* Input (MIDI) device */
@@ -543,7 +521,7 @@
 struct midi_info {
 		char		name[30];
 		int		device;		/* 0-N. INITIALIZE BEFORE CALLING */
-		unsigned long	capabilities;	/* To be defined later */
+		unsigned int	capabilities;	/* To be defined later */
 		int		dev_type;
 		int		dummies[18];	/* Reserve space */
 	};
@@ -1081,7 +1059,8 @@
 					_seqbuf[_seqbufptr+2] = (dev);\
 					_seqbuf[_seqbufptr+3] = (voice);\
 					_seqbuf[_seqbufptr+4] = (controller);\
-					*(short *)&_seqbuf[_seqbufptr+5] = (value);\
+					_seqbuf[_seqbufptr+5] = ((value)&0xff);\
+					_seqbuf[_seqbufptr+6] = ((value>>8)&0xff);\
 					_seqbuf[_seqbufptr+7] = 0;\
 					_SEQ_ADVBUF(8);}
 /*
diff -u --recursive --new-file v1.3.62/linux/include/linux/time.h linux/include/linux/time.h
--- v1.3.62/linux/include/linux/time.h	Sun Feb 11 15:32:46 1996
+++ linux/include/linux/time.h	Tue Feb 13 19:55:59 1996
@@ -2,8 +2,8 @@
 #define _LINUX_TIME_H
 
 struct timespec {
-	long	ts_sec;		/* seconds */
-	long	ts_nsec;	/* nanoseconds */
+	long	tv_sec;		/* seconds */
+	long	tv_nsec;	/* nanoseconds */
 };
 
 struct timeval {
diff -u --recursive --new-file v1.3.62/linux/include/linux/ultrasound.h linux/include/linux/ultrasound.h
--- v1.3.62/linux/include/linux/ultrasound.h	Tue Jul 11 10:02:59 1995
+++ linux/include/linux/ultrasound.h	Sun Feb 11 18:12:39 1996
@@ -1,35 +1,32 @@
 #ifndef _ULTRASOUND_H_
 #define _ULTRASOUND_H_
 /*
- * Copyright by Hannu Savolainen 1993
+ *	ultrasound.h - Macros for programming the Gravis Ultrasound
+ *			These macros are extremely device dependent
+ *			and not portable.
+ */
+/*
+ * Copyright by Hannu Savolainen 1993-1996
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- */
-
-/*
- *	ultrasound.h - Macros for programming the Gravis Ultrasound
- *			These macros are extremely device dependent
- *			and not portable.
  */
 
 /*
diff -u --recursive --new-file v1.3.62/linux/include/net/tcp.h linux/include/net/tcp.h
--- v1.3.62/linux/include/net/tcp.h	Sun Feb 11 15:32:47 1996
+++ linux/include/net/tcp.h	Wed Feb 14 13:20:12 1996
@@ -95,7 +95,7 @@
 
 extern __inline int after(__u32 seq1, __u32 seq2)
 {
-	return (__s32)(seq1-seq2) > 0;
+	return (__s32)(seq2-seq1) < 0;
 }
 
 
@@ -132,7 +132,7 @@
 extern void tcp_retransmit(struct sock *, int);
 extern void tcp_do_retransmit(struct sock *, int);
 extern void tcp_send_check(struct tcphdr *th, unsigned long saddr, 
-		unsigned long daddr, int len, struct sock *sk);
+		unsigned long daddr, int len, struct sk_buff *skb);
 
 /* tcp_output.c */
 
diff -u --recursive --new-file v1.3.62/linux/init/main.c linux/init/main.c
--- v1.3.62/linux/init/main.c	Sun Feb 11 15:32:47 1996
+++ linux/init/main.c	Tue Feb 13 10:30:26 1996
@@ -56,6 +56,7 @@
 
 extern void swap_setup(char *str, int *ints);
 extern void buff_setup(char *str, int *ints);
+extern void panic_setup(char *str, int *ints);
 extern void bmouse_setup(char *str, int *ints);
 extern void eth_setup(char *str, int *ints);
 extern void xd_setup(char *str, int *ints);
@@ -107,6 +108,9 @@
 #ifdef CONFIG_SJCD
 extern void sjcd_setup(char *str, int *ints);
 #endif CONFIG_SJCD
+#ifdef CONFIG_ISP16_CDI
+extern void isp16_setup(char *str, int *ints);
+#endif CONFIG_ISP16_CDI
 #ifdef CONFIG_BLK_DEV_RAM
 static void ramdisk_start_setup(char *str, int *ints);
 static void load_ramdisk(char *str, int *ints);
@@ -194,6 +198,7 @@
 #endif
 	{ "swap=", swap_setup },
 	{ "buff=", buff_setup },
+	{ "panic=", panic_setup },
 #ifdef CONFIG_BUGi386
 	{ "no-hlt", no_halt },
 	{ "no387", no_387 },
@@ -287,6 +292,9 @@
 #ifdef CONFIG_SJCD
 	{ "sjcd=", sjcd_setup },
 #endif CONFIG_SJCD
+#ifdef CONFIG_ISP16_CDI
+	{ "isp16=", isp16_setup },
+#endif CONFIG_ISP16_CDI
 #ifdef CONFIG_SOUND
 	{ "sound=", sound_setup },
 #endif
diff -u --recursive --new-file v1.3.62/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.3.62/linux/kernel/ksyms.c	Fri Feb  9 17:53:10 1996
+++ linux/kernel/ksyms.c	Wed Feb 14 11:57:08 1996
@@ -209,7 +209,6 @@
 	X(add_blkdev_randomness),
 	X(generic_file_read),
 	X(generic_readpage),
-	X(mark_buffer_uptodate),
 
 	/* device registration */
 	X(register_chrdev),
diff -u --recursive --new-file v1.3.62/linux/kernel/panic.c linux/kernel/panic.c
--- v1.3.62/linux/kernel/panic.c	Tue Jun 20 09:10:32 1995
+++ linux/kernel/panic.c	Mon Feb 12 06:45:31 1996
@@ -12,13 +12,24 @@
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/delay.h>
 
 asmlinkage void sys_sync(void);	/* it's really int */
+extern void hard_reset_now(void);
+
+static int timeout = -1;
+
+void panic_setup(char *str, int *ints)
+{
+	if (ints[0] == 1)
+		timeout = ints[1];
+}
 
 NORET_TYPE void panic(const char * fmt, ...)
 {
 	static char buf[1024];
 	va_list args;
+	int i;
 
 	va_start(args, fmt);
 	vsprintf(buf, fmt, args);
@@ -28,6 +39,17 @@
 		printk(KERN_EMERG "In swapper task - not syncing\n");
 	else
 		sys_sync();
+	if (timeout >= 0)
+	{
+		/*
+	 	 * Delay timeout seconds before rebooting the machine. 
+		 * We can't use the "normal" timers since we just paniced..
+	 	 */
+		printk(KERN_EMERG "Rebooting in %d seconds..",timeout);
+		for(i = 0; i < (timeout*1000); i++)
+			udelay(1000);
+		hard_reset_now();
+	}
 	for(;;);
 }
 
diff -u --recursive --new-file v1.3.62/linux/kernel/sched.c linux/kernel/sched.c
--- v1.3.62/linux/kernel/sched.c	Sun Feb 11 15:32:47 1996
+++ linux/kernel/sched.c	Tue Feb 13 19:56:06 1996
@@ -1115,8 +1115,8 @@
 	if (error)
 		return error;
 	
-	t.ts_sec = 0;
-	t.ts_nsec = 0;   /* <-- Linus, please fill correct value in here */
+	t.tv_sec = 0;
+	t.tv_nsec = 0;   /* <-- Linus, please fill correct value in here */
 	return -ENOSYS;  /* and then delete this line. Thanks!           */
 	memcpy_tofs(interval, &t, sizeof(struct timespec));
 
diff -u --recursive --new-file v1.3.62/linux/net/core/dev.c linux/net/core/dev.c
--- v1.3.62/linux/net/core/dev.c	Fri Feb  9 17:53:10 1996
+++ linux/net/core/dev.c	Wed Feb 14 12:26:05 1996
@@ -329,8 +329,8 @@
 void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
 {
 	unsigned long flags;
-	struct packet_type *ptype;
-	int where = 0;		/* used to say if the packet should go	*/
+	struct sk_buff_head *list;
+	int retransmission = 0;	/* used to say if the packet should go	*/
 				/* at the front or the back of the	*/
 				/* queue - front is a retransmit try	*/
 
@@ -350,7 +350,7 @@
   	if (pri < 0) 
   	{
 		pri = -pri-1;
-		where = 1;
+		retransmission = 1;
   	}
 
 #ifdef CONFIG_NET_DEBUG
@@ -382,46 +382,44 @@
 	if (net_alias_is(dev))
 	  	skb->dev = dev = net_alias_main_dev(dev);
 #endif
+	list = dev->buffs + pri;
 
 	save_flags(flags);
-	cli();	
-	if (!where)	 	/* Always keep order. It helps other hosts
-					   far more than it costs us */
-	{
-		/*
-		 *	Check we are not overruning the device queue length.
-		 */
-		 
-		if(skb_queue_len(dev->buffs + pri) > dev->tx_queue_len)
-		{
-			dev_kfree_skb(skb, FREE_WRITE);
-			return;
+	/* if this isn't a retransmission, use the first packet instead... */
+	if (!retransmission) {
+		if (skb_queue_len(list)) {
+			/* avoid overrunning the device queue.. */
+			if (skb_queue_len(list) > dev->tx_queue_len) {
+				dev_kfree_skb(skb, FREE_WRITE);
+				return;
+			}
+			cli();
+			skb_device_unlock(skb);		/* Buffer is on the device queue and can be freed safely */
+			__skb_queue_tail(list, skb);
+			skb = __skb_dequeue(list);
+			skb_device_lock(skb);		/* New buffer needs locking down */
+			restore_flags(flags);
 		}
-		skb_queue_tail(dev->buffs + pri,skb);
-		skb_device_unlock(skb);		/* Buffer is on the device queue and can be freed safely */
-		skb = skb_dequeue(dev->buffs + pri);
-		skb_device_lock(skb);		/* New buffer needs locking down */
-	}
-	restore_flags(flags);
-
-	/* copy outgoing packets to any sniffer packet handlers */
-	if(!where && dev_nit)
-	{
-		skb->stamp=xtime;
-		for (ptype = ptype_all; ptype!=NULL; ptype = ptype->next) 
-		{
-			/* Never send packets back to the socket
-			 * they originated from - MvS (miquels@drinkel.ow.org)
-			 */
-			if ((ptype->dev == dev || !ptype->dev) &&
-			   ((struct sock *)ptype->data != skb->sk))
+		
+		/* copy outgoing packets to any sniffer packet handlers */
+		if (dev_nit) {
+			struct packet_type *ptype;
+			skb->stamp=xtime;
+			for (ptype = ptype_all; ptype!=NULL; ptype = ptype->next) 
 			{
-				struct sk_buff *skb2;
-				if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)
-					break;
-				skb2->h.raw = skb2->data + dev->hard_header_len;
-				skb2->mac.raw = skb2->data;
-				ptype->func(skb2, skb->dev, ptype);
+				/* Never send packets back to the socket
+				 * they originated from - MvS (miquels@drinkel.ow.org)
+				 */
+				if ((ptype->dev == dev || !ptype->dev) &&
+				   ((struct sock *)ptype->data != skb->sk))
+				{
+					struct sk_buff *skb2;
+					if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)
+						break;
+					skb2->h.raw = skb2->data + dev->hard_header_len;
+					skb2->mac.raw = skb2->data;
+					ptype->func(skb2, skb->dev, ptype);
+				}
 			}
 		}
 	}
@@ -441,7 +439,7 @@
 	 */
 	cli();
 	skb_device_unlock(skb);
-	skb_queue_head(dev->buffs + pri,skb);
+	__skb_queue_head(list,skb);
 	restore_flags(flags);
 }
 
@@ -585,7 +583,7 @@
 	 *	While the queue is not empty
 	 */
 	 
-	while((skb=skb_dequeue(&backlog))!=NULL)
+	while((skb=__skb_dequeue(&backlog))!=NULL)
 	{
 		/*
 		 *	We have a packet. Therefore the queue has shrunk
@@ -671,7 +669,7 @@
 		 *	[Ought to take this out judging by tests it slows
 		 *	 us down not speeds us up]
 		 */
-#ifdef CONFIG_XMIT_EVERY
+#ifdef XMIT_EVERY
 		dev_transmit();
 #endif		
 		cli();
@@ -687,8 +685,10 @@
 	/*
 	 *	One last output flush.
 	 */
-	 
+
+#ifdef XMIT_AFTER	 
 	dev_transmit();
+#endif
 }
 
 
@@ -700,8 +700,8 @@
 void dev_tint(struct device *dev)
 {
 	int i;
-	struct sk_buff *skb;
 	unsigned long flags;
+	struct sk_buff_head * head;
 	
 	/*
 	 * aliases do not transmit (for now :) )
@@ -710,21 +710,19 @@
 #ifdef CONFIG_NET_ALIAS
 	if (net_alias_is(dev)) return;
 #endif
-	save_flags(flags);	
+	head = dev->buffs;
+	save_flags(flags);
+	cli();
+
 	/*
 	 *	Work the queues in priority order
-	 */
-	 
-	for(i = 0;i < DEV_NUMBUFFS; i++) 
+	 */	 
+	for(i = 0;i < DEV_NUMBUFFS; i++,head++)
 	{
-		/*
-		 *	Pull packets from the queue
-		 */
-		 
+		struct sk_buff *skb = skb_peek(head);
 
-		cli();
-		while((skb=skb_dequeue(&dev->buffs[i]))!=NULL)
-		{
+		if (skb) {
+			__skb_unlink(skb, head);
 			/*
 			 *	Stop anyone freeing the buffer while we retransmit it
 			 */
diff -u --recursive --new-file v1.3.62/linux/net/core/iovec.c linux/net/core/iovec.c
--- v1.3.62/linux/net/core/iovec.c	Wed Nov  8 07:11:45 1995
+++ linux/net/core/iovec.c	Tue Feb 13 16:57:42 1996
@@ -33,9 +33,10 @@
 	
 	if(m->msg_name!=NULL)
 	{
-		if(mode==VERIFY_READ)
+		if(mode==VERIFY_READ) {
 			err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
-		else
+			m->msg_name = address;
+		} else
 			err=verify_area(mode, m->msg_name, m->msg_namelen);
 		if(err<0)
 			return err;
diff -u --recursive --new-file v1.3.62/linux/net/core/skbuff.c linux/net/core/skbuff.c
--- v1.3.62/linux/net/core/skbuff.c	Wed Feb  7 15:11:42 1996
+++ linux/net/core/skbuff.c	Tue Feb 13 09:53:26 1996
@@ -50,11 +50,11 @@
  *	Resource tracking variables
  */
 
-volatile unsigned long net_skbcount = 0;
-volatile unsigned long net_locked = 0;
-volatile unsigned long net_allocs = 0;
-volatile unsigned long net_fails  = 0;
-volatile unsigned long net_free_locked = 0;
+unsigned long net_skbcount = 0;
+unsigned long net_locked = 0;
+unsigned long net_allocs = 0;
+unsigned long net_fails  = 0;
+unsigned long net_free_locked = 0;
 
 extern unsigned long ip_frag_mem;
 
@@ -517,7 +517,6 @@
 struct sk_buff *alloc_skb(unsigned int size,int priority)
 {
 	struct sk_buff *skb;
-	unsigned long flags;
 	int len=size;
 	unsigned char *bptr;
 
@@ -574,10 +573,7 @@
 	skb->localroute = 0;
 	skb->ip_summed = 0;
 	memset(skb->proto_priv, 0, sizeof(skb->proto_priv));
-	save_flags(flags);
-	cli();
 	net_skbcount++;
-	restore_flags(flags);
 #if CONFIG_SKB_CHECK
 	skb->magic_debug_cookie = SK_GOOD_SKB;
 #endif
@@ -596,6 +592,15 @@
  *	Free an skbuff by memory
  */
 
+static inline void __kfree_skbmem(struct sk_buff *skb)
+{
+	/* don't do anything if somebody still uses us */
+	if (--skb->count <= 0) {
+		kfree(skb->head);
+		net_skbcount--;
+	}
+}
+
 void kfree_skbmem(struct sk_buff *skb)
 {
 	unsigned long flags;
@@ -608,7 +613,7 @@
 		/* free the skb that contains the actual data if we've clone()'d */
 		if (skb->data_skb) {
 			addr = skb;
-			kfree_skbmem(skb->data_skb);
+			__kfree_skbmem(skb->data_skb);
 		}
 		kfree(addr);
 		net_skbcount--;
@@ -623,8 +628,8 @@
 
 struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
 {
-	struct sk_buff *n;
 	unsigned long flags;
+	struct sk_buff *n;
 
 	IS_SKB(skb);
 	n = kmalloc(sizeof(*n), priority);
@@ -649,22 +654,6 @@
 	n->tries = 0;
 	n->lock = 0;
 	n->users = 0;
-	n->h.raw=skb->h.raw;
-	n->mac.raw=skb->mac.raw;
-	n->dev=skb->dev;
-	n->ip_hdr=skb->ip_hdr;
-	n->saddr=skb->saddr;
-	n->daddr=skb->daddr;
-	n->raddr=skb->raddr;
-	n->seq=skb->seq;
-	n->end_seq=skb->end_seq;
-	n->ack_seq=skb->ack_seq;
-	n->acked=skb->acked;
-	memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
-	n->used=skb->used;
-	n->arp=skb->arp;
-	n->pkt_type=skb->pkt_type;
-	n->stamp=skb->stamp;
 	return n;
 }
 
diff -u --recursive --new-file v1.3.62/linux/net/core/sock.c linux/net/core/sock.c
--- v1.3.62/linux/net/core/sock.c	Sun Feb 11 15:32:47 1996
+++ linux/net/core/sock.c	Wed Feb 14 09:26:25 1996
@@ -544,45 +544,37 @@
 
 void release_sock(struct sock *sk)
 {
-	unsigned long flags;
 #ifdef CONFIG_INET
 	struct sk_buff *skb;
 #endif
 
+	/*
+	 * First, mark it not in use: this ensures that we will not
+	 * get any new backlog packets..
+	 */
+	sk->inuse = 0;
+
+#ifdef CONFIG_INET
 	if (!sk->prot)
 		return;
+		
 	/*
-	 *	Make the backlog atomic. If we don't do this there is a tiny
-	 *	window where a packet may arrive between the sk->blog being 
-	 *	tested and then set with sk->inuse still 0 causing an extra 
-	 *	unwanted re-entry into release_sock().
+	 *	This is only ever called from a user process context, hence
+	 *	(until fine grained SMP) its safe. sk->inuse must be volatile
+	 *	so the compiler doesn't do anything unfortunate with it.
 	 */
 
-	save_flags(flags);
-	cli();
-	if (sk->blog) 
-	{
-		restore_flags(flags);
-		return;
-	}
-	sk->blog=1;
-	sk->inuse = 1;
-	restore_flags(flags);
-#ifdef CONFIG_INET
 	/* See if we have any packets built up. */
-	while((skb = skb_dequeue(&sk->back_log)) != NULL) 
+	while ((skb = __skb_dequeue(&sk->back_log)) != NULL) 
 	{
-		sk->blog = 1;
+		sk->inuse = 1;		/* Very important.. */
 		if (sk->prot->rcv) 
 			sk->prot->rcv(skb, skb->dev, (struct options*)skb->proto_priv,
 				 skb->saddr, skb->len, skb->daddr, 1,
 				/* Only used for/by raw sockets. */
 				(struct inet_protocol *)sk->pair); 
+		sk->inuse = 0;
 	}
-#endif  
-	sk->blog = 0;
-	sk->inuse = 0;
-#ifdef CONFIG_INET  
 	if (sk->dead && sk->state == TCP_CLOSE) 
 	{
 		/* Should be about 2 rtt's */
diff -u --recursive --new-file v1.3.62/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v1.3.62/linux/net/ipv4/af_inet.c	Sun Feb 11 15:32:47 1996
+++ linux/net/ipv4/af_inet.c	Wed Feb 14 09:26:25 1996
@@ -587,8 +587,9 @@
 	if (sk == NULL) 
 		return(-ENOBUFS);
 	memset(sk,0,sizeof(*sk));	/* Efficient way to set most fields to zero */
-/*	sk->num = 0;
- *	sk->reuse = 0;*/
+	/*
+	 *	Note for tcp that also wiped the dummy_th block for us.
+	 */
 	switch(sock->type) 
 	{
 		case SOCK_STREAM:
@@ -653,8 +654,6 @@
 	sk->socket = sock;
 #ifdef CONFIG_TCP_NAGLE_OFF
 	sk->nonagle = 1;
-#else    
-/*	sk->nonagle = 0;*/
 #endif  
 	sk->type = sock->type;
 	sk->protocol = protocol;
@@ -693,6 +692,13 @@
 	*sk->ip_mc_name=0;
 	sk->ip_mc_list=NULL;
 #endif
+	/*
+	 *	Speed up by setting some standard state for the dummy_th
+	 *	if TCP uses it (maybe move to tcp_init later)
+	 */
+  	
+  	sk->dummy_th.ack=1;	
+  	sk->dummy_th.doff=sizeof(struct tcphdr)>>2;
   	
 	sk->state_change = def_callback1;
 	sk->data_ready = def_callback2;
diff -u --recursive --new-file v1.3.62/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v1.3.62/linux/net/ipv4/tcp.c	Sun Feb 11 15:32:48 1996
+++ linux/net/ipv4/tcp.c	Wed Feb 14 09:26:25 1996
@@ -802,14 +802,31 @@
  *	Modified January 1995 from a go-faster DOS routine by
  *	Jorge Cwik <jorge@laser.satlink.net>
  */
- 
+#undef DEBUG_TCP_CHECK
 void tcp_send_check(struct tcphdr *th, unsigned long saddr, 
-		unsigned long daddr, int len, struct sock *sk)
+		unsigned long daddr, int len, struct sk_buff *skb)
 {
+#ifdef DEBUG_TCP_CHECK
+	u16 check;
+#endif
+	th->check = 0;
+	th->check = tcp_check(th, len, saddr, daddr,
+		csum_partial((char *)th,sizeof(*th),skb->csum));
+
+#ifdef DEBUG_TCP_CHECK
+	check = th->check;
 	th->check = 0;
 	th->check = tcp_check(th, len, saddr, daddr,
 		csum_partial((char *)th,len,0));
-	return;
+	if (check != th->check) {
+		static int count = 0;
+		if (++count < 10) {
+			printk("Checksum %x (%x) from %p\n", th->check, check,
+				(&th)[-1]);
+			printk("TCP=<off:%d a:%d s:%d f:%d>\n", th->doff*4, th->ack, th->syn, th->fin);
+		}
+	}
+#endif
 }
 
 
@@ -823,9 +840,6 @@
 	memcpy(th,(void *) &(sk->dummy_th), sizeof(*th));
 	th->seq = htonl(sk->write_seq);
 	th->psh =(push == 0) ? 1 : 0;
-	th->doff = sizeof(*th)/4;
-	th->ack = 1;
-	th->fin = 0;
 	sk->ack_backlog = 0;
 	sk->bytes_rcv = 0;
 	sk->ack_timed = 0;
@@ -1003,30 +1017,29 @@
 	
 			if ((skb = tcp_dequeue_partial(sk)) != NULL) 
 			{
-				int hdrlen;
+				int tcp_size;
 
-				 /* IP header + TCP header */
-				hdrlen = ((unsigned long)skb->h.th - (unsigned long)skb->data)
-					 + sizeof(struct tcphdr);
+				tcp_size = skb->tail - (unsigned char *)(skb->h.th + 1);
 	
 				/* Add more stuff to the end of skb->len */
 				if (!(flags & MSG_OOB)) 
 				{
-					copy = min(sk->mss - (skb->len - hdrlen), seglen);
+					copy = min(sk->mss - tcp_size, seglen);
 					if (copy <= 0) 
 					{
 						printk("TCP: **bug**: \"copy\" <= 0\n");
 				  		return -EFAULT;
-					}		  
+					}
+					tcp_size += copy;
 					memcpy_fromfs(skb_put(skb,copy), from, copy);
+					skb->csum = csum_partial(skb->tail - tcp_size, tcp_size, 0);
 					from += copy;
 					copied += copy;
 					len -= copy;
 					sk->write_seq += copy;
 					seglen -= copy;
 				}
-				if ((skb->len - hdrlen) >= sk->mss ||
-					(flags & MSG_OOB) || !sk->packets_out)
+				if (tcp_size >= sk->mss || (flags & MSG_OOB) || !sk->packets_out)
 					tcp_send_skb(sk, skb);
 				else
 					tcp_enqueue_partial(skb, sk);
@@ -1058,6 +1071,11 @@
 			send_tmp = NULL;
 			if (copy < sk->mss && !(flags & MSG_OOB) && sk->packets_out) 
 			{
+#if EXTRA_RELEASE
+/*
+ * we don't really need to release even if we sleep: our packets
+ * will be backlogged for us, and that's just fine.
+ */
 				/*
 				 *	We will release the socket in case we sleep here. 
 				 */
@@ -1066,16 +1084,19 @@
 				 *	NB: following must be mtu, because mss can be increased.
 				 *	mss is always <= mtu 
 				 */
+#endif
 				skb = sock_wmalloc(sk, sk->mtu + 128 + prot->max_header + 15, 0, GFP_KERNEL);
 				sk->inuse = 1;
 				send_tmp = skb;
 			} 
 			else 
 			{
+#if EXTRA_RELEASE
 				/*
 				 *	We will release the socket in case we sleep here. 
 				 */
 				release_sock(sk);
+#endif
 				skb = sock_wmalloc(sk, copy + prot->max_header + 15 , 0, GFP_KERNEL);
   				sk->inuse = 1;
 			}
@@ -1156,7 +1177,8 @@
 				skb->h.th->urg_ptr = ntohs(copy);
 			}
 
-			memcpy_fromfs(skb_put(skb,copy), from, copy);
+			skb->csum = csum_partial_copy_fromuser(from,
+				skb_put(skb,copy), copy, 0);
 		
 			from += copy;
 			copied += copy;
@@ -1240,6 +1262,7 @@
 
 	buff->sk = sk;
 	buff->localroute = sk->localroute;
+	buff->csum = 0;
 	
 	/*
 	 *	Put in the IP header and routing stuff. 
@@ -1258,14 +1281,6 @@
 
 	memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
 	t1->seq = htonl(sk->sent_seq);
-	t1->ack = 1;
-	t1->res1 = 0;
-	t1->res2 = 0;
-	t1->rst = 0;
-	t1->urg = 0;
-	t1->syn = 0;
-	t1->psh = 0;
-
 
 	sk->ack_backlog = 0;
 	sk->bytes_rcv = 0;
@@ -1274,13 +1289,90 @@
 	t1->window = htons(sk->window);
 	t1->ack_seq = htonl(sk->acked_seq);
 	t1->doff = sizeof(*t1)/4;
-	tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
+	tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), buff);
 	sk->prot->queue_xmit(sk, dev, buff, 1);
 	tcp_statistics.TcpOutSegs++;
 }
 
 
 /*
+ *	Handle reading urgent data. BSD has very simple semantics for
+ *	this, no blocking and very strange errors 8)
+ */
+ 
+static int tcp_recv_urg(struct sock * sk, int nonblock,
+	     struct msghdr *msg, int len, int flags, int *addr_len)
+{
+	/*
+	 *	No URG data to read
+	 */
+	if (sk->urginline || !sk->urg_data || sk->urg_data == URG_READ)
+		return -EINVAL;	/* Yes this is right ! */
+		
+	if (sk->err) 
+		return sock_error(sk);
+		
+	if (sk->state == TCP_CLOSE || sk->done) 
+	{
+		if (!sk->done) 
+		{
+			sk->done = 1;
+			return 0;
+		}
+		return -ENOTCONN;
+	}
+
+	if (sk->shutdown & RCV_SHUTDOWN) 
+	{
+		sk->done = 1;
+		return 0;
+	}
+	sk->inuse = 1;
+	if (sk->urg_data & URG_VALID) 
+	{
+		char c = sk->urg_data;
+		if (!(flags & MSG_PEEK))
+			sk->urg_data = URG_READ;
+		memcpy_toiovec(msg->msg_iov, &c, 1);
+		if(msg->msg_name)
+		{
+			struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
+			sin->sin_family=AF_INET;
+			sin->sin_addr.s_addr=sk->daddr;
+			sin->sin_port=sk->dummy_th.dest;
+		}
+		if(addr_len)
+			*addr_len=sizeof(struct sockaddr_in);
+		release_sock(sk);
+		return 1;
+	}
+	release_sock(sk);
+	
+	/*
+	 * Fixed the recv(..., MSG_OOB) behaviour.  BSD docs and
+	 * the available implementations agree in this case:
+	 * this call should never block, independent of the
+	 * blocking state of the socket.
+	 * Mike <pall@rz.uni-karlsruhe.de>
+	 */
+	return -EAGAIN;
+}
+
+/*
+ *	Release a skb if it is no longer needed. This routine
+ *	must be called with interrupts disabled or "sk->inuse = 1"
+ *	so that the sk_buff queue operation is ok.
+ */
+ 
+static inline void tcp_eat_skb(struct sock *sk, struct sk_buff * skb)
+{
+	sk->ack_backlog++;
+	skb->sk = sk;
+	__skb_unlink(skb, &sk->receive_queue);
+	kfree_skb(skb, FREE_READ);
+}
+
+/*
  * 	FIXME:
  * 	This routine frees used buffers.
  * 	It should consider sending an ACK to let the
@@ -1289,37 +1381,20 @@
 
 static void cleanup_rbuf(struct sock *sk)
 {
-	unsigned long flags;
 	struct sk_buff *skb;
 	unsigned long rspace;
 
-	save_flags(flags);
-	cli();
-
 	/*
-	 * See if we have anything to free up?
+	 * NOTE! 'sk->inuse' must be set, so that we don't get
+	 * a messed-up receive queue.
 	 */
-
-	skb = skb_peek(&sk->receive_queue);
-	if (!skb || !skb->used || skb->users) {
-		restore_flags(flags);
-		return;
+	while ((skb=skb_peek(&sk->receive_queue)) != NULL) {
+		if (!skb->used || skb->users)
+			break;
+		tcp_eat_skb(sk, skb);
 	}
 
 	/*
-	 *	We have to loop through all the buffer headers,
-	 *	and try to free up all the space we can.
-	 */
-
-	do {
-		skb_unlink(skb);
-		skb->sk = sk;
-		kfree_skb(skb, FREE_READ);
-		skb = skb_peek(&sk->receive_queue);
-	} while (skb && skb->used && !skb->users);
-	restore_flags(flags);
-
-	/*
 	 *	FIXME:
 	 *	At this point we should send an ack if the difference
 	 *	in the window, and the amount of space is bigger than
@@ -1339,7 +1414,6 @@
 	 * immediately.  Otherwise we will wait up to .5 seconds in case
 	 * the user reads some more.
 	 */
-	sk->ack_backlog++;
 
 	/*
 	 * It's unclear whether to use sk->mtu or sk->mss here.  They differ only
@@ -1370,70 +1444,6 @@
 
 
 /*
- *	Handle reading urgent data. BSD has very simple semantics for
- *	this, no blocking and very strange errors 8)
- */
- 
-static int tcp_recv_urg(struct sock * sk, int nonblock,
-	     struct msghdr *msg, int len, int flags, int *addr_len)
-{
-	/*
-	 *	No URG data to read
-	 */
-	if (sk->urginline || !sk->urg_data || sk->urg_data == URG_READ)
-		return -EINVAL;	/* Yes this is right ! */
-		
-	if (sk->err) 
-		return sock_error(sk);
-		
-	if (sk->state == TCP_CLOSE || sk->done) 
-	{
-		if (!sk->done) 
-		{
-			sk->done = 1;
-			return 0;
-		}
-		return -ENOTCONN;
-	}
-
-	if (sk->shutdown & RCV_SHUTDOWN) 
-	{
-		sk->done = 1;
-		return 0;
-	}
-	sk->inuse = 1;
-	if (sk->urg_data & URG_VALID) 
-	{
-		char c = sk->urg_data;
-		if (!(flags & MSG_PEEK))
-			sk->urg_data = URG_READ;
-		memcpy_toiovec(msg->msg_iov, &c, 1);
-		if(msg->msg_name)
-		{
-			struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
-			sin->sin_family=AF_INET;
-			sin->sin_addr.s_addr=sk->daddr;
-			sin->sin_port=sk->dummy_th.dest;
-		}
-		if(addr_len)
-			*addr_len=sizeof(struct sockaddr_in);
-		release_sock(sk);
-		return 1;
-	}
-	release_sock(sk);
-	
-	/*
-	 * Fixed the recv(..., MSG_OOB) behaviour.  BSD docs and
-	 * the available implementations agree in this case:
-	 * this call should never block, independent of the
-	 * blocking state of the socket.
-	 * Mike <pall@rz.uni-karlsruhe.de>
-	 */
-	return -EAGAIN;
-}
-
-
-/*
  *	This routine copies from a sock struct into the user buffer. 
  */
  
@@ -1637,6 +1647,8 @@
 		if (flags & MSG_PEEK)
 			continue;
 		skb->used = 1;
+		if (!skb->users)
+			tcp_eat_skb(sk, skb);		
 		continue;
 
 	found_fin_ok:
@@ -2001,13 +2013,7 @@
 	buff->end_seq = sk->write_seq;
 	t1->ack = 0;
 	t1->window = 2;
-	t1->res1=0;
-	t1->res2=0;
-	t1->rst = 0;
-	t1->urg = 0;
-	t1->psh = 0;
 	t1->syn = 1;
-	t1->urg_ptr = 0;
 	t1->doff = 6;
 	/* use 512 or whatever user asked for */
 	
@@ -2056,8 +2062,9 @@
 	ptr[1] = 4;
 	ptr[2] = (sk->mtu) >> 8;
 	ptr[3] = (sk->mtu) & 0xff;
+	buff->csum = csum_partial(ptr, 4, 0);
 	tcp_send_check(t1, sk->saddr, sk->daddr,
-		  sizeof(struct tcphdr) + 4, sk);
+		  sizeof(struct tcphdr) + 4, buff);
 
 	/*
 	 *	This must go first otherwise a really quick response will get reset. 
diff -u --recursive --new-file v1.3.62/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v1.3.62/linux/net/ipv4/tcp_input.c	Sun Feb 11 15:32:48 1996
+++ linux/net/ipv4/tcp_input.c	Wed Feb 14 09:26:26 1996
@@ -24,10 +24,97 @@
 #include <net/tcp.h>
 
 /*
+ *	Policy code extracted so its now seperate
+ */
+
+/*
+ *	Called each time to estimate the delayed ack timeout. This is
+ *	how it should be done so a fast link isnt impacted by ack delay.
+ */
+ 
+extern __inline__ void tcp_delack_estimator(struct sock *sk)
+{
+	/*
+	 *	Delayed ACK time estimator.
+	 */
+	
+	if (sk->lrcvtime == 0) 
+	{
+		sk->lrcvtime = jiffies;
+		sk->ato = HZ/3;
+	}
+	else 
+	{
+		int m;
+		
+		m = jiffies - sk->lrcvtime;
+
+		sk->lrcvtime = jiffies;
+
+		if (m <= 0)
+			m = 1;
+
+		if (m > (sk->rtt >> 3)) 
+		{
+			sk->ato = sk->rtt >> 3;
+			/*
+			 * printk(KERN_DEBUG "ato: rtt %lu\n", sk->ato);
+			 */
+		}
+		else 
+		{
+			sk->ato = (sk->ato >> 1) + m;
+			/*
+			 * printk(KERN_DEBUG "ato: m %lu\n", sk->ato);
+			 */
+		}
+	}
+}
+
+/*
+ *	Called on frames that were known _not_ to have been
+ *	retransmitted [see Karn/Partridge Proceedings SIGCOMM 87]. 
+ *	The algorithm is from the SIGCOMM 88 piece by Van Jacobson.
+ */
+ 
+extern __inline__ void tcp_rtt_estimator(struct sock *sk, struct sk_buff *oskb)
+{
+	long m;
+	/*
+	 *	The following amusing code comes from Jacobson's
+	 *	article in SIGCOMM '88.  Note that rtt and mdev
+	 *	are scaled versions of rtt and mean deviation.
+	 *	This is designed to be as fast as possible 
+	 *	m stands for "measurement".
+	 */
+	
+	m = jiffies - oskb->when;  /* RTT */
+	if(m<=0)
+		m=1;		/* IS THIS RIGHT FOR <0 ??? */
+	m -= (sk->rtt >> 3);    /* m is now error in rtt est */
+	sk->rtt += m;           /* rtt = 7/8 rtt + 1/8 new */
+	if (m < 0)
+		m = -m;		/* m is now abs(error) */
+	m -= (sk->mdev >> 2);   /* similar update on mdev */
+	sk->mdev += m;	    	/* mdev = 3/4 mdev + 1/4 new */
+
+	/*
+	 *	Now update timeout.  Note that this removes any backoff.
+	 */
+			 
+	sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1;
+	if (sk->rto > 120*HZ)
+		sk->rto = 120*HZ;
+	if (sk->rto < HZ/5)	/* Was 1*HZ - keep .2 as minimum cos of the BSD delayed acks */
+		sk->rto = HZ/5;
+	sk->backoff = 0;
+}
+
+/*
  *	Cached last hit socket
  */
  
-static volatile unsigned long 	th_cache_saddr,th_cache_daddr;
+static volatile unsigned long 	th_cache_saddr, th_cache_daddr;
 static volatile unsigned short  th_cache_dport, th_cache_sport;
 static volatile struct sock *th_cache_sk;
 
@@ -37,8 +124,10 @@
 }
 
 /*
- *	Find the socket, using the last hit cache if applicable.
+ *	Find the socket, using the last hit cache if applicable. The cache is not quite
+ *	right...
  */
+
 static inline struct sock * get_tcp_sock(u32 saddr, u16 sport, u32 daddr, u16 dport)
 {
 	struct sock * sk;
@@ -61,6 +150,7 @@
 /*
  * React to a out-of-window TCP sequence number in an incoming packet
  */
+ 
 static void bad_tcp_sequence(struct sock *sk, struct tcphdr *th, short len,
 	     struct options *opt, unsigned long saddr, struct device *dev)
 {
@@ -79,8 +169,16 @@
 		tcp_send_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev, sk->ip_tos,sk->ip_ttl);
 		return;
 	}
-
-	/* Try to resync things. */
+	
+	/*
+	 *	4.3reno machines look for these kind of acks so they can do fast
+	 *	recovery. Three identical 'old' acks lets it know that one frame has
+	 *	been lost and should be resent. Because this is before the whole window
+	 *	of data has timed out it can take one lost frame per window without
+	 *	stalling. [See Jacobson RFC1323, Stevens TCP/IP illus vol2]
+	 *
+	 *	We also should be spotting triple bad sequences.
+	 */
 	tcp_send_ack(sk->sent_seq, sk->acked_seq, sk, th, saddr);
 	return;
 }
@@ -99,20 +197,29 @@
 }
 
 /*
- *	When we get a reset we do this.
+ *	When we get a reset we do this. This probably is a tcp_output routine
+ *	really.
  */
 
 static int tcp_reset(struct sock *sk, struct sk_buff *skb)
 {
 	sk->zapped = 1;
+	/*
+	 *	We want the right error as BSD sees it (and indeed as we do).
+	 */
 	sk->err = ECONNRESET;
 	if (sk->state == TCP_SYN_SENT)
 		sk->err = ECONNREFUSED;
 	if (sk->state == TCP_CLOSE_WAIT)
 		sk->err = EPIPE;
-#ifdef TCP_DO_RFC1337		
+#ifdef CONFIG_TCP_RFC1337
 	/*
 	 *	Time wait assassination protection [RFC1337]
+	 *
+	 *	This is a good idea, but causes more sockets to take time to close.
+	 *
+	 *	Ian Heavens has since shown this is an inadequate fix for the protocol
+	 *	bug in question.
 	 */
 	if(sk->state!=TCP_TIME_WAIT)
 	{	
@@ -228,8 +335,11 @@
 	}
 
 	/*
-	 * Make sure we can accept more.  This will prevent a
-	 * flurry of syns from eating up all our memory.
+	 *	Make sure we can accept more.  This will prevent a
+	 *	flurry of syns from eating up all our memory.
+	 *
+	 *	BSD does some funnies here and allows 3/2 times the
+	 *	set backlog as a fudge factor. Thats just too gross.
 	 */
 
 	if (sk->ack_backlog >= sk->max_ack_backlog) 
@@ -259,21 +369,24 @@
 	memcpy(newsk, sk, sizeof(*newsk));
 	newsk->opt = NULL;
 	newsk->ip_route_cache  = NULL;
-	if (opt && opt->optlen) {
-	  sk->opt = (struct options*)kmalloc(sizeof(struct options)+opt->optlen, GFP_ATOMIC);
-	  if (!sk->opt) {
-	        kfree_s(newsk, sizeof(struct sock));
-		tcp_statistics.TcpAttemptFails++;
-		kfree_skb(skb, FREE_READ);
-		return;
-	  }
-	  if (ip_options_echo(sk->opt, opt, daddr, saddr, skb)) {
-		kfree_s(sk->opt, sizeof(struct options)+opt->optlen);
-	        kfree_s(newsk, sizeof(struct sock));
-		tcp_statistics.TcpAttemptFails++;
-		kfree_skb(skb, FREE_READ);
-		return;
-	  }
+	if (opt && opt->optlen) 
+	{
+		sk->opt = (struct options*)kmalloc(sizeof(struct options)+opt->optlen, GFP_ATOMIC);
+		if (!sk->opt) 
+		{
+	        	kfree_s(newsk, sizeof(struct sock));
+			tcp_statistics.TcpAttemptFails++;
+			kfree_skb(skb, FREE_READ);
+			return;
+		}
+		if (ip_options_echo(sk->opt, opt, daddr, saddr, skb)) 
+		{
+			kfree_s(sk->opt, sizeof(struct options)+opt->optlen);
+	        	kfree_s(newsk, sizeof(struct sock));
+			tcp_statistics.TcpAttemptFails++;
+			kfree_skb(skb, FREE_READ);
+			return;
+		}
 	}
 	skb_queue_head_init(&newsk->write_queue);
 	skb_queue_head_init(&newsk->receive_queue);
@@ -336,15 +449,6 @@
 	newsk->rcv_saddr = daddr;
 
 	put_sock(newsk->num,newsk);
-	newsk->dummy_th.res1 = 0;
-	newsk->dummy_th.doff = 6;
-	newsk->dummy_th.fin = 0;
-	newsk->dummy_th.syn = 0;
-	newsk->dummy_th.rst = 0;	
-	newsk->dummy_th.psh = 0;
-	newsk->dummy_th.ack = 0;
-	newsk->dummy_th.urg = 0;
-	newsk->dummy_th.res2 = 0;
 	newsk->acked_seq = skb->seq + 1;
 	newsk->copied_seq = skb->seq + 1;
 	newsk->socket = NULL;
@@ -409,14 +513,83 @@
 	tcp_send_synack(newsk, sk, skb);
 }
 
+
+/*
+ * Handle a TCP window that shrunk on us. It shouldn't happen,
+ * but..
+ *
+ * We may need to move packets from the send queue
+ * to the write queue, if the window has been shrunk on us.
+ * The RFC says you are not allowed to shrink your window
+ * like this, but if the other end does, you must be able
+ * to deal with it.
+ */
+void tcp_window_shrunk(struct sock * sk, u32 window_seq)
+{
+	struct sk_buff *skb;
+	struct sk_buff *skb2;
+	struct sk_buff *wskb = NULL;
+ 	
+	skb2 = sk->send_head;
+	sk->send_head = NULL;
+	sk->send_tail = NULL;
+
+	/*
+	 *	This is an artifact of a flawed concept. We want one
+	 *	queue and a smarter send routine when we send all.
+	 */
+	cli();
+	while (skb2 != NULL) 
+	{
+		skb = skb2;
+		skb2 = skb->link3;
+		skb->link3 = NULL;
+		if (after(skb->end_seq, window_seq)) 
+		{
+			if (sk->packets_out > 0) 
+				sk->packets_out--;
+			/* We may need to remove this from the dev send list. */
+			if (skb->next != NULL) 
+			{
+				skb_unlink(skb);				
+			}
+			/* Now add it to the write_queue. */
+			if (wskb == NULL)
+				skb_queue_head(&sk->write_queue,skb);
+			else
+				skb_append(wskb,skb);
+			wskb = skb;
+		} 
+		else 
+		{
+			if (sk->send_head == NULL) 
+			{
+				sk->send_head = skb;
+				sk->send_tail = skb;
+			}
+			else
+			{
+				sk->send_tail->link3 = skb;
+				sk->send_tail = skb;
+			}
+			skb->link3 = NULL;
+		}
+	}
+	sti();
+}
+
+
 /*
  *	This routine deals with incoming acks, but not outgoing ones.
+ *
+ *	This routine is totally _WRONG_. The list structuring is wrong,
+ *	the algorithm is wrong, the code is wrong.
  */
 
 static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len)
 {
 	int flag = 0;
-	unsigned window;
+	u32 window_seq;
 
 	/* 
 	 * 1 - there was data in packet as well as ack or new data is sent or 
@@ -429,29 +602,11 @@
 		return(1);	/* Dead, cant ack any more so why bother */
 
 	/*
-	 *	Have we discovered a larger window
-	 */
-	 
-	window = ntohs(th->window);
-
-	if (window > sk->max_window) 
-	{
-  		sk->max_window = window;
-#ifdef CONFIG_INET_PCTCP
-		/* Hack because we don't send partial packets to non SWS
-		   handling hosts */
-		sk->mss = min(window>>1, sk->mtu);
-#else
-		sk->mss = min(window, sk->mtu);
-#endif	
-	}
-
-	/*
 	 *	We have dropped back to keepalive timeouts. Thus we have
 	 *	no retransmits pending.
 	 */
 	 
-	if (sk->retransmits && sk->ip_xmit_timeout == TIME_KEEPOPEN)
+	if (sk->ip_xmit_timeout == TIME_KEEPOPEN)
 	  	sk->retransmits = 0;
 
 	/*
@@ -460,30 +615,7 @@
 	 */
 	 
 	if (after(ack, sk->sent_seq) || before(ack, sk->rcv_ack_seq)) 
-	{
-		if(sk->debug)
-			printk("Ack ignored %u %u\n",ack,sk->sent_seq);
-			
-		/*
-		 *	Keepalive processing.
-		 */
-		 
-		if (after(ack, sk->sent_seq)) 
-		{
-			return(0);
-		}
-		
-		/*
-		 *	Restart the keepalive timer.
-		 */
-		 
-		if (sk->keepopen) 
-		{
-			if(sk->ip_xmit_timeout==TIME_KEEPOPEN)
-				tcp_reset_xmit_timer(sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
-		}
-		return(1);
-	}
+		goto uninteresting_ack;
 
 	/*
 	 *	If there is data set flag 1
@@ -493,78 +625,38 @@
 		flag |= 1;
 
 	/*
-	 *	See if our window has been shrunk. 
+	 *	Have we discovered a larger window
 	 */
-
-	if (after(sk->window_seq, ack+window)) 
+	window_seq = ntohs(th->window);
+	if (window_seq > sk->max_window) 
 	{
-		/*
-		 * We may need to move packets from the send queue
-		 * to the write queue, if the window has been shrunk on us.
-		 * The RFC says you are not allowed to shrink your window
-		 * like this, but if the other end does, you must be able
-		 * to deal with it.
-		 */
-		struct sk_buff *skb;
-		struct sk_buff *skb2;
-		struct sk_buff *wskb = NULL;
-  	
-		skb2 = sk->send_head;
-		sk->send_head = NULL;
-		sk->send_tail = NULL;
-	
-		/*
-		 *	This is an artifact of a flawed concept. We want one
-		 *	queue and a smarter send routine when we send all.
-		 */
-	
-		flag |= 4;	/* Window changed */
-	
-		sk->window_seq = ack + window;
-		cli();
-		while (skb2 != NULL) 
-		{
-			skb = skb2;
-			skb2 = skb->link3;
-			skb->link3 = NULL;
-			if (after(skb->end_seq, sk->window_seq)) 
-			{
-				if (sk->packets_out > 0) 
-					sk->packets_out--;
-				/* We may need to remove this from the dev send list. */
-				if (skb->next != NULL) 
-				{
-					skb_unlink(skb);				
-				}
-				/* Now add it to the write_queue. */
-				if (wskb == NULL)
-					skb_queue_head(&sk->write_queue,skb);
-				else
-					skb_append(wskb,skb);
-				wskb = skb;
-			} 
-			else 
-			{
-				if (sk->send_head == NULL) 
-				{
-					sk->send_head = skb;
-					sk->send_tail = skb;
-				}
-				else
-				{
-					sk->send_tail->link3 = skb;
-					sk->send_tail = skb;
-				}
-				skb->link3 = NULL;
-			}
-		}
-		sti();
+  		sk->max_window = window_seq;
+#ifdef CONFIG_INET_PCTCP
+		/* Hack because we don't send partial packets to non SWS
+		   handling hosts */
+		sk->mss = min(window_seq>>1, sk->mtu);
+#else
+		sk->mss = min(window_seq, sk->mtu);
+#endif	
 	}
+	window_seq += ack;
 
 	/*
-	 *	Pipe has emptied
+	 *	See if our window has been shrunk. 
 	 */
-	 
+	if (after(sk->window_seq, window_seq)) {
+		flag |= 4;
+		tcp_window_shrunk(sk, window_seq);
+	}
+
+	/*
+	 *	Update the right hand window edge of the host
+	 */
+	sk->window_seq = window_seq;
+
+	/*
+	 *	Pipe has emptied
+	 */	 
 	if (sk->send_tail == NULL || sk->send_head == NULL) 
 	{
 		sk->send_head = NULL;
@@ -573,18 +665,13 @@
 	}
 
 	/*
-	 *	Update the right hand window edge of the host
-	 */
-	 
-	sk->window_seq = ack + window;
-
-	/*
 	 *	We don't want too many packets out there. 
 	 */
 	 
 	if (sk->ip_xmit_timeout == TIME_WRITE && 
 		sk->cong_window < 2048 && after(ack, sk->rcv_ack_seq)) 
 	{
+		
 		/* 
 		 * This is Jacobson's slow start and congestion avoidance. 
 		 * SIGCOMM '88, p. 328.  Because we keep cong_window in integral
@@ -722,38 +809,7 @@
 			oskb = sk->send_head;
 
 			if (!(flag&2)) 	/* Not retransmitting */
-			{
-				long m;
-	
-				/*
-				 *	The following amusing code comes from Jacobson's
-				 *	article in SIGCOMM '88.  Note that rtt and mdev
-				 *	are scaled versions of rtt and mean deviation.
-				 *	This is designed to be as fast as possible 
-				 *	m stands for "measurement".
-				 */
-	
-				m = jiffies - oskb->when;  /* RTT */
-				if(m<=0)
-					m=1;		/* IS THIS RIGHT FOR <0 ??? */
-				m -= (sk->rtt >> 3);    /* m is now error in rtt est */
-				sk->rtt += m;           /* rtt = 7/8 rtt + 1/8 new */
-				if (m < 0)
-					m = -m;		/* m is now abs(error) */
-				m -= (sk->mdev >> 2);   /* similar update on mdev */
-				sk->mdev += m;	    	/* mdev = 3/4 mdev + 1/4 new */
-	
-				/*
-				 *	Now update timeout.  Note that this removes any backoff.
-				 */
-			 
-				sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1;
-				if (sk->rto > 120*HZ)
-					sk->rto = 120*HZ;
-				if (sk->rto < HZ/5)	/* Was 1*HZ - keep .2 as minimum cos of the BSD delayed acks */
-					sk->rto = HZ/5;
-				sk->backoff = 0;
-			}
+				tcp_rtt_estimator(sk,oskb);
 			flag |= (2|4);	/* 2 is really more like 'don't adjust the rtt 
 					   In this case as we just set it up */
 			cli();
@@ -1000,7 +1056,31 @@
 		}
 	}
 
-	return(1);
+	return 1;
+
+uninteresting_ack:
+	if(sk->debug)
+		printk("Ack ignored %u %u\n",ack,sk->sent_seq);
+			
+	/*
+	 *	Keepalive processing.
+	 */
+		 
+	if (after(ack, sk->sent_seq)) 
+	{
+		return 0;
+	}
+		
+	/*
+	 *	Restart the keepalive timer.
+	 */
+		 
+	if (sk->keepopen) 
+	{
+		if(sk->ip_xmit_timeout==TIME_KEEPOPEN)
+			tcp_reset_xmit_timer(sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
+	}
+	return 1;
 }
 
 
@@ -1515,12 +1595,14 @@
 		/*
 		 *	Pull up the IP header.
 		 */
+	
 		skb_pull(skb, skb->h.raw-skb->data);
 
 		/*
 		 *	Try to use the device checksum if provided.
 		 */
-		switch (skb->ip_summed) {
+		switch (skb->ip_summed) 
+		{
 			case CHECKSUM_NONE:
 				skb->csum = csum_partial((char *)th, len, 0);
 			case CHECKSUM_HW:
@@ -1539,7 +1621,7 @@
 
 		skb->acked = 0;
 		skb->used = 0;
-		skb->free = 0;
+		skb->free = 1;
 		skb->saddr = daddr;
 		skb->daddr = saddr;
 	
@@ -1580,7 +1662,11 @@
 	 
 	skb->sk=sk;
 	sk->rmem_alloc += skb->truesize;
-
+	
+	/*
+	 *	We should now do header prediction.
+	 */
+	 
 	/*
 	 *	This basically follows the flow suggested by RFC793, with the corrections in RFC1122. We
 	 *	don't implement precedence and we process URG incorrectly (deliberately so) for BSD bug
@@ -1627,13 +1713,19 @@
 			 *	and Solaris 2.1 gives you a protocol error. For now we just ignore
 			 *	it, that fits the spec precisely and avoids incompatibilities. It
 			 *	would be nice in future to drop through and process the data.
+			 *
+			 *	Now TTCP is starting to use we ought to queue this data.
 			 */
 			 
 			release_sock(sk);
 			return 0;
 		}
 	
-		/* retransmitted SYN? */
+		/* 
+		 *	Retransmitted SYN for our socket. This is uninteresting. If sk->state==TCP_LISTEN
+		 *	then its a new connection
+		 */
+		 
 		if (sk->state == TCP_SYN_RECV && th->syn && skb->seq+1 == sk->acked_seq)
 		{
 			kfree_skb(skb, FREE_READ);
@@ -1643,7 +1735,8 @@
 		
 		/*
 		 *	SYN sent means we have to look for a suitable ack and either reset
-		 *	for bad matches or go to connected 
+		 *	for bad matches or go to connected. The SYN_SENT case is unusual and should
+		 *	not be in line code. [AC]
 		 */
 	   
 		if(sk->state==TCP_SYN_SENT)
@@ -1796,43 +1889,8 @@
 		return tcp_reset(sk,skb);	
 	}
 
-
-	/*
-	 *	Delayed ACK time estimator.
-	 */
+	tcp_delack_estimator(sk);
 	
-	if (sk->lrcvtime == 0) 
-	{
-		sk->lrcvtime = jiffies;
-		sk->ato = HZ/3;
-	}
-	else 
-	{
-		int m;
-		
-		m = jiffies - sk->lrcvtime;
-
-		sk->lrcvtime = jiffies;
-
-		if (m <= 0)
-			m = 1;
-
-		if (m > (sk->rtt >> 3)) 
-		{
-			sk->ato = sk->rtt >> 3;
-			/*
-			 * printk(KERN_DEBUG "ato: rtt %lu\n", sk->ato);
-			 */
-		}
-		else 
-		{
-			sk->ato = (sk->ato >> 1) + m;
-			/*
-			 * printk(KERN_DEBUG "ato: m %lu\n", sk->ato);
-			 */
-		}
-	}
-	  
 	/*
 	 *	Process the ACK
 	 */
@@ -1880,11 +1938,7 @@
 	 */
 	
 	if(tcp_data(skb,sk, saddr, len))
-	{
 		kfree_skb(skb, FREE_READ);
-		release_sock(sk);
-		return 0;
-	}
 
 	/*
 	 *	And done
diff -u --recursive --new-file v1.3.62/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v1.3.62/linux/net/ipv4/tcp_output.c	Sun Feb 11 15:32:48 1996
+++ linux/net/ipv4/tcp_output.c	Wed Feb 14 09:26:26 1996
@@ -97,13 +97,6 @@
 		}
 		skb_queue_tail(&sk->write_queue, skb);
 		
-		/*
-		 *	If we don't fit we have to start the zero window
-		 *	probes. This is broken - we really need to do a partial
-		 *	send _first_ (This is what causes the Cisco and PC/TCP
-		 *	grief).
-		 */
-		 
 		if (before(sk->window_seq, sk->write_queue.next->end_seq) &&
 		    sk->send_head == NULL && sk->ack_backlog == 0)
 			tcp_reset_xmit_timer(sk, TIME_PROBE0, sk->rto);
@@ -117,7 +110,7 @@
 		th->ack_seq = htonl(sk->acked_seq);
 		th->window = htons(tcp_select_window(sk));
 
-		tcp_send_check(th, sk->saddr, sk->daddr, size, sk);
+		tcp_send_check(th, sk->saddr, sk->daddr, size, skb);
 
 		sk->sent_seq = sk->write_seq;
 		
@@ -288,7 +281,7 @@
 			th->ack_seq = htonl(sk->acked_seq);
 			th->window = htons(tcp_select_window(sk));
 
-			tcp_send_check(th, sk->saddr, sk->daddr, size, sk);
+			tcp_send_check(th, sk->saddr, sk->daddr, size, skb);
 
 			sk->sent_seq = skb->end_seq;
 			
@@ -344,9 +337,9 @@
 		/*		   anyway, so we don't need all the fuss to prepare */
 		/*		   the buffer in this case. 			    */
 		/*		   (the skb_pull() changes skb->data while we may   */
-		/*		   actually try to send the data. Ough. A side	    */
+		/*		   actually try to send the data. Ouch. A side	    */
 		/*		   effect is that we'll send some unnecessary data, */
-		/*		   but the alternative is desastrous...		    */
+		/*		   but the alternative is disasterous...	    */
 		
 		if (skb_device_locked(skb))
 			break;
@@ -439,7 +432,7 @@
 			sk->ack_backlog = 0;
 			sk->bytes_rcv = 0;
 			th->window = ntohs(tcp_select_window(sk));
-			tcp_send_check(th, sk->saddr, sk->daddr, size, sk);
+			tcp_send_check(th, sk->saddr, sk->daddr, size, skb);
 		
 			/*
 			 *	If the interface is (still) up and running, kick it.
@@ -523,6 +516,7 @@
 	buff->sk = NULL;
 	buff->dev = dev;
 	buff->localroute = 0;
+	buff->csum = 0;
 
 	/*
 	 *	Put in the IP header and routing stuff. 
@@ -546,31 +540,26 @@
 
 	t1->dest = th->source;
 	t1->source = th->dest;
-	t1->rst = 1;  
-	t1->window = 0;
+	t1->syn = 0;
+	t1->fin = 0;
+	t1->urg = 0;
+	t1->rst = 1;
+	t1->psh = 0;  
   
 	if(th->ack)
 	{
 		t1->ack = 0;
 	  	t1->seq = th->ack_seq;
-	  	t1->ack_seq = 0;
 	}
 	else
 	{
-	  	t1->ack = 1;
 	  	if(!th->syn)
 			t1->ack_seq = th->seq;
 		else
 			t1->ack_seq = htonl(ntohl(th->seq)+1);
-		t1->seq = 0;
 	}
 
-	t1->syn = 0;
-	t1->urg = 0;
-	t1->fin = 0;
-	t1->psh = 0;
-	t1->doff = sizeof(*t1)/4;
-	tcp_send_check(t1, saddr, daddr, sizeof(*t1), NULL);
+	tcp_send_check(t1, saddr, daddr, sizeof(*t1), buff);
 	prot->queue_xmit(NULL, ndev, buff, 1);
 	tcp_statistics.TcpOutSegs++;
 }
@@ -606,6 +595,7 @@
 	 
 	buff->sk = sk;
 	buff->localroute = sk->localroute;
+	buff->csum = 0;
 
 	/*
 	 *	Put in the IP header and routing stuff. 
@@ -645,13 +635,10 @@
 	sk->write_seq++;
 	buff->end_seq = sk->write_seq;
 	t1->seq = htonl(buff->seq);
-	t1->ack = 1;
 	t1->ack_seq = htonl(sk->acked_seq);
 	t1->window = htons(sk->window=tcp_select_window(sk));
 	t1->fin = 1;
-	t1->rst = 0;
-	t1->doff = sizeof(*t1)/4;
-	tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
+	tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), buff);
 
 	/*
 	 * If there is data in the write queue, the fin must be appended to
@@ -737,15 +724,13 @@
 	t1->dest = skb->h.th->source;
 	t1->source = newsk->dummy_th.source;
 	t1->seq = ntohl(buff->seq);
-	t1->ack = 1;
 	newsk->sent_seq = newsk->write_seq;
 	t1->window = ntohs(tcp_select_window(newsk));
-	t1->res1 = 0;
-	t1->res2 = 0;
-	t1->rst = 0;
+	t1->syn = 1;
+	t1->ack = 1;
 	t1->urg = 0;
+	t1->rst = 0;
 	t1->psh = 0;
-	t1->syn = 1;
 	t1->ack_seq = htonl(newsk->acked_seq);
 	t1->doff = sizeof(*t1)/4+1;
 	ptr = skb_put(buff,4);
@@ -753,8 +738,8 @@
 	ptr[1] = 4;
 	ptr[2] = ((newsk->mtu) >> 8) & 0xff;
 	ptr[3] =(newsk->mtu) & 0xff;
-
-	tcp_send_check(t1, newsk->saddr, newsk->daddr, sizeof(*t1)+4, newsk);
+	buff->csum = csum_partial(ptr, 4, 0);
+	tcp_send_check(t1, newsk->saddr, newsk->daddr, sizeof(*t1)+4, buff);
 	newsk->prot->queue_xmit(newsk, ndev, buff, 0);
 	tcp_reset_xmit_timer(newsk, TIME_WRITE , TCP_TIMEOUT_INIT);
 	skb->sk = newsk;
@@ -817,6 +802,7 @@
 	 
 	buff->sk = sk;
 	buff->localroute = sk->localroute;
+	buff->csum = 0;
 
 	/* 
 	 *	Put in the IP header and routing stuff. 
@@ -832,7 +818,7 @@
 	}
 	t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
 
-	memcpy(t1, th, sizeof(*t1));
+	memcpy(t1, &sk->dummy_th, sizeof(*t1));
 
 	/*
 	 *	Swap the send and the receive. 
@@ -841,16 +827,8 @@
 	t1->dest = th->source;
 	t1->source = th->dest;
 	t1->seq = ntohl(sequence);
-	t1->ack = 1;
 	sk->window = tcp_select_window(sk);
 	t1->window = ntohs(sk->window);
-	t1->res1 = 0;
-	t1->res2 = 0;
-	t1->rst = 0;
-	t1->urg = 0;
-	t1->syn = 0;
-	t1->psh = 0;
-	t1->fin = 0;
 	
 	/*
 	 *	If we have nothing queued for transmit and the transmit timer
@@ -876,8 +854,7 @@
   	 */
   	 
   	t1->ack_seq = htonl(ack);
-  	t1->doff = sizeof(*t1)/4;
-  	tcp_send_check(t1, sk->saddr, daddr, sizeof(*t1), sk);
+  	tcp_send_check(t1, sk->saddr, daddr, sizeof(*t1), buff);
   	if (sk->debug)
   		 printk("\rtcp_ack: seq %x ack %x\n", sequence, ack);
   	sk->prot->queue_xmit(sk, dev, buff, 1);
@@ -930,7 +907,6 @@
 #if 0
 		unsigned long ow_size;
 #endif
-	    	void * tcp_data_start;
 	
 		/*
 		 *	How many bytes can we send ?
@@ -985,9 +961,9 @@
 
 		buff->dev = dev;
 
-		nth = (struct tcphdr *) skb_put(buff,th->doff*4);
+		nth = (struct tcphdr *) skb_put(buff,sizeof(*th));
 
-		memcpy(nth, th, th->doff * 4);
+		memcpy(nth, th, sizeof(*th));
 		
 		/*
 		 *	Correct the new header
@@ -999,16 +975,11 @@
 		nth->check = 0;
 
 		/*
-		 *	Find the first data byte.
-		 */
-		 
-		tcp_data_start = (char *) th + (th->doff << 2);
-
-		/*
-		 *	Add it to our new buffer
+		 *	Copy TCP options and data start to our new buffer
 		 */
 		 
-		memcpy(skb_put(buff,win_size), tcp_data_start, win_size);
+		buff->csum = csum_partial_copy((void *)(th + 1), skb_put(buff,win_size),
+				win_size + th->doff*4 - sizeof(*th), 0);
 		
 		/*
 		 *	Remember our right edge sequence number.
@@ -1024,7 +995,7 @@
 		 */
 		 
 	    	tcp_send_check(nth, sk->saddr, sk->daddr, 
-			   nth->doff * 4 + win_size , sk);
+			   nth->doff * 4 + win_size , buff);
 	}
 	else
 	{	
@@ -1035,6 +1006,7 @@
 		buff->free = 1;
 		buff->sk = sk;
 		buff->localroute = sk->localroute;
+		buff->csum = 0;
 
 		/*
 		 *	Put in the IP header and routing stuff. 
@@ -1057,18 +1029,10 @@
 		 */
 	 
 		t1->seq = htonl(sk->sent_seq-1);
-		t1->ack = 1; 
-		t1->res1= 0;
-		t1->res2= 0;
-		t1->rst = 0;
-		t1->urg = 0;
-		t1->psh = 0;
-		t1->fin = 0;	/* We are sending a 'previous' sequence, and 0 bytes of data - thus no FIN bit */
-		t1->syn = 0;
+/*		t1->fin = 0;	-- We are sending a 'previous' sequence, and 0 bytes of data - thus no FIN bit */
 		t1->ack_seq = htonl(sk->acked_seq);
 		t1->window = htons(tcp_select_window(sk));
-		t1->doff = sizeof(*t1)/4;
-		tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
+		tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), buff);
 
 	}		
 
diff -u --recursive --new-file v1.3.62/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- v1.3.62/linux/net/ipv4/tcp_timer.c	Sun Feb 11 15:32:49 1996
+++ linux/net/ipv4/tcp_timer.c	Wed Feb 14 09:26:26 1996
@@ -40,6 +40,8 @@
 }
 
 /*
+ *	POLICY:
+ *
  * 	This is the normal code called for timeouts.  It does the retransmission
  * 	and then does backoff.  tcp_do_retransmit is separated out because
  * 	tcp_ack needs to send stuff from the retransmit queue without
@@ -76,6 +78,9 @@
 }
 
 /*
+ *	POLICY:
+ *		Congestion control.
+ *
  *	A timer event has trigger a tcp retransmit timeout. The
  *	socket xmit queue is ready and set up to send. Because
  *	the ack receive code keeps the queue straight we do
@@ -101,7 +106,7 @@
 }
 
 /*
- *	A write timeout has occurred. Process the after effects.
+ *	A write timeout has occurred. Process the after effects. BROKEN (badly)
  */
 
 static int tcp_write_timeout(struct sock *sk)
diff -u --recursive --new-file v1.3.62/linux/net/socket.c linux/net/socket.c
--- v1.3.62/linux/net/socket.c	Wed Dec 27 09:12:15 1995
+++ linux/net/socket.c	Tue Feb 13 16:57:06 1996
@@ -1089,19 +1089,25 @@
 	if (!(sock = sockfd_lookup(fd, NULL)))
 		return(-ENOTSOCK);
 	
+	if(sock->ops->sendmsg==NULL)
+		return -EOPNOTSUPP;
+
+
 	err=verify_area(VERIFY_READ, msg,sizeof(struct msghdr));
 	if(err)
 		return err;
+
 	memcpy_fromfs(&msg_sys,msg,sizeof(struct msghdr));
+
+	/* do not move before msg_sys is valid */
 	if(msg_sys.msg_iovlen>MAX_IOVEC)
 		return -EINVAL;
+
 	err=verify_iovec(&msg_sys,iov,address, VERIFY_READ);
 	if(err<0)
 		return err;
 	total_len=err;
-	
-	if(sock->ops->sendmsg==NULL)
-		return -EOPNOTSUPP;
+
 	return sock->ops->sendmsg(sock, &msg_sys, total_len, (file->f_flags&O_NONBLOCK), flags);
 }
 
diff -u --recursive --new-file v1.3.62/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v1.3.62/linux/net/unix/af_unix.c	Fri Feb  9 17:53:13 1996
+++ linux/net/unix/af_unix.c	Tue Feb 13 17:16:52 1996
@@ -677,6 +677,9 @@
 	return 0;
 }
 
+/* if msg->accrights != NULL, we have fds to pass.
+ * Current implementation passes at most one fd.
+ */
 static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags)
 {
 	unix_socket *sk=sock->data;
@@ -686,6 +689,8 @@
 	struct sk_buff *skb;
 	int limit=0;
 	int sent=0;
+	/* for passing  fd, NULL indicates no fd */
+	struct file *filp;
 
 	if(sk->err)
 		return sock_error(sk);
@@ -693,7 +698,7 @@
 	if(flags&MSG_OOB)
 		return -EOPNOTSUPP;
 			
-	if(flags || msg->msg_accrights)	/* For now */
+	if(flags)	/* For now */
 		return -EINVAL;
 		
 	if(sunaddr!=NULL)
@@ -706,6 +711,7 @@
 				return -EOPNOTSUPP;
 		}
 	}
+
 	if(sunaddr==NULL)
 	{
 		if(sk->protinfo.af_unix.other==NULL)
@@ -713,6 +719,26 @@
 	}
 
 
+	/* see if we want to access rights (fd) -- at the moment, 
+	 * we can pass none or 1 fd
+         */
+	filp = NULL;
+	if(msg->msg_accrights) {
+		/* then accrightslen is meaningful */
+		if(msg->msg_accrightslen == sizeof(int)) {
+			int fd;
+
+			fd = get_user_long(msg->msg_accrights);
+			filp = file_from_fd(fd);
+			if(!filp)
+				return -EBADF;
+		} else if(msg->msg_accrightslen != 0) {
+			/* if we have accrights, we fail here */
+			return -EINVAL;
+		}
+	}
+
+	/* invariant -- flip points to a file to pass or NULL */
 	while(sent < len)
 	{
 		/*
@@ -792,8 +818,16 @@
 					return err;
 			}
 		}
+		/* at this point, we want to add an fd if we have one  */
+		skb->h.filp = filp;
+		if (filp) {
+			filp->f_count++;
+		}
+		
 		skb_queue_tail(&other->receive_queue, skb);
 		sti();
+		/* if we sent an fd, only do it once */
+		filp = NULL;	
 		other->data_ready(other,size);
 		sent+=size;
 	}
@@ -815,6 +849,36 @@
 	sti();
 }
 		
+
+/*
+ * return 0 if we can stick the fd, negative errno if we can't
+ */
+static int stick_fd(struct file *filp, int *uaddr, int size)
+{
+	int slot;
+	int upper_bound;
+
+	if (!uaddr || size < sizeof(int))
+		return -EINVAL;
+
+	upper_bound = current->rlim[RLIMIT_NOFILE].rlim_cur;
+
+	if (upper_bound > NR_OPEN)
+		upper_bound = NR_OPEN;
+
+	for (slot = 0; slot < upper_bound;  slot++) {
+		if (current->files->fd[slot])
+			continue;
+		/* have an fd */
+		current->files->fd[slot] = filp;
+		FD_CLR(slot, &current->files->close_on_exec);
+		/* need verify area here? */
+		put_user_long(slot, uaddr);
+		return 0;
+	} 
+	return -EMFILE;
+}
+
 static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len)
 {
 	unix_socket *sk=sock->data;
@@ -826,7 +890,8 @@
 	int num;
 	struct iovec *iov=msg->msg_iov;
 	int ct=msg->msg_iovlen;
-	
+	struct file *filp;
+
 	if(flags&MSG_OOB)
 		return -EOPNOTSUPP;
 		
@@ -879,8 +944,16 @@
 					if(addr_len)
 						*addr_len=sizeof(short);
 			}
+
 			num=min(skb->len,size-copied);
 			memcpy_tofs(sp, skb->data, num);
+
+			if ((filp = skb->h.filp) != NULL) {
+				skb->h.filp = NULL;
+				if (stick_fd(filp, msg->msg_accrights, msg->msg_accrightslen) < 0)
+					close_fp(filp);
+			}
+
 			copied+=num;
 			done+=num;
 			sp+=num;
diff -u --recursive --new-file v1.3.62/linux/scripts/Configure linux/scripts/Configure
--- v1.3.62/linux/scripts/Configure	Fri Feb  9 17:53:13 1996
+++ linux/scripts/Configure	Tue Feb 13 10:47:13 1996
@@ -25,6 +25,8 @@
 # 281295 Paul Gortmaker - make tri_state functions collapse to boolean
 # if module support is not enabled.
 #
+# 010296 Aaron Ucko (ucko@vax1.rockhurst.edu) - fix int and hex to accept
+# arbitrary ranges
 
 #
 # Make sure we're really running bash.
@@ -64,15 +66,15 @@
      var=$(echo "$1"|sed 's/[][\/.^$*]/\\&/g')
      #now pick out the right help text:
      text=$(sed -n "/^$var[ 	]*\$/,\${
-                        /^$var[ 	]*\$/b
-                        /^#.*/b;/^[ 	]*\$/q
-                        p
-                    }" Documentation/Configure.help)
+			/^$var[ 	]*\$/b
+			/^#.*/b;/^[ 	]*\$/q
+			p
+		    }" Documentation/Configure.help)
      if [ -z "$text" ]
      then
-          echo; echo "  Sorry, no help available for this option yet.";echo
+	  echo; echo "  Sorry, no help available for this option yet.";echo
      else
-          (echo; echo "$text"; echo) | more
+	  (echo; echo "$text"; echo) | more
      fi
   else
      echo;
@@ -116,21 +118,21 @@
 #	define_bool define value
 #
 function define_bool () {
-        case "$2" in
-         "y")
+	case "$2" in
+	 "y")
 		echo "$1=y" >>$CONFIG
 		echo "#define $1 1" >>$CONFIG_H
 		;;
 
-         "m")
+	 "m")
 		echo "$1=m" >>$CONFIG
 		echo "#undef  $1" >>$CONFIG_H
 		;;
 
-         "n")
+	 "n")
 		echo "# $1 is not set" >>$CONFIG
 		echo "#undef  $1" >>$CONFIG_H
-                ;;
+		;;
 	esac
 	eval "$1=$2"
 }
@@ -142,24 +144,24 @@
 #
 function bool () {
 	def=$(eval echo "\${$2:-'n'}")
-        case "$def" in
-         "y" | "m") defprompt="Y/n/?"
-              def="y"
-              ;;
-         "n") defprompt="N/y/?"
-              ;;
-        esac
-        while :; do
-          readln "$1 ($2) [$defprompt] " "$def"
-          case "$ans" in
-            [yY] | [yY]es ) define_bool "$2" "y"
-                            break;;
-            [nN] | [nN]o )  define_bool "$2" "n"
-                            break;;
-            * )             help "$2"
-                            ;;
-          esac
-        done
+	case "$def" in
+	 "y" | "m") defprompt="Y/n/?"
+	      def="y"
+	      ;;
+	 "n") defprompt="N/y/?"
+	      ;;
+	esac
+	while :; do
+	  readln "$1 ($2) [$defprompt] " "$def"
+	  case "$ans" in
+	    [yY] | [yY]es ) define_bool "$2" "y"
+			    break;;
+	    [nN] | [nN]o )  define_bool "$2" "n"
+			    break;;
+	    * )             help "$2"
+			    ;;
+	  esac
+	done
 }
 
 #
@@ -168,32 +170,32 @@
 #	tristate question define
 #
 function tristate () {
-        if [ "$CONFIG_MODULES" != "y" ]; then
-          bool "$1" "$2"
-        else 
+	if [ "$CONFIG_MODULES" != "y" ]; then
+	  bool "$1" "$2"
+	else 
 	  def=$(eval echo "\${$2:-'n'}")
-          case "$def" in
-           "y") defprompt="Y/m/n/?"
-                ;;
-           "m") defprompt="M/n/y/?"
-                ;;
-           "n") defprompt="N/y/m/?"
-                ;;
-          esac
-          while :; do
-            readln "$1 ($2) [$defprompt] " "$def"
-            case "$ans" in
-              [yY] | [yY]es ) define_bool "$2" "y"
-                              break ;;
-              [nN] | [nN]o )  define_bool "$2" "n"
-                              break ;;
-              [mM] )          define_bool "$2" "m"
-                              break ;;
+	  case "$def" in
+	   "y") defprompt="Y/m/n/?"
+		;;
+	   "m") defprompt="M/n/y/?"
+		;;
+	   "n") defprompt="N/y/m/?"
+		;;
+	  esac
+	  while :; do
+	    readln "$1 ($2) [$defprompt] " "$def"
+	    case "$ans" in
+	      [yY] | [yY]es ) define_bool "$2" "y"
+			      break ;;
+	      [nN] | [nN]o )  define_bool "$2" "n"
+			      break ;;
+	      [mM] )          define_bool "$2" "m"
+			      break ;;
 	      * )             help "$2"
-                              ;;
-            esac
-          done
-        fi
+			      ;;
+	    esac
+	  done
+	fi
 }
 
 #
@@ -208,37 +210,39 @@
 #
 function dep_tristate () {
 	def=$(eval echo "\${$2:-'n'}")
-	if [ "$3" != "m" ]; then
+	if [ "$3" = "n" ]; then
+		define_bool "$2" "n"
+	elif [ "$3" = "y" ]; then
 		tristate "$1" "$2"
 	else
-           if [ "$CONFIG_MODULES" = "y" ]; then
-	        case "$def" in
-        	 "y" | "m") defprompt="M/n/?"
+	   if [ "$CONFIG_MODULES" = "y" ]; then
+		case "$def" in
+		 "y" | "m") defprompt="M/n/?"
 		      def="m"
-        	      ;;
-        	 "n") defprompt="N/m/?"
-        	      ;;
-	        esac
-                while :; do
-                  readln "$1 ($2) [$defprompt] " "$def"
-                  case "$ans" in
-                      [nN] | [nN]o )  define_bool "$2" "n"
-                                      break ;;
-                      [mM] )          define_bool "$2" "m"
-                                      break ;;
-                      [yY] | [yY]es ) echo 
+		      ;;
+		 "n") defprompt="N/m/?"
+		      ;;
+		esac
+		while :; do
+		  readln "$1 ($2) [$defprompt] " "$def"
+		  case "$ans" in
+		      [nN] | [nN]o )  define_bool "$2" "n"
+				      break ;;
+		      [mM] )          define_bool "$2" "m"
+				      break ;;
+		      [yY] | [yY]es ) echo 
    echo "  This answer is not allowed, because it is not consistent with"
    echo "  your other choices."
    echo "  This driver depends on another one which you chose to compile"
    echo "  as a module. This means that you can either compile this one"
    echo "  as a module as well (with M) or leave it out altogether (N)."
-                                      echo
-                                      ;;
-                      * )             help "$2"
-                                      ;;
-                  esac
-                done
-           fi
+				      echo
+				      ;;
+		      * )             help "$2"
+				      ;;
+		  esac
+		done
+	   fi
 	fi
 }
 
@@ -260,17 +264,15 @@
 #
 function int () {
 	def=$(eval echo "\${$2:-$3}")
-        while :; do
-          readln "$1 ($2) [$def] " "$def"
-          case "$ans" in
-             -1 | [1-9] | [1-9][0-9] |\
-             [1-9][0-9][0-9] | [1-9][0-9][0-9][0-9] | [1-9][0-9][0-9][0-9][0-9]) 
-                 define_int "$2" "$ans"
-                 break;;
-             * ) help "$2"
-                 ;;
-          esac
-        done
+	while :; do
+	  readln "$1 ($2) [$def] " "$def"
+	  if expr "$ans" : '0$\|-?[1-9][0-9]*$' > /dev/null; then
+	    define_int "$2" "$ans"
+	    break
+	  else
+	    help "$2"
+	  fi
+	done
 }
 #
 # define_hex sets the value of a hexadecimal argument
@@ -291,20 +293,16 @@
 function hex () {
 	def=$(eval echo "\${$2:-$3}")
 	def=${def#*[x,X]}
-        while :; do
-          readln "$1 ($2) [$def] " "$def"
-          ans=${ans#*[x,X]}
-          case "$ans" in
-             [0-9,a-f,A-F] |\
-             [0-9,a-f,A-F][0-9,a-f,A-F] |\
-             [0-9,a-f,A-F][0-9,a-f,A-F][0-9,a-f,A-F] |\
-             [0-9,a-f,A-F][0-9,a-f,A-F][0-9,a-f,A-F][0-9,a-f,A-F])\
-                 define_hex "$2" "$ans"
-                 break;;
-             * ) help "$2"
-                 ;;
-          esac
-        done
+	while :; do
+	  readln "$1 ($2) [$def] " "$def"
+	  ans=${ans#*[x,X]}
+	 if expr "$ans" : '[0-9a-fA-F]+$' > /dev/null; then
+	   define_hex "$2" "$ans"
+	   break
+	 else
+	    help "$2"
+	 fi
+	done
 }
 
 #
@@ -329,7 +327,7 @@
 	# determine default answer:
 	names=""
 	set -- $choices
-        firstvar=$2
+	firstvar=$2
 	while [ -n "$2" ]; do
 		if [ -n "$names" ]; then
 			names="$names, $1"
@@ -344,7 +342,7 @@
 
 	val=""
 	while [ -z "$val" ]; do
-                ambg=n
+		ambg=n
 		readln "$question ($names) [$def] " "$def"
 		ans=$(echo $ans | tr a-z A-Z)
 		set -- $choices
@@ -359,19 +357,19 @@
 					if [ -n "$val" ]; then
 						echo;echo \
 		"  Sorry, \"$ans\" is ambiguous; please enter a longer string."
-                                                echo
+						echo
 						val=""
-                                                ambg=y
+						ambg=y
 						break
 					else
 						val="$2"
 					fi;;
 			esac
 			shift; shift
-                done
-	        if [ "$val" = "" -a "$ambg" = "n" ]; then
-                        help "$firstvar"
-                fi
+		done
+		if [ "$val" = "" -a "$ambg" = "n" ]; then
+			help "$firstvar"
+		fi
 	done
 	set -- $choices
 	while [ -n "$2" ]; do
