diff -u --recursive --new-file v1.3.90/linux/CREDITS linux/CREDITS
--- v1.3.90/linux/CREDITS	Wed Apr 17 09:06:31 1996
+++ linux/CREDITS	Wed Apr 17 09:01:18 1996
@@ -665,6 +665,13 @@
 S: D53424 Remagen
 S: Germany
 
+N: Phil Lewis
+E: beans@bucket.ualr.edu
+D: Promised to send money if I would put his name in the source tree.
+S: PO Box 371
+S: North Little Rock, Arkansas 72115
+S: US
+
 N: Martin von Loewis
 E: loewis@informatik.hu-berlin.de
 D: script binary format
@@ -774,6 +781,15 @@
 D: 8 bit XT hard disk driver for OMTI5520
 S: Branderweg 4
 S: D-91058 Erlangen
+S: Germany
+
+N: Michael Meskes
+E: meskes@informatik.rwth-aachen.de
+D: Kernel hacker. Software watchdog daemon.
+D: Maintainer of several Debian packages
+S: Lehrstuhl fuer angewandte Mathematik insb. Informatik
+S: RWTH-Aachen
+S: D-52056 Aachen
 S: Germany
 
 N: Craig Metz
diff -u --recursive --new-file v1.3.90/linux/Documentation/Changes linux/Documentation/Changes
--- v1.3.90/linux/Documentation/Changes	Wed Apr 17 09:06:31 1996
+++ linux/Documentation/Changes	Thu Apr 18 15:00:12 1996
@@ -2,7 +2,7 @@
 important packages for Linux as well as instructions for newcomers to
 the 1.3.x series of kernels.
 
-Last updated: Apr 15, 1996.
+Last updated: Apr 17, 1996.
 Authors: Alessandro Sigala (ssigala@globalnet.it) and Chris Ricker
 (gt1355b@prism.gatech.edu).
 
@@ -18,9 +18,9 @@
 - Dynamic linker (ld.so) 1.7.14
 - GNU CC		 2.7.2
 - Binutils		 2.6.0.12
-- Linux C Library	 Stable:  5.2.18, Exp:  5.3.9
+- Linux C Library	 Stable:  5.2.18, Exp:  5.3.9, Alpha:  5.3.11
 - Linux C++ Library	 2.7.1.4
-- Termcap		 2.0.7
+- Termcap		 2.0.8
 - Procps		 0.99a
 - Gpm			 1.06
 - SysVinit		 2.60
@@ -86,7 +86,7 @@
 The Termcap Library
 ===================
 
-   The current Termcap release is 2.0.7. If you upgrade to this release
+   The current Termcap release is 2.0.8. If you upgrade to this release
 read the `README' file contained into the package to get some important
 information about the `tgetent' function changes!
 
@@ -162,7 +162,7 @@
    Linux's handling of named pipes changed (it now does it The Right Way
 instead of the SunOS way ;-).  This broke some programs that depended
 on the SunOS behavior, most notably SysVinit.  If you're running 2.59
-or earlier, you will probably get a weird error on shutdown in which
+or earlier, you will probably get a wierd error on shutdown in which
 your computer shuts down fine but "INIT: error reading initrequest" or
 words to that effect scroll across your screen hundreds of times.  To
 fix, upgrade to
@@ -188,7 +188,7 @@
    ln -s /usr/lib/terminfo/l/linux /usr/lib/terminfo/c/console
 
    Better yet, just get the latest official Linux termcap from
-ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.7.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.tar.gz
 
 Hdparm
 ======
@@ -353,7 +353,7 @@
 Termcap Library
 ===============
 
-ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.7.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.tar.gz
 
 Modules utilities
 =================
diff -u --recursive --new-file v1.3.90/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v1.3.90/linux/Documentation/Configure.help	Wed Apr 17 09:06:31 1996
+++ linux/Documentation/Configure.help	Wed Apr 17 09:01:18 1996
@@ -2196,6 +2196,23 @@
   Multiple-Ethernet-mini-HOWTO, available from
   sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
 
+DECchip Tulip (dc21x4x) PCI support
+CONFIG_DEC_ELCP
+  This driver is developed for the SMC EtherPower series ethernet
+  cards and also works with the DECchip 21040/21041/21140
+  (Tulip series) based other cards.  If you have a network card of
+  this type, say Y and read the Ethernet-HOWTO, available via ftp
+  (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. More
+  specific information is contained in
+  Documentation/networking/tulip.txt. This driver is also available
+  as a module ( = code which can be inserted in and removed from
+  the running kernel whenever you want).  If you want to compile
+  it as a module, say M here and read Documentation/modules.txt as
+  well as Documentation/networking/net-modules.txt.
+  ******************************************************************
+      If your card is NOT SMC EtherPower 10/100 PCI (smc9332dst),
+      you can try the de4x5.c driver.
+
 ICL EtherTeam 16i/32 support
 CONFIG_ETH16I
   If you have a network (ethernet) card of this type, say Y and read
@@ -2751,12 +2768,16 @@
   This selects whether you want to include the driver for the standard
   serial ports.  People who might say N here are those that are
   setting up dedicated ethernet WWW/ftp servers, or users that have
-  one of the various bus mice instead of a serial mouse.  Note that
-  the Cyclades and Stallion drivers do not need this driver to be
-  built in for them to work. They are completely independent of each
-  other. Most people will say Y here however, so that they can use
-  serial mice, modems and similar devices connecting to the standard
-  serial ports.
+  one of the various bus mice instead of a serial mouse.  (Note that
+  the Cyclades and Stallion drivers do not need this driver built in
+  for them to work. They are completely independent of each other.)
+  If you want to compile this driver as a module, say M here and read
+  Documentation/modules.txt.  [WARNING: Do not compile this driver as
+  a module if you are using non-standard serial ports, since the
+  configuration information will be lost when kerneld automatically
+  unloads the driver.  This limitation may be lifted in the future.]
+  Most people will say Y or M here, so that they can use serial mice,
+  modems and similar devices connecting to the standard serial ports.
 
 Digiboard PC/X Support
 CONFIG_DIGI
diff -u --recursive --new-file v1.3.90/linux/Documentation/digiboard.txt linux/Documentation/digiboard.txt
--- v1.3.90/linux/Documentation/digiboard.txt	Fri Apr 12 15:51:43 1996
+++ linux/Documentation/digiboard.txt	Wed Apr 17 08:12:58 1996
@@ -21,25 +21,25 @@
 
 Supporting Tools:
 -----------------
-Some tools and more detailed up to date information can be found at
+Some tools and more detailed information can be found at
 ftp://ftp.fuller.edu/Linux/digi
 
+WARNING: Most of the stuff available right now uses the WRONG Major Device
+numbers and the wrong call out devices. Be careful and check them first.
+Better not use any of the software in that directory if you run a recent
+1.3.X Kernel or later!
+
 The "ditty" tool described in the Digiboard Manuals for other Unixes
 is also available.
 
 Currently the Linux MAKEDEV command does not support generating the Digiboard
 Devices. Use the following script to generate the devices:
 
-WARNING: Most of the stuff available right now uses the WRONG Major Device
-numbers and is severely outdated. Be careful and check them first.
-Better not use any of the software in that directory if you run a recent
-1.3.X Kernel!
-
 ------------------ mkdigidev begin
 #!/bin/sh
 #
 # Script to create Digiboard Devices
-# Christoph Lameter, April 6, 1996
+# Christoph Lameter, April 16, 1996
 #
 # Usage:
 # mkdigidev [<number of devices>]
@@ -60,14 +60,53 @@
   for c in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15;
   do
 	name=`expr $boardnum \* 16 + $c`
-	mknod /dev/ttyd$name c $DIGIMAJOR $name
+	mknod /dev/cud$name c $DIGIMAJOR $name
 	mknod /dev/ttyD$name c $DIGICUMAJOR $name
   done
   boardnum=`expr $boardnum + 1`
 done
 ------------------ mkdigidev end
+or apply the following patch to /dev/MAKEDEV and do a 
+make digi
+----- MAKDEV Patch
+--- /dev/MAKEDEV	Sun Aug 13 15:48:23 1995
++++ MAKEDEV	Tue Apr 16 17:53:27 1996
+@@ -120,7 +120,7 @@
+ 	while [ $# -ne 0 ]
+ 	do
+ 		case "$1" in
+-			mem|tty|ttyp|cua|cub)	;;
++			mem|tty|ttyp|cua|cub|cud)	;;
+ 			hd)	echo hda hdb hdc hdd ;;
+ 			xd)	echo xda xdb ;;
+ 			fd)	echo fd0 fd1 ;;
+@@ -140,6 +140,7 @@
+ 			dcf)		echo dcf ;;
+ 			pcmcia)	;; # taken care of by its own driver
+ 			ttyC)	echo cyclades ;;
++			ttyD)	echo digi ;;
+ 			*)	echo "$0: don't know what \"$1\" is" >&2 ;;
+ 		esac
+ 		shift
+@@ -208,6 +209,15 @@
+ 		do
+ 			makedev ttyC$i c $major1 `expr 32 + $i` $tty
+ 			makedev cub$i c $major2 `expr 32 + $i` $dialout
++		done
++		;;
++	digi)
++		major1=`Major ttyD` || continue
++		major2=`Major cud` || continue
++		for i in 0 1 2 3 4 5 6 7 # 8 9 10 11 12 13 14 15
++		do
++			makedev ttyD$i c $major1 `expr 32 + $i` $tty
++			makedev cud$i c $major2 `expr 32 + $i` $dialout
+ 		done
+ 		;;
+ 	par[0-2])
+----- End Makedev patch
 
-The ttyd devices behave like the /dev/cua?? devices
+The /dev/cud?? devices behave like the /dev/cua?? devices
 and the ttyD devices are like the /dev/ttyS?? devices.
 
 Sources of Information
@@ -80,7 +119,7 @@
 (Write e-mail to that address to subscribe. Common ListServ commands work.
 Archive of messages available)
 
-Christoph Lameter (clameter@fuller.edu) 6. April 1996.
+Christoph Lameter (clameter@fuller.edu) 16. April 1996.
 
 -----------------------------------------------------------------------------
 
diff -u --recursive --new-file v1.3.90/linux/Documentation/networking/tulip.txt linux/Documentation/networking/tulip.txt
--- v1.3.90/linux/Documentation/networking/tulip.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/networking/tulip.txt	Wed Apr 17 08:32:47 1996
@@ -0,0 +1,110 @@
+                Tulip ethernet card driver
+
+The Tulip driver is developed by Donald Becker and changed by
+Takashi Manabe. This driver is designed to work with PCI ethernet
+cards which use the DECchip DC21x4x family. This driver hopefully
+works with all of 1.2.x and 1.3.x kernels, but I tested only
+with 1.2.13, 1.3.39, 1.3.49, 1.3.52, 1.3.57 and later.
+
+Hopefully, the de4x5.c driver will support all cards supported
+by the tulip.c driver. However, the SMC's 9332dst card and some
+cards do not work with the de4x5.c driver. So, if your card is
+not a 9332dst, please try the de4x5.c driver first.
+
+Success List
+============
+
++-------------------------------------+-----------+-------------+
+|vendor/card                          |chip       |system       |
++-------------------------------------+-----------+-------------+
+|SMC                                  |           |             |
+|     EtherPower 10 PCI(8432T/8432BT) |21040/21041|Pentium      |
++-------------------------------------+-----------+-------------+
+|SMC                                  |           |             |
+|     EtherPower 10/100 PCI(9332DST)  |21140      |Pentium/UDB  |
++-------------------------------------+-----------+-------------+
+|DEC                                  |           |             |
+|     EtherWorks 100/10 PCI(DE500-XA) |21140      |Pentium      |
++-------------------------------------+-----------+-------------+
+|DEC                                  |           |             |
+|     EtherWorks 10 PCI(DE450)        |21041      |Pentium      |
++-------------------------------------+-----------+-------------+
+|DEC                                  |           |             |
+|     QSILVER's                       |21040      |UDB          |
++-------------------------------------+-----------+-------------+
+|ZNYX                                 |           |             |
+|     312 etherarray                  |21040      |Pentium      |
++-------------------------------------+-----------+-------------+
+|Allied Telesis                       |           |             |
+|     LA100PCI-T                      |21140      |Pentium/UDB  |
++-------------------------------------+-----------+-------------+
+|Danpex ('Planet Japan' in Japan?)    |           |             |
+|     EN-9400                         |21040      |Pentium      |
++-------------------------------------+-----------+-------------+
+|Cogent                               |           |             |
+|     EM110                           |21140      |Pentium      |
++-------------------------------------+-----------+-------------+
+
+Pentium: PCI machine with Pentium CPU
+UDB:     Universal Desktop Box(aka Multia) with Alpha 21066 CPU
+
+Known bug(s)
+============
+This driver's media detection is very simple and sometimes
+it causes serious problem. The driver automatically switches
+media when it causes timeout. If you want to speficy or to fix
+a media;
+
+- Modify TULIP_PORT in tulip.c, line 33.
+- Uncommennt the definition of TULIP_FIX_PORT in tulip.c, line 40.
+
+or
+
+- Use patched ifconfig command and specify 'link='. The patch
+  against ifconfig.c in net-tools-1.3.50-BETA6e is included in
+  this file.
+
+Thanks
+======
+
+o becker@CESDIS.gsfc.nasa.gov (author of the tulip.c driver)
+o davies@wanton.lkg.dec.com (author of the de4x5.c driver)
+
+o siekas@mailhost.tcs.tulane.edu
+
+o jheiss@calvin.caltech.edu (providing information about smc8432 card)
+o goto@plathome.co.jp (lending me a DE450 card)
+o ted@physics.ucsb.edu
+o pmheuvel@xs4all.nl
+o hjl@lucon.org (EN-9400)
+o niles@axp745.gsfc.nasa.gov (ZNYX312)
+o pkc@scs.carleton.ca (EM110)
+o and testers...
+
+-----------------------------------------------------------------------
+*** ifconfig.c-dist	Wed Jan 17 07:25:36 1996
+--- ifconfig.c	Tue Apr  9 15:24:25 1996
+***************
+*** 765,770 ****
+--- 766,786 ----
+  			continue;
+  		}
+  		ifr.ifr_map.irq = atoi(*spp);
++ 		if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
++ 			fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno));
++ 			goterr = 1;
++ 		}
++ 		spp++;
++ 		continue;
++ 	}
++ 
++ 	if (!strcmp(*spp, "link")) {
++ 		if (*++spp == NULL) usage();
++ 		if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
++ 			goterr = 1;
++ 			continue;
++ 		}
++ 		ifr.ifr_map.port = atoi(*spp);
+  		if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
+  			fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno));
+  			goterr = 1;
diff -u --recursive --new-file v1.3.90/linux/MAINTAINERS linux/MAINTAINERS
--- v1.3.90/linux/MAINTAINERS	Wed Apr 17 09:06:31 1996
+++ linux/MAINTAINERS	Thu Apr 18 14:56:45 1996
@@ -102,6 +102,18 @@
 L:	linux-scsi@vger.rutgers.edu
 S:	Maintained
 
+EATA ISA/EISA SCSI DRIVER
+P:	Dario Ballabio
+M:	dario@milano.europe.dg.com
+L:	linux-kernel@vger.rutgers.edu
+S:	Maintained
+
+U14-34F SCSI DRIVER
+P:	Dario Ballabio
+M:	dario@milano.europe.dg.com
+L:	linux-kernel@vger.rutgers.edu
+S:	Maintained
+
 EATA-DMA SCSI DRIVER
 P:	Michael Neuffer
 M:	mike@i-Connect.Net
@@ -205,7 +217,7 @@
 L:	samba@listproc.anu.edu.au
 S:	Odd Fixes
 
-SMP:
+SMP: (except SPARC)
 P:	Alan Cox
 M:	smp-patches@lxorguk.ukuu.org.uk
 L:	linux-smp@vger.rutgers.edu
@@ -227,6 +239,18 @@
 P:	Christoph Lameter
 M:	clameter@fuller.edu
 L:	digiboard@list.fuller.edu
+S:	Maintained
+
+MOUSE AND MISC DEVICES [GENERAL]
+P:	Alessandro Rubini
+M:	rubini@ipvvis.unipv.it
+L:	linux-kernel@vger.rutgers.edu
+S:	Mantained
+
+MENUCONFIG:
+P:	William Roadcap
+M:	roadcapw@cfw.com
+L:	linux-kernel@vger.rutgers.edu
 S:	Maintained
 
 REST:
diff -u --recursive --new-file v1.3.90/linux/Makefile linux/Makefile
--- v1.3.90/linux/Makefile	Mon Apr 15 12:20:17 1996
+++ linux/Makefile	Tue Apr 16 19:52:36 1996
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 89
+SUBLEVEL = 91
 
 ARCH = i386
 
diff -u --recursive --new-file v1.3.90/linux/arch/alpha/kernel/alcor.c linux/arch/alpha/kernel/alcor.c
--- v1.3.90/linux/arch/alpha/kernel/alcor.c	Wed Feb 28 15:48:17 1996
+++ linux/arch/alpha/kernel/alcor.c	Wed Apr 17 09:01:18 1996
@@ -410,6 +410,20 @@
 		hwrpb->max_asn = MAX_ASN;
 	}
 
+        /*
+         * Finally, clear the CIA_CFG register, which gets used
+         *  for PCI Config Space accesses. That is the way
+         *  we want to use it, and we do not want to depend on
+         *  what ARC or SRM might have left behind...
+         */
+        {
+#if 0
+          unsigned int cia_cfg = *((unsigned int *)ALCOR_IOC_CFG); mb();
+          if (cia_cfg) printk("alcor_init: CFG was 0x%x\n", cia_cfg);
+#endif
+          *((unsigned int *)ALCOR_IOC_CFG) = 0; mb();
+        }
+ 
 	return mem_start;
 }
 
diff -u --recursive --new-file v1.3.90/linux/arch/alpha/kernel/apecs.c linux/arch/alpha/kernel/apecs.c
--- v1.3.90/linux/arch/alpha/kernel/apecs.c	Sun Mar 31 00:13:16 1996
+++ linux/arch/alpha/kernel/apecs.c	Wed Apr 17 09:01:18 1996
@@ -453,6 +453,22 @@
 	    hwrpb->chksum = sum;
 	}
 #endif /* CONFIG_ALPHA_CABRIOLET */
+
+       /*
+        * Finally, clear the HAXR2 register, which gets used
+        *  for PCI Config Space accesses. That is the way
+        *  we want to use it, and we do not want to depend on
+        *  what ARC or SRM might have left behind...
+        */
+       {
+#if 0
+         unsigned int haxr2 = *((unsigned int *)APECS_IOC_HAXR2); mb();
+         if (haxr2) printk("apecs_init: HAXR2 was 0x%x\n", haxr2);
+#endif
+         *((unsigned int *)APECS_IOC_HAXR2) = 0; mb();
+       }
+
+
 	return mem_start;
 }
 
diff -u --recursive --new-file v1.3.90/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
--- v1.3.90/linux/arch/alpha/kernel/bios32.c	Fri Apr 12 15:51:45 1996
+++ linux/arch/alpha/kernel/bios32.c	Wed Apr 17 09:01:18 1996
@@ -25,6 +25,10 @@
  */
 #include <linux/config.h>
 
+#if 0
+#define DEBUG_PRINT_DEVS 1
+#endif
+
 #ifndef CONFIG_PCI
 
 int pcibios_present(void)
@@ -265,6 +269,10 @@
 
 	pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND,
 				  cmd | PCI_COMMAND_MASTER);
+#if DEBUG_PRINT_DEVS
+printk("layout_dev: bus %d  slot 0x%x  VID 0x%x  DID 0x%x  class 0x%x\n",
+       bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class);
+#endif
 }
 
 
@@ -274,6 +282,10 @@
 	struct pci_bus *child;
 	struct pci_dev *dev;
 
+#if DEBUG_PRINT_DEVS
+printk("layout_bus: starting bus %d\n", bus->number);
+#endif
+
 	if (!bus->devices && !bus->children)
 	  return;
 
@@ -302,6 +314,10 @@
 	/*
 	 * Allocate space to each device:
 	 */
+#if DEBUG_PRINT_DEVS
+printk("layout_bus: starting bus %d devices\n", bus->number);
+#endif
+
 	for (dev = bus->devices; dev; dev = dev->sibling) {
 		if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) {
 			layout_dev(dev);
@@ -310,6 +326,10 @@
 	/*
 	 * Recursively allocate space for all of the sub-buses:
 	 */
+#if DEBUG_PRINT_DEVS
+printk("layout_bus: starting bus %d children\n", bus->number);
+#endif
+
     	for (child = bus->children; child; child = child->next) {
 		layout_bus(child);
         }
@@ -560,9 +580,9 @@
 			}
 		}
 
-		if (ide_base) {
-		        enable_ide(ide_base);
-		}
+	}
+	if (ide_base) {
+		enable_ide(ide_base);
 	}
 }
 
@@ -732,7 +752,7 @@
 	 */
 	const unsigned int route_tab = 0x0b0a090f;
 	unsigned int level_bits;
-	unsigned char pin;
+	unsigned char pin, slot;
 	int pirq;
 
 	pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60, route_tab);
@@ -742,23 +762,41 @@
 	 */
 	level_bits = inb(0x4d0) | (inb(0x4d1) << 8);
 	for (dev = pci_devices; dev; dev = dev->next) {
+	        if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE)
+			continue;
 		dev->irq = 0;
 		if (dev->bus->number != 0) {
-			printk("bios32.sio_fixup: don't know how to fixup devices on bus %d\n",
-			       dev->bus->number);
-			continue;
-		}
-		if (PCI_SLOT(dev->devfn) < 6 ||
-		    PCI_SLOT(dev->devfn) >= 6 + sizeof(pirq_tab)/sizeof(pirq_tab[0]))
-		{
-			printk("bios32.sio_fixup: "
-			       "weird, found device %04x:%04x in non-existent slot %d!!\n",
-			       dev->vendor, dev->device, PCI_SLOT(dev->devfn));
-			continue;
+			struct pci_dev *curr = dev ;
+			/* read the pin and do the PCI-PCI bridge
+			   interrupt pin swizzle */
+			pcibios_read_config_byte(dev->bus->number, dev->devfn,
+						 PCI_INTERRUPT_PIN, &pin);
+			/* cope with 0 */
+			if (pin == 0) pin = 1 ;
+			/* follow the chain of bridges, swizzling as we go */
+			do {
+				/* swizzle */
+				pin = bridge_swizzle(pin, PCI_SLOT(curr->devfn)) ;
+				/* move up the chain of bridges */
+				curr = curr->bus->self ;
+			} while (curr->bus->self) ;
+			/* The slot is the slot of the last bridge. */
+			slot = PCI_SLOT(curr->devfn) ;
+		} else {
+			/* work out the slot */
+			slot = PCI_SLOT(dev->devfn) ;
+			/* read the pin */
+			pcibios_read_config_byte(dev->bus->number, dev->devfn,
+						 PCI_INTERRUPT_PIN, &pin);
 		}
-		pcibios_read_config_byte(dev->bus->number, dev->devfn,
-					 PCI_INTERRUPT_PIN, &pin);
-		pirq = pirq_tab[PCI_SLOT(dev->devfn) - 6][pin];
+
+		pirq = pirq_tab[slot - 6][pin];
+
+#if DEBUG_PRINT_DEVS
+printk("sio_fixup: bus %d  slot 0x%x  VID 0x%x  DID 0x%x  int_slot 0x%x  int_pin 0x%x,  pirq 0x%x\n",
+       dev->bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, slot, pin, pirq);
+#endif
+
 		if (pirq < 0) {
 			continue;
 		}
@@ -790,6 +828,7 @@
 	 * these registers must be accessed byte-wise.  outw() doesn't
 	 * work.
 	 */
+	level_bits |= (inb(0x4d0) | (inb(0x4d1) << 8));
 	outb((level_bits >> 0) & 0xff, 0x4d0);
 	outb((level_bits >> 8) & 0xff, 0x4d1);
 	enable_ide(0x26e);
diff -u --recursive --new-file v1.3.90/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c
--- v1.3.90/linux/arch/alpha/kernel/signal.c	Mon Mar 11 09:39:33 1996
+++ linux/arch/alpha/kernel/signal.c	Thu Apr 18 14:00:23 1996
@@ -194,7 +194,9 @@
 	put_fs_quad(0x43ecf40047de0410, sc->sc_retcode+0);
 	put_fs_quad(0x0000000000000083, sc->sc_retcode+1);
 	regs->r26 = (unsigned long) sc->sc_retcode;
-	regs->r16 = signr;
+	regs->r16 = signr;		/* a0: signal number */
+	regs->r17 = 0;			/* a1: exception code; see gentrap.h */
+	regs->r18 = (unsigned long) sc;	/* a2: sigcontext pointer */
 	*fp = sc;
 }
 
diff -u --recursive --new-file v1.3.90/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- v1.3.90/linux/arch/i386/kernel/signal.c	Wed Apr 17 09:06:31 1996
+++ linux/arch/i386/kernel/signal.c	Wed Apr 17 14:04:29 1996
@@ -4,6 +4,8 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
+#include <linux/config.h>
+
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
@@ -42,6 +44,42 @@
 }
 
 /*
+ * FIXME. We don't currently restore emulator state
+ */
+#define restore_i387_soft(x) do { } while (0)
+
+static inline void restore_i387_hard(struct _fpstate *buf)
+{
+#ifdef __SMP__
+	if (current->flags & PF_USEDFPU) {
+		stts();
+	}
+#else
+	if (current == last_task_used_math) {
+		last_task_used_math = NULL;
+		stts();
+	}
+#endif
+	current->used_math = 1;
+	current->flags &= PF_USEDFPU;
+	memcpy_fromfs(&current->tss.i387.hard, buf, sizeof(*buf));
+}
+
+static void restore_i387(struct _fpstate *buf)
+{
+#ifndef CONFIG_MATH_EMULATION
+	restore_i387_hard(buf);
+#else
+	if (hard_math) {
+		restore_i387_hard(buf);
+		return;
+	}
+	restore_i387_soft(buf);
+#endif	
+}
+	
+
+/*
  * This sets regs->esp even though we don't actually use sigstacks yet..
  */
 asmlinkage int sys_sigreturn(unsigned long __unused)
@@ -73,12 +111,56 @@
 	regs->eflags &= ~0x40DD5;
 	regs->eflags |= context.eflags & 0x40DD5;
 	regs->orig_eax = -1;		/* disable syscall checks */
+	if (context.fpstate) {
+		struct _fpstate * buf = context.fpstate;
+		if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+			goto badframe;
+		restore_i387(buf);
+	}
 	return context.eax;
 badframe:
 	do_exit(SIGSEGV);
 }
 
 /*
+ * FIXME. We currently don't save 387 state if we use emulation
+ */
+#define save_i387_soft(x) NULL
+
+static inline struct _fpstate * save_i387_hard(struct _fpstate * buf)
+{
+#ifdef __SMP__
+	if (current->flags & PF_USEDFPU) {
+		__asm__ __volatile__("fnsave %0":"=m" (current->tss.i387.hard));
+		stts();
+		current->flags &= PF_USEDFPU;
+	}
+#else
+	if (current == last_task_used_math) {
+		__asm__ __volatile__("fnsave %0":"=m" (current->tss.i387.hard));
+		last_task_used_math = NULL;
+		__asm__ __volatile__("fwait");	/* not needed on 486+ */
+		stts();
+	}
+#endif
+	current->tss.i387.hard.status = current->tss.i387.hard.swd;
+	memcpy_tofs(buf, &current->tss.i387.hard, sizeof(*buf));
+	current->used_math = 0;
+	return buf;
+}
+
+static struct _fpstate * save_i387(struct _fpstate * buf)
+{
+#ifndef CONFIG_MATH_EMULATION
+	return save_i387_hard(buf);
+#else
+	if (hard_math)
+		return save_i387_hard(buf);
+	return save_i387_soft(buf);
+#endif
+}
+
+/*
  * Set up a signal frame... Make the stack look the way iBCS2 expects
  * it to look.
  */
@@ -91,8 +173,8 @@
 	frame = (unsigned long *) regs->esp;
 	if (regs->ss != USER_DS && sa->sa_restorer)
 		frame = (unsigned long *) sa->sa_restorer;
-	frame -= 32;
-	if (verify_area(VERIFY_WRITE,frame,32*4))
+	frame -= 64;
+	if (verify_area(VERIFY_WRITE,frame,64*4))
 		do_exit(SIGSEGV);
 
 /* set up the "normal" stack seen by the signal handler (iBCS2) */
@@ -122,7 +204,7 @@
 	put_user(regs->eflags, frame+18);
 	put_user(regs->esp, frame+19);
 	put_user(regs->ss, frame+20);
-	put_user(NULL,frame+21);
+	put_user(save_i387((struct _fpstate *)(frame+32)),frame+21);
 /* non-iBCS2 extensions.. */
 	put_user(oldmask, frame+22);
 	put_user(current->tss.cr2, frame+23);
diff -u --recursive --new-file v1.3.90/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v1.3.90/linux/arch/i386/kernel/traps.c	Fri Apr 12 15:51:46 1996
+++ linux/arch/i386/kernel/traps.c	Thu Apr 18 14:09:12 1996
@@ -241,37 +241,36 @@
  */
 void math_error(void)
 {
-	struct i387_hard_struct * env;
+	struct task_struct * task;
+
+	clts();
 #ifdef __SMP__
-	env=&current->tss.i387.hard;
-	send_sig(SIGFPE, current, 1);
+	task = current;
+#else
+	task = last_task_used_math;
+	last_task_used_math = NULL;
+	if (!task) {
+		__asm__("fnclex");
+		return;
+	}
+#endif
 	/*
 	 *	Save the info for the exception handler
 	 */
-	__asm__ __volatile__("fnsave %0":"=m" (*env));
-	current->flags&=~PF_USEDFPU;
+	__asm__ __volatile__("fnsave %0":"=m" (task->tss.i387.hard));
+	task->flags&=~PF_USEDFPU;
+
+	send_sig(SIGFPE, task, 1);
+	task->tss.trap_no = 16;
+	task->tss.error_code = 0;
+
 	/*
-	 *	Cause a trap if they use the FPU again.
+	 * Give the process a clean slate next time they use
+	 * the FPU (and if they haven't accepted the SIGFP before
+	 * that, it's their problem..)
 	 */
 	stts();
-#else
-	clts();
-	if (!last_task_used_math) {
-		__asm__("fnclex");
-		return;
-	}
-	env = &last_task_used_math->tss.i387.hard;
-	send_sig(SIGFPE, last_task_used_math, 1);
-	last_task_used_math->tss.trap_no = 16;
-	last_task_used_math->tss.error_code = 0;
-	__asm__ __volatile__("fnsave %0":"=m" (*env));
-	last_task_used_math = NULL;
-	stts();
-	env->fcs = (env->swd & 0x0000ffff) | (env->fcs & 0xffff0000);
-	env->fos = env->twd;
-	env->swd &= 0xffff3800;
-	env->twd = 0xffffffff;
-#endif	
+	task->used_math = 0;
 }
 
 asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
@@ -289,7 +288,8 @@
  */
 asmlinkage void math_state_restore(void)
 {
-#ifdef __SMP__
+	__asm__ __volatile__("clts");		/* Allow maths ops (or we recurse) */
+
 /*
  *	SMP is actually simpler than uniprocessor for once. Because
  *	we can't pull the delayed FPU switching trick Linus does
@@ -297,10 +297,17 @@
  *	set the flag. switch_to() will always save the state in
  *	case we swap processors. We also don't use the coprocessor
  *	timer - IRQ 13 mode isn't used with SMP machines (thank god).
- *
- *	If this actually works it will be a miracle however
  */
-	__asm__ __volatile__("clts");		/* Allow maths ops (or we recurse) */
+#ifndef __SMP__
+	if (last_task_used_math == current)
+		return;
+	if (last_task_used_math)
+		__asm__("fnsave %0":"=m" (last_task_used_math->tss.i387));
+	else
+		__asm__("fnclex");
+	last_task_used_math = current;
+#endif
+
 	if(current->used_math)
 		__asm__("frstor %0": :"m" (current->tss.i387));
 	else
@@ -312,25 +319,6 @@
 		current->used_math = 1;
 	}
 	current->flags|=PF_USEDFPU;		/* So we fnsave on switch_to() */
-#else
-	__asm__ __volatile__("clts");
-	if (last_task_used_math == current)
-		return;
-	timer_table[COPRO_TIMER].expires = jiffies+50;
-	timer_active |= 1<<COPRO_TIMER;	
-	if (last_task_used_math)
-		__asm__("fnsave %0":"=m" (last_task_used_math->tss.i387));
-	else
-		__asm__("fnclex");
-	last_task_used_math = current;
-	if (current->used_math) {
-		__asm__("frstor %0": :"m" (current->tss.i387));
-	} else {
-		__asm__("fninit");
-		current->used_math=1;
-	}
-	timer_active &= ~(1<<COPRO_TIMER);
-#endif	
 }
 
 #ifndef CONFIG_MATH_EMULATION
diff -u --recursive --new-file v1.3.90/linux/drivers/block/md.c linux/drivers/block/md.c
--- v1.3.90/linux/drivers/block/md.c	Fri Apr 12 15:51:50 1996
+++ linux/drivers/block/md.c	Wed Apr 17 15:08:58 1996
@@ -34,7 +34,7 @@
 #ifdef CONFIG_KERNELD
 #include <linux/kerneld.h>
 #endif
-#include <errno.h>
+#include <linux/errno.h>
 
 #define MAJOR_NR MD_MAJOR
 #define MD_DRIVER
diff -u --recursive --new-file v1.3.90/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog
--- v1.3.90/linux/drivers/char/ChangeLog	Fri Apr 12 15:51:51 1996
+++ linux/drivers/char/ChangeLog	Wed Apr 17 09:01:18 1996
@@ -1,3 +1,33 @@
+Mon Apr  1 10:22:01 1996    <tytso@rsts-11.mit.edu>
+
+	* serial.c (rs_close): Cleaned up modularization changes.
+		Remove code which forced line discpline back to N_TTY
+		this is done in the tty upper layers, and there's no
+		reason to do it here.  (Making this change also
+		removed the requirement that the serial module access
+		the internal kernel symbol "ldiscs".)
+
+	* tty_io.c (tty_init): Formally register a tty_driver entry for
+		/dev/tty (device 4, 0) and /dev/console (device 5, 0).
+		This guarantees that major device numbers 4 and 5 will be
+		reserved for the tty subsystem (as they have to be because
+		of /dev/tty and /dev/console).  Removed tty_regdev, as
+		this interface is no longer necessary.
+
+Sun Mar 17 20:42:47 GMT 1996 <ah@doc.ic.ac.uk>
+
+	* serial.c : modularisation (changes in linux/fs/device.c allow
+		kerneld to automatically load the serial module).
+
+	* Makefile, Config.in : serial modularisation adds.
+
+	* tty_io.c : tty_init_ctty used by to register "cua" driver just
+		for the /dev/tty device (5,0).  Added tty_regdev.
+	
+	* serial.c (shutdown, rs_ioctl) : when port shuts down wakeup processes
+	  waiting on delta_msr_wait. The TIOCMIWAIT ioctl returns EIO
+	  if no change was done since the time of call.
+
 Sat Mar 16 14:33:13 1996 <aeb@cwi.nl>
 
 	* tty_io.c (disassociate_ctty): If disassociate_ctty is called by
diff -u --recursive --new-file v1.3.90/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v1.3.90/linux/drivers/char/Config.in	Mon Apr 15 12:20:17 1996
+++ linux/drivers/char/Config.in	Wed Apr 17 09:17:46 1996
@@ -4,7 +4,7 @@
 mainmenu_option next_comment
 comment 'Character devices'
 
-bool 'Standard/generic serial support' CONFIG_SERIAL
+tristate 'Standard/generic serial support' CONFIG_SERIAL
 bool 'Digiboard PC/X Support' CONFIG_DIGI
 tristate 'Cyclades async mux support' CONFIG_CYCLADES
 bool 'Stallion multiport serial support' CONFIG_STALDRV
diff -u --recursive --new-file v1.3.90/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v1.3.90/linux/drivers/char/Makefile	Mon Apr 15 12:20:17 1996
+++ linux/drivers/char/Makefile	Wed Apr 17 09:17:46 1996
@@ -25,7 +25,11 @@
 	defkeymap.o consolemap.o selection.o
  
 ifeq ($(CONFIG_SERIAL),y)
-L_OBJS += serial.o
+LX_OBJS += serial.o
+else
+  ifeq ($(CONFIG_SERIAL),m)
+  MX_OBJS += serial.o
+  endif
 endif
 
 ifeq ($(CONFIG_DIGI),y)
diff -u --recursive --new-file v1.3.90/linux/drivers/char/README.stallion linux/drivers/char/README.stallion
--- v1.3.90/linux/drivers/char/README.stallion	Wed Mar 27 08:19:28 1996
+++ linux/drivers/char/README.stallion	Wed Apr 17 15:08:57 1996
@@ -26,9 +26,9 @@
 The following ftp sites (and their mirrors) definitely have the stallion
 driver utility package: ftp.stallion.com, tsx-11.mit.edu, sunsite.unc.edu.
 
-ftp.stallion.com:/drivers/ata5/Linux/stallion-1.0.7.tar.gz
-tsx-11.mit.edu:/pub/linux/BETA/serial/stallion/stallion-1.0.7.tar.gz
-sunsite.unc.edu:/pub/Linux/kernel/patches/serial/stallion-1.0.7.tar.gz
+ftp.stallion.com:/drivers/ata5/Linux/stallion-1.1.0.tar.gz
+tsx-11.mit.edu:/pub/linux/BETA/serial/stallion/stallion-1.1.0.tar.gz
+sunsite.unc.edu:/pub/Linux/kernel/patches/serial/stallion-1.1.0.tar.gz
 
 If you are using the EasyIO or EasyConnection 8/32 boards then you don't
 need this package. Although it does have a handy script to create the
@@ -250,11 +250,11 @@
 possible, most system utilities should work as they do for the standard
 COM ports. Most importantly "stty" works as expected and "setserial" can be
 also be used (excepting the ability to auto-configure the I/O and IRQ
-addresses of boards). Higher baud rates are supported in the
-usual fashion through setserial or using the CBAUDEX extensions. Note that
-the EasyIO and EasyConnection (all types) support 57600 and 115200 baud. The
-older boards including ONboard, Brumby and the original Stallion support a
-maximum baud rate of 38400.
+addresses of boards). Higher baud rates are supported in the usual fashion
+through setserial or using the CBAUDEX extensions. Note that the EasyIO and
+EasyConnection (all types) support 57600 and 115200 baud. The older boards
+including ONboard, Brumby and the original Stallion support a maximum baud
+rate of 38400.
 
 If you are unfamiliar with how to use serial ports, then get the Serial-HOWTO
 by Greg Hankins. It will explain everything you need to know!
@@ -280,12 +280,12 @@
 they can be very difficult to get into a system. If you have 16 Mb of RAM
 then you have no choice but to put them somewhere in the 640K -> 1Mb range.
 ONboards require 64K, so typically 0xd0000 is good, or 0xe0000 on some
-systems. If you have an original Stallion board, "V4.0" or Rev.O,
-then you need a 64K memory address space, so again 0xd0000 and 0xe0000 are
-good. Older Stallion boards are a much bigger problem. They need 128K of
-address space and must be on a 128K boundary. If you don't have a VGA card
-then 0xc0000 might be usable - there is really no other place you can put
-them below 1Mb.
+systems. If you have an original Stallion board, "V4.0" or Rev.O, then you
+need a 64K memory address space, so again 0xd0000 and 0xe0000 are good.
+Older Stallion boards are a much bigger problem. They need 128K of address
+space and must be on a 128K boundary. If you don't have a VGA card then
+0xc0000 might be usable - there is really no other place you can put them
+below 1Mb.
 
 Both the ONboard and old Stallion boards can use higher memory addresses as
 well, but you must have less than 16Mb of RAM to be able to use them. Usual
diff -u --recursive --new-file v1.3.90/linux/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c
--- v1.3.90/linux/drivers/char/apm_bios.c	Mon Apr  8 19:01:43 1996
+++ linux/drivers/char/apm_bios.c	Wed Apr 17 09:01:18 1996
@@ -319,7 +319,6 @@
 #ifdef CONFIG_APM_CPU_IDLE
 static int			clock_slowed = 0;
 #endif
-static int			apm_major;
 static int			suspends_pending = 0;
 static int			standbys_pending = 0;
 
diff -u --recursive --new-file v1.3.90/linux/drivers/char/digi.h linux/drivers/char/digi.h
--- v1.3.90/linux/drivers/char/digi.h	Wed Apr  3 16:06:55 1996
+++ linux/drivers/char/digi.h	Wed Apr 17 08:12:58 1996
@@ -1,41 +1,41 @@
 /*          Definitions for DigiBoard ditty(1) command.                 */
 
 #if !defined(TIOCMODG)
-#define	TIOCMODG	('d'<<8) | 250		/* get modem ctrl state	*/
-#define	TIOCMODS	('d'<<8) | 251		/* set modem ctrl state	*/
+#define	TIOCMODG	(('d'<<8) | 250)		/* get modem ctrl state	*/
+#define	TIOCMODS	(('d'<<8) | 251)		/* set modem ctrl state	*/
 #endif
 
 #if !defined(TIOCMSET)
-#define	TIOCMSET	('d'<<8) | 252		/* set modem ctrl state	*/
-#define	TIOCMGET	('d'<<8) | 253		/* set modem ctrl state	*/
+#define	TIOCMSET	(('d'<<8) | 252)		/* set modem ctrl state	*/
+#define	TIOCMGET	(('d'<<8) | 253)		/* set modem ctrl state	*/
 #endif
 
 #if !defined(TIOCMBIC)
-#define	TIOCMBIC	('d'<<8) | 254		/* set modem ctrl state */
-#define	TIOCMBIS	('d'<<8) | 255		/* set modem ctrl state */
+#define	TIOCMBIC	(('d'<<8) | 254)		/* set modem ctrl state */
+#define	TIOCMBIS	(('d'<<8) | 255)		/* set modem ctrl state */
 #endif
 
 #if !defined(TIOCSDTR)
-#define	TIOCSDTR	('e'<<8) | 0		/* set DTR		*/
-#define	TIOCCDTR	('e'<<8) | 1		/* clear DTR		*/
+#define	TIOCSDTR	(('e'<<8) | 0)		/* set DTR		*/
+#define	TIOCCDTR	(('e'<<8) | 1)		/* clear DTR		*/
 #endif
 
 /************************************************************************
  * Ioctl command arguments for DIGI parameters.
  ************************************************************************/
-#define DIGI_GETA	('e'<<8) | 94		/* Read params		*/
+#define DIGI_GETA	(('e'<<8) | 94)		/* Read params		*/
 
-#define DIGI_SETA	('e'<<8) | 95		/* Set params		*/
-#define DIGI_SETAW	('e'<<8) | 96		/* Drain & set params	*/
-#define DIGI_SETAF	('e'<<8) | 97		/* Drain, flush & set params */
+#define DIGI_SETA	(('e'<<8) | 95)		/* Set params		*/
+#define DIGI_SETAW	(('e'<<8) | 96)		/* Drain & set params	*/
+#define DIGI_SETAF	(('e'<<8) | 97)		/* Drain, flush & set params */
 
-#define	DIGI_GETFLOW	('e'<<8) | 99		/* Get startc/stopc flow */
+#define	DIGI_GETFLOW	(('e'<<8) | 99)		/* Get startc/stopc flow */
 						/* control characters 	 */
-#define	DIGI_SETFLOW	('e'<<8) | 100		/* Set startc/stopc flow */
+#define	DIGI_SETFLOW	(('e'<<8) | 100)		/* Set startc/stopc flow */
 						/* control characters	 */
-#define	DIGI_GETAFLOW	('e'<<8) | 101		/* Get Aux. startc/stopc */
+#define	DIGI_GETAFLOW	(('e'<<8) | 101)		/* Get Aux. startc/stopc */
 						/* flow control chars 	 */
-#define	DIGI_SETAFLOW	('e'<<8) | 102		/* Set Aux. startc/stopc */
+#define	DIGI_SETAFLOW	(('e'<<8) | 102)		/* Set Aux. startc/stopc */
 						/* flow control chars	 */
 
 struct	digiflow_struct {
diff -u --recursive --new-file v1.3.90/linux/drivers/char/istallion.c linux/drivers/char/istallion.c
--- v1.3.90/linux/drivers/char/istallion.c	Fri Apr 12 15:51:52 1996
+++ linux/drivers/char/istallion.c	Wed Apr 17 15:08:57 1996
@@ -39,6 +39,7 @@
 #include <linux/serial.h>
 #include <linux/cdk.h>
 #include <linux/comstats.h>
+#include <linux/istallion.h>
 #include <linux/string.h>
 #include <linux/malloc.h>
 #include <linux/ioport.h>
@@ -167,12 +168,6 @@
 #define	STL_DRVTYPSERIAL	1
 #define	STL_DRVTYPCALLOUT	2
 
-#define	STL_MAXBRDS		4
-#define	STL_MAXPANELS		4
-#define	STL_MAXPORTS		64
-#define	STL_MAXCHANS		(STL_MAXPORTS + 1)
-#define	STL_MAXDEVS		(STL_MAXBRDS * STL_MAXPORTS)
-
 /*****************************************************************************/
 
 /*
@@ -180,7 +175,7 @@
  *	all the local structures required by a serial tty driver.
  */
 static char	*stli_drvname = "Stallion Intelligent Multiport Serial Driver";
-static char	*stli_drvversion = "1.0.8";
+static char	*stli_drvversion = "1.1.1";
 static char	*stli_serialname = "ttyE";
 static char	*stli_calloutname = "cue";
 
@@ -236,92 +231,11 @@
 static comstats_t	stli_comstats;
 static combrd_t		stli_brdstats;
 static asystats_t	stli_cdkstats;
+static stlibrd_t	stli_dummybrd;
+static stliport_t	stli_dummyport;
 
 /*****************************************************************************/
 
-/*
- *	Define a set of structures to hold all the board/panel/port info
- *	for our ports. These will be dynamically allocated as required at
- *	driver initialization time.
- */
-
-/*
- *	Port and board structures to hold status info about each object.
- *	The board structure contains pointers to structures for each port
- *	connected to it. Panels are not distinguished here, since
- *	communication with the slave board will always be on a per port
- *	basis.
- */
-typedef struct {
-	int			portnr;
-	int			panelnr;
-	int			brdnr;
-	unsigned long		state;
-	int			devnr;
-	int			flags;
-	int			baud_base;
-	int			custom_divisor;
-	int			close_delay;
-	int			closing_wait;
-	int			refcount;
-	int			openwaitcnt;
-	int			rc;
-	int			argsize;
-	void			*argp;
-	long			session;
-	long			pgrp;
-	unsigned int		rxmarkmsk;
-	struct tty_struct	*tty;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
-	struct wait_queue	*raw_wait;
-	struct tq_struct	tqhangup;
-	struct termios		normaltermios;
-	struct termios		callouttermios;
-	asysigs_t		asig;
-	unsigned long		addr;
-	unsigned long		rxoffset;
-	unsigned long		txoffset;
-	unsigned long		sigs;
-	unsigned long		pflag;
-	unsigned int		rxsize;
-	unsigned int		txsize;
-	unsigned char		reqbit;
-	unsigned char		portidx;
-	unsigned char		portbit;
-} stliport_t;
-
-/*
- *	Use a structure of function pointers to do board level operations.
- *	These include, enable/disable, paging shared memory, interrupting, etc.
- */
-typedef struct stlbrd {
-	int		brdnr;
-	int		brdtype;
-	int		state;
-	int		nrpanels;
-	int		nrports;
-	int		nrdevs;
-	unsigned int	iobase;
-	unsigned long	memaddr;
-	void		*membase;
-	int		memsize;
-	int		pagesize;
-	int		hostoffset;
-	int		slaveoffset;
-	int		bitsize;
-	int		panels[STL_MAXPANELS];
-	int		panelids[STL_MAXPANELS];
-	void		(*init)(struct stlbrd *brdp);
-	void		(*enable)(struct stlbrd *brdp);
-	void		(*reenable)(struct stlbrd *brdp);
-	void		(*disable)(struct stlbrd *brdp);
-	char		*(*getmemptr)(struct stlbrd *brdp, unsigned long offset, int line);
-	void		(*intr)(struct stlbrd *brdp);
-	void		(*reset)(struct stlbrd *brdp);
-	stliport_t	*ports[STL_MAXPORTS];
-} stlibrd_t;
-
 static stlibrd_t	*stli_brds[STL_MAXBRDS];
 
 static int		stli_shared = 0;
@@ -674,6 +588,8 @@
 static int	stli_getbrdstats(combrd_t *bp);
 static int	stli_getportstats(stliport_t *portp, comstats_t *cp);
 static int	stli_clrportstats(stliport_t *portp, comstats_t *cp);
+static int	stli_getportstruct(unsigned long arg);
+static int	stli_getbrdstruct(unsigned long arg);
 static void	*stli_memalloc(int len);
 
 static void	stli_ecpinit(stlibrd_t *brdp);
@@ -1378,13 +1294,22 @@
 static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *filp)
 {
 	unsigned long	flags;
-	int		rc;
+	int		rc, doclocal;
 
 #if DEBUG
 	printk("stli_waitcarrier(brdp=%x,portp=%x,filp=%x)\n", (int) brdp, (int) portp, (int) filp);
 #endif
 
 	rc = 0;
+	doclocal = 0;
+
+	if (portp->flags & ASYNC_CALLOUT_ACTIVE) {
+		if (portp->normaltermios.c_cflag & CLOCAL)
+			doclocal++;
+	} else {
+		if (portp->tty->termios->c_cflag & CLOCAL)
+			doclocal++;
+	}
 
 	save_flags(flags);
 	cli();
@@ -1407,8 +1332,7 @@
 		}
 		if (((portp->flags & ASYNC_CALLOUT_ACTIVE) == 0) &&
 				((portp->flags & ASYNC_CLOSING) == 0) &&
-				((portp->tty->termios->c_cflag & CLOCAL) ||
-				(portp->sigs & TIOCM_CD))) {
+				(doclocal || (portp->sigs & TIOCM_CD))) {
 			break;
 		}
 		if (current->signal & ~current->blocked) {
@@ -2540,10 +2464,12 @@
 			if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
 				wake_up_interruptible(&portp->open_wait);
 			if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
-				if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) &&
-						(portp->flags & ASYNC_CALLOUT_NOHUP))) {
-					if (tty != (struct tty_struct *) NULL)
-						queue_task_irq_off(&portp->tqhangup, &tq_scheduler);
+				if (portp->flags & ASYNC_CHECK_CD) {
+					if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) &&
+							(portp->flags & ASYNC_CALLOUT_NOHUP))) {
+						if (tty != (struct tty_struct *) NULL)
+							queue_task_irq_off(&portp->tqhangup, &tq_scheduler);
+					}
 				}
 			}
 		}
@@ -2552,8 +2478,10 @@
 			clear_bit(ST_TXBUSY, &portp->state);
 		if (nt.data & (DT_TXEMPTY | DT_TXLOW)) {
 			if (tty != (struct tty_struct *) NULL) {
-				if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
+				if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
 					(tty->ldisc.write_wakeup)(tty);
+					EBRDENABLE(brdp);
+				}
 				wake_up_interruptible(&tty->write_wait);
 			}
 		}
@@ -2565,8 +2493,10 @@
 					*tty->flip.flag_buf_ptr++ = TTY_BREAK;
 					*tty->flip.char_buf_ptr++ = 0;
 #ifndef MODULE
-					if (portp->flags & ASYNC_SAK)
+					if (portp->flags & ASYNC_SAK) {
 						do_SAK(tty);
+						EBRDENABLE(brdp);
+					}
 #endif
 					tty_schedule_flip(tty);
 				}
@@ -2798,6 +2728,14 @@
 		portp->rxmarkmsk |= BRKINT;
 
 /*
+ *	Set up clocal processing as required.
+ */
+	if (tiosp->c_cflag & CLOCAL)
+		portp->flags &= ~ASYNC_CHECK_CD;
+	else
+		portp->flags |= ASYNC_CHECK_CD;
+
+/*
  *	Transfer any persistent flags into the asyport structure.
  */
 	pp->pflag = portp->pflag;
@@ -2876,6 +2814,7 @@
 		}
 
 		memset(portp, 0, sizeof(stliport_t));
+		portp->magic = STLI_PORTMAGIC;
 		portp->portnr = i;
 		portp->brdnr = brdp->brdnr;
 		portp->panelnr = panelnr;
@@ -4061,6 +4000,7 @@
 		}
 		memset(brdp, 0, sizeof(stlibrd_t));
 
+		brdp->magic = STLI_BOARDMAGIC;
 		brdp->brdnr = stli_nrbrds++;
 		eid = inb(iobase + 0xc82);
 		if (eid == ECP_EISAID)
@@ -4114,6 +4054,7 @@
 		}
 		memset(brdp, 0, sizeof(stlibrd_t));
 
+		brdp->magic = STLI_BOARDMAGIC;
 		brdp->brdnr = i;
 		brdp->brdtype = confp->brdtype;
 		brdp->iobase = confp->ioaddr1;
@@ -4336,6 +4277,7 @@
 
 static int stli_getportstats(stliport_t *portp, comstats_t *cp)
 {
+	unsigned long	flags;
 	stlibrd_t	*brdp;
 	int		rc;
 
@@ -4353,23 +4295,28 @@
 	if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, &stli_cdkstats, sizeof(asystats_t), 1)) < 0)
 		return(rc);
 
+	memset(&stli_comstats, 0, sizeof(comstats_t));
+	stli_comstats.brd = portp->brdnr;
+	stli_comstats.panel = portp->panelnr;
+	stli_comstats.port = portp->portnr;
 	stli_comstats.state = portp->state;
 	stli_comstats.flags = portp->flags;
+
+	save_flags(flags);
+	cli();
 	if (portp->tty != (struct tty_struct *) NULL) {
-		stli_comstats.ttystate = portp->tty->flags;
-		stli_comstats.cflags = portp->tty->termios->c_cflag;
-		stli_comstats.iflags = portp->tty->termios->c_iflag;
-		stli_comstats.oflags = portp->tty->termios->c_oflag;
-		stli_comstats.lflags = portp->tty->termios->c_lflag;
-		stli_comstats.rxbuffered = portp->tty->flip.count;
-	} else {
-		stli_comstats.ttystate = 0;
-		stli_comstats.cflags = 0;
-		stli_comstats.iflags = 0;
-		stli_comstats.oflags = 0;
-		stli_comstats.lflags = 0;
-		stli_comstats.rxbuffered = 0;
+		if (portp->tty->driver_data == portp) {
+			stli_comstats.ttystate = portp->tty->flags;
+			stli_comstats.rxbuffered = portp->tty->flip.count;
+			if (portp->tty->termios != (struct termios *) NULL) {
+				stli_comstats.cflags = portp->tty->termios->c_cflag;
+				stli_comstats.iflags = portp->tty->termios->c_iflag;
+				stli_comstats.oflags = portp->tty->termios->c_oflag;
+				stli_comstats.lflags = portp->tty->termios->c_lflag;
+			}
+		}
 	}
+	restore_flags(flags);
 
 	stli_comstats.txtotal = stli_cdkstats.txchars;
 	stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover;
@@ -4432,6 +4379,45 @@
 /*****************************************************************************/
 
 /*
+ *	Return the entire driver ports structure to a user app.
+ */
+
+static int stli_getportstruct(unsigned long arg)
+{
+	stliport_t	*portp;
+
+	memcpy_fromfs(&stli_dummyport, (void *) arg, sizeof(stliport_t));
+	portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr,
+		 stli_dummyport.portnr);
+	if (portp == (stliport_t *) NULL)
+		return(-ENODEV);
+	memcpy_tofs((void *) arg, portp, sizeof(stliport_t));
+	return(0);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the entire driver board structure to a user app.
+ */
+
+static int stli_getbrdstruct(unsigned long arg)
+{
+	stlibrd_t	*brdp;
+
+	memcpy_fromfs(&stli_dummybrd, (void *) arg, sizeof(stlibrd_t));
+	if ((stli_dummybrd.brdnr < 0) || (stli_dummybrd.brdnr >= STL_MAXBRDS))
+		return(-ENODEV);
+	brdp = stli_brds[stli_dummybrd.brdnr];
+	if (brdp == (stlibrd_t *) NULL)
+		return(-ENODEV);
+	memcpy_tofs((void *) arg, brdp, sizeof(stlibrd_t));
+	return(0);
+}
+
+/*****************************************************************************/
+
+/*
  *	The "staliomem" device is also required to do some special operations on
  *	the board. We need to be able to send an interrupt to the board,
  *	reset it, and start/stop it.
@@ -4486,6 +4472,14 @@
 	case COM_GETBRDSTATS:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(combrd_t))) == 0)
 			rc = stli_getbrdstats((combrd_t *) arg);
+		break;
+	case COM_READPORT:
+		if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(stliport_t))) == 0)
+			rc = stli_getportstruct(arg);
+		break;
+	case COM_READBOARD:
+		if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(stlibrd_t))) == 0)
+			rc = stli_getbrdstruct(arg);
 		break;
 	default:
 		rc = -ENOIOCTLCMD;
diff -u --recursive --new-file v1.3.90/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v1.3.90/linux/drivers/char/misc.c	Mon Apr 15 12:20:17 1996
+++ linux/drivers/char/misc.c	Wed Apr 17 09:22:07 1996
@@ -176,8 +176,8 @@
 	X(misc_register),
 	X(misc_deregister),
 #ifndef MODULE
-	X(set_selection),   /* used by the kmisc module, can only */
-	X(clear_selection), /* be exported if misc.c is in linked in */
+	X(set_selection),   /* used by the kmouse module, can only */
+	X(paste_selection), /* be exported if misc.c is in linked in */
 #endif
 #include <linux/symtab_end.h>
 };
@@ -196,7 +196,7 @@
 #ifdef CONFIG_BUSMOUSE
 	bus_mouse_init();
 #endif
-#if defined CONFIG_PSMOUSE || defined CONFIG_82C710_MOUSE
+#if defined CONFIG_PSMOUSE
 	psaux_init();
 #endif
 #ifdef CONFIG_MS_BUSMOUSE
diff -u --recursive --new-file v1.3.90/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c
--- v1.3.90/linux/drivers/char/pcxx.c	Fri Apr 12 15:51:52 1996
+++ linux/drivers/char/pcxx.c	Wed Apr 17 08:12:58 1996
@@ -28,6 +28,8 @@
  *  1.5.5 April 5, 1996 Major device numbers corrected.
  *              Mike McLagan<mike.mclagan@linux.org>: Add setup
  *              variable handling, instead of using the old pcxxconfig.h
+ *  1.5.6 April 16, 1996 Christoph Lameter: Pointer cleanup, macro cleanup.
+ *		Call out devices changed to /dev/cudxx.
  *
  */
 
@@ -64,8 +66,8 @@
 #include <asm/segment.h>
 #include <asm/bitops.h>
 
-#define VERSION 	"1.5.5"
-static char *banner = "Digiboard PC/X{i,e,eve,em} driver v1.5.5.  Christoph Lameter <clameter@fuller.edu>.";
+#define VERSION 	"1.5.6"
+static char *banner = "Digiboard PC/X{i,e,eve} driver v1.5.6.  Christoph Lameter <clameter@fuller.edu>.";
 
 /*#define	DEFAULT_HW_FLOW	1 */
 /*#define	DEBUG_IOCTL */
@@ -81,16 +83,13 @@
  */
 static struct board_info boards[MAX_DIGI_BOARDS] = { {	ENABLED, 0, ON, 16, 0x200, 0xd0000,0 } };
  
-static int               numcards = 1;
-static int               nbdevs = 0;
+static int numcards = 1;
+static int nbdevs = 0;
  
-/* C is a pain!  I want a pointer to an array of structs */
-static struct channel    *(*digi_channels);
-
-/* this is supposed to be a pointer to an array of pointers */
-static struct tty_struct *(*pcxe_table)[];
-static struct termios    *(*pcxe_termios)[];
-static struct termios    *(*pcxe_termios_locked)[];
+static struct channel    *digi_channels;
+static struct tty_struct **pcxe_table;
+static struct termios    **pcxe_termios;
+static struct termios    **pcxe_termios_locked;
  
 int pcxx_ncook=sizeof(pcxx_cook);
 int pcxx_nbios=sizeof(pcxx_bios);
@@ -150,7 +149,7 @@
 {
 	if (tty) {
 		register struct channel *ch=(struct channel *)tty->driver_data;
-		if ((ch >= &((*digi_channels)[0])) && (ch < &((*digi_channels)[nbdevs]))) {
+		if (ch >= digi_channels && ch < digi_channels+nbdevs) {
 			if (ch->magic==PCXX_MAGIC)
 				return ch;
 		}
@@ -319,7 +318,7 @@
 		return(-ENODEV);
 	}
 
-	ch = &((*digi_channels)[line]);
+	ch = digi_channels+line;
 
 	if(ch->brdchan == 0) {
 		tty->driver_data = NULL;
@@ -990,22 +989,21 @@
 
 	/*
 	 * this turns out to be more memory efficient, as there are no 
-	 * unused spaces.  There is *NO* way I'm going to explain these
-	 * convoluted casts, suffice it to say they WORK!  :)
+	 * unused spaces.
 	 */
-	digi_channels = (struct channel **) kmalloc(sizeof(struct channel) * nbdevs, GFP_KERNEL);
+	digi_channels = kmalloc(sizeof(struct channel) * nbdevs, GFP_KERNEL);
 	if (!digi_channels)
 		panic("Unable to allocate digi_channel struct");
 
-	pcxe_table = (struct tty_struct *(*)[]) kmalloc(sizeof(struct tty_struct *) * nbdevs, GFP_KERNEL);
+	pcxe_table =  kmalloc(sizeof(struct tty_struct *) * nbdevs, GFP_KERNEL);
 	if (!pcxe_table)
 		panic("Unable to allocate pcxe_table struct");
 
-	pcxe_termios = (struct termios *(*)[]) kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL);
+	pcxe_termios = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL);
 	if (!pcxe_termios)
 		panic("Unable to allocate pcxe_termios struct");
 
-	pcxe_termios_locked = (struct termios *(*)[]) kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL);
+	pcxe_termios_locked = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL);
 	if (!pcxe_termios_locked)
 		panic("Unable to allocate pcxe_termios_locked struct");
 
@@ -1018,7 +1016,7 @@
 
 	memset(&pcxe_driver, 0, sizeof(struct tty_driver));
 	pcxe_driver.magic = TTY_DRIVER_MAGIC;
-	pcxe_driver.name = "ttyd";
+	pcxe_driver.name = "cud";
 	pcxe_driver.major = DIGI_MAJOR; 
 	pcxe_driver.minor_start = 0;
 
@@ -1031,9 +1029,9 @@
 	pcxe_driver.flags = TTY_DRIVER_REAL_RAW;
 	pcxe_driver.refcount = &pcxe_refcount;
 
-	pcxe_driver.table = *pcxe_table;
-	pcxe_driver.termios = *pcxe_termios;
-	pcxe_driver.termios_locked = *pcxe_termios_locked;
+	pcxe_driver.table = pcxe_table;
+	pcxe_driver.termios = pcxe_termios;
+	pcxe_driver.termios_locked = pcxe_termios_locked;
 
 	pcxe_driver.open = pcxe_open;
 	pcxe_driver.close = pcxe_close;
@@ -1259,8 +1257,8 @@
 		if(bd->status == DISABLED)
 			continue;
 
-		ch = &((*digi_channels)[bd->first_minor]);
-		pcxxassert(ch < &((*digi_channels)[nbdevs]), "ch out of range");
+		ch = digi_channels+bd->first_minor;
+		pcxxassert(ch < digi_channels+nbdevs, "ch out of range");
 
 		bc = (volatile struct board_chan *)((ulong)memaddr + CHANSTRUCT);
 		gd = (volatile struct global_data *)((ulong)memaddr + GLOBAL);
@@ -1391,7 +1389,7 @@
 	for(crd=0; crd < numcards; crd++) {
 		bd = &boards[crd];
 
-		ch = &((*digi_channels)[bd->first_minor]);
+		ch = digi_channels+bd->first_minor;
 
 		if(bd->status == DISABLED)
 			continue;
@@ -1428,8 +1426,8 @@
 
 	bd = &boards[crd];
 
-	chan0 = &((*digi_channels)[bd->first_minor]);
-	pcxxassert(chan0 < &((*digi_channels)[nbdevs]), "ch out of range");
+	chan0 = digi_channels+bd->first_minor;
+	pcxxassert(chan0 < digi_channels+nbdevs, "ch out of range");
 
 
 	assertgwinon(chan0);
diff -u --recursive --new-file v1.3.90/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v1.3.90/linux/drivers/char/serial.c	Mon Apr  8 19:01:43 1996
+++ linux/drivers/char/serial.c	Wed Apr 17 09:01:19 1996
@@ -11,7 +11,9 @@
  *  set_serial_info fixed to set the flags, custom divisor, and uart
  * 	type fields.  Fix suggested by Michael K. Johnson 12/12/92.
  *
- *  TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis <ah@doc.ic.ac.uk>
+ *  11/95: TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis <ah@doc.ic.ac.uk>
+ *
+ *  03/96: Modularised by Angelo Haritsis <ah@doc.ic.ac.uk>
  *
  * This module exports the following rs232 io functions:
  *
@@ -19,6 +21,7 @@
  * 	int rs_open(struct tty_struct * tty, struct file * filp)
  */
 
+#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -41,6 +44,9 @@
 #include <asm/segment.h>
 #include <asm/bitops.h>
 
+static char *serial_name = "Serial driver";
+static char *serial_version = "4.12";
+
 DECLARE_TASK_QUEUE(tq_serial);
 
 struct tty_driver serial_driver, callout_driver;
@@ -80,6 +86,13 @@
 
 #define _INLINE_ inline
   
+#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
+#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
+ kdevname(tty->device), (info->flags), serial_refcount,info->count,tty->count,s)
+#else
+#define DBG_CNT(s)
+#endif
+
 /*
  * IRQ_timeout		- How long the timeout should be for each IRQ
  * 				should be after the IRQ has been active.
@@ -1076,6 +1089,12 @@
 #endif
 	
 	save_flags(flags); cli(); /* Disable interrupts */
+
+	/*
+	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+	 * here so the queue might never be waken up
+	 */
+	wake_up_interruptible(&info->delta_msr_wait);
 	
 	/*
 	 * First unlink the serial port from the IRQ chain...
@@ -2002,6 +2021,9 @@
 				cli();
 				cnow = info->icount;	/* atomic copy */
 				sti();
+				if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 
+				    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+					return -EIO; /* no change => error */
 				if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
 				     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
 				     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
@@ -2089,6 +2111,8 @@
 	save_flags(flags); cli();
 	
 	if (tty_hung_up_p(filp)) {
+		DBG_CNT("before DEC-hung");
+		MOD_DEC_USE_COUNT;
 		restore_flags(flags);
 		return;
 	}
@@ -2114,6 +2138,8 @@
 		info->count = 0;
 	}
 	if (info->count) {
+		DBG_CNT("before DEC-2");
+		MOD_DEC_USE_COUNT;
 		restore_flags(flags);
 		return;
 	}
@@ -2165,14 +2191,6 @@
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
-	if (tty->ldisc.num != ldiscs[N_TTY].num) {
-		if (tty->ldisc.close)
-			(tty->ldisc.close)(tty);
-		tty->ldisc = ldiscs[N_TTY];
-		tty->termios->c_line = N_TTY;
-		if (tty->ldisc.open)
-			(tty->ldisc.open)(tty);
-	}
 	if (info->blocked_open) {
 		if (info->close_delay) {
 			current->state = TASK_INTERRUPTIBLE;
@@ -2184,6 +2202,7 @@
 	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
 			 ASYNC_CLOSING);
 	wake_up_interruptible(&info->close_wait);
+	MOD_DEC_USE_COUNT;
 	restore_flags(flags);
 }
 
@@ -2387,6 +2406,7 @@
 	if (retval)
 		return retval;
 
+	MOD_INC_USE_COUNT;
 	retval = block_til_ready(tty, filp, info);
 	if (retval) {
 #ifdef SERIAL_DEBUG_OPEN
@@ -2428,7 +2448,7 @@
  */
 static void show_serial_version(void)
 {
-	printk("Serial driver version 4.11a with");
+ 	printk("%s version %s with", serial_name, serial_version);
 #ifdef CONFIG_HUB6
 	printk(" HUB-6");
 #define SERIAL_OPT
@@ -2663,6 +2683,16 @@
 	restore_flags(flags);
 }
 
+int register_serial(struct serial_struct *req);
+void unregister_serial(int line);
+
+static struct symbol_table serial_syms = {
+#include <linux/symtab_begin.h>
+	X(register_serial),
+	X(unregister_serial),
+#include <linux/symtab_end.h>
+};
+
 /*
  * The serial driver boot-time initialization code!
  */
@@ -2791,6 +2821,7 @@
 				break;
 		}
 	}
+	register_symtab(&serial_syms);
 	return 0;
 }
 
@@ -2867,3 +2898,30 @@
 	printk("tty%02d unloaded\n", info->line);
 	restore_flags(flags);
 }
+
+#ifdef MODULE
+int init_module(void)
+{
+	return rs_init();
+}
+
+void cleanup_module(void) 
+{
+	unsigned long flags;
+	int e1, e2;
+
+	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
+	save_flags(flags);
+	cli();
+	timer_active &= ~(1 << RS_TIMER);
+	timer_table[RS_TIMER].fn = NULL;
+	timer_table[RS_TIMER].expires = 0;
+	if ((e1 = tty_unregister_driver(&serial_driver)))
+		printk("SERIAL: failed to unregister serial driver (%d)\n",
+		       e1);
+	if ((e2 = tty_unregister_driver(&callout_driver)))
+		printk("SERIAL: failed to unregister callout driver (%d)\n", 
+		       e2);
+	restore_flags(flags);
+}
+#endif /* MODULE */
diff -u --recursive --new-file v1.3.90/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v1.3.90/linux/drivers/char/stallion.c	Sat Apr 13 18:22:06 1996
+++ linux/drivers/char/stallion.c	Wed Apr 17 15:08:57 1996
@@ -38,6 +38,7 @@
 #include <linux/serial.h>
 #include <linux/cd1400.h>
 #include <linux/comstats.h>
+#include <linux/stallion.h>
 #include <linux/string.h>
 #include <linux/malloc.h>
 #include <linux/ioport.h>
@@ -124,12 +125,6 @@
 #define	STL_DRVTYPSERIAL	1
 #define	STL_DRVTYPCALLOUT	2
 
-#define	STL_MAXBRDS		4
-#define	STL_MAXPANELS		4
-#define	STL_PORTSPERPANEL	16
-#define	STL_MAXPORTS		64
-#define	STL_MAXDEVS		(STL_MAXBRDS * STL_MAXPORTS)
-
 /*
  *	I haven't really decided (or measured) what TX buffer size gives
  *	a good balance between performance and memory usage. These seem
@@ -145,7 +140,7 @@
  *	all the local structures required by a serial tty driver.
  */
 static char	*stl_drvname = "Stallion Multiport Serial Driver";
-static char	*stl_drvversion = "1.0.8";
+static char	*stl_drvversion = "1.1.1";
 static char	*stl_serialname = "ttyE";
 static char	*stl_calloutname = "cue";
 
@@ -186,6 +181,8 @@
  */
 static comstats_t	stl_comstats;
 static combrd_t		stl_brdstats;
+static stlbrd_t		stl_dummybrd;
+static stlport_t	stl_dummyport;
 
 /*
  *	Keep track of what interrupts we have requested for us.
@@ -197,98 +194,6 @@
 
 /*****************************************************************************/
 
-/*
- *	Define a set of structures to hold all the board/panel/port info
- *	for our ports. These will be dynamically allocated as required.
- */
-
-/*
- *	Define a ring queue structure for each port. This will hold the
- *	TX data waiting to be output. Characters are fed into this buffer
- *	from the line discipline (or even direct from user space!) and
- *	then fed into the UARTs during interrupts. Will use a classic ring
- *	queue here for this. The good thing about this type of ring queue
- *	is that the head and tail pointers can be updated without interrupt
- *	protection - since "write" code only needs to change the head, and
- *	interrupt code only needs to change the tail.
- */
-typedef struct {
-	char	*buf;
-	char	*head;
-	char	*tail;
-} stlrq_t;
-
-/*
- *	Port, panel and board structures to hold status info about each.
- *	The board structure contains pointers to structures for each panel
- *	connected to it, and in turn each panel structure contains pointers
- *	for each port structure for each port on that panel. Note that
- *	the port structure also contains the board and panel number that it
- *	is associated with, this makes it (fairly) easy to get back to the
- *	board/panel info for a port.
- */
-typedef struct {
-	int			portnr;
-	int			panelnr;
-	int			brdnr;
-	int			ioaddr;
-	int			uartaddr;
-	int			pagenr;
-	int			istate;
-	int			flags;
-	int			baud_base;
-	int			custom_divisor;
-	int			close_delay;
-	int			closing_wait;
-	int			refcount;
-	int			openwaitcnt;
-	int			brklen;
-	long			session;
-	long			pgrp;
-	unsigned int		sigs;
-	unsigned int		rxignoremsk;
-	unsigned int		rxmarkmsk;
-	unsigned long		clk;
-	unsigned long		hwid;
-	struct tty_struct	*tty;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
-	struct termios		normaltermios;
-	struct termios		callouttermios;
-	struct tq_struct	tqueue;
-	comstats_t		stats;
-	stlrq_t			tx;
-} stlport_t;
-
-typedef struct {
-	int		panelnr;
-	int		brdnr;
-	int		pagenr;
-	int		nrports;
-	int		iobase;
-	unsigned int	hwid;
-	unsigned int	ackmask;
-	stlport_t	*ports[STL_PORTSPERPANEL];
-} stlpanel_t;
-
-typedef struct {
-	int		brdnr;
-	int		brdtype;
-	int		state;
-	int		nrpanels;
-	int		nrports;
-	int		irq;
-	int		irqtype;
-	unsigned int	ioaddr1;
-	unsigned int	ioaddr2;
-	unsigned int	iostatus;
-	unsigned int	ioctrl;
-	unsigned int	ioctrlval;
-	unsigned int	hwid;
-	unsigned long	clk;
-	stlpanel_t	*panels[STL_MAXPANELS];
-} stlbrd_t;
-
 static stlbrd_t		*stl_brds[STL_MAXBRDS];
 
 /*
@@ -501,6 +406,8 @@
 static int	stl_getbrdstats(combrd_t *bp);
 static int	stl_getportstats(stlport_t *portp, comstats_t *cp);
 static int	stl_clrportstats(stlport_t *portp, comstats_t *cp);
+static int	stl_getportstruct(unsigned long arg);
+static int	stl_getbrdstruct(unsigned long arg);
 static void	stl_setreg(stlport_t *portp, int regnr, int value);
 static int	stl_getreg(stlport_t *portp, int regnr);
 static int	stl_updatereg(stlport_t *portp, int regnr, int value);
@@ -785,13 +692,22 @@
 static int stl_waitcarrier(stlport_t *portp, struct file *filp)
 {
 	unsigned long	flags;
-	int		rc;
+	int		rc, doclocal;
 
 #if DEBUG
 	printk("stl_waitcarrier(portp=%x,filp=%x)\n", (int) portp, (int) filp);
 #endif
 
 	rc = 0;
+	doclocal = 0;
+
+	if (portp->flags & ASYNC_CALLOUT_ACTIVE) {
+		if (portp->normaltermios.c_cflag & CLOCAL)
+			doclocal++;
+	} else {
+		if (portp->tty->termios->c_cflag & CLOCAL)
+			doclocal++;
+	}
 
 	save_flags(flags);
 	cli();
@@ -811,8 +727,7 @@
 		}
 		if (((portp->flags & ASYNC_CALLOUT_ACTIVE) == 0) &&
 				((portp->flags & ASYNC_CLOSING) == 0) &&
-				((portp->tty->termios->c_cflag & CLOCAL) ||
-				(portp->sigs & TIOCM_CD))) {
+				(doclocal || (portp->sigs & TIOCM_CD))) {
 			break;
 		}
 		if (current->signal & ~current->blocked) {
@@ -1747,8 +1662,10 @@
 				if (status & ST_BREAK) {
 					status = TTY_BREAK;
 #ifndef MODULE
-					if (portp->flags & ASYNC_SAK)
+					if (portp->flags & ASYNC_SAK) {
 						do_SAK(tty);
+						BRDENABLE(portp->brdnr, portp->pagenr);
+					}
 #endif
 				} else if (status & ST_PARITY) {
 					status = TTY_PARITY;
@@ -1995,9 +1912,11 @@
 		if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
 			wake_up_interruptible(&portp->open_wait);
 		if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
-			if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) &&
-					(portp->flags & ASYNC_CALLOUT_NOHUP))) {
-				tty_hangup(tty);
+			if (portp->flags & ASYNC_CHECK_CD) {
+				if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) &&
+						(portp->flags & ASYNC_CALLOUT_NOHUP))) {
+					tty_hangup(tty);
+				}
 			}
 		}
 	}
@@ -2164,6 +2083,9 @@
 		mcor1 |= MCOR1_DCD;
 		mcor2 |= MCOR2_DCD;
 		sreron |= SRER_MODEM;
+		portp->flags |= ASYNC_CHECK_CD;
+	} else {
+		portp->flags &= ~ASYNC_CHECK_CD;
 	}
 
 /*
@@ -2533,6 +2455,7 @@
 			break;
 		}
 		memset(portp, 0, sizeof(stlport_t));
+		portp->magic = STL_PORTMAGIC;
 		portp->portnr = i;
 		portp->brdnr = panelp->brdnr;
 		portp->panelnr = panelp->panelnr;
@@ -2617,6 +2540,7 @@
 	}
 	memset(panelp, 0, sizeof(stlpanel_t));
 
+	panelp->magic = STL_PANELMAGIC;
 	panelp->brdnr = brdp->brdnr;
 	panelp->panelnr = 0;
 	panelp->nrports = brdp->nrports;
@@ -2722,6 +2646,7 @@
 			break;
 		}
 		memset(panelp, 0, sizeof(stlpanel_t));
+		panelp->magic = STL_PANELMAGIC;
 		panelp->brdnr = brdp->brdnr;
 		panelp->panelnr = panelnr;
 		panelp->iobase = ioaddr;
@@ -2854,6 +2779,7 @@
 				return(-ENOMEM);
 			}
 			memset(brdp, 0, sizeof(stlbrd_t));
+			brdp->magic = STL_BOARDMAGIC;
 			brdp->brdnr = stl_nrbrds++;
 			brdp->brdtype = BRD_ECHPCI;
 
@@ -2923,6 +2849,7 @@
 		}
 		memset(brdp, 0, sizeof(stlbrd_t));
 
+		brdp->magic = STL_BOARDMAGIC;
 		brdp->brdnr = i;
 		brdp->brdtype = confp->brdtype;
 		brdp->ioaddr1 = confp->ioaddr1;
@@ -3020,6 +2947,7 @@
 static int stl_getportstats(stlport_t *portp, comstats_t *cp)
 {
 	unsigned char	*head, *tail;
+	unsigned long	flags;
 
 	if (portp == (stlport_t *) NULL) {
 		memcpy_fromfs(&stl_comstats, cp, sizeof(comstats_t));
@@ -3031,21 +2959,29 @@
 	portp->stats.state = portp->istate;
 	portp->stats.flags = portp->flags;
 	portp->stats.hwid = portp->hwid;
+
+	portp->stats.ttystate = 0;
+	portp->stats.cflags = 0;
+	portp->stats.iflags = 0;
+	portp->stats.oflags = 0;
+	portp->stats.lflags = 0;
+	portp->stats.rxbuffered = 0;
+
+	save_flags(flags);
+	cli();
 	if (portp->tty != (struct tty_struct *) NULL) {
-		portp->stats.ttystate = portp->tty->flags;
-		portp->stats.cflags = portp->tty->termios->c_cflag;
-		portp->stats.iflags = portp->tty->termios->c_iflag;
-		portp->stats.oflags = portp->tty->termios->c_oflag;
-		portp->stats.lflags = portp->tty->termios->c_lflag;
-		portp->stats.rxbuffered = portp->tty->flip.count;
-	} else {
-		portp->stats.ttystate = 0;
-		portp->stats.cflags = 0;
-		portp->stats.iflags = 0;
-		portp->stats.oflags = 0;
-		portp->stats.lflags = 0;
-		portp->stats.rxbuffered = 0;
+		if (portp->tty->driver_data == portp) {
+			portp->stats.ttystate = portp->tty->flags;
+			portp->stats.rxbuffered = portp->tty->flip.count;
+			if (portp->tty->termios != (struct termios *) NULL) {
+				portp->stats.cflags = portp->tty->termios->c_cflag;
+				portp->stats.iflags = portp->tty->termios->c_iflag;
+				portp->stats.oflags = portp->tty->termios->c_oflag;
+				portp->stats.lflags = portp->tty->termios->c_lflag;
+			}
+		}
 	}
+	restore_flags(flags);
 
 	head = portp->tx.head;
 	tail = portp->tx.tail;
@@ -3083,6 +3019,45 @@
 /*****************************************************************************/
 
 /*
+ *	Return the entire driver ports structure to a user app.
+ */
+
+static int stl_getportstruct(unsigned long arg)
+{
+	stlport_t	*portp;
+
+	memcpy_fromfs(&stl_dummyport, (void *) arg, sizeof(stlport_t));
+	portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
+		 stl_dummyport.portnr);
+	if (portp == (stlport_t *) NULL)
+		return(-ENODEV);
+	memcpy_tofs((void *) arg, portp, sizeof(stlport_t));
+	return(0);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the entire driver board structure to a user app.
+ */
+
+static int stl_getbrdstruct(unsigned long arg)
+{
+	stlbrd_t	*brdp;
+
+	memcpy_fromfs(&stl_dummybrd, (void *) arg, sizeof(stlbrd_t));
+	if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
+		return(-ENODEV);
+	brdp = stl_brds[stl_dummybrd.brdnr];
+	if (brdp == (stlbrd_t *) NULL)
+		return(-ENODEV);
+	memcpy_tofs((void *) arg, brdp, sizeof(stlbrd_t));
+	return(0);
+}
+
+/*****************************************************************************/
+
+/*
  *	The "staliomem" device is also required to do some special operations
  *	on the board and/or ports. In this driver it is mostly used for stats
  *	collection.
@@ -3118,6 +3093,14 @@
 	case COM_GETBRDSTATS:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(combrd_t))) == 0)
 			rc = stl_getbrdstats((combrd_t *) arg);
+		break;
+	case COM_READPORT:
+		if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(stlport_t))) == 0)
+			rc = stl_getportstruct(arg);
+		break;
+	case COM_READBOARD:
+		if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(stlbrd_t))) == 0)
+			rc = stl_getbrdstruct(arg);
 		break;
 	default:
 		rc = -ENOIOCTLCMD;
diff -u --recursive --new-file v1.3.90/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v1.3.90/linux/drivers/char/tty_io.c	Wed Apr  3 16:06:55 1996
+++ linux/drivers/char/tty_io.c	Wed Apr 17 09:01:19 1996
@@ -1763,6 +1763,9 @@
 		else if (p->major == driver->major)
 			othername = p->name;
 	}
+	
+	if (!found)
+		return -ENOENT;
 
 	if (othername == NULL) {
 		retval = unregister_chrdev(driver->major, driver->name);
@@ -1814,6 +1817,8 @@
 	return con_init(kmem_start);
 }
 
+static struct tty_driver dev_tty_driver, dev_console_driver;
+
 /*
  * Ok, now we can initialize the rest of the tty devices and can count
  * on memory allocations, interrupts etc..
@@ -1822,6 +1827,31 @@
 {
 	if (sizeof(struct tty_struct) > PAGE_SIZE)
 		panic("size of tty structure > PAGE_SIZE!");
+
+	/*
+	 * dev_tty_driver and dev_console_driver are actually magic
+	 * devices which get redirected at open time.  Nevertheless,
+	 * we register them so that register_chrdev is called
+	 * appropriately.
+	 */
+	memset(&dev_tty_driver, 0, sizeof(struct tty_driver));
+	dev_tty_driver.magic = TTY_DRIVER_MAGIC;
+	dev_tty_driver.name = "tty";
+	dev_tty_driver.name_base = 0;
+	dev_tty_driver.major = TTY_MAJOR;
+	dev_tty_driver.minor_start = 0;
+	dev_tty_driver.num = 1;
+	
+	if (tty_register_driver(&dev_tty_driver))
+		panic("Couldn't register /dev/tty driver\n");
+
+	dev_console_driver = dev_tty_driver;
+	dev_console_driver.name = "console";
+	dev_console_driver.major = TTYAUX_MAJOR;
+
+	if (tty_register_driver(&dev_console_driver))
+		panic("Couldn't register /dev/console driver\n");
+	
 	kbd_init();
 #ifdef CONFIG_SERIAL
 	rs_init();
@@ -1843,10 +1873,6 @@
 #endif
 	pty_init();
 	vcs_init();
-	if (register_chrdev(TTY_MAJOR,"tty",&tty_fops))
-		panic("unable to get major %d for tty device", TTY_MAJOR);
-	if (register_chrdev(TTYAUX_MAJOR,"cua",&tty_fops))
-		panic("unable to get major %d for tty device", TTYAUX_MAJOR);
-
 	return 0;
 }
+
diff -u --recursive --new-file v1.3.90/linux/drivers/net/3c505.c linux/drivers/net/3c505.c
--- v1.3.90/linux/drivers/net/3c505.c	Fri Apr 12 15:51:54 1996
+++ linux/drivers/net/3c505.c	Wed Apr 17 07:20:07 1996
@@ -10,7 +10,7 @@
  *              be here without 3C505 technical reference provided by
  *              3Com.
  *
- * $Id: 3c505.c,v 1.7 1996/04/09 19:01:30 phil Exp phil $
+ * $Id: 3c505.c,v 1.10 1996/04/16 13:06:27 phil Exp $
  *
  * Authors:     Linux 3c505 device driver by
  *                      Craig Southeren, <craigs@ineluki.apana.org.au>
@@ -174,8 +174,7 @@
  * Last element MUST BE 0!
  *****************************************************************/
 
-const int addr_list[] =
-{0x300, 0x280, 0x310, 0};
+const int addr_list[] = {0x300, 0x280, 0x310, 0};
 
 /* Dma Memory related stuff */
 
@@ -249,10 +248,6 @@
  *
  *****************************************************************/
 
-/* We allocate 8k of DMA buffer for each adapter.  This gives us one buffer for
- * received data, and four for the transmit backlog.
- */
-
 #define DMA_BUFFER_SIZE  1600
 #define BACKLOG_SIZE      4
 
@@ -364,6 +359,10 @@
 		printk("%s: start receive command failed \n", dev->name);
 }
 
+/* Check to make sure that a DMA transfer hasn't timed out.  This should never happen
+ * in theory, but seems to occur occasionally if the card gets prodded at the wrong
+ * time.
+ */
 static inline void check_dma(struct device *dev)
 {
 	elp_device *adapter = dev->priv;
@@ -407,9 +406,6 @@
 	return TRUE;
 }
 
-static int
- start_receive(struct device *dev, pcb_struct * tx_pcb);
-
 /* Check to see if the receiver needs restarting, and kick it if so */
 static inline void prime_rx(struct device *dev)
 {
@@ -871,18 +867,15 @@
 						printk("%s: interrupt - packet sent\n", dev->name);
 					if (dev->start == 0)
 						break;
-					if (adapter->irx_pcb.data.xmit_resp.c_stat != 0) {
-						if (elp_debug >= 0)
-							printk("%s: interrupt - error sending packet %4.4x\n",
-							       dev->name, adapter->irx_pcb.data.xmit_resp.c_stat);
-						switch (adapter->irx_pcb.data.xmit_resp.c_stat) {
-						case 0xffff:
-							adapter->stats.tx_aborted_errors++;
-							break;
-						case 0xfffe:
-							adapter->stats.tx_fifo_errors++;
-							break;
-						}
+					switch (adapter->irx_pcb.data.xmit_resp.c_stat) {
+					case 0xffff:
+						adapter->stats.tx_aborted_errors++;
+						printk(KERN_INFO "%s: transmit timed out, network cable problem?\n", dev->name);
+						break;
+					case 0xfffe:
+						adapter->stats.tx_fifo_errors++;
+						printk(KERN_INFO "%s: transmit timed out, FIFO underrun\n", dev->name);
+						break;
 					}
 					dev->tbusy = 0;
 					mark_bh(NET_BH);
@@ -892,7 +885,7 @@
 					 * some unknown PCB
 					 */
 				default:
-					printk("%s: unknown PCB received - %2.2x\n", dev->name, adapter->irx_pcb.command);
+					printk(KERN_DEBUG "%s: unknown PCB received - %2.2x\n", dev->name, adapter->irx_pcb.command);
 					break;
 				}
 			} else {
@@ -1147,7 +1140,7 @@
 			return 1;
 
 		stat = inb_status(dev->base_addr);
-		printk("%s: transmit timed out, %s?\n", dev->name, (stat & ACRF) ? "IRQ conflict" : "network cable problem");
+		printk("%s: transmit timed out, lost %s?\n", dev->name, (stat & ACRF) ? "interrupt" : "command");
 		if (elp_debug >= 1)
 			printk("%s: status %#02x\n", dev->name, stat);
 		dev->trans_start = jiffies;
@@ -1200,8 +1193,7 @@
  *
  ******************************************************/
 
-static struct enet_statistics *
- elp_get_stats(struct device *dev)
+static struct enet_statistics *elp_get_stats(struct device *dev)
 {
 	elp_device *adapter = (elp_device *) dev->priv;
 
@@ -1544,27 +1536,27 @@
 			/* Nope, it's ignoring the command register.  This means that
 			 * either it's still booting up, or it's died.
 			 */
-			printk("%s: command register wouldn't drain, assuming ", dev->name);
+			printk("%s: command register wouldn't drain, ", dev->name);
 			if ((inb_status(dev->base_addr) & 7) == 3) {
 				/* If the adapter status is 3, it *could* still be booting.
 				 * Give it the benefit of the doubt for 10 seconds.
 				 */
-				printk("3c505 still starting\n");
+				printk("assuming 3c505 still starting\n");
 				timeout = jiffies + 10 * HZ;
 				while (jiffies < timeout && (inb_status(dev->base_addr) & 7));
 				if (inb_status(dev->base_addr) & 7) {
 					printk("%s: 3c505 failed to start\n", dev->name);
-					continue;
+				} else {
+					okay = 1;  /* It started */
 				}
 			} else {
 				/* Otherwise, it must just be in a strange state.  We probably
 				 * need to kick it.
 				 */
-				printk("3c505 dead\n");
-				continue;
+				printk("3c505 is sulking\n");
 			}
 		}
-		for (tries = 0; tries < 5; tries++) {
+		for (tries = 0; tries < 5 && okay; tries++) {
 
 			/*
 			 * Try to set the Ethernet address, to make sure that the board
@@ -1598,7 +1590,7 @@
 		outb_control(inb_control(dev->base_addr) | FLSH | ATTN, dev->base_addr);
 		outb_control(inb_control(dev->base_addr) & ~(FLSH | ATTN), dev->base_addr);
 	}
-	printk("%s: 3c505 is sulking, giving up\n", dev->name);
+	printk("%s: failed to initialise 3c505\n", dev->name);
 	return -ENODEV;
 
       okay:
@@ -1696,8 +1688,7 @@
 }
 
 #ifdef MODULE
-static char devicename[9] =
-{0,};
+static char devicename[9] = {0,};
 static struct device dev_3c505 =
 {
 	devicename,		/* device name is inserted by linux/drivers/net/net_init.c */
@@ -1715,7 +1706,6 @@
 	dev_3c505.base_addr = io;
 	dev_3c505.irq = irq;
 	if (register_netdev(&dev_3c505) != 0) {
-		printk("3c505: register_netdev() returned non-zero.\n");
 		return -EIO;
 	}
 	return 0;
diff -u --recursive --new-file v1.3.90/linux/drivers/net/CONFIG linux/drivers/net/CONFIG
--- v1.3.90/linux/drivers/net/CONFIG	Wed Mar  6 14:53:46 1996
+++ linux/drivers/net/CONFIG	Wed Apr 17 08:32:47 1996
@@ -60,6 +60,14 @@
 #                       The DC21040 will default to TP if TP_NW is specified
 #                       The DC21041 will default to BNC if BNC_AUI is specified
 #
+#  TULIP		Tulip (dc21040/dc21041/ds21140) driver
+#	TULIP_PORT	specify default if_port
+#			0: 10TP
+#			1: 100Tx(ds21140)/AUI(dc2104x)
+#			2: BNC(dc2104x)
+#	TULIP_FIX_PORT	don't change if_port automatically if defined
+#	TULIP_MAX_CARDS	maximum number of probed card
+#
 
 # The following options exist, but cannot be set in this file.
 #  lance.c
@@ -83,4 +91,4 @@
 EWRK3_OPTS	= 
 DE4X5_OPTS	= -DDE4X5_AUTOSENSE=AUTO
 ELP_OPTS	= -DELP_DEBUG=1 -DELP_NEED_HARD_RESET=0
-
+TULIP_OPTS	=
diff -u --recursive --new-file v1.3.90/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v1.3.90/linux/drivers/net/Config.in	Wed Apr 10 17:02:24 1996
+++ linux/drivers/net/Config.in	Wed Apr 17 08:32:47 1996
@@ -79,7 +79,7 @@
   fi
   tristate 'Apricot Xen-II on board ethernet' CONFIG_APRICOT
   tristate 'DE425, DE434, DE435, DE500 support' CONFIG_DE4X5
-  tristate 'DEC 21040 PCI support' CONFIG_DEC_ELCP
+  tristate 'DECchip Tulip (dc21x4x) PCI support' CONFIG_DEC_ELCP
 # bool 'LPL T100V 100Mbs support' CONFIG_LPL_T100
 # bool 'PCnet32 (32 bit VLB and PCI LANCE) support' CONFIG_PCNET32
   bool 'Zenith Z-Note support' CONFIG_ZNET
diff -u --recursive --new-file v1.3.90/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v1.3.90/linux/drivers/net/Makefile	Fri Apr 12 15:51:54 1996
+++ linux/drivers/net/Makefile	Wed Apr 17 08:32:47 1996
@@ -526,3 +526,5 @@
 
 dlci.o: dlci.c CONFIG
 
+tulip.o: tulip.c CONFIG
+	$(CC) $(CPPFLAGS) $(CFLAGS) $(TULIP_OPTS) -c $<
diff -u --recursive --new-file v1.3.90/linux/drivers/net/eql.c linux/drivers/net/eql.c
--- v1.3.90/linux/drivers/net/eql.c	Fri Apr 12 15:51:55 1996
+++ linux/drivers/net/eql.c	Thu Apr 18 14:35:33 1996
@@ -17,7 +17,7 @@
  */
 
 static const char *version = 
-	"Equalizer: $Revision: 3.12 $ $Date: 1995/01/19 $ Simon Janes (simon@ncm.com)\n";
+	"Equalizer1996: $Revision: 1.2 $ $Date: 1996/04/11 17:51:52 $ Simon Janes (simon@ncm.com)\n";
 
 /*
  * Sources:
@@ -31,6 +31,12 @@
 
 /*
  * $Log: eql.c,v $
+ * Revision 1.2  1996/04/11 17:51:52  guru
+ * Added one-line eql_remove_slave patch.
+ *
+ * Revision 1.1  1996/04/11 17:44:17  guru
+ * Initial revision
+ *
  * Revision 3.13  1996/01/21  15:17:18  alan
  * tx_queue_len changes.
  * reformatted.
@@ -287,6 +293,8 @@
 		printk ("%s: open\n", dev->name);
 #endif
 
+	printk ("%s: remember to turn off Van-Jacobson compression on your slave devices.\n", dev->name);
+
 	new_queue = eql_new_slave_queue (dev);
     
 	if (new_queue != 0)
@@ -431,8 +439,14 @@
 	int err;
 
 	err = verify_area(VERIFY_READ, (void *)srqp, sizeof (slaving_request_t));
-	if (err) 
+	if (err)  
+	  {
+#ifdef EQL_DEBUG
+	if (eql_debug >= 20)
+		printk ("EQL enslave: error detected by verify_area\n");
+#endif  
 		return err;
+	  }
 	memcpy_fromfs (&srq, srqp, sizeof (slaving_request_t));
 
 #ifdef EQL_DEBUG
@@ -458,8 +472,17 @@
 			eql_insert_slave (eql->queue, s);
 			return 0;
 		}
+#ifdef EQL_DEBUG
+	if (eql_debug >= 20)
+		printk ("EQL enslsave: slave is master or slave is already slave\n");
+#endif  
+
 		return -EINVAL;
 	}
+#ifdef EQL_DEBUG
+	if (eql_debug >= 20)
+		printk ("EQL enslave: master or slave are NULL");
+#endif  
 	return -EINVAL;
 }
 
@@ -798,6 +821,7 @@
 	{
 		prev->next = curr->next;
 		queue->num_slaves--;
+		curr->dev->flags = curr->dev->flags & ~IFF_SLAVE;
 		sti();
 		return curr;
 	}
@@ -806,30 +830,6 @@
 }
 
 
-#if 0
-static int eql_insert_slave_dev(slave_queue_t *queue, struct device *dev)
-{
-	slave_t *slave;
-	cli ();
-
-	if ( ! eql_is_full (queue) )
-	{
-		slave = eql_new_slave ();
-		slave->dev = dev;
-		slave->priority = EQL_DEFAULT_SLAVE_PRIORITY;
-		slave->priority_bps = EQL_DEFAULT_SLAVE_PRIORITY;
-		slave->priority_Bps = EQL_DEFAULT_SLAVE_PRIORITY / 8;
-		slave->next = queue->head->next;
-		queue->head->next = slave;
-		sti ();
-		return 0;
-	}
-	sti ();
-	return 1;
-}
-#endif
-
-
 static int eql_remove_slave_dev(slave_queue_t *queue, struct device *dev)
 {
 	slave_t *prev;
@@ -931,6 +931,7 @@
 					{
 						slave_load = (ULONG_MAX - (ULONG_MAX / 2)) - 
 							(priority_Bps) + bytes_queued * 8;
+
 		      				if (slave_load < best_load)
 						{
 							best_load = slave_load;
@@ -995,42 +996,6 @@
 static inline void eql_set_best_slave(slave_queue_t *queue, slave_t *slave)
 {
 	queue->best_slave = slave;
-}
-
-#if 0
-static inline int eql_lock_slave_queue(slave_queue_t *queue)
-{
-	int result = 0;
-
-	printk ("eql: lock == %d\n", queue->lock);
-	if (queue->lock)
-	{
-		printk ("eql: lock_slave-q sleeping for lock\n");
-		sleep_on (&eql_queue_lock);
-		printk ("eql: lock_slave-q woken up\n");
-		queue->lock = 1;
-	}
-	queue->lock = 1;
-	return result;
-}
-
-static inline int eql_unlock_slave_queue(slave_queue_t *queue)
-{
-	int result = 0;
-
-	if (queue->lock != 0)
-	{
-		queue->lock = 0;
-		printk ("eql: unlock_slave-q waking up lock waiters\n");
-		wake_up (&eql_queue_lock);
-	}
-	return result;
-}
-#endif 
-
-static inline int eql_is_locked_slave_queue(slave_queue_t *queue)
-{
-	return test_bit(1, (void *) &queue->lock);
 }
 
 static void eql_timer(unsigned long param)
diff -u --recursive --new-file v1.3.90/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- v1.3.90/linux/drivers/net/tulip.c	Mon Apr 15 12:20:18 1996
+++ linux/drivers/net/tulip.c	Wed Apr 17 09:31:21 1996
@@ -16,16 +16,18 @@
 
 static char *version =
 "tulip.c:v0.10 8/11/95 becker@cesdis.gsfc.nasa.gov\n"
-"        +0.68 3/09/96 "
-"http://www.dsl.tutics.tut.ac.jp/~manabe/linux/tulip.html\n";
+"        +0.72 4/17/96 "
+"http://www.dsl.tutics.tut.ac.jp/~linux/tulip\n";
 
 /* A few user-configurable values. */
 
-/* Default to using 10baseT (i.e. non-AUI/10base2/100baseT port) port. */
+/* Default to using 10baseT (i.e. AUI/10base2/100baseT port) port. */
 #define	TULIP_10TP_PORT		0
 #define	TULIP_100TP_PORT	1
 #define	TULIP_AUI_PORT		1
 #define	TULIP_BNC_PORT		2
+#define	TULIP_MAX_PORT		3
+#define	TULIP_AUTO_PORT		-1
 
 #ifndef	TULIP_PORT
 #define	TULIP_PORT			TULIP_10TP_PORT
@@ -34,36 +36,13 @@
 /* Define to force full-duplex operation on all Tulip interfaces. */
 /* #define  TULIP_FULL_DUPLEX 1 */
 
-/* Define to probe only first detected device */
-/* #define	TULIP_ONLY_ONE 1 */
-
-#include <linux/config.h>
+/* Define to fix port. */
+/* #define  TULIP_FIX_PORT 1 */
 
-#if defined(MODULE) && defined(CONFIG_MODVERSIONS)
-#define	MODVERSIONS
-#include <linux/modversions.h>
-#endif
-
-#include <linux/version.h>
+/* Define to probe only first detected device */
+/*#define	TULIP_MAX_CARDS 1*/
 
-#if LINUX_VERSION_CODE < 0x10300
-/* i.e. version 1.2.x */
-#define	virt_to_bus(address)	(unsigned long)(address)
-#define	bus_to_virt(address)	(void *)(address)
-#define	PCI_DEVICE_ID_DEC_TULIP_PLUS	0x0014
-#ifdef	MODULE
-#include <linux/module.h>
-char kernel_version[] = UTS_RELEASE;
-#else
-#undef	MOD_INC_USE_COUNT
-#undef	MOD_DEC_USE_COUNT
-#define	MOD_INC_USE_COUNT
-#define	MOD_DEC_USE_COUNT
-#endif
-#else
-/* i.e. version 1.3.x */
 #include <linux/module.h>
-#endif
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -75,6 +54,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/bios32.h>
+#include <linux/delay.h>
 #include <asm/byteorder.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -88,12 +68,6 @@
    longword-wide registers on a quadword boundary. */
 #define TULIP_TOTAL_SIZE 0x80
 
-#ifdef TULIP_DEBUG
-int tulip_debug = TULIP_DEBUG;
-#else
-int tulip_debug = 3;
-#endif
-
 /*
 				Theory of Operation
 
@@ -151,7 +125,6 @@
 register of the set CSR12-15 written.   Hmmm, now how is that possible?
 */
 
-
 /* A few values that may be tweaked. */
 /* Keep the ring sizes a power of two for efficiency. */
 #define TX_RING_SIZE	4
@@ -266,9 +239,15 @@
 #define	TINTR_ENABLE		0xFFFFFFFF
 #define	TINTR_DISABLE		0x00000000
 
+/* description of CSR11 G.P. timer (21041/21140) register */
+#define	TGEPT_COUNT			0x0001FFFF
+
 /* description of CSR12 SIA status(2104x)/GP(21140) register */
 #define	TSIAS_CONERROR		0x00000002	/* connection error */
 #define	TSIAS_LNKERROR		0x00000004	/* link error */
+#define TSIAS_ACTERROR		0x00000200  /* port Rx activity */
+#define TSIAS_RxACTIVE		0x00000100  /* port Rx activity */
+
 #define	TGEPR_LK10NG		0x00000080	/* 10Mbps N.G. (R) */
 #define	TGEPR_LK100NG		0x00000040	/* 100Mbps N.G. (R) */
 #define	TGEPR_DETECT		0x00000020	/* detect signal (R) */
@@ -354,12 +333,13 @@
 	struct enet_statistics stats;
 	int setup_frame[48];	/* Pseudo-Tx frame to init address table. */
 	void (*port_select)(struct device *dev);
-	int (*port_error)(struct device *dev);
+	int (*port_fail)(struct device *dev);
 	char *signature;
 	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
 	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
 	unsigned int tx_full:1;				/* The Tx queue is full. */
 	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
+	unsigned int port_fix:1;			/* Fix if_port to specified port. */
 };
 
 struct eeprom {
@@ -384,55 +364,55 @@
 static void tulip_init_ring(struct device *dev);
 static int tulip_start_xmit(struct sk_buff *skb, struct device *dev);
 static int tulip_rx(struct device *dev);
-static void tulip_interrupt(int irq, struct pt_regs *regs);
+static void tulip_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int tulip_close(struct device *dev);
 static struct enet_statistics *tulip_get_stats(struct device *dev);
 static struct device *tulip_alloc(struct device *dev);
-#if LINUX_VERSION_CODE < 0x10300
-static void set_multicast_list(struct device *dev, int num_addrs,
-							   void *addrs);
-#else
 static void set_multicast_list(struct device *dev);
-#endif
 
-#define	generic21140_error	NULL
+#define	generic21140_fail	NULL
 static void generic21040_select(struct device *dev);
 static void generic21140_select(struct device *dev);
 static void generic21041_select(struct device *dev);
 static void auto21140_select(struct device *dev);
-static int generic21040_error(struct device *dev);
-static int generic21041_error(struct device *dev);
+static void cogent21140_select(struct device *dev);
+static int generic21040_fail(struct device *dev);
+static int generic21041_fail(struct device *dev);
 
 static struct {
 	void (*port_select)(struct device *dev);
-	int (*port_error)(struct device *dev);
+	int (*port_fail)(struct device *dev);
 	unsigned int vendor_id, device_id;
 	char *signature;
-	unsigned int port_auto:1;
+	unsigned int array:1;
 } cardVendor[] = {
-	{generic21140_select, generic21140_error,
+	{generic21140_select, generic21140_fail,
 		 0x0000c000, PCI_DEVICE_ID_DEC_TULIP_FAST, "smc9332", 0},
-	{generic21041_select, generic21041_error,
+	{generic21041_select, generic21041_fail,
 		 0x0000c000, PCI_DEVICE_ID_DEC_TULIP_PLUS, "smc8432", 0},
-	{generic21040_select, generic21040_error,
+	{generic21040_select, generic21040_fail,
 		 0x0000c000, PCI_DEVICE_ID_DEC_TULIP, "old smc8432", 0},
-	{auto21140_select, generic21140_error,
-		 0x0000f400, PCI_DEVICE_ID_DEC_TULIP_FAST, "LA100PCI", 1},
-	{generic21140_select, generic21140_error,
+	{auto21140_select, generic21140_fail,
+		 0x0000f400, PCI_DEVICE_ID_DEC_TULIP_FAST, "LA100PCI", 0},
+	{cogent21140_select, generic21140_fail,
+		 0x00009200, PCI_DEVICE_ID_DEC_TULIP_FAST, "cogent_em110", 0},
+	{generic21140_select, generic21140_fail,
 		 0x0000f800, PCI_DEVICE_ID_DEC_TULIP_FAST, "DE500", 0},
-	{generic21041_select, generic21041_error,
+	{generic21041_select, generic21041_fail,
 		 0x0000f800, PCI_DEVICE_ID_DEC_TULIP_PLUS, "DE450", 0},
-	{generic21040_select, generic21040_error,
+	{generic21040_select, generic21040_fail,
 		 0x0000f800, PCI_DEVICE_ID_DEC_TULIP, "DE43x", 0},
-	{generic21040_select, generic21040_error,
+	{generic21040_select, generic21040_fail,
 		 0x0040c700, PCI_DEVICE_ID_DEC_TULIP, "EN9400", 0},
-	{generic21040_select, generic21040_error,
-		 0x00c09500, PCI_DEVICE_ID_DEC_TULIP, "ZNYX312", 0},
-	{generic21040_select, generic21040_error,
+	{generic21040_select, generic21040_fail,
+		 0x00c09500, PCI_DEVICE_ID_DEC_TULIP, "ZNYX312", 1},
+	{generic21040_select, generic21040_fail,
+		 0x08002b00, PCI_DEVICE_ID_DEC_TULIP, "QSILVER's", 0},
+	{generic21040_select, generic21040_fail,
 		 0, PCI_DEVICE_ID_DEC_TULIP, "21040", 0},
-	{generic21140_select, generic21140_error,
+	{generic21140_select, generic21140_fail,
 		 0, PCI_DEVICE_ID_DEC_TULIP_FAST, "21140", 0},
-	{generic21041_select, generic21041_error,
+	{generic21041_select, generic21041_fail,
 		 0, PCI_DEVICE_ID_DEC_TULIP_PLUS, "21041", 0},
 	{NULL, NULL, 0, 0, "Unknown", 0}
 };
@@ -449,26 +429,23 @@
 #define EE_DATA_READ	0x08	/* EEPROM chip data out. */
 #define EE_ENB			(0x4800 | EE_CS)
 
-/* Delay between EEPROM clock transitions.
-   This is a "nasty" timing loop, but PC compatible machines are *supposed*
-   to delay an ISA compatible period for the SLOW_DOWN_IO macro.  */
-
-#define eeprom_delay(nanosec)\
-	do { int _i = 3; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
-
 /* The EEPROM commands include the alway-set leading bit. */
 #define EE_WRITE_CMD	(5 << 6)
 #define EE_READ_CMD		(6 << 6)
 #define EE_ERASE_CMD	(7 << 6)
 
 #ifdef MODULE
-static u_long alloc_size;
+static int if_port=TULIP_AUTO_PORT;
+static size_t alloc_size;
+#ifdef TULIP_FULL_DUPLEX
+static int full_duplex=1;
+#else
+static int full_duplex=0;
+#endif
 #endif
 
-#ifdef	__i386__
 #define	tio_write(val, port)	outl(val, ioaddr + port)
 #define	tio_read(port)			inl(ioaddr + port)
-#endif
 
 static void inline
 tio_sia_write(u32 ioaddr, u32 val13, u32 val14, u32 val15)
@@ -479,7 +456,11 @@
 	tio_write(val13,CSR13);
 }
 
-static char *
+/*
+   card_type returns 1 if the card is 'etherarray'
+*/
+
+static int
 card_type(struct tulip_private *tp, int device_id, int vendor_id)
 {
 	int n;
@@ -489,9 +470,9 @@
 			&& (cardVendor[n].vendor_id == vendor_id
 				|| cardVendor[n].vendor_id == 0)) break;
 	tp->port_select = cardVendor[n].port_select;
-	tp->port_error = cardVendor[n].port_error;
+	tp->port_fail = cardVendor[n].port_fail;
 	tp->signature = cardVendor[n].signature;
-	return(cardVendor[n].signature);
+	return(cardVendor[n].array ? 1: 0);
 }
 
 static int
@@ -510,22 +491,21 @@
 		for (i = 10; i >= 0; i--) {
 			short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
 			tio_write(EE_ENB | dataval, CSR9);
-			eeprom_delay(100);
+			udelay(100);
 			tio_write(EE_ENB | dataval | EE_SHIFT_CLK, CSR9);
-			eeprom_delay(150);
+			udelay(150);
 			tio_write(EE_ENB | dataval, CSR9);
-			/* Finish EEPROM a clock tick. */
-			eeprom_delay(250);
+			udelay(250);
 		}
 		tio_write(EE_ENB, CSR9);
 
 		for (i = 16; i > 0; i--) {
 			tio_write(EE_ENB | EE_SHIFT_CLK, CSR9);
-			eeprom_delay(100);
+			udelay(100);
 			val = (val << 1)
 				| ((tio_read(CSR9) & EE_DATA_READ) ? 1 : 0);
 			tio_write(EE_ENB, CSR9);
-			eeprom_delay(100);
+			udelay(100);
 		}
 
 		/* Terminate the EEPROM access. */
@@ -540,9 +520,9 @@
 	return(-1); /* broken */
 }
 
-/* Is this correct ? */
+/* Is this required ? */
 static int
-generic21040_error(struct device *dev)
+generic21040_fail(struct device *dev)
 {
 	int ioaddr = dev->base_addr;
 
@@ -550,37 +530,38 @@
 }
 
 static int
-generic21041_error(struct device *dev)
+generic21041_fail(struct device *dev)
 {
 	int ioaddr = dev->base_addr;
+	u32 csr12 = tio_read(CSR12);
 
-	return(tio_read(CSR12) & TSIAS_LNKERROR);
+	return((!(csr12 & TSIAS_CONERROR)
+			|| !(csr12 & TSIAS_LNKERROR)) ? 0: 1);
 }
 
 static void
 generic21040_select(struct device *dev)
 {
 	int ioaddr = dev->base_addr;
-	const char *if_port;
+	const char *media;
 
 	dev->if_port &= 3;
 	switch (dev->if_port)
 	{
 	case TULIP_10TP_PORT:
-		if_port = "10baseT";
+		media = "10baseT";
 		break;
-	case TULIP_100TP_PORT:
-	/* TULIP_AUI_PORT is the same as TULIP_100TP_PORT. */
-		if_port = "100baseT/AUI";
+	case TULIP_AUI_PORT:
+		media = "AUI";
 		break;
 	case TULIP_BNC_PORT:
-		if_port = "BNC";
+		media = "BNC";
 		break;
 	default:
-		if_port = "unknown type";
+		media = "unknown type";
 		break;
 	}
-	printk("%s: enabling %s port.\n", dev->name, if_port);
+	printk("%s: enabling %s port.\n", dev->name, media);
 	/* Set the full duplex match frame. */
 	tio_write(FULL_DUPLEX_MAGIC, CSR11);
 	tio_write(TSIAC_RESET, CSR13);
@@ -588,6 +569,17 @@
 	tio_write((dev->if_port ? TSIAC_NO10TP: 0) | TSIAC_C21040, CSR13);
 }
 
+#if 0
+static void
+generic_timer(struct device *dev, u32 count)
+{
+	int ioaddr = dev->base_addr;
+
+	tio_write(count, CSR11);
+	while (tio_read(CSR11) & TGEPT_COUNT);
+}
+#endif
+
 static void
 generic21041_select(struct device *dev)
 {
@@ -596,33 +588,32 @@
 	u32 tsiax = TSIAX_10TP;
 	u32 tsiag = TSIAG_10TP;
 
-	printk("%s: enabling ", dev->name);
 	switch(dev->if_port) {
 	case TULIP_AUI_PORT:
 		tsiac |= TSIAC_NO10TP;
 		tsiax = TSIAX_NO10TP;
 		tsiag = TSIAG_AUI;
-		printk("AUI");
 		break;
 	case TULIP_BNC_PORT:
 		tsiac |= TSIAC_NO10TP;
 		tsiax = TSIAX_NO10TP;
 		tsiag = TSIAG_BNC;
-		printk("BNC");
 		break;
 	default:
 		dev->if_port = TULIP_10TP_PORT;
-		printk("10TP");
 		break;
 	}
 	tio_sia_write(ioaddr, tsiac, tsiax, tsiag);
-	printk(" port.\n");
+	if (dev->start)
+		printk("%s: enabling %s port.\n", dev->name,
+			   (dev->if_port == TULIP_AUI_PORT) ? "AUI":
+			   (dev->if_port == TULIP_BNC_PORT) ? "BNC": "10TP");
 }
 
 static void
 auto21140_select(struct device *dev)
 {
-	int ioaddr = dev->base_addr;
+	int i, ioaddr = dev->base_addr;
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 
 	/* kick port */
@@ -631,15 +622,35 @@
 	tio_write(TCMOD_AUTO|TCMOD_TRxSTART, CSR6);
 	dev->if_port = !(tio_read(CSR12) & TGEPR_FORCEALED);
 	printk("%s: probed %s port.\n",
-		   dev->name, dev->if_port ? "100baseTx" : "10baseT");
+		   dev->name, dev->if_port ? "100TX" : "10TP");
 	tio_write((dev->if_port ? TGEPR_FORCE100: 0)
 			  | (tp->full_duplex ? 0:TGEPR_HALFDUPLEX), CSR12);	
 	tio_write(TINTR_DISABLE, CSR7);
-	tio_read(CSR8) & 0xffff;
+	i = tio_read(CSR8) & 0xffff;
 	tio_write(TCMOD_AUTO, CSR6);
 }
 
 static void
+cogent21140_select(struct device *dev)
+{
+	int ioaddr = dev->base_addr, csr6;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	dev->if_port &= 1;
+	csr6 = tio_read(CSR6) &
+		~(TCMOD_10TP|TCMOD_100TP|TCMOD_TRxSTART|TCMOD_SCRM);
+	/* Stop the transmit process. */
+	tio_write(csr6 | TCMOD_RxSTART, CSR6);
+	printk("%s: enabling %s port.\n",
+		   dev->name, dev->if_port ? "100baseTx" : "10baseT");
+	/* Turn on the output drivers */
+	tio_write(0x0000013F, CSR12);
+	tio_write((dev->if_port ? TGEPR_FORCE100: 0)
+			  | (tp->full_duplex ? 0:TGEPR_HALFDUPLEX), CSR12);
+	tio_write((dev->if_port ? TCMOD_100TP: TCMOD_10TP)
+			  | TCMOD_TRxSTART | TCMOD_TH128 | csr6, CSR6);
+}
+
+static void
 generic21140_select(struct device *dev)
 {
 	int ioaddr = dev->base_addr, csr6;
@@ -651,8 +662,9 @@
 
 	/* Stop the transmit process. */
 	tio_write(csr6 | TCMOD_RxSTART, CSR6);
-	printk("%s: enabling %s port.\n",
-		   dev->name, dev->if_port ? "100baseTx" : "10baseT");
+	if (dev->start)
+		printk("%s: enabling %s port.\n",
+			   dev->name, dev->if_port ? "100TX" : "10TP");
 	tio_write((dev->if_port ? TCMOD_100TP: TCMOD_10TP)
 			  | TCMOD_TRxSTART | TCMOD_TH128 | csr6, CSR6);
 	tio_write((dev->if_port ? TGEPR_FORCE100: 0)
@@ -667,31 +679,16 @@
 
 	/* Reset the chip, holding bit 0 set at least 10 PCI cycles. */
 	tio_write(tio_read(CSR0)|TBMOD_RESET, CSR0);
-/*	tio_write(TBMOD_RESERVED|TBMOD_RESET, CSR0);*/
-	SLOW_DOWN_IO;
+	udelay(1000);
 	/* Deassert reset.  Set 8 longword cache alignment, 8 longword burst.
 	   -> Set 32 longword cache alignment, unlimited longword burst ?
 	   Wait the specified 50 PCI cycles after a reset by initializing
 	   Tx and Rx queues and the address filter list. */
 	tio_write(tio_read(CSR0)|TBMOD_ALIGN32|TBMOD_BURST0, CSR0);
-/*	tio_write(TBMOD_RESERVED|TBMOD_ALIGN32|TBMOD_BURST0, CSR0);*/
 
-	if (irq2dev_map[dev->irq] != NULL
-		|| (irq2dev_map[dev->irq] = dev) == NULL
-		|| dev->irq == 0
-#if LINUX_VERSION_CODE < 0x10346
-		|| request_irq(dev->irq, &tulip_interrupt, 0, tp->signature)) {
-#else
-		|| request_irq(dev->irq, (void *)&tulip_interrupt, 0,
-					   tp->signature, dev)) {
-#endif
+	if (request_irq(dev->irq, (void *)&tulip_interrupt, SA_SHIRQ,
+					tp->signature, dev))
 		return -EAGAIN;
-	}
-
-/*
-	if (tulip_debug > 1)
-		printk("%s: tulip_open() irq %d.\n", dev->name, dev->irq);
-*/
 
 	tulip_init_ring(dev);
 
@@ -722,8 +719,12 @@
 	tio_write(virt_to_bus(tp->rx_ring), CSR3);
 	tio_write(virt_to_bus(tp->tx_ring), CSR4);
 
-	dev->if_port = TULIP_PORT;
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
 	if (tp->port_select) tp->port_select(dev);
+
 	/* Start the chip's Tx and Rx processes. */
 	tio_write(tio_read(CSR6) | TCMOD_TRxSTART
 			  | (tp->full_duplex ? TCMOD_FULLDUPLEX:0), CSR6);
@@ -731,10 +732,6 @@
 	/* Trigger an immediate transmit demand to process the setup frame. */
 	tio_write(TPOLL_TRIGGER, CSR1);
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
 	/* Enable interrupts by setting the interrupt mask. */
 	tio_write(TINTR_ENABLE, CSR7);
 
@@ -778,13 +775,12 @@
 	int entry;
 
 	/* Transmitter timeout, serious problems. */
-	if (dev->tbusy) {
+	if (dev->tbusy || (tp->port_fail && tp->port_fail(dev))) {
 		int tickssofar = jiffies - dev->trans_start;
 		int i;
 		if (tickssofar < 40) return(1);
-		if (tp->port_select
-			&& (!tp->port_error || tp->port_error(dev))) {
-			dev->if_port ++;
+		if (tp->port_select) {
+			if (!tp->port_fix) dev->if_port ++;
 			tp->port_select(dev);
 			dev->trans_start = jiffies;
 			return(0);
@@ -793,10 +789,14 @@
 			   "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
 			   dev->name, tio_read(CSR5), tio_read(CSR12),
 			   tio_read(CSR13), tio_read(CSR14), tio_read(CSR15));
+#ifndef	__alpha__
 		printk("  Rx ring %8.8x: ", (int)tp->rx_ring);
+#endif
 		for (i = 0; i < RX_RING_SIZE; i++)
 			printk(" %8.8x", (unsigned int)tp->rx_ring[i].status);
+#ifndef	__alpha__
 		printk("\n  Tx ring %8.8x: ", (int)tp->tx_ring);
+#endif
 		for (i = 0; i < TX_RING_SIZE; i++)
 			printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
 		printk("\n");
@@ -856,9 +856,9 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static void tulip_interrupt(int irq, struct pt_regs *regs)
+static void tulip_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct device *dev = (struct device *)(irq2dev_map[irq]);
+	struct device *dev = (struct device *)dev_id;
 	struct tulip_private *lp;
 	int csr5, ioaddr, boguscnt=10;
 
@@ -878,7 +878,6 @@
 		csr5 = tio_read(CSR5);
 		/* Acknowledge all of the current interrupt sources ASAP. */
 		tio_write(csr5 & TSTAT_CLEARINTR, CSR5);
-
 		/* check interrupt ? */
 		if ((csr5 & (TSTAT_NORINTR|TSTAT_ABNINTR)) == 0) break;
 
@@ -967,11 +966,7 @@
 		if (dev->start == 0  &&  --stopit < 0) {
 			printk("%s: Emergency stop, looping startup interrupt.\n",
 				   dev->name);
-#if LINUX_VERSION_CODE < 0x10346
-			free_irq(irq);
-#else
 			free_irq(irq, dev);
-#endif
 		}
 	}
 
@@ -1005,11 +1000,7 @@
 			short pkt_len = lp->rx_ring[entry].status >> 16;
 			struct sk_buff *skb;
 
-#if LINUX_VERSION_CODE < 0x10300
-			skb = alloc_skb(pkt_len, GFP_ATOMIC);
-#else
 			skb = dev_alloc_skb(pkt_len + 2);
-#endif
 			if (skb == NULL) {
 				printk("%s: Memory squeeze, deferring packet.\n",
 					   dev->name);
@@ -1027,17 +1018,11 @@
 				break;
 			}
 			skb->dev = dev;
-#if LINUX_VERSION_CODE < 0x10300
-			skb->len = pkt_len;
-			memcpy(skb->data, bus_to_virt(lp->rx_ring[entry].buffer1),
-				   pkt_len);
-#else
 			skb_reserve(skb, 2);
 			memcpy(skb_put(skb, pkt_len),
 				   bus_to_virt(lp->rx_ring[entry].buffer1), pkt_len);
 			/* Needed for 1.3.x */
 			skb->protocol = eth_type_trans(skb,dev);
-#endif
 			netif_rx(skb);
 			lp->stats.rx_packets++;
 		}
@@ -1069,24 +1054,29 @@
 	tio_write(0, CSR13);
 /*	tio_write(0, CSR8);	wake up chip ? */
 
-#if LINUX_VERSION_CODE < 0x10346
-	free_irq(dev->irq);
-#else
 	free_irq(dev->irq, dev);
-#endif
-	irq2dev_map[dev->irq] = 0;
 
 	MOD_DEC_USE_COUNT;
 	return(0);
 }
 
+static int
+tulip_config(struct device *dev, struct ifmap *map)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+
+	if (map->port == 0xff) return(-EINVAL);
+	dev->if_port = map->port;
+	tp->port_fix = 1;
+	if (tp->port_select) tp->port_select(dev);
+	return(0);
+}
+
 static struct enet_statistics *
 tulip_get_stats(struct device *dev)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
-	short ioaddr = dev->base_addr;
-
-	tp->stats.rx_missed_errors += tio_read(CSR8) & 0xffff;
+	/*	short ioaddr = dev->base_addr;*/
 
 	return(&tp->stats);
 }
@@ -1095,12 +1085,7 @@
  *	Set or clear the multicast filter for this adaptor.
  */
 
-#if LINUX_VERSION_CODE < 0x10300
-static void set_multicast_list(struct device *dev, int num_addrs,
-							   void *addrs)
-#else
 static void set_multicast_list(struct device *dev)
-#endif
 {
 	short ioaddr = dev->base_addr;
 	int csr6 = tio_read(CSR6) & ~(TCMOD_MODEMASK|TCMOD_FILTERMASK);
@@ -1128,12 +1113,9 @@
 		   16 address perfect filtering of the Tulip.  Note that only
 		   the low shortword of setup_frame[] is valid. */
 		tio_write(csr6 | 0x0000, CSR6);
-		i=0;
-		while(dmi) 
-		{
+		for (i = 0; i < dev->mc_count; i ++) {
 			eaddrs=(unsigned short *)dmi->dmi_addr;
 			dmi=dmi->next;
-			i++;
 			*setup_frm++ = *eaddrs++;
 			*setup_frm++ = *eaddrs++;
 			*setup_frm++ = *eaddrs++;
@@ -1150,28 +1132,12 @@
 	}
 }
 
-#if 0
-static int
-set_mac_address(struct device *dev, void *addr)
-{
-	int i;
-	struct sockaddr *sa=(struct sockaddr *)addr;
-	if (dev->start)
-		return -EBUSY;
-	printk("%s: Setting MAC address to ", dev->name);
-	for (i = 0; i < ETH_ALEN - 1; i++)
-		printk("%2.2x:", dev->dev_addr[i] = sa->sa_data[i]);
-	printk("%2.2x.\n", dev->dev_addr[i] = sa->sa_data[i]);
-	return 0;
-}
-#endif
-
 static struct device *tulip_alloc(struct device *dev)
 {
 	struct tulip_private *tp;
 	char *buff;
 #ifndef	MODULE
-	int alloc_size;
+	size_t alloc_size;
 #endif
 	if (!dev || dev->priv) {
 		struct device *olddev = dev;
@@ -1210,14 +1176,14 @@
 			 int irq, int device_id)
 {
 	/* See note below on the Znyx 315 etherarray. */
-	unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
-	char detect_mesg[80], *mesgp=detect_mesg, *card_name=NULL;
+	static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
+	char detect_mesg[80], *mesgp=detect_mesg;
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int i;
 	unsigned short sum, bitsum;
 
 	if (check_region(ioaddr, TULIP_TOTAL_SIZE) != 0) {
-		printk("tulip_alloc: region already allocated at %#3x.\n",
+		printk("tulip_hwinit: region already allocated at %#3x.\n",
 			   ioaddr);
 		return(-1);
 	}
@@ -1229,11 +1195,11 @@
 	/* Stop the chip's Tx and Rx processes. */
 	tio_write(tio_read(CSR6) & ~TCMOD_TRxSTART, CSR6);
 	/* Clear the missed-packet counter. */
-	tio_read(CSR8) & 0xffff;
+	i = tio_read(CSR8) & 0xffff;
 
 	if (device_id == PCI_DEVICE_ID_DEC_TULIP_PLUS
 	    && (tio_read(CSR9) & 0x8000)) {
-		mesgp += sprintf(mesgp, "treat as 21040 ");
+		mesgp += sprintf(mesgp, " treat as 21040");
 	    device_id = PCI_DEVICE_ID_DEC_TULIP;
 	}
 	
@@ -1252,7 +1218,7 @@
 				value = tio_read(CSR9);
 			while (value < 0  && --boguscnt > 0);
 			dev->dev_addr[i] = value;
-			sum += value;
+			sum += value & 0xFF;
 			bitsum &= value;
 	    }
 	} else {
@@ -1282,41 +1248,50 @@
 		dev->dev_addr[i] = last_phys_addr[i] + 1;
 	}
 	for (i = 0; i < ETH_ALEN - 1; i++)
-		mesgp += sprintf(mesgp, "%2.2x:",
-						 last_phys_addr[i] = dev->dev_addr[i]);
+		mesgp += sprintf(mesgp, "%2.2x:", dev->dev_addr[i]);
 	mesgp += sprintf(mesgp, "%2.2x, IRQ %d\n",
 					 last_phys_addr[i] = dev->dev_addr[i], irq);
 
-	card_name = card_type(tp, device_id,
-						  htonl((*(int*)dev->dev_addr) & 0xFFFFFF));
-
+	/* copy ethernet address */
+	if (card_type(tp, device_id,
+				  htonl((*(int*)dev->dev_addr) & 0xFFFFFF)))
+		for (i = 0; i < ETH_ALEN - 1; i++)
+			last_phys_addr[i] = dev->dev_addr[i];
 	/* We do a request_region() only to register /proc/ioports info. */
 	request_region(ioaddr, TULIP_TOTAL_SIZE, tp->signature);
 
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
 
-#ifdef TULIP_FULL_DUPLEX
-	tp->full_duplex = 1;
-#endif
-
 	/* The Tulip-specific entries in the device structure. */
 	dev->open = &tulip_open;
 	dev->hard_start_xmit = &tulip_start_xmit;
 	dev->stop = &tulip_close;
 	dev->get_stats = &tulip_get_stats;
+	dev->set_config = &tulip_config;
 	dev->set_multicast_list = &set_multicast_list;
-#if 0
-	dev->set_mac_address = &set_mac_address;
-#endif
 
 #ifdef	MODULE
     ether_setup(dev);
+	if (if_port == TULIP_AUTO_PORT)
+		if_port = TULIP_PORT;
+	else
+		tp->port_fix = 1;
+	dev->if_port = if_port;
+	tp->full_duplex = full_duplex;
 #else
+#ifdef TULIP_FULL_DUPLEX
+	tp->full_duplex = 1;
+#endif
     init_etherdev(dev, 0);
+	dev->if_port = TULIP_PORT;
 #endif
 
-	printk("%s: %s %s", dev->name, card_name, detect_mesg);
+#ifdef	TULIP_FIX_PORT
+	tp->port_fix = 1;
+#endif
+
+	printk("%s: %s %s", dev->name, tp->signature, detect_mesg);
 
 	/* Reset the xcvr interface and turn on heartbeat. */
 	tio_write(TSIAC_RESET, CSR13);
@@ -1327,11 +1302,11 @@
 
 int tulip_probe(struct device *dev)
 {
-	static u_short probed_irqs=0;
+	static struct device *tulip_head=NULL;
 	u_char pci_bus, pci_device_fn, pci_latency, pci_irq;
 	u_int pci_ioaddr;
 	u_short pci_command;
-	u_long pci_chips[] = {
+	u_int pci_chips[] = {
 		PCI_DEVICE_ID_DEC_TULIP,
 		PCI_DEVICE_ID_DEC_TULIP_FAST,
 		PCI_DEVICE_ID_DEC_TULIP_PLUS,
@@ -1349,27 +1324,32 @@
 									pci_chips[cno],
 									pci_index, &pci_bus,
 									&pci_device_fn) == 0) {
-				/* get IRQ */
-				pcibios_read_config_byte(pci_bus, pci_device_fn,
-										 PCI_INTERRUPT_LINE, &pci_irq);
-				if (probed_irqs & (1 << pci_irq)) continue;
+				struct device *dp;
+
 				/* get IO address */
 				pcibios_read_config_dword(pci_bus, pci_device_fn,
 										  PCI_BASE_ADDRESS_0,
 										  &pci_ioaddr);
 				/* Remove I/O space marker in bit 0. */
 				pci_ioaddr &= ~3;
+				for (dp = tulip_head; dp != NULL; dp = dp->next)
+					if (dp->base_addr == pci_ioaddr) break;
+				if (dp) continue;
+				/* get IRQ */
+				pcibios_read_config_byte(pci_bus, pci_device_fn,
+										 PCI_INTERRUPT_LINE, &pci_irq);
 #ifdef	MODULE
 				/* compare requested IRQ/IO address */
-				if (dev && dev->irq && dev->base_addr &&
-					(dev->irq != pci_irq
-					 || dev->base_addr != pci_ioaddr)) continue;
+				if (dev && dev->base_addr &&
+					dev->base_addr != pci_ioaddr) continue;
 #else
 				if ((dev = tulip_alloc(dev)) == NULL) break;
 #endif
-				if (!probed_irqs) printk(version);
-				probed_irqs |= (1 << pci_irq);
-				
+				if (!tulip_head) {
+					printk(version);
+					tulip_head = dev;
+				}
+
 				/* Get and check the bus-master and latency values. */
 				pcibios_read_config_word(pci_bus, pci_device_fn,
 										 PCI_COMMAND, &pci_command);
@@ -1393,17 +1373,27 @@
 				if (tulip_hwinit(dev, pci_ioaddr, pci_irq,
 								 pci_chips[cno]) < 0) continue;
 				num ++;
-#if defined(MODULE) || defined(TULIP_ONLY_ONE)
+#ifdef	MODULE
 				return(0);
 #endif
+#ifdef	TULIP_MAX_CARDS
+				if (num >= TULIP_MAX_CARDS) return(0);
+#endif
 		}
 	}
 	return(num > 0 ? 0: -ENODEV);
 }
 
 #ifdef MODULE
-static int io = 0xfc00;
-static int irq = 9;
+#ifdef __alpha__
+#if 1
+static int io = 0xb000;
+#else
+static int io = 0x10400;
+#endif
+#else
+static int io = 0xfc80;
+#endif
 
 static struct device *mod_dev;
 
@@ -1412,7 +1402,7 @@
 	if ((mod_dev = tulip_alloc(0)) == NULL) return(-EIO);
 
 	mod_dev->base_addr = io;
-	mod_dev->irq = irq;
+	mod_dev->irq = 0;
 	mod_dev->init = &tulip_probe;
 
 	if (register_netdev(mod_dev)) {
diff -u --recursive --new-file v1.3.90/linux/drivers/net/wic.c linux/drivers/net/wic.c
--- v1.3.90/linux/drivers/net/wic.c	Mon Apr 15 12:20:18 1996
+++ linux/drivers/net/wic.c	Thu Apr 18 14:35:33 1996
@@ -1,6 +1,7 @@
 /* $Id: wic.c,v 1.0 1995/02/11 10:26:05 hayes Exp $ */
 /* WIC: A parallel port "network" driver for Linux. */
 /* based on the plip network driver */
+/* Modified for Linux 1.3.x by Alan Cox <Alan.Cox@linux.org> */
 
 char *version = "NET3 WIC version 0.9 hayes@netplumbing.com";
 
@@ -90,8 +91,7 @@
 int ack_resp(struct device *dev);
 int check_bfr(struct device *dev);
 void wic_reset(struct device *dev);
-void wic_set_multicast_list(struct device *dev, int num_addrs, 
-		void *addrs);
+void wic_set_multicast_list(struct device *dev);
 
 #define LOOPCNT 30000	
 unsigned char tog = 3;
@@ -249,12 +249,12 @@
 	nl->nibble	= WIC_NIBBLE_WAIT;
 
 	/* Initialize task queue structures */
-	nl->immediate.next = &tq_last;
+	nl->immediate.next = NULL;
 	nl->immediate.sync = 0;
 	nl->immediate.routine = (void *)(void *)wic_bh;
 	nl->immediate.data = dev;
 
-	nl->deferred.next = &tq_last;
+	nl->deferred.next = NULL;
 	nl->deferred.sync = 0;
 	nl->deferred.routine = (void *)(void *)wic_kick_bh;
 	nl->deferred.data = dev;
@@ -309,7 +309,7 @@
 };
 
 void 
-wic_set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+wic_set_multicast_list(struct device *dev)
 {
 	struct wicconf wc;
 	struct wic_net *wn;
@@ -327,16 +327,22 @@
 	while ((wc.len == 1) && (wc.data[0] == 0x7)) /* controller int */
 		wc.len = recv_cmd_resp(dev, (unsigned char *)&wc.data);
 	wn = (struct wic_net *)&wc.data;
-	switch (num_addrs) {
-		case -1:	/* promiscuous mode */
-			wn->mode |= (NET_MODE_ME | NET_MODE_BCAST | 
-				NET_MODE_MCAST | NET_MODE_PROM);
-	printk("%s: Setting promiscuous mode\n", dev->name);
-			break;
-		default:	/* my address and bcast addresses */
-			wn->mode &= ~(NET_MODE_PROM | NET_MODE_MCAST);
-			wn->mode |= (NET_MODE_ME | NET_MODE_BCAST);
-			/* break; */
+	if(dev->flags&IFF_PROMISC)
+	{
+		/* promiscuous mode */
+		wn->mode |= (NET_MODE_ME | NET_MODE_BCAST | 
+			NET_MODE_MCAST | NET_MODE_PROM);
+		printk("%s: Setting promiscuous mode\n", dev->name);
+	}
+	else if((dev->flags&IFF_ALLMULTI) || dev->mc_count)
+	{
+		wn->mode &= ~NET_MODE_PROM;
+		wn->mode |= (NET_MODE_MCAST | NET_MODE_ME | NET_MODE_BCAST);
+	}
+	else
+	{
+		wn->mode &= ~(NET_MODE_PROM | NET_MODE_MCAST);
+		wn->mode |= (NET_MODE_ME | NET_MODE_BCAST);
 	}
 	wc.len = 23;
 	wc.pcmd = WIC_SETNET;
@@ -1381,8 +1387,6 @@
 }
 
 #ifdef MODULE
-char kernel_version[] = UTS_RELEASE;
-
 struct device dev_wic0 = 
 {
 	"wic0" /*"wic"*/,
diff -u --recursive --new-file v1.3.90/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c
--- v1.3.90/linux/drivers/scsi/BusLogic.c	Wed Apr 17 09:06:32 1996
+++ linux/drivers/scsi/BusLogic.c	Wed Apr 17 09:01:19 1996
@@ -25,7 +25,7 @@
 
 
 #define BusLogic_DriverVersion		"1.3.2"
-#define BusLogic_DriverDate		"13 April 1996"
+#define BusLogic_DriverDate		"16 April 1996"
 
 
 #include <linux/module.h>
@@ -1676,15 +1676,15 @@
       return true;
     }
   /*
-    Issue the Inquire Devices command for "W" and "C" Series boards or the
-    Inquire Installed Devices ID 0 to 7 command for "S" and "A" Series boards.
+    Issue the Inquire Devices command for boards with firmware version 4.25 or
+    later, or the Inquire Installed Devices ID 0 to 7 command for older boards.
     This is necessary to force Synchronous Transfer Negotiation so that the
     Inquire Setup Information and Inquire Synchronous Period commands will
     return valid data.  The Inquire Devices command is preferable to Inquire
     Installed Devices ID 0 to 7 since it only probes Logical Unit 0 of each
     Target Device.
   */
-  if (HostAdapter->FirmwareVersion[0] >= '4')
+  if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0)
     {
       if (BusLogic_Command(HostAdapter, BusLogic_InquireDevices, NULL, 0,
 			   &InstalledDevices, sizeof(InstalledDevices))
@@ -2342,7 +2342,7 @@
       {
 	BusLogic_ResetHostAdapter(HostAdapter, NULL, 0);
 	HostAdapter->HostAdapterResetRequested = false;
-	scsi_mark_host_bus_reset(HostAdapter->SCSI_Host);
+	scsi_mark_host_reset(HostAdapter->SCSI_Host);
       }
 }
 
@@ -2788,7 +2788,7 @@
       }
   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
     HostAdapter->LastResetTime[TargetID] = jiffies;
-  Result = SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
+  Result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET;
   /*
     Release exclusive access to Host Adapter.
   */
@@ -2973,7 +2973,9 @@
 	     HostAdapter->HostNumber, TargetID);
     }
   if (ErrorRecoveryStrategy == BusLogic_ErrorRecovery_Default)
-    if (ResetFlags & SCSI_RESET_SUGGEST_BUS_RESET)
+    if (ResetFlags & SCSI_RESET_SUGGEST_HOST_RESET)
+      ErrorRecoveryStrategy = BusLogic_ErrorRecovery_HardReset;
+    else if (ResetFlags & SCSI_RESET_SUGGEST_BUS_RESET)
       ErrorRecoveryStrategy = BusLogic_ErrorRecovery_HardReset;
     else ErrorRecoveryStrategy = BusLogic_ErrorRecovery_BusDeviceReset;
   switch (ErrorRecoveryStrategy)
diff -u --recursive --new-file v1.3.90/linux/drivers/scsi/ChangeLog linux/drivers/scsi/ChangeLog
--- v1.3.90/linux/drivers/scsi/ChangeLog	Mon Apr 15 12:20:19 1996
+++ linux/drivers/scsi/ChangeLog	Wed Apr 17 09:01:19 1996
@@ -1,4 +1,4 @@
-Sat Apr 13 13:58:00 1996  Leonard N. Zubkoff <lnz@dandelion.com>
+Tue Apr 16 21:00:00 1996  Leonard N. Zubkoff <lnz@dandelion.com>
 
 	* BusLogic Driver Version 1.3.2 Released.
 
diff -u --recursive --new-file v1.3.90/linux/drivers/scsi/README.BusLogic linux/drivers/scsi/README.BusLogic
--- v1.3.90/linux/drivers/scsi/README.BusLogic	Mon Apr 15 12:20:19 1996
+++ linux/drivers/scsi/README.BusLogic	Wed Apr 17 09:01:19 1996
@@ -3,7 +3,7 @@
 		       Version 1.2.2 for Linux 1.2.13
 		       Version 1.3.2 for Linux 1.3.88
 
-				 13 April 1996
+				 16 April 1996
 
 			       Leonard N. Zubkoff
 			       Dandelion Digital
diff -u --recursive --new-file v1.3.90/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- v1.3.90/linux/drivers/scsi/eata.c	Fri Mar  1 07:50:52 1996
+++ linux/drivers/scsi/eata.c	Thu Apr 18 14:56:45 1996
@@ -1,6 +1,9 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *
+ *      16 Apr 1996 rev. 2.10 for linux 1.3.90
+ *          New argument "reset_flags" to the reset routine.
+ *
  *       6 Jul 1995 rev. 2.01 for linux 1.3.7
  *          Update required by the new /proc/scsi support.
  *
@@ -64,7 +67,7 @@
  *          This driver is based on the CAM (Common Access Method Committee)
  *          EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol.
  *
- *      Copyright (C) 1994, 1995 Dario Ballabio (dario@milano.europe.dg.com)
+ *  Copyright (C) 1994, 1995, 1996 Dario Ballabio (dario@milano.europe.dg.com)
  *
  */
 
@@ -581,7 +584,7 @@
       }
 
    if (j > 0) 
-      printk("EATA/DMA 2.0x: Copyright (C) 1994, 1995 Dario Ballabio.\n");
+      printk("EATA/DMA 2.0x: Copyright (C) 1994, 1995, 1996 Dario Ballabio.\n");
 
    restore_flags(flags);
    return j;
@@ -639,7 +642,8 @@
 
       if (HD(j)->in_reset) 
 	 printk("%s: qcomm, already in reset.\n", BN(j));
-      else if (eata2x_reset(SCpnt) == SCSI_RESET_SUCCESS) 
+      else if (eata2x_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET)
+               == SCSI_RESET_SUCCESS) 
 	 panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
 
       SCpnt->result = DID_BUS_BUSY << 16; 
@@ -772,7 +776,7 @@
    panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
 }
 
-int eata2x_reset (Scsi_Cmnd *SCarg) {
+int eata2x_reset (Scsi_Cmnd *SCarg, unsigned int reset_flags) {
    unsigned int i, j, flags, time, k, limit = 0;
    int arg_done = FALSE;
    Scsi_Cmnd *SCpnt;
@@ -780,8 +784,8 @@
    save_flags(flags);
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
-   printk("%s: reset, enter, target %d, pid %ld.\n", 
-	  BN(j), SCarg->target, SCarg->pid);
+   printk("%s: reset, enter, target %d, pid %ld, reset_flags %u.\n", 
+	  BN(j), SCarg->target, SCarg->pid, reset_flags);
 
    if (SCarg->host_scribble == NULL)
       printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid);
@@ -847,7 +851,7 @@
    HD(j)->in_reset = TRUE;
    sti();
    time = jiffies;
-   while (jiffies < (time + 100) && limit++ < 100000000);
+   while ((jiffies - time) < HZ && limit++ < 100000000);
    cli();
    printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit);
 
diff -u --recursive --new-file v1.3.90/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h
--- v1.3.90/linux/drivers/scsi/eata.h	Thu Sep 21 09:01:48 1995
+++ linux/drivers/scsi/eata.h	Thu Apr 18 14:56:45 1996
@@ -1,6 +1,5 @@
 /*
  *	eata.h - used by the low-level driver for EATA/DMA SCSI host adapters.
- *
  */
 #ifndef _EATA_H
 #define _EATA_H
@@ -10,9 +9,9 @@
 int eata2x_detect(Scsi_Host_Template *);
 int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int eata2x_abort(Scsi_Cmnd *);
-int eata2x_reset(Scsi_Cmnd *);
+int eata2x_reset(Scsi_Cmnd *, unsigned int);
 
-#define EATA_VERSION "2.01.00"
+#define EATA_VERSION "2.10.00"
 
 
 #define EATA {                                                 \
diff -u --recursive --new-file v1.3.90/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c
--- v1.3.90/linux/drivers/scsi/g_NCR5380.c	Mon Apr 15 12:20:19 1996
+++ linux/drivers/scsi/g_NCR5380.c	Wed Apr 17 09:01:18 1996
@@ -50,6 +50,23 @@
  * 
  * -1 should be specified for no or DMA interrupt, -2 to autoprobe for an 
  * 	IRQ line if overridden on the command line.
+ *
+ * 3.  When included as a module, with arguments passed on the command line:
+ *         ncr_irq=xx	the interrupt
+ *         ncr_addr=xx  the port or base address (for port or memory
+ *              	mapped, resp.)
+ *         ncr_dma=xx	the DMA
+ *         ncr_5380=1	to set up for a NCR5380 board
+ *         ncr_53c400=1	to set up for a NCR53C400 board
+ *     e.g.
+ *     modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1
+ *       for a port mapped NCR5380 board or
+ *     modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1
+ *       for a memory mapped NCR53C400 board with interrupts disabled.
+ * 
+ * 255 should be specified for no or DMA interrupt, 254 to autoprobe for an 
+ * 	IRQ line if overridden on the command line.
+ *     
  */
  
 /*
@@ -93,6 +110,13 @@
     S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
 
+#define NCR_NOT_SET 0
+static int ncr_irq=NCR_NOT_SET;
+static int ncr_dma=NCR_NOT_SET;
+static int ncr_addr=NCR_NOT_SET;
+static int ncr_5380=NCR_NOT_SET;
+static int ncr_53c400=NCR_NOT_SET;
+
 static struct override {
 	NCR5380_implementation_fields;
     int irq;
@@ -189,6 +213,17 @@
     int flags = 0;
     struct Scsi_Host *instance;
 
+    if (ncr_irq != NCR_NOT_SET)
+	overrides[0].irq=ncr_irq;
+    if (ncr_dma != NCR_NOT_SET)
+	overrides[0].dma=ncr_dma;
+    if (ncr_addr != NCR_NOT_SET)
+	overrides[0].NCR5380_map_name=(NCR5380_map_type)ncr_addr;
+    if (ncr_5380 != NCR_NOT_SET)
+	overrides[0].board=BOARD_NCR5380;
+    else if (ncr_53c400 != NCR_NOT_SET)
+	overrides[0].board=BOARD_NCR53C400;
+
     tpnt->proc_dir = &proc_scsi_g_ncr5380;
 
     for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
@@ -253,7 +288,8 @@
 
     NCR5380_setup(instance);
 
-    free_irq(instance->irq, NULL);
+    if (instance->irq != IRQ_NONE)
+	free_irq(instance->irq, NULL);
 
 	return 0;
 }
diff -u --recursive --new-file v1.3.90/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.3.90/linux/drivers/scsi/scsi.c	Wed Apr 17 09:06:32 1996
+++ linux/drivers/scsi/scsi.c	Wed Apr 17 09:01:19 1996
@@ -1935,14 +1935,25 @@
 
 /* Mark all SCSI Devices on a specific Host as having been reset. */
 
-void scsi_mark_host_bus_reset(struct Scsi_Host *Host)
+void scsi_mark_host_reset(struct Scsi_Host *Host)
 {
   Scsi_Cmnd *SCpnt;
-  for(SCpnt = Host->host_queue; SCpnt; SCpnt = SCpnt->next)
+  for (SCpnt = Host->host_queue; SCpnt; SCpnt = SCpnt->next)
     scsi_mark_device_reset(SCpnt->device);
 }
 
 
+/* Mark all SCSI Devices on a specific Host Bus as having been reset. */
+
+void scsi_mark_bus_reset(struct Scsi_Host *Host, int channel)
+{
+  Scsi_Cmnd *SCpnt;
+  for (SCpnt = Host->host_queue; SCpnt; SCpnt = SCpnt->next)
+      if (SCpnt->channel == channel)
+	  scsi_mark_device_reset(SCpnt->device);
+}
+
+
 int scsi_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags)
 {
     int temp;
@@ -2071,8 +2082,10 @@
              */
             switch(temp & SCSI_RESET_ACTION) {
 	    case SCSI_RESET_SUCCESS:
-	        if (temp & SCSI_RESET_BUS_RESET)
-		  scsi_mark_host_bus_reset(host);
+	        if (temp & SCSI_RESET_HOST_RESET)
+		  scsi_mark_host_reset(host);
+	        else if (temp & SCSI_RESET_BUS_RESET)
+		  scsi_mark_bus_reset(host, SCpnt->channel);
 		else scsi_mark_device_reset(SCpnt->device);
 		save_flags(flags);
 		cli();
@@ -2080,8 +2093,10 @@
 		restore_flags(flags);
 		return 0;
 	    case SCSI_RESET_PENDING:
-	        if (temp & SCSI_RESET_BUS_RESET)
-		  scsi_mark_host_bus_reset(host);
+	        if (temp & SCSI_RESET_HOST_RESET)
+		  scsi_mark_host_reset(host);
+	        else if (temp & SCSI_RESET_BUS_RESET)
+		  scsi_mark_bus_reset(host, SCpnt->channel);
 		else scsi_mark_device_reset(SCpnt->device);
 	    case SCSI_RESET_NOT_RUNNING:
 		return 0;
@@ -2090,8 +2105,10 @@
                 scsi_request_sense (SCpnt);
                 return 0;
 	    case SCSI_RESET_WAKEUP:
-	        if (temp & SCSI_RESET_BUS_RESET)
-		  scsi_mark_host_bus_reset(host);
+	        if (temp & SCSI_RESET_HOST_RESET)
+		  scsi_mark_host_reset(host);
+	        else if (temp & SCSI_RESET_BUS_RESET)
+		  scsi_mark_bus_reset(host, SCpnt->channel);
 		else scsi_mark_device_reset(SCpnt->device);
 		SCpnt->internal_timeout &= ~IN_RESET;
 		scsi_request_sense (SCpnt);
diff -u --recursive --new-file v1.3.90/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v1.3.90/linux/drivers/scsi/scsi.h	Wed Apr 17 09:06:32 1996
+++ linux/drivers/scsi/scsi.h	Wed Apr 17 09:01:19 1996
@@ -317,13 +317,18 @@
 #define SCSI_RESET_SYNCHRONOUS		0x01
 #define SCSI_RESET_ASYNCHRONOUS		0x02
 #define SCSI_RESET_SUGGEST_BUS_RESET	0x04
-
+#define SCSI_RESET_SUGGEST_HOST_RESET	0x08
 /*
  * This is a bitmask that is ored with one of the above codes.
  * It tells the mid-level code that we did a hard reset.
  */
 #define SCSI_RESET_BUS_RESET 0x100
 /*
+ * This is a bitmask that is ored with one of the above codes.
+ * It tells the mid-level code that we did a host adapter reset.
+ */
+#define SCSI_RESET_HOST_RESET 0x200
+/*
  * Used to mask off bits and to obtain the basic action that was
  * performed.  
  */
@@ -477,7 +482,8 @@
 extern void print_driverbyte(int scsiresult);
 extern void print_hostbyte(int scsiresult);
 
-extern void scsi_mark_host_bus_reset(struct Scsi_Host *Host);
+extern void scsi_mark_host_reset(struct Scsi_Host *Host);
+extern void scsi_mark_bus_reset(struct Scsi_Host *Host, int channel);
 
 #if defined(MAJOR_NR) && (MAJOR_NR != SCSI_TAPE_MAJOR)
 #include "hosts.h"
diff -u --recursive --new-file v1.3.90/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- v1.3.90/linux/drivers/scsi/scsi_syms.c	Thu Feb 15 09:21:30 1996
+++ linux/drivers/scsi/scsi_syms.c	Wed Apr 17 09:01:19 1996
@@ -61,7 +61,8 @@
     X(need_isa_buffer),
     X(request_queueable),
     X(print_Scsi_Cmnd),
-    X(scsi_mark_host_bus_reset),
+    X(scsi_mark_host_reset),
+    X(scsi_mark_bus_reset),
 #if defined(CONFIG_PROC_FS)
     X(proc_print_scsidevice),
 #endif
diff -u --recursive --new-file v1.3.90/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
--- v1.3.90/linux/drivers/scsi/u14-34f.c	Fri Apr 12 15:52:01 1996
+++ linux/drivers/scsi/u14-34f.c	Thu Apr 18 14:56:45 1996
@@ -1,9 +1,15 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *      16 Apr 1996 rev. 2.10 for linux 1.3.90
+ *          New argument "reset_flags" to the reset routine.
+ *
+ *      21 Jul 1995 rev. 2.02 for linux 1.3.11
+ *          Fixed Data Transfer Direction for some SCSI commands.
+ *
  *      13 Jun 1995 rev. 2.01 for linux 1.2.10
- *         HAVE_OLD_UX4F_FIRMWARE should be defined for U34F boards when
- *         the firmware prom is not the latest one (28008-006).
+ *          HAVE_OLD_UX4F_FIRMWARE should be defined for U34F boards when
+ *          the firmware prom is not the latest one (28008-006).
  *
  *      11 Mar 1995 rev. 2.00 for linux 1.2.0
  *          Fixed a bug which prevented media change detection for removable
@@ -55,7 +61,7 @@
  * 
  *          Multiple U14F and/or U34F host adapters are supported.
  *
- *      Copyright (C) 1994, 1995 Dario Ballabio (dario@milano.europe.dg.com)
+ *  Copyright (C) 1994, 1995, 1996 Dario Ballabio (dario@milano.europe.dg.com)
  *
  *      WARNING: if your 14/34F board has an old firmware revision (see below)
  *               you must change "#undef" into "#define" in the following
@@ -226,6 +232,8 @@
 #define ASOK              0x00
 #define ASST              0x91
 
+#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])
+
 #define PACKED          __attribute__((packed))
 
 /* MailBox SCSI Command Packet */
@@ -330,7 +338,7 @@
 
    sti();
    time = jiffies;
-   while (jiffies < (time + 100) && limit++ < 100000000);
+   while ((jiffies - time) < HZ && limit++ < 100000000);
    cli();
 
    if (cpp->adapter_status || HD(j)->cp_stat[0] != FREE) {
@@ -540,7 +548,7 @@
       }
 
    if (j > 0) 
-      printk("UltraStor 14F/34F: Copyright (C) 1994, 1995 Dario Ballabio.\n");
+      printk("UltraStor 14F/34F: Copyright (C) 1994, 1995, 1996 Dario Ballabio.\n");
 
    restore_flags(flags);
    return j;
@@ -567,6 +575,12 @@
    unsigned int i, j, k, flags;
    struct mscp *cpp;
 
+   static const unsigned char data_out_cmds[] = {
+      0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x0b, 0x10, 0x16, 0x18, 0x1d, 
+      0x24, 0x2b, 0x2e, 0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 
+      0x3f, 0x40, 0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea
+      };
+
    save_flags(flags);
    cli();
    /* j is the board number */
@@ -593,7 +607,8 @@
 
       if (HD(j)->in_reset) 
 	 printk("%s: qcomm, already in reset.\n", BN(j));
-      else if (u14_34f_reset(SCpnt) == SCSI_RESET_SUCCESS) 
+      else if (u14_34f_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET) 
+               == SCSI_RESET_SUCCESS) 
 	 panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
 
       SCpnt->result = DID_BUS_BUSY << 16; 
@@ -615,8 +630,15 @@
    if (do_trace) printk("%s: qcomm, mbox %d, target %d, pid %ld.\n",
 			BN(j), i, SCpnt->target, SCpnt->pid);
 
+   cpp->xdir = DTD_IN;
+
+   for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
+     if (SCpnt->cmnd[0] == data_out_cmds[k]) {
+	cpp->xdir = DTD_OUT;
+	break;
+	}
+
    cpp->opcode = OP_SCSI;
-   cpp->xdir = DTD_SCSI;
    cpp->target = SCpnt->target;
    cpp->lun = SCpnt->lun;
    cpp->SCpnt = SCpnt;
@@ -715,7 +737,7 @@
    panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
 }
 
-int u14_34f_reset(Scsi_Cmnd * SCarg) {
+int u14_34f_reset(Scsi_Cmnd * SCarg, unsigned int reset_flags) {
    unsigned int i, j, flags, time, k, limit = 0;
    int arg_done = FALSE;
    Scsi_Cmnd *SCpnt;
@@ -723,8 +745,8 @@
    save_flags(flags);
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
-   printk("%s: reset, enter, target %d, pid %ld.\n", 
-	  BN(j), SCarg->target, SCarg->pid);
+   printk("%s: reset, enter, target %d, pid %ld, reset_flags %u.\n", 
+	  BN(j), SCarg->target, SCarg->pid, reset_flags);
 
    if (SCarg->host_scribble == NULL)
       printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid);
@@ -791,7 +813,7 @@
    HD(j)->in_reset = TRUE;
    sti();
    time = jiffies;
-   while (jiffies < (time + 100) && limit++ < 100000000);
+   while ((jiffies - time) < HZ && limit++ < 100000000);
    cli();
    printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit);
 
diff -u --recursive --new-file v1.3.90/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h
--- v1.3.90/linux/drivers/scsi/u14-34f.h	Mon Sep 18 08:54:10 1995
+++ linux/drivers/scsi/u14-34f.h	Thu Apr 18 14:56:45 1996
@@ -7,10 +7,10 @@
 int u14_34f_detect(Scsi_Host_Template *);
 int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int u14_34f_abort(Scsi_Cmnd *);
-int u14_34f_reset(Scsi_Cmnd *);
+int u14_34f_reset(Scsi_Cmnd *, unsigned int);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "2.01.00"
+#define U14_34F_VERSION "2.10.00"
 
 #define ULTRASTOR_14_34F {                                            \
 		NULL, /* Ptr for modules */                           \
diff -u --recursive --new-file v1.3.90/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c
--- v1.3.90/linux/drivers/sound/dmabuf.c	Fri Apr 12 15:52:02 1996
+++ linux/drivers/sound/dmabuf.c	Thu Apr 18 08:22:20 1996
@@ -770,6 +770,13 @@
       }
       break;
 
+    case SNDCTL_DSP_SETDUPLEX:
+      if (audio_devs[dev]->flags & DMA_DUPLEX)
+	 return 0;
+      else
+         return -EIO;
+      break;
+
     case SNDCTL_DSP_SETFRAGMENT:
       {
 	int             fact = get_fs_long ((long *) arg);
diff -u --recursive --new-file v1.3.90/linux/fs/devices.c linux/fs/devices.c
--- v1.3.90/linux/fs/devices.c	Tue Jan  9 12:26:53 1996
+++ linux/fs/devices.c	Wed Apr 17 09:01:19 1996
@@ -19,6 +19,13 @@
 #include <linux/errno.h>
 #ifdef CONFIG_KERNELD
 #include <linux/kerneld.h>
+
+#include <linux/tty.h>
+
+/* serial module kerneld load support */
+struct tty_driver *get_tty_driver(kdev_t device);
+#define isa_tty_dev(ma)	(ma == TTY_MAJOR || ma == TTYAUX_MAJOR)
+#define need_serial(ma,mi) (get_tty_driver(to_kdev_t(MKDEV(ma,mi))) == NULL)
 #endif
 
 struct device_struct {
@@ -53,17 +60,20 @@
 	}
 	return len;
 }
+
 /*
 	Return the function table of a device.
 	Load the driver if needed.
 */
 static struct file_operations * get_fops(
 	unsigned int major,
+	unsigned int minor,
 	unsigned int maxdev,
 	const char *mangle,		/* String to use to build the module name */
 	struct device_struct tb[])
 {
 	struct file_operations *ret = NULL;
+
 	if (major < maxdev){
 #ifdef CONFIG_KERNELD
 		/*
@@ -75,8 +85,14 @@
 		 * it locks the reboot process :-(
 		 *
 		 * Jacques Gelinas (jacques@solucorp.qc.ca)
+		 *
+		 * A. Haritsis <ah@doc.ic.ac.uk>: fix for serial module
+		 *  though we need the minor here to check if serial dev,
+		 *  we pass only the normal major char dev to kerneld 
+		 *  as there is no other loadable dev on these majors
 		 */
-		if (!tb[major].fops && major != 0) {
+		if ((isa_tty_dev(major) && need_serial(major,minor)) ||
+		    (major != 0 && !tb[major].fops)) {
 			char name[20];
 			sprintf(name, mangle, major);
 			request_module(name);
@@ -94,12 +110,12 @@
 */
 struct file_operations * get_blkfops(unsigned int major)
 {
-	return get_fops (major,MAX_BLKDEV,"block-major-%d",blkdevs);
+	return get_fops (major,0,MAX_BLKDEV,"block-major-%d",blkdevs);
 }
 
-struct file_operations * get_chrfops(unsigned int major)
+struct file_operations * get_chrfops(unsigned int major, unsigned int minor)
 {
-	return get_fops (major,MAX_CHRDEV,"char-major-%d",chrdevs);
+	return get_fops (major,minor,MAX_CHRDEV,"char-major-%d",chrdevs);
 }
 
 int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)
@@ -271,7 +287,8 @@
 int chrdev_open(struct inode * inode, struct file * filp)
 {
 	int ret = -ENODEV;
-	filp->f_op = get_chrfops(MAJOR(inode->i_rdev));
+
+	filp->f_op = get_chrfops(MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
 	if (filp->f_op != NULL){
 		ret = 0;
 		if (filp->f_op->open != NULL)
diff -u --recursive --new-file v1.3.90/linux/fs/inode.c linux/fs/inode.c
--- v1.3.90/linux/fs/inode.c	Mon Apr  8 19:01:44 1996
+++ linux/fs/inode.c	Wed Apr 17 10:56:16 1996
@@ -497,7 +497,7 @@
 repeat:
 	inode = first_inode;
 	best = NULL;
-	for (i = 0; i<nr_inodes; inode = inode->i_next, i++) {
+	for (i = nr_inodes/2; i > 0; i--,inode = inode->i_next) {
 		if (!inode->i_count) {
 			unsigned long i = value(inode);
 			if (i < badness) {
diff -u --recursive --new-file v1.3.90/linux/fs/isofs/rock.c linux/fs/isofs/rock.c
--- v1.3.90/linux/fs/isofs/rock.c	Mon Apr 15 12:20:21 1996
+++ linux/fs/isofs/rock.c	Wed Apr 17 08:26:43 1996
@@ -255,6 +255,7 @@
 			   struct inode * inode){
   int len;
   unsigned char * chr;
+  int symlink_len = 0;
   CONTINUE_DECLS;
 
   if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
@@ -334,7 +335,7 @@
 	 struct SL_component * slp;
 	 slen = rr->len - 5;
 	 slp = &rr->u.SL.link;
-	 inode->i_size = 0;
+	 inode->i_size = symlink_len;
 	 while (slen > 1){
 	   rootflag = 0;
 	   switch(slp->flags &~1){
@@ -359,8 +360,9 @@
 
 	   if(slen < 2) break;
 	   if(!rootflag) inode->i_size += 1;
-	 };
-       };
+	 }
+	}
+	symlink_len = inode->i_size;
 	break;
       case SIG('R','E'):
 	printk("Attempt to read inode for relocated directory\n");
@@ -458,7 +460,6 @@
   
  repeat:
   while (len > 1){ /* There may be one byte for padding somewhere */
-    if (rpnt) break;
     rr = (struct rock_ridge *) chr;
     if (rr->len == 0) goto out; /* Something got screwed up here */
     sig = (chr[0] << 8) + chr[1];
diff -u --recursive --new-file v1.3.90/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v1.3.90/linux/fs/ncpfs/dir.c	Wed Apr  3 16:06:56 1996
+++ linux/fs/ncpfs/dir.c	Wed Apr 17 07:02:16 1996
@@ -189,12 +189,30 @@
 static int                c_seen_eof;
 static int                c_last_returned_index;
 static struct ncp_dirent* c_entry = NULL;
+static int                c_lock = 0;
+static struct wait_queue *c_wait = NULL;
+
+static inline void
+ncp_lock_dircache(void)
+{
+	while (c_lock)
+		sleep_on(&c_wait);
+	c_lock = 1;
+}
+
+static inline void
+ncp_unlock_dircache(void)
+{
+	c_lock = 0;
+	wake_up(&c_wait);
+}
 
 static int
 ncp_readdir(struct inode *inode, struct file *filp,
             void *dirent, filldir_t filldir)
 {
-	int result, i = 0;
+	int result = 0;
+	int i = 0;
         int index = 0;
 	struct ncp_dirent *entry = NULL;
         struct ncp_server *server = NCP_SERVER(inode);
@@ -215,6 +233,8 @@
 		return -EIO;
 	}
 
+	ncp_lock_dircache();
+
 	if (c_entry == NULL) 
 	{
 		i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
@@ -222,7 +242,8 @@
 		if (c_entry == NULL)
 		{
 			printk("ncp_readdir: no MEMORY for cache\n");
-			return -ENOMEM;
+			result = -ENOMEM;
+			goto finished;
 		}
 	}
 
@@ -232,7 +253,7 @@
 		if (filldir(dirent,".",1, filp->f_pos,
 			    ncp_info_ino(server, dir)) < 0)
 		{
-			return 0;
+			goto finished;
 		}
 		filp->f_pos += 1;
         }
@@ -242,7 +263,7 @@
 		if (filldir(dirent,"..",2, filp->f_pos,
 			    ncp_info_ino(server, dir->dir)) < 0)
 		{
-			return 0;
+			goto finished;
 		}
 		filp->f_pos += 1;
 	}
@@ -261,42 +282,44 @@
 		}
                 if ((entry == NULL) && c_seen_eof)
 		{
-                        return 0;
+			goto finished;
 		}
 	}
 
 	if (entry == NULL)
 	{
+		int entries;
 		DDPRINTK("ncp_readdir: Not found in cache.\n");
 
 		if (ncp_is_server_root(inode))
 		{
-			result = ncp_read_volume_list(server, filp->f_pos,
-						      NCP_READDIR_CACHE_SIZE);
-			DPRINTK("ncp_read_volume_list returned %d\n", result);
+			entries = ncp_read_volume_list(server, filp->f_pos,
+						       NCP_READDIR_CACHE_SIZE);
+			DPRINTK("ncp_read_volume_list returned %d\n", entries);
 
 		}
 		else
 		{
-			result = ncp_do_readdir(server, inode, filp->f_pos,
-						NCP_READDIR_CACHE_SIZE,
-						c_entry);
-			DPRINTK("ncp_readdir returned %d\n", result);
+			entries = ncp_do_readdir(server, inode, filp->f_pos,
+						 NCP_READDIR_CACHE_SIZE,
+						 c_entry);
+			DPRINTK("ncp_readdir returned %d\n", entries);
 		}
 
-		if (result < 0)
+		if (entries < 0)
 		{
 			c_dev = 0;
 			c_ino = 0;
-			return result;
+			result = entries;
+			goto finished;
 		}
 
-		if (result > 0)
+		if (entries > 0)
 		{
-                        c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
+                        c_seen_eof = (entries < NCP_READDIR_CACHE_SIZE);
 			c_dev  = inode->i_dev;
 			c_ino  = inode->i_ino;
-			c_size = result;
+			c_size = entries;
 			entry = c_entry;
                         c_last_returned_index = 0;
                         index = 0;
@@ -311,7 +334,7 @@
         if (entry == NULL)
 	{
                 /* Nothing found, even from a ncp call */
-                return 0;
+		goto finished;
         }
 
         while (index < c_size)
@@ -363,7 +386,9 @@
                 index += 1;
                 entry += 1;
 	}
-	return 0;
+ finished:
+	ncp_unlock_dircache();
+	return result;
 }
 
 static int
@@ -809,6 +834,7 @@
            server. */
 
         found_in_cache = 0;
+	ncp_lock_dircache();
 
         if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino))
 	{
@@ -832,6 +858,7 @@
                 }
 		while (i != first);
         }
+	ncp_unlock_dircache();
 
         if (found_in_cache == 0)
 	{
diff -u --recursive --new-file v1.3.90/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v1.3.90/linux/fs/ncpfs/inode.c	Fri Apr 12 15:52:04 1996
+++ linux/fs/ncpfs/inode.c	Wed Apr 17 07:02:16 1996
@@ -91,7 +91,7 @@
         inode->i_nlink   = 1;
         inode->i_uid     = NCP_SERVER(inode)->m.uid;
         inode->i_gid     = NCP_SERVER(inode)->m.gid;
-        inode->i_blksize = 1024;
+        inode->i_blksize = 512;
         inode->i_rdev    = 0;
 
         if ((inode->i_blksize != 0) && (inode->i_size != 0))
@@ -370,8 +370,10 @@
 void
 ncp_trigger_message(struct ncp_server *server)
 {
+#ifdef CONFIG_KERNELD
 	char command[ sizeof(server->m.mount_point)
 		     + sizeof(NCP_MSG_COMMAND) + 2];
+#endif
 
 	if (server == NULL)
 	{
diff -u --recursive --new-file v1.3.90/linux/fs/ncpfs/sock.c linux/fs/ncpfs/sock.c
--- v1.3.90/linux/fs/ncpfs/sock.c	Wed Apr  3 16:06:56 1996
+++ linux/fs/ncpfs/sock.c	Wed Apr 17 07:02:16 1996
@@ -330,6 +330,7 @@
 	int timeout;
 	int retrans;
 	int major_timeout_seen;
+	int acknowledge_seen;
 	char *server_name;
 	int n;
 	int addrlen;
@@ -352,9 +353,10 @@
 		return -EBADF;
 	}
 	init_timeout = server->m.time_out;
-	max_timeout = NCP_MAX_RPC_TIMEOUT*HZ/10;
+	max_timeout = NCP_MAX_RPC_TIMEOUT;
 	retrans = server->m.retry_count;
 	major_timeout_seen = 0;
+	acknowledge_seen = 0;
 	server_name = server->m.server_name;
 	old_mask = current->blocked;
 	current->blocked |= ~(_S(SIGKILL)
@@ -405,12 +407,15 @@
 		{
 			if (timeout > max_timeout)
 			{
-			  /* JEJB/JSP 2/7/94
-			   * This is useful to see if the system is
-			   * hanging */
-			  printk("NCP max timeout reached on %s\n",
-				 server_name);
-			  timeout = max_timeout;
+				/* JEJB/JSP 2/7/94
+				 * This is useful to see if the system is
+				 * hanging */
+				if (acknowledge_seen == 0)
+				{
+					printk("NCP max timeout reached on "
+					       "%s\n", server_name);
+				}
+				timeout = max_timeout;
 			}
 			current->timeout = jiffies + timeout;
 			schedule();
@@ -438,8 +443,8 @@
 				init_timeout <<= 1;
 				if (!major_timeout_seen)
 				{
-				  printk("NCP server %s not responding, "
-					 "still trying\n", server_name);
+					printk("NCP server %s not responding, "
+					       "still trying\n", server_name);
 				}
 				major_timeout_seen = 1;
 				continue;
@@ -484,6 +489,9 @@
 			DPRINTK("ncp_rpc_call: got positive acknowledge\n");
 			_recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
 				  NULL, &addrlen);
+			n = 0;
+			timeout = max_timeout;
+			acknowledge_seen = 1;
 			goto re_select;
 		}
 
diff -u --recursive --new-file v1.3.90/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v1.3.90/linux/fs/nfs/dir.c	Sat Apr 13 18:22:07 1996
+++ linux/fs/nfs/dir.c	Wed Apr 17 07:50:07 1996
@@ -671,7 +671,6 @@
 	if (inode->i_size != fattr->size)
 		NFS_CACHEINV(inode);
 	inode->i_size = fattr->size;
-	inode->i_blksize = fattr->blocksize;
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 		inode->i_rdev = to_kdev_t(fattr->rdev);
 	else
diff -u --recursive --new-file v1.3.90/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v1.3.90/linux/fs/nfs/inode.c	Mon Apr 15 12:20:21 1996
+++ linux/fs/nfs/inode.c	Wed Apr 17 07:50:07 1996
@@ -62,6 +62,12 @@
  */
 static void nfs_read_inode(struct inode * inode)
 {
+	int rsize = inode->i_sb->u.nfs_sb.s_server.rsize;
+	int size = inode->i_sb->u.nfs_sb.s_server.wsize;
+
+	if (rsize > size)
+		size = rsize;
+	inode->i_blksize = size;
 	inode->i_mode = 0;
 	inode->i_op = NULL;
 	NFS_CACHEINV(inode);
diff -u --recursive --new-file v1.3.90/linux/fs/proc/array.c linux/fs/proc/array.c
--- v1.3.90/linux/fs/proc/array.c	Mon Apr 15 12:20:21 1996
+++ linux/fs/proc/array.c	Thu Apr 18 14:35:33 1996
@@ -686,8 +686,8 @@
 	nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY;
 
 	return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
-%lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu \
-%lu %lu %lu %lu\n",
+%lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
+%lu %lu %lu %lu %lu %lu %lu %lu\n",
 		pid,
 		tsk->comm,
 		state,
@@ -722,7 +722,9 @@
 		tsk->blocked,
 		sigignore,
 		sigcatch,
-		wchan);
+		wchan,
+		tsk->nswap,
+		tsk->cnswap);
 }
 		
 static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
diff -u --recursive --new-file v1.3.90/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v1.3.90/linux/include/asm-i386/processor.h	Thu Mar 21 08:55:09 1996
+++ linux/include/asm-i386/processor.h	Wed Apr 17 11:20:47 1996
@@ -52,6 +52,7 @@
 	long	foo;
 	long	fos;
 	long	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
+	long	status;		/* software status information */
 };
 
 struct i387_soft_struct {
diff -u --recursive --new-file v1.3.90/linux/include/asm-i386/sigcontext.h linux/include/asm-i386/sigcontext.h
--- v1.3.90/linux/include/asm-i386/sigcontext.h	Thu Jul 20 09:13:26 1995
+++ linux/include/asm-i386/sigcontext.h	Wed Apr 17 12:23:31 1996
@@ -1,6 +1,31 @@
 #ifndef _ASMi386_SIGCONTEXT_H
 #define _ASMi386_SIGCONTEXT_H
 
+/*
+ * As documented in the iBCS2 standard..
+ *
+ * The first part of "struct _fpstate" is just the
+ * normal i387 hardware setup, the extra "status"
+ * word is used to save the coprocessor status word
+ * before entering the handler.
+ */
+struct _fpreg {
+	unsigned short significand[4];
+	unsigned short exponent;
+};
+
+struct _fpstate {
+	unsigned long 	cw,
+			sw,
+			tag,
+			ipoff,
+			cssel,
+			dataoff,
+			datasel;
+	struct _fpreg	_st[8];
+	unsigned long	status;
+};
+
 struct sigcontext_struct {
 	unsigned short gs, __gsh;
 	unsigned short fs, __fsh;
@@ -21,7 +46,7 @@
 	unsigned long eflags;
 	unsigned long esp_at_signal;
 	unsigned short ss, __ssh;
-	unsigned long i387;
+	struct _fpstate * fpstate;
 	unsigned long oldmask;
 	unsigned long cr2;
 };
diff -u --recursive --new-file v1.3.90/linux/include/linux/comstats.h linux/include/linux/comstats.h
--- v1.3.90/linux/include/linux/comstats.h	Fri Apr 12 15:52:07 1996
+++ linux/include/linux/comstats.h	Wed Apr 17 15:08:58 1996
@@ -104,5 +104,15 @@
 #define	COM_CLRPORTSTATS	_IO('c',31)
 #define	COM_GETBRDSTATS		_IO('c',32)
 
+
+/*
+ *	Define the set of ioctls that give user level access to the
+ *	private port, panel and board structures. The argument required
+ *	will be driver dependant!  
+ */
+#define	COM_READPORT		_IO('c',40)
+#define	COM_READBOARD		_IO('c',41)
+#define	COM_READPANEL		_IO('c',42)
+
 /*****************************************************************************/
 #endif
diff -u --recursive --new-file v1.3.90/linux/include/linux/fs.h linux/include/linux/fs.h
--- v1.3.90/linux/include/linux/fs.h	Mon Apr 15 12:20:21 1996
+++ linux/include/linux/fs.h	Thu Apr 18 15:21:09 1996
@@ -36,7 +36,7 @@
 /* And dynamically-tunable limits and defaults: */
 extern int max_inodes, nr_inodes;
 extern int max_files, nr_files;
-#define NR_INODE 2048	/* this should be bigger than NR_FILE */
+#define NR_INODE 3072	/* this should be bigger than NR_FILE */
 #define NR_FILE 1024	/* this can well be larger on a larger system */
 
 #define MAY_EXEC 1
diff -u --recursive --new-file v1.3.90/linux/include/linux/istallion.h linux/include/linux/istallion.h
--- v1.3.90/linux/include/linux/istallion.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/istallion.h	Wed Apr 17 15:08:58 1996
@@ -0,0 +1,131 @@
+/*****************************************************************************/
+
+/*
+ *	istallion.h  -- stallion intelligent multiport serial driver.
+ *
+ *	Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
+ *
+ *	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.
+ */
+
+/*****************************************************************************/
+#ifndef	_ISTALLION_H
+#define	_ISTALLION_H
+/*****************************************************************************/
+
+/*
+ *	Define important driver constants here.
+ */
+#define	STL_MAXBRDS		4
+#define	STL_MAXPANELS		4
+#define	STL_MAXPORTS		64
+#define	STL_MAXCHANS		(STL_MAXPORTS + 1)
+#define	STL_MAXDEVS		(STL_MAXBRDS * STL_MAXPORTS)
+
+
+/*
+ *	Define a set of structures to hold all the board/panel/port info
+ *	for our ports. These will be dynamically allocated as required at
+ *	driver initialization time.
+ */
+
+/*
+ *	Port and board structures to hold status info about each object.
+ *	The board structure contains pointers to structures for each port
+ *	connected to it. Panels are not distinguished here, since
+ *	communication with the slave board will always be on a per port
+ *	basis.
+ */
+typedef struct {
+	unsigned long		magic;
+	int			portnr;
+	int			panelnr;
+	int			brdnr;
+	unsigned long		state;
+	int			devnr;
+	int			flags;
+	int			baud_base;
+	int			custom_divisor;
+	int			close_delay;
+	int			closing_wait;
+	int			refcount;
+	int			openwaitcnt;
+	int			rc;
+	int			argsize;
+	void			*argp;
+	long			session;
+	long			pgrp;
+	unsigned int		rxmarkmsk;
+	struct tty_struct	*tty;
+	struct wait_queue	*open_wait;
+	struct wait_queue	*close_wait;
+	struct wait_queue	*raw_wait;
+	struct tq_struct	tqhangup;
+	struct termios		normaltermios;
+	struct termios		callouttermios;
+	asysigs_t		asig;
+	unsigned long		addr;
+	unsigned long		rxoffset;
+	unsigned long		txoffset;
+	unsigned long		sigs;
+	unsigned long		pflag;
+	unsigned int		rxsize;
+	unsigned int		txsize;
+	unsigned char		reqbit;
+	unsigned char		portidx;
+	unsigned char		portbit;
+} stliport_t;
+
+/*
+ *	Use a structure of function pointers to do board level operations.
+ *	These include, enable/disable, paging shared memory, interrupting, etc.
+ */
+typedef struct stlibrd {
+	unsigned long	magic;
+	int		brdnr;
+	int		brdtype;
+	int		state;
+	int		nrpanels;
+	int		nrports;
+	int		nrdevs;
+	unsigned int	iobase;
+	unsigned long	memaddr;
+	void		*membase;
+	int		memsize;
+	int		pagesize;
+	int		hostoffset;
+	int		slaveoffset;
+	int		bitsize;
+	int		panels[STL_MAXPANELS];
+	int		panelids[STL_MAXPANELS];
+	void		(*init)(struct stlibrd *brdp);
+	void		(*enable)(struct stlibrd *brdp);
+	void		(*reenable)(struct stlibrd *brdp);
+	void		(*disable)(struct stlibrd *brdp);
+	char		*(*getmemptr)(struct stlibrd *brdp, unsigned long offset, int line);
+	void		(*intr)(struct stlibrd *brdp);
+	void		(*reset)(struct stlibrd *brdp);
+	stliport_t	*ports[STL_MAXPORTS];
+} stlibrd_t;
+
+
+/*
+ *	Define MAGIC numbers used for above structures.
+ */
+#define	STLI_PORTMAGIC	0xe671c7a1
+#define	STLI_BOARDMAGIC	0x4bc6c825
+
+/*****************************************************************************/
+#endif
diff -u --recursive --new-file v1.3.90/linux/include/linux/md.h linux/include/linux/md.h
--- v1.3.90/linux/include/linux/md.h	Sat Mar  2 21:21:51 1996
+++ linux/include/linux/md.h	Wed Apr 17 15:08:58 1996
@@ -18,6 +18,7 @@
 #ifndef _MD_H
 #define _MD_H
 
+#include <asm/segment.h>
 #include <linux/major.h>
 #include <linux/mm.h>
 #include <linux/ioctl.h>
@@ -60,7 +61,7 @@
 #ifdef __KERNEL__
 
 #include <linux/config.h>
-#include <sys/types.h>
+#include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/blkdev.h>
 
diff -u --recursive --new-file v1.3.90/linux/include/linux/mm.h linux/include/linux/mm.h
--- v1.3.90/linux/include/linux/mm.h	Wed Apr 17 09:06:32 1996
+++ linux/include/linux/mm.h	Thu Apr 18 15:21:09 1996
@@ -175,7 +175,7 @@
  * A page may be used for kmalloc() or anyone else who does a
  * get_free_page(). In this case the page->count is at least 1, and
  * all other fields are unused but should be 0 or NULL. The
- * managament of this page is the responsibility of the one who uses
+ * management of this page is the responsibility of the one who uses
  * it.
  *
  * The other pages (we may call them "process pages") are completely
diff -u --recursive --new-file v1.3.90/linux/include/linux/ncp_fs.h linux/include/linux/ncp_fs.h
--- v1.3.90/linux/include/linux/ncp_fs.h	Mon Mar 25 10:26:16 1996
+++ linux/include/linux/ncp_fs.h	Thu Apr 18 15:26:45 1996
@@ -63,7 +63,7 @@
 #define NCP_READDIR_CACHE_SIZE        64
 
 
-#define NCP_MAX_RPC_TIMEOUT (60) /* 6 seconds */
+#define NCP_MAX_RPC_TIMEOUT (6*HZ)
 
 /* Guess, what 0x564c is :-) */
 #define NCP_SUPER_MAGIC  0x564c
diff -u --recursive --new-file v1.3.90/linux/include/linux/netrom.h linux/include/linux/netrom.h
--- v1.3.90/linux/include/linux/netrom.h	Wed Aug 16 15:10:11 1995
+++ linux/include/linux/netrom.h	Thu Apr 18 14:35:33 1996
@@ -5,11 +5,15 @@
 #define NETROM_T2	2
 #define NETROM_N2	3
 #define	NETROM_HDRINCL	4
+#define	NETROM_PACLEN	5
+
+#define	NETROM_KILL	99
 
 #define	SIOCNRGETPARMS		(SIOCPROTOPRIVATE+0)
 #define	SIOCNRSETPARMS		(SIOCPROTOPRIVATE+1)
 #define	SIOCNRDECOBS		(SIOCPROTOPRIVATE+2)
 #define	SIOCNRRTCTL		(SIOCPROTOPRIVATE+3)
+#define	SIOCNRCTLCON		(SIOCPROTOPRIVATE+4)
 
 struct nr_route_struct {
 #define	NETROM_NEIGH	0
@@ -32,4 +36,12 @@
 	unsigned int busy_delay;
 	unsigned int tries;
 	unsigned int window;
+	unsigned int paclen;
+};
+
+struct nr_ctl_struct {
+	unsigned char index;
+	unsigned char id;
+	unsigned int  cmd;
+	unsigned long arg;
 };
diff -u --recursive --new-file v1.3.90/linux/include/linux/stallion.h linux/include/linux/stallion.h
--- v1.3.90/linux/include/linux/stallion.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/stallion.h	Wed Apr 17 15:08:58 1996
@@ -0,0 +1,142 @@
+/*****************************************************************************/
+
+/*
+ *	stallion.h  -- stallion multiport serial driver.
+ *
+ *	Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
+ *
+ *	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.
+ */
+
+/*****************************************************************************/
+#ifndef	_STALLION_H
+#define	_STALLION_H
+/*****************************************************************************/
+
+/*
+ *	Define important driver constants here.
+ */
+#define	STL_MAXBRDS		4
+#define	STL_MAXPANELS		4
+#define	STL_PORTSPERPANEL	16
+#define	STL_MAXPORTS		64
+#define	STL_MAXDEVS		(STL_MAXBRDS * STL_MAXPORTS)
+
+
+/*
+ *	Define a set of structures to hold all the board/panel/port info
+ *	for our ports. These will be dynamically allocated as required.
+ */
+
+/*
+ *	Define a ring queue structure for each port. This will hold the
+ *	TX data waiting to be output. Characters are fed into this buffer
+ *	from the line discipline (or even direct from user space!) and
+ *	then fed into the UARTs during interrupts. Will use a clasic ring
+ *	queue here for this. The good thing about this type of ring queue
+ *	is that the head and tail pointers can be updated without interrupt
+ *	protection - since "write" code only needs to change the head, and
+ *	interrupt code only needs to change the tail.
+ */
+typedef struct {
+	char	*buf;
+	char	*head;
+	char	*tail;
+} stlrq_t;
+
+/*
+ *	Port, panel and board structures to hold status info about each.
+ *	The board structure contains pointers to structures for each panel
+ *	connected to it, and in turn each panel structure contains pointers
+ *	for each port structure for each port on that panel. Note that
+ *	the port structure also contains the board and panel number that it
+ *	is associated with, this makes it (fairly) easy to get back to the
+ *	board/panel info for a port.
+ */
+typedef struct {
+	unsigned long		magic;
+	int			portnr;
+	int			panelnr;
+	int			brdnr;
+	int			ioaddr;
+	int			uartaddr;
+	int			pagenr;
+	int			istate;
+	int			flags;
+	int			baud_base;
+	int			custom_divisor;
+	int			close_delay;
+	int			closing_wait;
+	int			refcount;
+	int			openwaitcnt;
+	int			brklen;
+	long			session;
+	long			pgrp;
+	unsigned int		sigs;
+	unsigned int		rxignoremsk;
+	unsigned int		rxmarkmsk;
+	unsigned long		clk;
+	unsigned long		hwid;
+	struct tty_struct	*tty;
+	struct wait_queue	*open_wait;
+	struct wait_queue	*close_wait;
+	struct termios		normaltermios;
+	struct termios		callouttermios;
+	struct tq_struct	tqueue;
+	comstats_t		stats;
+	stlrq_t			tx;
+} stlport_t;
+
+typedef struct {
+	unsigned long	magic;
+	int		panelnr;
+	int		brdnr;
+	int		pagenr;
+	int		nrports;
+	int		iobase;
+	unsigned int	hwid;
+	unsigned int	ackmask;
+	stlport_t	*ports[STL_PORTSPERPANEL];
+} stlpanel_t;
+
+typedef struct {
+	unsigned long	magic;
+	int		brdnr;
+	int		brdtype;
+	int		state;
+	int		nrpanels;
+	int		nrports;
+	int		irq;
+	int		irqtype;
+	unsigned int	ioaddr1;
+	unsigned int	ioaddr2;
+	unsigned int	iostatus;
+	unsigned int	ioctrl;
+	unsigned int	ioctrlval;
+	unsigned int	hwid;
+	unsigned long	clk;
+	stlpanel_t	*panels[STL_MAXPANELS];
+} stlbrd_t;
+
+
+/*
+ *	Define MAGIC numbers used for above structures.
+ */
+#define	STL_PORTMAGIC	0x5a7182c9
+#define	STL_PANELMAGIC	0x7ef621a1
+#define	STL_BOARDMAGIC	0xa2267f52
+
+/*****************************************************************************/
+#endif
diff -u --recursive --new-file v1.3.90/linux/include/net/netrom.h linux/include/net/netrom.h
--- v1.3.90/linux/include/net/netrom.h	Fri Apr 12 15:52:08 1996
+++ linux/include/net/netrom.h	Thu Apr 18 14:35:33 1996
@@ -45,6 +45,7 @@
 #define	NR_DEFAULT_TTL		16			/* Default Time To Live */
 #define NR_MODULUS 		256
 #define NR_MAX_WINDOW_SIZE	127			/* Maximum Window Allowable */
+#define	NR_DEFAULT_PACLEN	236			/* Default Packet Length */
 
 typedef struct {
 	ax25_address		user_addr, source_addr, dest_addr;
@@ -56,7 +57,7 @@
 	unsigned char		n2, n2count;
 	unsigned short		t1, t2, rtt;
 	unsigned short		t1timer, t2timer, t4timer;
-	unsigned short		fraglen;
+	unsigned short		fraglen, paclen;
 	struct sk_buff_head	ack_queue;
 	struct sk_buff_head	reseq_queue;
 	struct sk_buff_head	frag_queue;
diff -u --recursive --new-file v1.3.90/linux/include/net/sock.h linux/include/net/sock.h
--- v1.3.90/linux/include/net/sock.h	Fri Apr 12 15:52:09 1996
+++ linux/include/net/sock.h	Thu Apr 18 15:23:46 1996
@@ -498,8 +498,8 @@
 		return -ENOMEM;
 	atomic_add(skb->truesize, &sk->rmem_alloc);
 	skb->sk=sk;
-	skb_queue_tail(&sk->receive_queue,skb);
-	if(!sk->dead)
+	__skb_queue_tail(&sk->receive_queue,skb);
+	if (!sk->dead)
 		sk->data_ready(sk,skb->len);
 	return 0;
 }
diff -u --recursive --new-file v1.3.90/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v1.3.90/linux/net/ax25/af_ax25.c	Fri Apr 12 15:52:11 1996
+++ linux/net/ax25/af_ax25.c	Thu Apr 18 14:35:34 1996
@@ -534,8 +534,7 @@
  *		  includes a KILL command to abort any connection.
  *		  VERY useful for debugging ;-)
  */
-
-static int ax25_ctl_ioctl(const unsigned int cmd, const unsigned long arg)
+static int ax25_ctl_ioctl(const unsigned int cmd, void *arg)
 {
 	struct ax25_ctl_struct ax25_ctl;
 	struct device *dev;
@@ -543,10 +542,10 @@
 	unsigned long flags;
 	int err;
 	
-	if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(ax25_ctl))) != 0)
+	if ((err = verify_area(VERIFY_READ, arg, sizeof(ax25_ctl))) != 0)
 		return err;
 
-	memcpy_fromfs(&ax25_ctl, (void *) arg, sizeof(ax25_ctl));
+	memcpy_fromfs(&ax25_ctl, arg, sizeof(ax25_ctl));
 	
 	if ((dev = ax25rtr_get_dev(&ax25_ctl.port_addr)) == NULL)
 		return -ENODEV;
@@ -574,6 +573,7 @@
 			ax25_dama_off(ax25);
 			ax25_set_timer(ax25);
 	  		break;
+
 	  	case AX25_WINDOW:
 	  		if (ax25->modulus == MODULUS) {
 	  			if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7) 
@@ -584,6 +584,7 @@
 	  		}
 	  		ax25->window = ax25_ctl.arg;
 	  		break;
+
 	  	case AX25_T1:
   			if (ax25_ctl.arg < 1) 
   				return -EINVAL;
@@ -594,6 +595,7 @@
   				ax25->t1timer = ax25->t1;
   			restore_flags(flags);
   			break;
+
 	  	case AX25_T2:
 	  		if (ax25_ctl.arg < 1) 
 	  			return -EINVAL;
@@ -603,12 +605,14 @@
 	  			ax25->t2timer = ax25->t2;
 	  		restore_flags(flags);
 	  		break;
+
 	  	case AX25_N2:
 	  		if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31) 
 	  			return -EINVAL;
 	  		ax25->n2count = 0;
 	  		ax25->n2 = ax25_ctl.arg;
 	  		break;
+
 	  	case AX25_T3:
 	  		if (ax25_ctl.arg < 1) 
 	  			return -EINVAL;
@@ -618,6 +622,7 @@
 	  			ax25->t3timer = ax25->t3;
 	  		restore_flags(flags);
 	  		break;
+
 	  	case AX25_IDLE:
 	  		if (ax25_ctl.arg < 1) 
 	  			return -EINVAL;
@@ -629,20 +634,21 @@
 	  			ax25->idletimer = ax25->idle;
 	  		restore_flags(flags);
 	  		break;
+
 	  	case AX25_PACLEN:
 	  		if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535) 
 	  			return -EINVAL;
-
 	  		if (ax25_ctl.arg > 256) /* we probably want this */
-	  			printk("ax25_ctl_ioctl(): Warning --- huge paclen %d", (int) ax25_ctl.arg);
+	  			printk("ax25_ctl_ioctl: Warning --- huge paclen %d\n", (int)ax25_ctl.arg);
 	  		ax25->paclen = ax25_ctl.arg;
 	  		break;
+
 	  	case AX25_IPMAXQUEUE:
 	  		if (ax25_ctl.arg < 1)
 	  			return -EINVAL;
-	  			
 	  		ax25->maxqueue = ax25_ctl.arg;
 	  		break;
+
 	  	default:
 	  		return -EINVAL;
 	  }
@@ -650,7 +656,6 @@
 	  return 0;
 }
 
-
 /*
  * Create an empty AX.25 control block.
  */
@@ -1189,6 +1194,7 @@
 	ax25->t3      = osk->ax25->t3;
 	ax25->n2      = osk->ax25->n2;
 	ax25->idle    = osk->ax25->idle;
+	ax25->paclen  = osk->ax25->paclen;
 
 	ax25->window  = osk->ax25->window;
 
@@ -2235,7 +2241,7 @@
 		case SIOCAX25CTLCON:
 			if (!suser())
 				return -EPERM;
-			return ax25_ctl_ioctl(cmd, arg);
+			return ax25_ctl_ioctl(cmd, (void *)arg);
 
 		case SIOCGIFADDR:
 		case SIOCSIFADDR:
@@ -2250,11 +2256,11 @@
 			return -EINVAL;
 
 		default:
-			return(dev_ioctl(cmd, (void *)arg));
+			return dev_ioctl(cmd, (void *)arg);
 	}
 
 	/*NOTREACHED*/
-	return(0);
+	return 0;
 }
 
 
@@ -2534,6 +2540,7 @@
 
 int ax25_rebuild_header(unsigned char *bp, struct device *dev, unsigned long dest, struct sk_buff *skb)
 {
+	struct sk_buff *ourskb;
 	int mode;
 
   	if (arp_find(bp + 1, dest, dev, dev->pa_addr, skb))
@@ -2556,20 +2563,22 @@
 			 *	as we have pulled the frame from the queue by
 			 *	freeing it).
 			 */
-			struct sk_buff *ourskb=skb_clone(skb, GFP_ATOMIC);
-
-			if(ourskb==NULL) {
+			if ((ourskb = skb_clone(skb, GFP_ATOMIC)) == NULL) {
 				dev_kfree_skb(skb, FREE_WRITE);
 				return 1;
 			}
 
 			ourskb->sk = skb->sk;
+
 			if (ourskb->sk != NULL)
 				atomic_add(ourskb->truesize, &ourskb->sk->wmem_alloc);
 
 			dev_kfree_skb(skb, FREE_WRITE);
+
 			skb_pull(ourskb, AX25_HEADER_LEN - 1);	/* Keep PID */
+
 			ax25_send_frame(ourskb, (ax25_address *)(bp + 8), (ax25_address *)(bp + 1), NULL, dev);
+
 			return 1;
 		}
 	}
diff -u --recursive --new-file v1.3.90/linux/net/ax25/ax25_subr.c linux/net/ax25/ax25_subr.c
--- v1.3.90/linux/net/ax25/ax25_subr.c	Fri Apr 12 15:52:11 1996
+++ linux/net/ax25/ax25_subr.c	Thu Apr 18 14:35:34 1996
@@ -494,13 +494,9 @@
                 return 0;
         }
 
-	skbq = (struct sk_buff *) list->next;
-
-	while (skbq != (struct sk_buff *)list) {
+	for (skbq = list->next; skbq != (struct sk_buff *)list; skbq = skbq->next)
 		if (skb->sk == skbq->sk)
 			count++;
-		skbq = skbq->next;
-	}
 
         restore_flags(flags);
         return count;
@@ -512,7 +508,7 @@
 
 int ax25_queue_length(ax25_cb *ax25, struct sk_buff *skb)
 {
-	return ax25_list_length(&ax25->write_queue, skb)+ax25_list_length(&ax25->ack_queue, skb);
+	return ax25_list_length(&ax25->write_queue, skb) + ax25_list_length(&ax25->ack_queue, skb);
 }
 
 /*
diff -u --recursive --new-file v1.3.90/linux/net/bridge/br.c linux/net/bridge/br.c
--- v1.3.90/linux/net/bridge/br.c	Fri Apr 12 15:52:11 1996
+++ linux/net/bridge/br.c	Thu Apr 18 15:25:53 1996
@@ -16,8 +16,9 @@
  *	and use a netlink notifier so a daemon can maintain the bridge
  *	port group (could we also do multiple groups ????).
  *		A nice /proc file interface.
- *		Put the path costs in the port info and devices
+ *		Put the path costs in the port info and devices.
  *		Put the bridge port number in the device structure for speed.
+ *		Bridge SNMP stats.
  *	
  */
  
@@ -81,15 +82,14 @@
 /** Elements of Procedure (4.6) **/
 
 /*
- * this section of code was graciously borrowed from the IEEE 802.1d
+ * this section of code was gratiously borrowed from the IEEE 802.1d
  * specification section 4.9.1 starting on pg 69.  It has been
  * modified somewhat to fit within out framework and structure.  It
  * implements the spanning tree algorithm that is the heart of the
  * 802.1d bridging protocol.
  */
 
-void
-transmit_config(int port_no)			  /* (4.6.1)	 */
+void transmit_config(int port_no)			  /* (4.6.1)	 */
 {
 	if (hold_timer[port_no].active) {	  /* (4.6.1.3.1)	 */
 		port_info[port_no].config_pending = TRUE;	/* (4.6.1.3.1)	 */
@@ -132,15 +132,13 @@
 	}
 }
 
-int
-root_bridge(void)
+int root_bridge(void)
 {
 	return (br_cmp(bridge_info.designated_root.BRIDGE_ID,
 		 bridge_info.bridge_id.BRIDGE_ID)?FALSE:TRUE);
 }
 
-int
-supersedes_port_info(int port_no, Config_bpdu *config)	  /* (4.6.2.2)	 */
+int supersedes_port_info(int port_no, Config_bpdu *config)	  /* (4.6.2.2)	 */
 {
 	return (
 		(br_cmp(config->root_id.BRIDGE_ID,
@@ -177,8 +175,7 @@
 		);
 }
 
-void
-record_config_information(int port_no, Config_bpdu *config)	  /* (4.6.2)	 */
+void record_config_information(int port_no, Config_bpdu *config)	  /* (4.6.2)	 */
 {
 	port_info[port_no].designated_root = config->root_id;	/* (4.6.2.3.1)   */
 	port_info[port_no].designated_cost = config->root_path_cost;
@@ -187,8 +184,7 @@
 	start_message_age_timer(port_no, config->message_age);	/* (4.6.2.3.2)   */
 }
 
-void
-record_config_timeout_values(Config_bpdu *config)		  /* (4.6.3)	 */
+void record_config_timeout_values(Config_bpdu *config)		  /* (4.6.3)	 */
 {
 	bridge_info.max_age = config->max_age;	  /* (4.6.3.3)	 */
 	bridge_info.hello_time = config->hello_time;
@@ -197,8 +193,7 @@
 		bridge_info.top_change = 1;
 }
 
-void
-config_bpdu_generation(void)
+void config_bpdu_generation(void)
 {						  /* (4.6.4)	 */
 	int             port_no;
 	for (port_no = One; port_no <= No_of_ports; port_no++) {	/* (4.6.4.3) */
@@ -211,8 +206,7 @@
 	}
 }
 
-int
-designated_port(int port_no)
+int designated_port(int port_no)
 {
 	return ((br_cmp(port_info[port_no].designated_bridge.BRIDGE_ID,
 		 bridge_info.bridge_id.BRIDGE_ID) == 0
@@ -224,14 +218,12 @@
 		);
 }
 
-void
-reply(int port_no)					  /* (4.6.5)	 */
+void reply(int port_no)					  /* (4.6.5)	 */
 {
 	transmit_config(port_no);		  /* (4.6.5.3)	 */
 }
 
-void
-transmit_tcn(void)
+void transmit_tcn(void)
 {						  /* (4.6.6)	 */
 	int             port_no;
 
@@ -240,8 +232,7 @@
 	send_tcn_bpdu(port_no, &tcn_bpdu[bridge_info.root_port]);	/* (4.6.6.3)     */
 }
 
-void
-configuration_update(void)	/* (4.6.7) */
+void configuration_update(void)	/* (4.6.7) */
 {
 	root_selection();			  /* (4.6.7.3.1)	 */
 	/* (4.6.8.2)	 */
@@ -249,8 +240,7 @@
 	/* (4.6.9.2)	 */
 }
 
-void
-root_selection(void)
+void root_selection(void)
 {						  /* (4.6.8) */
 	int             root_port;
 	int             port_no;
@@ -330,8 +320,7 @@
 	}
 }
 
-void
-designated_port_selection(void)
+void designated_port_selection(void)
 {						  /* (4.6.9)	 */
 	int             port_no;
 
@@ -368,8 +357,7 @@
 	}
 }
 
-void
-become_designated_port(int port_no)
+void become_designated_port(int port_no)
 {						  /* (4.6.10)	 */
 
 	/* (4.6.10.3.1) */
@@ -382,8 +370,7 @@
 	port_info[port_no].designated_port = port_info[port_no].port_id;
 }
 
-void
-port_state_selection(void)
+void port_state_selection(void)
 {						  /* (4.6.11) */
 	int             port_no;
 	for (port_no = One; port_no <= No_of_ports; port_no++) {
@@ -403,8 +390,7 @@
 
 }
 
-void
-make_forwarding(int port_no)
+void make_forwarding(int port_no)
 {						  /* (4.6.12) */
 	if (port_info[port_no].state == Blocking) {	/* (4.6.12.3) */
 		set_port_state(port_no, Listening);	/* (4.6.12.3.1) */
@@ -412,8 +398,7 @@
 	}
 }
 
-void 
-topology_change_detection(void)
+void topology_change_detection(void)
 {						  /* (4.6.14)       */
 	if (root_bridge()) {			  /* (4.6.14.3.1)   */
 		bridge_info.top_change = 1;
@@ -425,22 +410,19 @@
 	bridge_info.top_change = 1;
 }
 
-void
-topology_change_acknowledged(void)
+void topology_change_acknowledged(void)
 {						  /* (4.6.15) */
 	bridge_info.top_change_detected = 0;
 	stop_tcn_timer();			  /* (4.6.15.3.2) */
 }
 
-void
-acknowledge_topology_change(int port_no)
+void acknowledge_topology_change(int port_no)
 {						  /* (4.6.16) */
 	port_info[port_no].top_change_ack = 1;
 	transmit_config(port_no);		  /* (4.6.16.3.2) */
 }
 
-void
-make_blocking(int port_no)				  /* (4.6.13)	 */
+void make_blocking(int port_no)				  /* (4.6.13)	 */
 {
 
 	if ((port_info[port_no].state != Disabled)
@@ -460,14 +442,12 @@
 	}
 }
 
-void
-set_port_state(int port_no, int state)
+void set_port_state(int port_no, int state)
 {
 	port_info[port_no].state = state;
 }
 
-void
-received_config_bpdu(int port_no, Config_bpdu *config)		  /* (4.7.1)	 */
+void received_config_bpdu(int port_no, Config_bpdu *config)		  /* (4.7.1)	 */
 {
 	int         root;
 
@@ -504,8 +484,7 @@
 	}
 }
 
-void
-received_tcn_bpdu(int port_no, Tcn_bpdu *tcn)			  /* (4.7.2)	 */
+void received_tcn_bpdu(int port_no, Tcn_bpdu *tcn)			  /* (4.7.2)	 */
 {
 	if (port_info[port_no].state != Disabled) {
 		if (designated_port(port_no)) {
@@ -516,15 +495,13 @@
 	}
 }
 
-void
-hello_timer_expiry(void)
+void hello_timer_expiry(void)
 {						  /* (4.7.3)	 */
 	config_bpdu_generation();		  /* (4.6.4.2.2)	 */
 	start_hello_timer();
 }
 
-void
-message_age_timer_expiry(int port_no)		  /* (4.7.4)	 */
+void message_age_timer_expiry(int port_no)		  /* (4.7.4)	 */
 {
 	int         root;
 	root = root_bridge();
@@ -549,8 +526,7 @@
 	}
 }
 
-void
-forward_delay_timer_expiry(int port_no)		  /* (4.7.5)	 */
+void forward_delay_timer_expiry(int port_no)		  /* (4.7.5)	 */
 {
 	if (port_info[port_no].state == Listening) {	/* (4.7.5.1)	 */
 		set_port_state(port_no, Learning);	/* (4.7.5.1.1)	 */
@@ -564,8 +540,7 @@
 	}
 }
 
-int
-designated_for_some_port(void)
+int designated_for_some_port(void)
 {
 	int             port_no;
 
@@ -580,31 +555,27 @@
 	return (FALSE);
 }
 
-void
-tcn_timer_expiry(void)
+void tcn_timer_expiry(void)
 {						  /* (4.7.6)	 */
 	transmit_tcn();				  /* (4.7.6.1)	 */
 	start_tcn_timer();			  /* (4.7.6.2)	 */
 }
 
-void
-topology_change_timer_expiry(void)
+void topology_change_timer_expiry(void)
 {						  /* (4.7.7)	 */
 	bridge_info.top_change_detected = 0;
 	bridge_info.top_change = 0;
 	  /* (4.7.7.2)	 */
 }
 
-void
-hold_timer_expiry(int port_no)			  /* (4.7.8)	 */
+void hold_timer_expiry(int port_no)			  /* (4.7.8)	 */
 {
 	if (port_info[port_no].config_pending) {
 		transmit_config(port_no);	  /* (4.7.8.1)	 */
 	}					  /* (4.6.1.2.3)	 */
 }
 
-void
-br_init(void)
+void br_init(void)
 {						  /* (4.8.1)	 */
 	int             port_no;
 
@@ -633,17 +604,16 @@
 	config_bpdu_generation();		  /* (4.8.1.6)	 */
 	
 	/* initialize system timer */
-	tl.expires = HZ;	/* 1 second */
+	tl.expires = jiffies+HZ;	/* 1 second */
 	tl.function = br_tick;
 	add_timer(&tl);
 
 	register_netdevice_notifier(&br_dev_notifier);
-	br_stats.flags = BR_UP | BR_DEBUG;	/* enable bridge */
-	start_hello_timer();
+	br_stats.flags = 0; /*BR_UP | BR_DEBUG*/;	/* enable bridge */
+	/*start_hello_timer();*/
 }
 
-void
-br_init_port(int port_no)
+void br_init_port(int port_no)
 {
 	become_designated_port(port_no);	  /* (4.8.1.4.1) */
 	set_port_state(port_no, Blocking);	  /* (4.8.1.4.2)    */
@@ -654,15 +624,13 @@
 	stop_hold_timer(port_no);		  /* (4.8.1.4.7)	 */
 }
 
-void
-enable_port(int port_no)				  /* (4.8.2)	 */
+void enable_port(int port_no)				  /* (4.8.2)	 */
 {
 	br_init_port(port_no);
 	port_state_selection();			  /* (4.8.2.7)	 */
 }						  /* */
 
-void
-disable_port(int port_no)				  /* (4.8.3)	 */
+void disable_port(int port_no)				  /* (4.8.3)	 */
 {
 	int         root;
 
@@ -687,8 +655,7 @@
 }
 
 
-void
-set_bridge_priority(bridge_id_t *new_bridge_id)		  /* (4.8.4)	 */
+void set_bridge_priority(bridge_id_t *new_bridge_id)		  /* (4.8.4)	 */
 {
 
 	int         root;
@@ -714,8 +681,7 @@
 	}
 }
 
-void
-set_port_priority(int port_no, unsigned short new_port_id)		  /* (4.8.5)	 */
+void set_port_priority(int port_no, unsigned short new_port_id)		  /* (4.8.5)	 */
 {
 	if (designated_port(port_no)) {		  /* (4.8.5.2)	 */
 		port_info[port_no].designated_port = new_port_id;
@@ -735,16 +701,14 @@
 	}
 }
 
-void
-set_path_cost(int port_no, unsigned short path_cost)		  /* (4.8.6)	 */
+void set_path_cost(int port_no, unsigned short path_cost)		  /* (4.8.6)	 */
 {
 	port_info[port_no].path_cost = path_cost; /* (4.8.6.1)	 */
 	configuration_update();			  /* (4.8.6.2)	 */
 	port_state_selection();			  /* (4.8.6.3)	 */
 }
 
-static void
-br_tick(unsigned long arg)
+static void br_tick(unsigned long arg)
 {
 	int             port_no;
 
@@ -769,26 +733,23 @@
 		}
 	}
 	/* call me again sometime... */
-	tl.expires = HZ;	/* 1 second */
+	tl.expires = jiffies+HZ;	/* 1 second */
 	tl.function = br_tick;
 	add_timer(&tl);
 }
 
-void
-start_hello_timer(void)
+void start_hello_timer(void)
 {
 	hello_timer.value = 0;
 	hello_timer.active = TRUE;
 }
 
-void
-stop_hello_timer(void)
+void stop_hello_timer(void)
 {
 	hello_timer.active = FALSE;
 }
 
-int
-hello_timer_expired(void)
+int hello_timer_expired(void)
 {
 	if (hello_timer.active && (++hello_timer.value >= bridge_info.hello_time)) {
 		hello_timer.active = FALSE;
@@ -797,21 +758,18 @@
 	return (FALSE);
 }
 
-void
-start_tcn_timer(void)
+void start_tcn_timer(void)
 {
 	tcn_timer.value = 0;
 	tcn_timer.active = TRUE;
 }
 
-void
-stop_tcn_timer(void)
+void stop_tcn_timer(void)
 {
 	tcn_timer.active = FALSE;
 }
 
-int
-tcn_timer_expired(void)
+int tcn_timer_expired(void)
 {
 	if (tcn_timer.active && (++tcn_timer.value >=
 				 bridge_info.bridge_hello_time)) {
@@ -822,21 +780,18 @@
 
 }
 
-void
-start_topology_change_timer(void)
+void start_topology_change_timer(void)
 {
 	topology_change_timer.value = 0;
 	topology_change_timer.active = TRUE;
 }
 
-void
-stop_topology_change_timer(void)
+void stop_topology_change_timer(void)
 {
 	topology_change_timer.active = FALSE;
 }
 
-int
-topology_change_timer_expired(void)
+int topology_change_timer_expired(void)
 {
 	if (topology_change_timer.active
 			&& (++topology_change_timer.value
@@ -848,21 +803,18 @@
 	return (FALSE);
 }
 
-void
-start_message_age_timer(int port_no, unsigned short message_age)
+void start_message_age_timer(int port_no, unsigned short message_age)
 {
 	message_age_timer[port_no].value = message_age;
 	message_age_timer[port_no].active = TRUE;
 }
 
-void
-stop_message_age_timer(int port_no)
+void stop_message_age_timer(int port_no)
 {
 	message_age_timer[port_no].active = FALSE;
 }
 
-int
-message_age_timer_expired(int port_no)
+int message_age_timer_expired(int port_no)
 {
 	if (message_age_timer[port_no].active &&
 	      (++message_age_timer[port_no].value >= bridge_info.max_age)) {
@@ -872,21 +824,18 @@
 	return (FALSE);
 }
 
-void
-start_forward_delay_timer(int port_no)
+void start_forward_delay_timer(int port_no)
 {
 	forward_delay_timer[port_no].value = 0;
 	forward_delay_timer[port_no].active = TRUE;
 }
 
-void
-stop_forward_delay_timer(int port_no)
+void stop_forward_delay_timer(int port_no)
 {
 	forward_delay_timer[port_no].active = FALSE;
 }
 
-int
-forward_delay_timer_expired(int port_no)
+int forward_delay_timer_expired(int port_no)
 {
 		if (forward_delay_timer[port_no].active &&
 				(++forward_delay_timer[port_no].value >= bridge_info.forward_delay)) {
@@ -896,22 +845,19 @@
 		return (FALSE);
 }
 
-void
-start_hold_timer(int port_no)
+void start_hold_timer(int port_no)
 {
 	hold_timer[port_no].value = 0;
 	hold_timer[port_no].active = TRUE;
 }
 
-void
-stop_hold_timer(int port_no)
+void stop_hold_timer(int port_no)
 {
 	hold_timer[port_no].active = FALSE;
 }
 
 
-int
-hold_timer_expired(int port_no)
+int hold_timer_expired(int port_no)
 {
 	if (hold_timer[port_no].active &&
 		   (++hold_timer[port_no].value >= bridge_info.hold_time)) {
@@ -922,8 +868,7 @@
 
 }
 
-int
-send_config_bpdu(int port_no, Config_bpdu *config_bpdu)
+int send_config_bpdu(int port_no, Config_bpdu *config_bpdu)
 {
 struct sk_buff *skb;
 struct device *dev = port_info[port_no].dev;
@@ -982,8 +927,7 @@
 	return(0);
 }
 
-int
-send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu)
+int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu)
 {
 struct sk_buff *skb;
 struct device *dev = port_info[port_no].dev;
@@ -1039,8 +983,7 @@
 	return(0);
 }
 
-static int 
-br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
+static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
 {
 	struct device *dev = ptr;
 	int i;
@@ -1103,8 +1046,7 @@
  * frame, 0 when it does not
  */
 
-int
-br_receive_frame(struct sk_buff *skb)	/* 3.5 */
+int br_receive_frame(struct sk_buff *skb)	/* 3.5 */
 {
 	int port;
 	
@@ -1115,12 +1057,15 @@
 		printk("no skb!\n");
 		return(1);
 	}
+
+	skb->pkt_bridged = IS_BRIDGED;
+
 	/* check for loopback */
 	if (skb->dev->flags & IFF_LOOPBACK)
 		return(0);
 
 	port = find_port(skb->dev);
-	skb->h.raw = skb->data;
+	skb->h.raw = skb->mac.raw;
 	if (br_stats.flags & BR_DEBUG)
 		printk("port %i src %02x:%02x:%02x:%02x:%02x:%02x\
 			dest %02x:%02x:%02x:%02x:%02x:%02x\n", 
@@ -1139,11 +1084,13 @@
 			skb->h.eth->h_dest[5]);
 
 	if (!port) {
-		printk("\nbr_receive_frame: no port!\n");
+		if(br_stats.flags&BR_DEBUG)
+			printk("\nbr_receive_frame: no port!\n");
 		return(0);
 	}
 
-	switch (port_info[port].state) {
+	switch (port_info[port].state) 
+	{
 		case Learning:
 			(void) br_learn(skb, port);	/* 3.8 */
 			/* fall through */
@@ -1167,19 +1114,22 @@
 			(void) br_learn(skb, port);	/* 3.8 */
 			/* process BPDUs */
 			if (memcmp(skb->h.eth->h_dest, bridge_ula, 
-					ETH_ALEN) == 0) {
-				printk("frame bpdu processor for me!!!\n");
+					ETH_ALEN) == 0) 
+			{
+				/*printk("frame bpdu processor for me!!!\n");*/
 				br_bpdu(skb);
 				return(1); /* br_bpdu consumes skb */
 			}
 			/* is frame for me? */	
 			if (memcmp(skb->h.eth->h_dest, 
 					port_info[port].dev->dev_addr, 
-					ETH_ALEN) == 0) {
+					ETH_ALEN) == 0) 
+			{
 				return(0);	/* pass frame up our stack (this will */
 						/* happen in net_bh() in dev.c) */
 			}
 			/* ok, forward this frame... */
+			skb_device_lock(skb);
 			return(br_forward(skb, port));
 		default:
 			printk("br_receive_frame: port [%i] unknown state [%i]\n",
@@ -1194,13 +1144,13 @@
  * 0 when it does not.
  */
 
-int
-br_tx_frame(struct sk_buff *skb)	/* 3.5 */
+int br_tx_frame(struct sk_buff *skb)	/* 3.5 */
 {
 	int port;
 	
 	/* sanity */
-	if (!skb) {
+	if (!skb) 
+	{
 		printk("br_tx_frame: no skb!\n");
 		return(0);
 	}
@@ -1235,8 +1185,7 @@
  * state or lack of resources...
  */
 
-int
-br_learn(struct sk_buff *skb, int port)	/* 3.8 */
+int br_learn(struct sk_buff *skb, int port)	/* 3.8 */
 {
 	struct fdb *f;
 
@@ -1285,23 +1234,31 @@
  * this routine always consumes the frame
  */
 
-int
-br_drop(struct sk_buff *skb)
+int br_drop(struct sk_buff *skb)
 {
 	kfree_skb(skb, 0);
 	return(1);
 }
 
 /*
+ * this routine always consumes the frame
+ */
+
+int br_dev_drop(struct sk_buff *skb)
+{
+	dev_kfree_skb(skb, 0);
+	return(1);
+}
+
+/*
  * this routine returns 1 if it consumes the frame, 0
  * if not...
  */
 
-int
-br_forward(struct sk_buff *skb, int port)	/* 3.7 */
+int br_forward(struct sk_buff *skb, int port)	/* 3.7 */
 {
-struct fdb *f;
-unsigned long flags;
+	struct fdb *f;
+	unsigned long flags;
 	
 	/*
    	 * flood all ports with frames destined for a group
@@ -1310,19 +1267,32 @@
 	 * Multicast frames will also need to be seen
 	 * by our upper layers.
 	 */	
-	if (skb->h.eth->h_dest[0] & 0x01) {	/* group address */
+	if (skb->h.eth->h_dest[0] & 0x01) 
+	{
+		/* group address */
 		br_flood(skb, port);
+		/*
+		 *	External groups are fed out via the normal source
+		 *	This probably should be dropped since the flood will
+		 *	have sent it anyway.
+		 */
 		if (port == 0) 			/* locally generated */
-			return(br_drop(skb));
+			return(br_dev_drop(skb));
 		return(0);
 	} else {
 		/* locate port to forward to */
 		f = br_avl_find_addr(skb->h.eth->h_dest);
+		/*
+		 *	Send flood and drop.
+		 */
 		if (!f | !(f->flags & FDB_ENT_VALID)) {
 		 	/* not found; flood all ports */
 			br_flood(skb, port);
-			return(br_drop(skb));
+			return(br_dev_drop(skb));
 		}
+		/*
+		 *	Sending
+		 */
 		if (port_info[f->port].state == Forwarding) {
 			/* has entry expired? */
 			if (f->timer + fdb_aging_time < CURRENT_TIME) {
@@ -1330,33 +1300,34 @@
 				f->flags &= ~FDB_ENT_VALID;
 				if (br_stats.flags & BR_DEBUG)
 					printk("fdb entry expired...\n");
+				/*
+				 *	Send flood and drop original
+				 */
 				br_flood(skb, port);
-				return(br_drop(skb));
+				return(br_dev_drop(skb));
 			}
 			/* mark that's we've been here... */
 			skb->pkt_bridged = IS_BRIDGED;
 			
-			/*
-			 * if the frame is originating in this host,
-			 * we may need to resolve the outgoing address
-			if (port != 0)
-				skb->arp = 1;
-			 */
-		
 			/* reset the skb->ip pointer */	
 			skb->h.raw = skb->data + ETH_HLEN;
 
-			/* we must unlock the skb before requeueing it... */
-			if (skb_device_locked(skb))
-				skb_device_unlock(skb);
-
-			save_flags(flags);	/* enter critical section */
-			cli();
-			skb_queue_head(port_info[f->port].dev->buffs, skb);
-			restore_flags(flags);	/* exit critical section */
+			/*
+			 *	Send the buffer out.
+			 */
+			 
+			skb->dev=port_info[f->port].dev;
+			 
+			/*
+			 *	We send this still locked
+			 */
+			dev_queue_xmit(skb, skb->dev,1);
 			return(1);	/* skb has been consumed */
 		} else {
-			return(br_drop(skb));
+			/*
+			 *	Arrived on the right port, we discard
+			 */
+			return(br_dev_drop(skb));
 		}
 	}
 }
@@ -1367,40 +1338,34 @@
  * consumes the original frame.
  */
 	
-int
-br_flood(struct sk_buff *skb, int port)
+int br_flood(struct sk_buff *skb, int port)
 {
-int i;
-struct sk_buff *nskb;
-unsigned long flags;
+	int i;
+	struct sk_buff *nskb;
+	unsigned long flags;
 
-	for (i = One; i <= No_of_ports; i++) {
+	for (i = One; i <= No_of_ports; i++) 
+	{
 		if (i == port)
 			continue;
-		if (port_info[i].state == Forwarding) {
+		if (port_info[i].state == Forwarding) 
+		{
 			nskb = skb_clone(skb, GFP_ATOMIC);
 			/* mark that's we've been here... */
 			nskb->pkt_bridged = IS_BRIDGED;
-			/*
-			 * if the frame is originating in this host,
-			 * we may need to resolve the outgoing address
-			if (port != 0)
-				nskb->arp = 1;
-			 */
+			nskb->arp = skb->arp;
+			
+/*			printk("Flood to port %d\n",i);*/
 			nskb->h.raw = nskb->data + ETH_HLEN;
-			save_flags(flags);
-			cli();
-			skb_queue_tail(port_info[i].dev->buffs, nskb);
-			restore_flags(flags);
+			dev_queue_xmit(nskb,nskb->dev,1);
 		}
 	}
 	return(0);
 }
 
-int
-find_port(struct device *dev)
+int find_port(struct device *dev)
 {
-int i;
+	int i;
 
 	for (i = One; i <= No_of_ports; i++)
 		if ((port_info[i].dev == dev) && 
@@ -1409,8 +1374,7 @@
 	return(0);
 }
 
-int
-br_port_cost(struct device *dev)	/* 4.10.2 */
+int br_port_cost(struct device *dev)	/* 4.10.2 */
 {
 	if (strncmp(dev->name, "eth", 3) == 0)	/* ethernet */
 		return(100);
@@ -1425,11 +1389,10 @@
  * this routine always consumes the skb 
  */
 
-void
-br_bpdu(struct sk_buff *skb) /* consumes skb */
+void br_bpdu(struct sk_buff *skb) /* consumes skb */
 {
-Tcn_bpdu *bpdu;
-int port;
+	Tcn_bpdu *bpdu;
+	int port;
 
 	port = find_port(skb->dev);
 	if (port == 0) {	/* unknown port */
@@ -1453,8 +1416,7 @@
 	br_drop(skb);
 }
 
-int
-br_ioctl(unsigned int cmd, void *arg)
+int br_ioctl(unsigned int cmd, void *arg)
 {
 	int err;
 	struct br_cf bcf;
@@ -1484,7 +1446,6 @@
 					if (br_stats.flags & BR_UP)
 						return(-EALREADY);	
 					printk("br: enabling bridging function\n");
-					register_netdevice_notifier(&br_dev_notifier);
 					br_stats.flags |= BR_UP;	/* enable bridge */
 					start_hello_timer();
 					break;
@@ -1492,12 +1453,13 @@
 					if (!(br_stats.flags & BR_UP))
 						return(-EALREADY);	
 					printk("br: disabling bridging function\n");
-					unregister_netdevice_notifier(&br_dev_notifier);
 					br_stats.flags &= ~BR_UP;	/* disable bridge */
 					stop_hello_timer();
+#if 0					
 					for (i = One; i <= No_of_ports; i++)
 						if (port_info[i].state != Disabled)
 							disable_port(i);
+#endif							
 					break;
 				case BRCMD_PORT_ENABLE:
 					if (port_info[bcf.arg1].dev == 0)
@@ -1548,7 +1510,8 @@
 int br_cmp(unsigned int *a, unsigned int *b)
 {
 	int i;	
-	for (i=0; i<2; i++) {
+	for (i=0; i<2; i++) 
+	{
 		if (a[i] == b[i])
 			continue;
 		if (a[i] < b[i])
diff -u --recursive --new-file v1.3.90/linux/net/ipv4/ip_options.c linux/net/ipv4/ip_options.c
--- v1.3.90/linux/net/ipv4/ip_options.c	Fri Apr 12 15:52:12 1996
+++ linux/net/ipv4/ip_options.c	Thu Apr 18 09:47:39 1996
@@ -277,7 +277,7 @@
 		if (optlen<2 || optlen>l)
 		{
 			pp_ptr = optptr;
-			break;
+			goto error;
 		}
 		switch (*optptr) 
 		{
@@ -286,25 +286,25 @@
 			if (optlen < 3) 
 			{
 				pp_ptr = optptr + 1;
-				break;
+				goto error;
 			}
 			if (optptr[2] < 4) 
 			{
 				pp_ptr = optptr + 2;
-				break;
+				goto error;
 			}
 			/* NB: cf RFC-1812 5.2.4.1 */
 			if (opt->srr) 
 			{
 				pp_ptr = optptr;
-				break;
+				goto error;
 			}
 			if (!skb) 
 			{
 				if (optptr[2] != 4 || optlen < 7 || ((optlen-3) & 3)) 
 				{
 					pp_ptr = optptr + 1;
-					break;
+					goto error;
 				}
 				memcpy(&opt->faddr, &optptr[3], 4);
 				if (optlen > 7)
@@ -317,24 +317,24 @@
 			if (opt->rr) 
 			{
 				pp_ptr = optptr;
-				break;
+				goto error;
 			}
 			if (optlen < 3) 
 			{
 				pp_ptr = optptr + 1;
-				break;
+				goto error;
 			}
 			if (optptr[2] < 4) 
 			{
 				pp_ptr = optptr + 2;
-				break;
+				goto error;
 			}
 			if (optptr[2] <= optlen) 
 			{
 				if (optptr[2]+3 > optlen) 
 				{
 					pp_ptr = optptr + 2;
-					break;
+					goto error;
 				}
 				if (skb) 
 				{
@@ -350,17 +350,17 @@
 			if (opt->ts) 
 			{
 				pp_ptr = optptr;
-				break;
+				goto error;
 			}
 			if (optlen < 4) 
 			{
 				pp_ptr = optptr + 1;
-				break;
+				goto error;
 			}
 			if (optptr[2] < 5) 
 			{
 				pp_ptr = optptr + 2;
-				break;
+				goto error;
 			}
 			if (optptr[2] <= optlen) 
 			{
@@ -369,7 +369,7 @@
 				if (ts->ptr+3 > ts->len) 
 				{
 					pp_ptr = optptr + 2;
-					break;
+					goto error;
 				}
 				switch (ts->flags) 
 				{
@@ -384,7 +384,7 @@
 					if (ts->ptr+7 > ts->len) 
 					{
 						pp_ptr = optptr + 2;
-						break;
+						goto error;
 					}
 					opt->ts = optptr - iph;
 					if (skb) 
@@ -400,7 +400,7 @@
 					if (ts->ptr+7 > ts->len) 
 					{
 						pp_ptr = optptr + 2;
-						break;
+						goto error;
 					}
 					opt->ts = optptr - iph;
 					{
@@ -417,7 +417,7 @@
 					break;
 				      default:
 					pp_ptr = optptr + 3;
-					break;
+					goto error;
 				}
 				if (timeptr) 
 				{
@@ -435,7 +435,7 @@
 				if (ts->overflow == 15) 
 				{
 					pp_ptr = optptr + 3;
-					break;
+					goto error;
 				}
 				opt->ts = optptr - iph;
 				if (skb) 
@@ -451,7 +451,7 @@
 			if (!skb) 
 			{
 				pp_ptr = optptr;
-				break;
+				goto error;
 			}
 			break;
 		}
@@ -463,6 +463,7 @@
 	if (!pp_ptr)
 		return 0;
 
+error:
 	if (skb) 
 	{
 		icmp_send(skb, ICMP_PARAMETERPROB, 0, pp_ptr-iph, skb->dev);
diff -u --recursive --new-file v1.3.90/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- v1.3.90/linux/net/ipv4/ip_output.c	Fri Apr 12 15:52:12 1996
+++ linux/net/ipv4/ip_output.c	Thu Apr 18 14:35:34 1996
@@ -137,7 +137,7 @@
 #endif
 			skb->arp = 0;
 			skb->raddr = daddr;
-			return -dev->hard_header_len;
+			return dev->hard_header_len;
 		}
 		mac = dev->hard_header(skb, dev, ETH_P_IP, NULL, NULL, len);
 		if (mac < 0)
diff -u --recursive --new-file v1.3.90/linux/net/ipv4/raw.c linux/net/ipv4/raw.c
--- v1.3.90/linux/net/ipv4/raw.c	Sun Mar 10 09:28:57 1996
+++ linux/net/ipv4/raw.c	Thu Apr 18 13:17:03 1996
@@ -109,6 +109,33 @@
 	return;
 }
 
+static inline void raw_rcv_skb(struct sock * sk, struct sk_buff * skb)
+{
+	/* Charge it to the socket. */
+	
+	if (sock_queue_rcv_skb(sk,skb)<0)
+	{
+		ip_statistics.IpInDiscards++;
+		skb->sk=NULL;
+		kfree_skb(skb, FREE_READ);
+		return;
+	}
+
+	ip_statistics.IpInDelivers++;
+}
+
+/*
+ * This is the prot->rcv() function. It's called when we have
+ * backlogged packets from core/sock.c if we couldn't receive it
+ * when the packet arrived.
+ */
+static int raw_rcv_redo(struct sk_buff *skb, struct device *dev, struct options *opt,
+	__u32 daddr, unsigned short len,
+	__u32 saddr, int redo, struct inet_protocol * protocol)
+{
+	raw_rcv_skb(skb->sk, skb);
+	return 0;
+}
 
 /*
  *	This should be the easiest of all, all we do is
@@ -137,17 +164,11 @@
 		skb->ip_hdr->tot_len=ntohs(skb->ip_hdr->tot_len-4*skb->ip_hdr->ihl);
 #endif
 	
-	/* Charge it to the socket. */
-	
-	if(sock_queue_rcv_skb(sk,skb)<0)
-	{
-		ip_statistics.IpInDiscards++;
-		skb->sk=NULL;
-		kfree_skb(skb, FREE_READ);
-		return(0);
+	if (sk->users) {
+		__skb_queue_tail(&sk->back_log, skb);
+		return 0;
 	}
-
-	ip_statistics.IpInDelivers++;
+	raw_rcv_skb(sk, skb);
 	return 0;
 }
 
@@ -357,7 +378,7 @@
 	NULL,
 	NULL,
 	NULL,
-	NULL,
+	raw_rcv_redo,
 	datagram_select,
 #ifdef CONFIG_IP_MROUTE	
 	ipmr_ioctl,
diff -u --recursive --new-file v1.3.90/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v1.3.90/linux/net/ipv4/tcp_input.c	Wed Apr 17 09:06:33 1996
+++ linux/net/ipv4/tcp_input.c	Thu Apr 18 14:10:41 1996
@@ -92,14 +92,20 @@
 	 */
 	
 	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 */
+	if (sk->rtt != 0) {
+		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 */
+	} else {
+		/* no previous measure. */
+		sk->rtt = m<<3;		/* take the measured time to be rtt */
+		sk->mdev = m<<2;	/* make sure rto = 3*rtt */
+	}
 
 	/*
 	 *	Now update timeout.  Note that this removes any backoff.
@@ -714,7 +720,7 @@
 	 * (2) it has the same window as the last ACK,
 	 * (3) we have outstanding data that has not been ACKed
 	 * (4) The packet was not carrying any data.
-	 * I've tried to order these in occurance of most likely to fail
+	 * I've tried to order these in occurrence of most likely to fail
 	 * to least likely to fail.
 	 * [These are the rules BSD stacks use to determine if an ACK is a
 	 *  duplicate.]
diff -u --recursive --new-file v1.3.90/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v1.3.90/linux/net/ipv4/udp.c	Fri Apr 12 15:52:12 1996
+++ linux/net/ipv4/udp.c	Thu Apr 18 12:50:04 1996
@@ -135,8 +135,6 @@
 	restore_flags(flags);
 }
 
-static int udp_deliver(struct sock *sk, struct udphdr *uh, struct sk_buff *skb, struct device *dev, long saddr, long daddr, int len);
-
 #define min(a,b)	((a)<(b)?(a):(b))
 
 
@@ -583,6 +581,37 @@
 	destroy_sock(sk);
 }
 
+static inline void udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
+{
+	/*
+	 *	Charge it to the socket, dropping if the queue is full.
+	 */
+
+	/* I assume this includes the IP options, as per RFC1122 (4.1.3.2). */
+	/* If not, please let me know. -- MS */
+
+	if (sock_queue_rcv_skb(sk,skb)<0) {
+		udp_statistics.UdpInErrors++;
+		ip_statistics.IpInDiscards++;
+		ip_statistics.IpInDelivers--;
+		skb->sk = NULL;
+		kfree_skb(skb, FREE_WRITE);
+		return;
+	}
+	udp_statistics.UdpInDatagrams++;
+}
+
+
+static inline void udp_deliver(struct sock *sk, struct sk_buff *skb)
+{
+	skb->sk = sk;
+
+	if (sk->users) {
+		__skb_queue_tail(&sk->back_log, skb);
+		return;
+	}
+	udp_queue_rcv_skb(sk, skb);
+}
 
 /*
  *	All we need to do is get the socket, and then do a checksum. 
@@ -595,8 +624,23 @@
   	struct sock *sk;
   	struct udphdr *uh;
 	unsigned short ulen;
-	int addr_type = IS_MYADDR;
-	
+	int addr_type;
+
+	/*
+	 * If we're doing a "redo" (the socket was busy last time
+	 * around), we can just queue the packet now..
+	 */
+	if (redo) {
+		udp_queue_rcv_skb(skb->sk, skb);
+		return 0;
+	}
+
+	/*
+	 * First time through the loop.. Do all the setup stuff
+	 * (including finding out the socket we go to etc)
+	 */
+
+	addr_type = IS_MYADDR;
 	if(!dev || dev->pa_addr!=daddr)
 		addr_type=ip_chk_addr(daddr);
 		
@@ -651,9 +695,18 @@
 		return(0);
 	}
 
+	/*
+	 *	These are supposed to be switched. 
+	 */
+	 
+	skb->daddr = saddr;
+	skb->saddr = daddr;
 
 	len=ulen;
 
+	skb->dev = dev;
+	skb_trim(skb,len);
+
 #ifdef CONFIG_IP_MULTICAST
 	if (addr_type!=IS_MYADDR)
 	{
@@ -675,7 +728,7 @@
 				else
 					skb1=skb;
 				if(skb1)
-					udp_deliver(sk, uh, skb1, dev,saddr,daddr,len);
+					udp_deliver(sk, skb1);
 				sk=sknext;
 			}
 			while(sknext!=NULL);
@@ -712,43 +765,9 @@
 		kfree_skb(skb, FREE_WRITE);
 		return(0);
   	}
-	return udp_deliver(sk,uh,skb,dev, saddr, daddr, len);
-}
-
-static int udp_deliver(struct sock *sk, struct udphdr *uh, struct sk_buff *skb, struct device *dev, long saddr, long daddr, int len)
-{
-	skb->sk = sk;
-	skb->dev = dev;
-	skb_trim(skb,len);
-
-	/*
-	 *	These are supposed to be switched. 
-	 */
-	 
-	skb->daddr = saddr;
-	skb->saddr = daddr;
-
-
-	/*
-	 *	Charge it to the socket, dropping if the queue is full.
-	 */
-
-	/* I assume this includes the IP options, as per RFC1122 (4.1.3.2). */
-	/* If not, please let me know. -- MS */
-
-	if (sock_queue_rcv_skb(sk,skb)<0) 
-	{
-		udp_statistics.UdpInErrors++;
-		ip_statistics.IpInDiscards++;
-		ip_statistics.IpInDelivers--;
-		skb->sk = NULL;
-		kfree_skb(skb, FREE_WRITE);
-		return(0);
-	}
-  	udp_statistics.UdpInDatagrams++;
-	return(0);
+	udp_deliver(sk, skb);
+	return 0;
 }
-
 
 struct proto udp_prot = {
 	udp_close,
diff -u --recursive --new-file v1.3.90/linux/net/ipv6/README linux/net/ipv6/README
--- v1.3.90/linux/net/ipv6/README	Thu Jan  1 02:00:00 1970
+++ linux/net/ipv6/README	Thu Apr 18 14:35:34 1996
@@ -0,0 +1,4 @@
+To join in the work on Linux IPv6 join the majordomo managed mailing list
+		"netdev@nuclecu.unam.mx"
+
+Alan
diff -u --recursive --new-file v1.3.90/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v1.3.90/linux/net/netrom/af_netrom.c	Fri Apr 12 15:52:13 1996
+++ linux/net/netrom/af_netrom.c	Thu Apr 18 14:35:34 1996
@@ -282,6 +282,82 @@
 	return -EINVAL;
 }
 
+/*
+ * dl1bke 960311: set parameters for existing NET/ROM connections,
+ *		  includes a KILL command to abort any connection.
+ *		  VERY useful for debugging ;-)
+ */
+static int nr_ctl_ioctl(const unsigned int cmd, void *arg)
+{
+	struct nr_ctl_struct nr_ctl;
+	struct sock *sk;
+	unsigned long flags;
+	int err;
+	
+	if ((err = verify_area(VERIFY_READ, arg, sizeof(nr_ctl))) != 0)
+		return err;
+
+	memcpy_fromfs(&nr_ctl, arg, sizeof(nr_ctl));
+	
+	if ((sk = nr_find_socket(nr_ctl.index, nr_ctl.id)) == NULL)
+		return -ENOTCONN;
+
+	switch (nr_ctl.cmd) {
+		case NETROM_KILL:
+			nr_clear_queues(sk);
+			nr_write_internal(sk, NR_DISCREQ);
+			sk->nr->state = NR_STATE_0;
+			sk->state = TCP_CLOSE;
+			sk->err   = ENETRESET;
+			if (!sk->dead)
+				sk->state_change(sk);
+			sk->dead  = 1;
+			nr_set_timer(sk);
+	  		break;
+
+	  	case NETROM_T1:
+  			if (nr_ctl.arg < 1) 
+  				return -EINVAL;
+  			sk->nr->rtt = (nr_ctl.arg * PR_SLOWHZ) / 2;
+  			sk->nr->t1 = nr_ctl.arg * PR_SLOWHZ;
+  			save_flags(flags); cli();
+  			if (sk->nr->t1timer > sk->nr->t1)
+  				sk->nr->t1timer = sk->nr->t1;
+  			restore_flags(flags);
+  			break;
+
+	  	case NETROM_T2:
+	  		if (nr_ctl.arg < 1) 
+	  			return -EINVAL;
+	  		save_flags(flags); cli();
+	  		sk->nr->t2 = nr_ctl.arg * PR_SLOWHZ;
+	  		if (sk->nr->t2timer > sk->nr->t2)
+	  			sk->nr->t2timer = sk->nr->t2;
+	  		restore_flags(flags);
+	  		break;
+
+	  	case NETROM_N2:
+	  		if (nr_ctl.arg < 1 || nr_ctl.arg > 10) 
+	  			return -EINVAL;
+	  		sk->nr->n2count = 0;
+	  		sk->nr->n2 = nr_ctl.arg;
+	  		break;
+
+	  	case NETROM_PACLEN:
+	  		if (nr_ctl.arg < 16 || nr_ctl.arg > 65535) 
+	  			return -EINVAL;
+	  		if (nr_ctl.arg > 236) /* we probably want this */
+	  			printk("nr_ctl_ioctl: Warning --- huge paclen %d\n", (int)nr_ctl.arg);
+	  		sk->nr->paclen = nr_ctl.arg;
+	  		break;
+
+	  	default:
+	  		return -EINVAL;
+	  }
+	  
+	  return 0;
+}
+
 static int nr_setsockopt(struct socket *sock, int level, int optname,
 	char *optval, int optlen)
 {
@@ -326,6 +402,12 @@
 		case NETROM_HDRINCL:
 			sk->nr->hdrincl = opt ? 1 : 0;
 			return 0;
+
+		case NETROM_PACLEN:
+			if (opt < 1 || opt > 65536)
+				return -EINVAL;
+			sk->nr->paclen = opt;
+			return 0;
 			
 		default:
 			return -ENOPROTOOPT;
@@ -364,6 +446,10 @@
 			val = sk->nr->hdrincl;
 			break;
 
+		case NETROM_PACLEN:
+			val = sk->nr->paclen;
+			break;
+
 		default:
 			return -ENOPROTOOPT;
 	}
@@ -461,6 +547,7 @@
 	nr->t1       = nr_default.timeout;
 	nr->t2       = nr_default.ack_delay;
 	nr->n2       = nr_default.tries;
+	nr->paclen   = nr_default.paclen;
 
 	nr->t1timer  = 0;
 	nr->t2timer  = 0;
@@ -542,6 +629,7 @@
 	nr->t1       = osk->nr->t1;
 	nr->t2       = osk->nr->t2;
 	nr->n2       = osk->nr->n2;
+	nr->paclen   = osk->nr->paclen;
 
 	nr->device   = osk->nr->device;
 	nr->bpqext   = osk->nr->bpqext;
@@ -1216,12 +1304,16 @@
 			return 0;
 		}
 		
-		default:
+ 		case SIOCNRCTLCON:
+ 			if (!suser()) return -EPERM;
+ 			return nr_ctl_ioctl(cmd, (void *)arg);
+ 
+ 		default:
 			return dev_ioctl(cmd, (void *)arg);
 	}
 
 	/*NOTREACHED*/
-	return(0);
+	return 0;
 }
 
 static int nr_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
@@ -1235,7 +1327,7 @@
   
 	cli();
 
-	len += sprintf(buffer, "user_addr dest_node src_node  dev    my  your  st vs vr va    t1     t2    n2  rtt wnd Snd-Q Rcv-Q\n");
+	len += sprintf(buffer, "user_addr dest_node src_node  dev    my  your  st vs vr va    t1     t2    n2  rtt wnd paclen Snd-Q Rcv-Q\n");
 
 	for (s = nr_list; s != NULL; s = s->next) {
 		if ((dev = s->nr->device) == NULL)
@@ -1247,7 +1339,7 @@
 			ax2asc(&s->nr->user_addr));
 		len += sprintf(buffer + len, "%-9s ",
 			ax2asc(&s->nr->dest_addr));
-		len += sprintf(buffer + len, "%-9s %-3s  %02X/%02X %02X/%02X %2d %2d %2d %2d %3d/%03d %2d/%02d %2d/%02d %3d %3d %5d %5d\n",
+		len += sprintf(buffer + len, "%-9s %-3s  %02X/%02X %02X/%02X %2d %2d %2d %2d %3d/%03d %2d/%02d %2d/%02d %3d %3d %6d %5d %5d\n",
 			ax2asc(&s->nr->source_addr),
 			devname, s->nr->my_index, s->nr->my_id,
 			s->nr->your_index, s->nr->your_id,
@@ -1259,7 +1351,7 @@
 			s->nr->t2      / PR_SLOWHZ,
 			s->nr->n2count, s->nr->n2,
 			s->nr->rtt     / PR_SLOWHZ,
-			s->window,
+			s->window, s->nr->paclen,
 			s->wmem_alloc, s->rmem_alloc);
 		
 		pos = begin + len;
@@ -1324,6 +1416,7 @@
 	nr_default.busy_delay = NR_DEFAULT_T4;
 	nr_default.tries      = NR_DEFAULT_N2;
 	nr_default.window     = NR_DEFAULT_WINDOW;
+	nr_default.paclen     = NR_DEFAULT_PACLEN;
 
 	proc_net_register(&(struct proc_dir_entry) {
 		PROC_NET_NR, 2, "nr",
diff -u --recursive --new-file v1.3.90/linux/net/netrom/nr_dev.c linux/net/netrom/nr_dev.c
--- v1.3.90/linux/net/netrom/nr_dev.c	Mon Mar 25 08:58:26 1996
+++ linux/net/netrom/nr_dev.c	Thu Apr 18 14:35:34 1996
@@ -15,6 +15,8 @@
  *	History
  *	NET/ROM 001	Jonathan(G4KLX)	Cloned from loopback.c
  *	NET/ROM 002	Steve Whitehouse(GW7RRM) fixed the set_mac_address
+ *	NET/ROM 003	Jonathan(G4KLX)	Put nr_rebuild_header into line with
+ *					ax25_rebuild_header
  */
 
 #include <linux/config.h>
@@ -109,12 +111,10 @@
 {
 	struct enet_statistics *stats = (struct enet_statistics *)dev->priv;
 	unsigned char *bp = (unsigned char *)buff;
-
-	skb_device_unlock(skb);
+	struct sk_buff *skbn;
 
 	if (!arp_query(bp + 7, raddr, dev)) {
-		skb->free = 1;
-		kfree_skb(skb, FREE_WRITE);
+		dev_kfree_skb(skb, FREE_WRITE);
 		return 1;
 	}
 
@@ -127,9 +127,20 @@
 	bp[6] |= LAPB_E;
 	bp[6] |= SSSID_SPARE;
 
-	if (!nr_route_frame(skb, NULL)) {
-		skb->free = 1;
-		kfree_skb(skb, FREE_WRITE);
+	if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
+		dev_kfree_skb(skb, FREE_WRITE);
+		return 1;
+	}
+
+	skbn->sk = skb->sk;
+	
+	if (skbn->sk != NULL)
+		atomic_add(skbn->truesize, &skbn->sk->wmem_alloc);
+
+	dev_kfree_skb(skb, FREE_WRITE);
+
+	if (!nr_route_frame(skbn, NULL)) {
+		dev_kfree_skb(skbn, FREE_WRITE);
 		stats->tx_errors++;
 	}
 
diff -u --recursive --new-file v1.3.90/linux/net/netrom/nr_out.c linux/net/netrom/nr_out.c
--- v1.3.90/linux/net/netrom/nr_out.c	Wed Feb 21 08:33:26 1996
+++ linux/net/netrom/nr_out.c	Thu Apr 18 14:35:34 1996
@@ -52,7 +52,7 @@
 	unsigned char transport[NR_TRANSPORT_LEN];
 	int err, frontlen, len, mtu;
 
-	mtu = sk->nr->device->mtu;
+	mtu = sk->nr->paclen;
 	
 	if (skb->len - NR_TRANSPORT_LEN > mtu) {
 		/* Save a copy of the Transport Header */
diff -u --recursive --new-file v1.3.90/linux/scripts/Menuconfig linux/scripts/Menuconfig
--- v1.3.90/linux/scripts/Menuconfig	Fri Apr 12 15:52:13 1996
+++ linux/scripts/Menuconfig	Thu Apr 18 14:38:54 1996
@@ -82,7 +82,7 @@
 	n)	flag=" " ;;
 	esac
 
-	echo -ne "'$2' '($flag) $1' " >>MCmenu
+	echo -ne "'$2' '[$flag] $1' " >>MCmenu
 
 	echo -e "function $2 () { l_bool '$2' \"\$1\" }\n" >>MCradiolists
 }
@@ -245,10 +245,10 @@
 	if extract_help $1 >help.out
 	then
 		$DIALOG	--backtitle "$backtitle" --title "$2"\
-			--textbox help.out $LINES $COLS
+			--textbox help.out $ROWS $COLS
 	else
 		$DIALOG	--backtitle "$backtitle" \
-			--textbox help.out $LINES $COLS
+			--textbox help.out $ROWS $COLS
 	fi
 	rm help.out
 }
@@ -258,7 +258,7 @@
 #
 function show_readme () {
 	$DIALOG --backtitle "$backtitle" \
-		--textbox scripts/README.Menuconfig $LINES $COLS
+		--textbox scripts/README.Menuconfig $ROWS $COLS
 }
 
 #
@@ -269,7 +269,7 @@
 	echo -ne "$DIALOG --title '$1'\
 			--backtitle '$backtitle' \
 			--menu '$menu_instructions' \
-			$LINES $COLS $((LINES-10)) \
+			$ROWS $COLS $((ROWS-10)) \
 			'$default' " >MCmenu
 	>MCradiolists
 }
@@ -306,6 +306,11 @@
 	then
 		case "$2" in
 		y|m)	eval $1=y ;;
+		c)	eval x=\$$1
+		   	case $x in
+		   	y) eval $1=n ;;
+		   	n) eval $1=y ;;
+		   	esac ;;
 		*)	eval $1=n ;;
 		esac
 	else
@@ -336,7 +341,19 @@
 	if [ -n "$2" ]
 	then
 		case "$2" in
-		y|m)	eval $1=m ;;
+		y)	echo -en "\007"
+			${DIALOG} --backtitle "$backtitle" \
+				  --infobox "\
+This feature depends on another which has been configured as a module.  \
+As a result, this feature will be built as a module." 4 70
+			sleep 5
+			eval $1=m ;;
+		m)	eval $1=m ;;
+		c)	eval x=\$$1
+			case $x in
+			m) eval $1=n ;;
+			n) eval $1=m ;;
+			esac ;;
 		*)	eval $1=n ;;
 		esac
 	else
@@ -350,9 +367,17 @@
 function l_tristate () {
 	if [ -n "$2" ]
 	then
+		eval x=\$$1
+
 		case "$2" in
 		y) eval $1=y ;;
 		m) eval $1=m ;;
+		c) eval x=\$$1
+		   case $x in
+		   y) eval $1=n ;;
+		   n) eval $1=m ;;
+		   m) eval $1=y ;;
+		   esac ;;
 		*) eval $1=n ;;
 		esac
 	else
@@ -628,18 +653,19 @@
 		read selection <MCdialog.out
 
 		case "$ret" in
-		0|3|4|5)
+		0|3|4|5|6)
 			defaults="$selection$defaults"  #pseudo stack
 			case "$ret" in
 			0) eval $selection   ;;
 			3) eval $selection y ;;
 			4) eval $selection n ;;
 			5) eval $selection m ;;
+			6) eval $selection c ;;
 			esac
 			default="${defaults%%*}" defaults="${defaults#*}"
 			;;
 		2)	
-			default="${selection%% *}"
+			default="${selection%%\ *}"
 
 			case "$selection" in
 			*"-->"*|*"alt_config"*)
@@ -711,7 +737,7 @@
 EOM
 			$DIALOG	--backtitle "$backtitle"\
 				--title "Load Alternate Configuration"\
-				--textbox help.out $LINES $COLS
+				--textbox help.out $ROWS $COLS
 		fi
 	done
 
@@ -771,7 +797,7 @@
 EOM
 			$DIALOG	--backtitle "$backtitle"\
 				--title "Store Alternate Configuration"\
-				--textbox help.out $LINES $COLS
+				--textbox help.out $ROWS $COLS
 		fi
 	done
 
@@ -991,35 +1017,38 @@
 	rm -f .tmpconfig .tmpconfig.h
 }
 
-x=`stty -a`
-case $x in
-*\ rows\ *\;*)
-	LINES=${x##*rows}    LINES=${LINES%%;*} LINES=$((${LINES:-25}-4))
-	COLS=${x##*columns}  COLS=${COLS%%;*}   COLS=$((${COLS:-80}-5))
-	;;
-*)
-	LINES=21
-	COLS=75
-	;;
-esac
-
-if [ $LINES -lt 15 -o $COLS -lt 75 ]
-then
-	echo -e "\n\007Your display is too small to run Menuconfig!\n"
-	echo "It is currently set to $LINES lines by $COLS columns."
-	echo "It must be at least 15 lines by 75 columns."
-	exit 0
-fi
+set_geometry () {
+	# Some distributions export these with incorrect values
+	# which can really screw up some ncurses programs.
+	unset LINES COLUMNS
+
+	ROWS=${1:-24}  COLS=${2:-80} 
+
+	# Just in case the nasty rlogin bug returns.
+	#
+	[ $ROWS = 0 ] && ROWS=24
+	[ $COLS = 0 ] && COLS=80
+
+	if [ $ROWS -lt 19 -o $COLS -lt 80 ]
+	then
+		echo -e "\n\007Your display is too small to run Menuconfig!"
+		echo "It must be at least 19 lines by 80 columns."
+		exit 0
+	fi 
+
+	ROWS=$((ROWS-4))  COLS=$((COLS-5))
+}
+
 
+set_geometry `stty size 2>/dev/null`
 
 menu_instructions="\
 Arrow keys navigate the menu.  \
+<Enter> selects submenus --->.  \
 Highlighted letters are hotkeys.  \
-Pressing <Y> includes a feature, <N> excludes it, <M> makes it modular.  \
-Press <Esc><Esc> to exit or <?> for Help.  \
-(*) shows built in features.  \
-(M) shows modules.  \
-< > features are module capable."
+Pressing <Y> includes, <N> excludes, <M> modularizes features.  \
+Press <Esc><Esc> to exit, <?> for Help.  \
+Legend: [*] built-in  [ ] excluded  <M> module  < > module capable"
 
 radiolist_instructions="\
 Use the arrow keys to navigate this window or \
diff -u --recursive --new-file v1.3.90/linux/scripts/README.Menuconfig linux/scripts/README.Menuconfig
--- v1.3.90/linux/scripts/README.Menuconfig	Fri Apr 12 15:52:13 1996
+++ linux/scripts/README.Menuconfig	Thu Apr 18 14:38:54 1996
@@ -11,27 +11,28 @@
 kernel parameters which are not really features, but must be 
 entered in as decimal or hexadecimal numbers or possibly text.
 
-Menu items beginning with (*), (M) or ( ) represent features 
+Menu items beginning with [*], <M> or [ ] represent features 
 configured to be built in, modularized or removed respectively.
 Pointed brackets <> represent module capable features.
                                                              more...
 
 To change any of these features, highlight it with the cursor 
 keys and press <Y> to build it in, <M> to make it a module or
-<N> to removed it.  (See keyboard hints below)
+<N> to removed it.  You may also press the <Space Bar> to cycle
+through the available options (ie. Y->N->M->Y). 
 
 Items beginning with numbers or other text within parenthesis can 
 be changed by highlighting the item and pressing <Enter>.  Then
 enter the new parameter into the dialog box that pops up.
 
 
-Some keyboard hints:
+Some additional keyboard hints:
 
 Menus
 ----------
 o  Use the Up/Down arrow keys (cursor keys) to highlight the item 
-   you wish to change or submenu wish to select.  Submenus are
-   designated by "--->".
+   you wish to change or submenu wish to select and press <Enter>.
+   Submenus are designated by "--->".
 
    Shortcut: Press the option's highlighted letter (hotkey).
              Pressing a hotkey more than once will sequence
@@ -136,8 +137,13 @@
 
 Menuconfig will display larger menus on screens or xterms which are
 set to display more than the standard 25 row by 80 column geometry.
-In order for this to work, the "stty -a" command must be able to 
-display the screen's current row and column geometry.
+In order for this to work, the "stty size" command must be able to 
+display the screen's current row and column geometry.  I STRONGLY
+RECOMMEND that you make sure you do NOT have the shell variables
+LINES and COLUMNS exported into your environment.  Some distributions
+export those variables via /etc/profile.  Some ncurses programs can
+become confused when those variables (LINES & COLUMNS) don't reflect
+the true screen size.
 
 
 NOTICE:  lxdialog requires the ncurses libraries to compile.  If you
diff -u --recursive --new-file v1.3.90/linux/scripts/lxdialog/dialog.h linux/scripts/lxdialog/dialog.h
--- v1.3.90/linux/scripts/lxdialog/dialog.h	Fri Apr 12 15:52:13 1996
+++ linux/scripts/lxdialog/dialog.h	Thu Apr 18 14:38:54 1996
@@ -131,7 +131,7 @@
 		chtype border);
 void draw_shadow (WINDOW * win, int y, int x, int height, int width);
 
-int first_alpha (const char *string);
+int first_alpha (const char *string, const char *exempt);
 int dialog_yesno (const char *title, const char *prompt, int height, int width);
 int dialog_msgbox (const char *title, const char *prompt, int height,
 		int width, int pause);
@@ -145,8 +145,6 @@
 extern unsigned char dialog_input_result[];
 int dialog_inputbox (const char *title, const char *prompt, int height,
 		int width, const char *init);
-int dialog_gauge (const char *title, const char *prompt, int height, int width,
-		int percent);
 
 /*
  * This is the base for fictitious keys, which activate
diff -u --recursive --new-file v1.3.90/linux/scripts/lxdialog/menubox.c linux/scripts/lxdialog/menubox.c
--- v1.3.90/linux/scripts/lxdialog/menubox.c	Wed Mar 27 08:19:29 1996
+++ linux/scripts/lxdialog/menubox.c	Thu Apr 18 14:38:54 1996
@@ -34,7 +34,7 @@
 
     strncpy(menu_item, item, menu_width);
     menu_item[menu_width] = 0;
-    j = first_alpha(menu_item);
+    j = first_alpha(menu_item, "YyNnMm");
 
     /* Clear 'residue' of last item */
     wattrset (win, menubox_attr);
@@ -205,13 +205,13 @@
 		i = max_choice;
 	else {
         for (i = choice+1; i < max_choice; i++) {
-		j = first_alpha(items[(scroll+i)*2+1]);
+		j = first_alpha(items[(scroll+i)*2+1], "YyNnMm");
 		if (key == tolower(items[(scroll+i)*2+1][j]))
                 	break;
 	}
 	if (i == max_choice)
        		for (i = 0; i < max_choice; i++) {
-			j = first_alpha(items[(scroll+i)*2+1]);
+			j = first_alpha(items[(scroll+i)*2+1], "YyNnMm");
 			if (key == tolower(items[(scroll+i)*2+1][j]))
                 		break;
 		}
@@ -308,15 +308,20 @@
 	    print_buttons(dialog, height, width, button);
 	    wrefresh (dialog);
 	    break;
+	case ' ':
 	case 's':
 	case 'y':
 	case 'n':
 	case 'm':
 	    delwin (dialog);
             fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
-            if (key == 'y') return 3;
-            if (key == 'n') return 4;
-            if (key == 'm') return 5;
+            switch (key) {
+            case 's': return 3;
+            case 'y': return 3;
+            case 'n': return 4;
+            case 'm': return 5;
+            case ' ': return 6;
+            }
 	    return 0;
 	case 'h':
 	case '?':
@@ -327,7 +332,7 @@
             	fprintf(stderr, "%s \"%s\"\n", 
 			items[(scroll + choice) * 2],
 			items[(scroll + choice) * 2 + 1] +
-			first_alpha(items[(scroll + choice) * 2 + 1]));
+			first_alpha(items[(scroll + choice) * 2 + 1],""));
 	    else
             	fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
 
diff -u --recursive --new-file v1.3.90/linux/scripts/lxdialog/util.c linux/scripts/lxdialog/util.c
--- v1.3.90/linux/scripts/lxdialog/util.c	Wed Mar 27 08:19:29 1996
+++ linux/scripts/lxdialog/util.c	Thu Apr 18 14:38:54 1996
@@ -36,33 +36,33 @@
 {
     A_NORMAL,			/* screen_attr */
     A_NORMAL,			/* shadow_attr */
-    A_REVERSE,			/* dialog_attr */
-    A_REVERSE,			/* title_attr */
-    A_REVERSE,			/* border_attr */
-    A_BOLD,			/* button_active_attr */
+    A_NORMAL,			/* dialog_attr */
+    A_BOLD,			/* title_attr */
+    A_NORMAL,			/* border_attr */
+    A_REVERSE,			/* button_active_attr */
     A_DIM,			/* button_inactive_attr */
-    A_UNDERLINE,		/* button_key_active_attr */
-    A_UNDERLINE,		/* button_key_inactive_attr */
-    A_NORMAL,			/* button_label_active_attr */
+    A_REVERSE,			/* button_key_active_attr */
+    A_BOLD,			/* button_key_inactive_attr */
+    A_REVERSE,			/* button_label_active_attr */
     A_NORMAL,			/* button_label_inactive_attr */
-    A_REVERSE,			/* inputbox_attr */
-    A_REVERSE,			/* inputbox_border_attr */
-    A_REVERSE,			/* searchbox_attr */
-    A_REVERSE,			/* searchbox_title_attr */
-    A_REVERSE,			/* searchbox_border_attr */
-    A_REVERSE,			/* position_indicator_attr */
-    A_REVERSE,			/* menubox_attr */
-    A_REVERSE,			/* menubox_border_attr */
-    A_REVERSE,			/* item_attr */
-    A_NORMAL,			/* item_selected_attr */
-    A_REVERSE,			/* tag_attr */
+    A_NORMAL,			/* inputbox_attr */
+    A_NORMAL,			/* inputbox_border_attr */
+    A_NORMAL,			/* searchbox_attr */
+    A_BOLD,			/* searchbox_title_attr */
+    A_NORMAL,			/* searchbox_border_attr */
+    A_BOLD,			/* position_indicator_attr */
+    A_NORMAL,			/* menubox_attr */
+    A_NORMAL,			/* menubox_border_attr */
+    A_NORMAL,			/* item_attr */
+    A_REVERSE,			/* item_selected_attr */
+    A_BOLD,			/* tag_attr */
     A_REVERSE,			/* tag_selected_attr */
-    A_NORMAL,			/* tag_key_attr */
-    A_BOLD,			/* tag_key_selected_attr */
-    A_REVERSE,			/* check_attr */
+    A_BOLD,			/* tag_key_attr */
+    A_REVERSE,			/* tag_key_selected_attr */
+    A_BOLD,			/* check_attr */
     A_REVERSE,			/* check_selected_attr */
-    A_REVERSE,			/* uarrow_attr */
-    A_REVERSE			/* darrow_attr */
+    A_BOLD,			/* uarrow_attr */
+    A_BOLD			/* darrow_attr */
 };
 
 
@@ -340,7 +340,7 @@
  *  Return the position of the first alphabetic character in a string.
  */
 int
-first_alpha(const char *string)
+first_alpha(const char *string, const char *exempt)
 {
 	int i, in_paren=0, c;
 
@@ -351,7 +351,7 @@
 		if (c == ')') --in_paren;
 
 		if ((! in_paren) && isalpha(c) && 
-		     strchr("nNyYmM", c) == 0)
+		     strchr(exempt, c) == 0)
 			return i;
 	}
 
