## Automatically generated incremental diff
## From:   linux-2.2.5-pre2
## To:     linux-2.2.5
## Robot:  $Id: make-incremental-diff,v 1.5 2001/12/01 08:32:36 hpa Exp $

diff -urN linux-2.2.5-pre2/Documentation/stallion.txt linux/Documentation/stallion.txt
--- linux-2.2.5-pre2/Documentation/stallion.txt	Fri Oct 23 08:26:03 1998
+++ linux/Documentation/stallion.txt	Mon Dec  3 18:36:42 2001
@@ -2,10 +2,10 @@
 Stallion Multiport Serial Driver Readme
 ---------------------------------------
 
-Copyright (C) 1994-1998,  Stallion Technologies (support@stallion.com).
+Copyright (C) 1994-1999,  Stallion Technologies (support@stallion.com).
 
-Version:   5.4.7
-Date:      23OCT98
+Version:   5.5.1
+Date:      28MAR99
 
 
 
@@ -15,28 +15,28 @@
 multiport serial boards. One is for the Stallion smart boards - that is
 EasyIO, EasyConnection 8/32 and EasyConnection 8/64-PCI, the other for
 the true Stallion intelligent multiport boards - EasyConnection 8/64
-(ISA and EISA), ONboard and Brumby.
+(ISA, EISA, MCA), EasyConnection/RA-PCI, ONboard and Brumby.
 
 If you are using any of the Stallion intelligent multiport boards (Brumby,
-ONboard, EasyConnection 8/64 (ISA or EISA)) with Linux you will need to
-get the driver utility package. This package is available at most of the
-Linux archive sites (and on CD-ROMs that contain these archives). The file
-will be called stallion-X.X.X.tar.gz where X.X.X will be the version
-number. In particular this package contains the board embedded executable
-images that are required for these boards. It also contains the downloader
-program. These boards cannot be used without this.
+ONboard, EasyConnection 8/64 (ISA, EISA, MCA), EasyConnection/RA-PCI) with
+Linux you will need to get the driver utility package. This package is
+available at most of the Linux archive sites (and on CD-ROMs that contain
+these archives). The file will be called stallion-X.X.X.tar.gz where X.X.X
+will be the version number. In particular this package contains the board
+embedded executable images that are required for these boards. It also
+contains the downloader program. These boards cannot be used without this.
 
 The Stallion Technologies ftp site, ftp.stallion.com, will always have
 the latest version of the driver utility package. Other sites that usually
 have the latest version are tsx-11.mit.edu, sunsite.unc.edu and their
 mirrors.
 
-ftp.stallion.com:/drivers/ata5/Linux/v544.tar.gz
-tsx-11.mit.edu:/pub/linux/packages/stallion/stallion-5.4.4.tar.gz
-sunsite.unc.edu:/pub/Linux/kernel/patches/serial/stallion-5.4.4.tar.gz
+ftp.stallion.com:/drivers/ata5/Linux/v550.tar.gz
+tsx-11.mit.edu:/pub/linux/packages/stallion/stallion-5.5.0.tar.gz
+sunsite.unc.edu:/pub/Linux/kernel/patches/serial/stallion-5.5.0.tar.gz
 
 As of the printing of this document the latest version of the driver
-utility package is 5.4.4. If a later version is now available then you
+utility package is 5.5.0. If a later version is now available then you
 should use the latest version.
 
 If you are using the EasyIO, EasyConnection 8/32 or EasyConnection 8/64-PCI
@@ -44,7 +44,7 @@
 script to create the /dev device nodes for these boards, and a serial stats
 display program.
 
-If you require DIP switch settings, EISA/MCA configuration files, or any
+If you require DIP switch settings, EISA or MCA configuration files, or any
 other information related to Stallion boards then have a look at Stallion's
 web pages at http://www.stallion.com.
 
@@ -55,12 +55,101 @@
 The drivers can be used as loadable modules or compiled into the kernel.
 You can choose which when doing a "config" on the kernel.
 
-All ISA, EISA and MCA boards that you want to use need to be entered into
-the driver(s) configuration structures. All PCI boards will be automatically
-detected when you load the driver - so they do not need to be entered into
-the driver(s) configuration structure. (Note that kernel PCI BIOS32 support
-is required to use PCI boards.)
+All ISA, EISA and MCA boards that you want to use need to be configured into
+the driver(s). All PCI boards will be automatically detected when you load
+the driver - so they do not need to be entered into the driver(s)
+configuration structure. Note that kernel PCI support is required to use PCI
+boards.
 
+There are two methods of configuring ISA, EISA and MCA boards into the drivers.
+If using the driver as a loadable module then the simplist method is to pass
+the driver configuration as module arguments. The other method is to modify
+the driver source to add configuration lines for each board in use.
+
+If you have pre-built Stallion driver modules then the module argument
+configuration method should be used. A lot of Linux distributions come with
+pre-built driver modules in /lib/modules/X.Y.Z/misc for the kernel in use.
+That makes things pretty simple to get going.
+
+
+2.1 MODULE DRIVER CONFIGURATION:
+
+The simplest configuration for modules is to use the module load arguments
+to configure any ISA, EISA or MCA boards. PCI boards are automatically
+detected, so do not need any additional configuration at all.
+
+If using EasyIO, EasyConnection 8/32 ISA or MCA, or EasyConnection 8/63-PCI
+boards then use the "stallion" driver module, Otherwise if you are using
+an EasyConnection 8/64 ISA, EISA or MCA, EasyConnection/RA-PCI, ONboard,
+Brumby or original Stallion board then use the "istallion" driver module.
+
+Typically to load up the smart board driver use:
+
+    insmod stallion.o
+
+This will load the EasyIO and EasyConnection 8/32 driver. It will output a
+message to say that it loaded and print the driver version number. It will
+also print out whether it found the configured boards or not. These messages
+may not appear on the console, but typically are always logged to
+/var/adm/messages or /var/log/syslog files - depending on how the klogd and
+syslogd daemons are setup on your system.
+
+To load the intelligent board driver use:
+
+    insmod istallion.o
+
+It will output similar messages to the smart board driver.
+
+If not using an auto-detectable board type (that is a PCI board) then you
+will also need to supply command line arguments to the "insmod" command
+when loading the driver. The general form of the configuration argument is
+
+    board?=<name>[,<ioaddr>[,<addr>][,<irq>]]
+
+where:
+
+    board?  -- specifies the arbitary board number of this board,
+               can be in the range 0 to 3.
+
+    name    -- textual name of this board. The board name is the comman
+               board name, or any "shortened" version of that. The board
+               type number may also be used here.
+
+    ioaddr  -- specifies the I/O address of this board. This argument is
+               optional, but should generally be specified.
+
+    addr    -- optional second address argument. Some board types require
+               a second I/O address, some require a memory address. The
+               exact meaning of this argument depends on the board type.
+
+    irq     -- optional IRQ line used by this board.
+
+Up to 4 board configuration arguments can be specified on the load line.
+Here is some examples:
+
+    insmod stallion.o board0=easyio,0x2a0,5
+
+This configures an EasyIO board as board 0 at I/O address 0x2a0 and IRQ 5.
+
+    insmod istallion.o board3=ec8/64,0x2c0,0xcc000
+
+This configures an EasyConnection 8/64 ISA as board 3 at I/O address 0x2c0 at
+memory address 0xcc000.
+
+    insmod stallion.o board1=ec8/32-at,0x2a0,0x280,10
+
+This configures an EasyConnection 8/32 ISA board at primary I/O address 0x2a0,
+secondary address 0x280 and IRQ 10.
+
+You will probably want to enter this module load and configuration information
+into your system startup scripts so that the drivers are loaded and configured
+on each system boot. Typically the start up script would be something line
+/etc/rc.d/rc.modules.
+
+
+2.2 STATIC DRIVER CONFIGURATION:
+
+For static driver configuration you need to modify the driver source code.
 Entering ISA, EISA and MCA boards into the driver(s) configuration structure
 involves editing the driver(s) source file. It's pretty easy if you follow
 the instructions below. Both drivers can support up to 4 boards. The smart
@@ -96,14 +185,16 @@
 driver will emit some kernel trace messages about whether the configured
 boards were detected or not. Depending on how your system logger is set
 up these may come out on the console, or just be logged to
-/var/adm/messages. You should check the messages to confirm that all is well.
+/var/adm/messages or /var/log/syslog. You should check the messages to
+confirm that all is well.
 
 
-2.1 SHARING INTERRUPTS
+2.3 SHARING INTERRUPTS
 
 It is possible to share interrupts between multiple EasyIO and
-EasyConnection 8/32 boards in an EISA system. To do this you will need to
-do a couple of things:
+EasyConnection 8/32 boards in an EISA system. To do this you must be using
+static driver configuration, modifying the driver source code to add driver
+configuration. Then a couple of extra things are required:
 
 1. When entering the board resources into the stallion.c file you need to
    mark the boards as using level triggered interrupts. Do this by replacing
@@ -130,7 +221,7 @@
 sharing interrupts.
 
 
-2.2 USING HIGH SHARED MEMORY
+2.4 USING HIGH SHARED MEMORY
 
 The EasyConnection 8/64-EI, ONboard and Stallion boards are capable of
 using shared memory addresses above the usual 640K - 1Mb range. The ONboard
@@ -145,16 +236,18 @@
 
 
 
-2.3 TROUBLE SHOOTING
+2.5 TROUBLE SHOOTING
 
 If a board is not found by the driver but is actually in the system then the
-most likely problem is that the I/O address is wrong. Change it in the driver
-stallion.c or istallion.c configuration structure and rebuild the kernel or
-modules, or change it on the board. On EasyIO and EasyConnection 8/32 boards
-the IRQ is software programmable, so if there is a conflict you may need to
-change the IRQ used for a board in the stallion.c configuration structure.
-There are no interrupts to worry about for ONboard, Brumby or EasyConnection
-8/64 (ISA, EISA and MCA) boards. The memory region on EasyConnection 8/64 and
+most likely problem is that the I/O address is wrong. Change the module load
+argument for the loadable module form. Or change it in the driver stallion.c
+or istallion.c configuration structure and rebuild the kernel or modules, or
+change it on the board.
+
+On EasyIO and EasyConnection 8/32 boards the IRQ is software programmable, so
+if there is a conflict you may need to change the IRQ used for a board. There
+are no interrupts to worry about for ONboard, Brumby or EasyConnection 8/64
+(ISA, EISA and MCA) boards. The memory region on EasyConnection 8/64 and
 ONboard boards is software programmable, but not on the Brumby boards.
 
 
@@ -167,9 +260,13 @@
 to them. This is done via a user level application supplied in the driver
 utility package called "stlload". Compile this program wherever you dropped
 the package files, by typing "make". In its simplest form you can then type
+
     ./stlload -i cdk.sys
+
 in this directory and that will download board 0 (assuming board 0 is an
-EasyConnection 8/64 board). To download to an ONboard, Brumby or Stallion do:
+EasyConnection 8/64 or EasyConnection/RA board). To download to an
+ONboard, Brumby or Stallion do:
+
     ./stlload -i 2681.sys
 
 Normally you would want all boards to be downloaded as part of the standard
@@ -182,6 +279,7 @@
 and put the cdk.sys and 2681.sys files in it. (It's a convenient place to put
 them anyway). As an example your /etc/rc.d/rc.S file might have the
 following lines added to it (if you had 3 boards):
+
     /usr/sbin/stlload -b 0 -i /usr/lib/stallion/cdk.sys
     /usr/sbin/stlload -b 1 -i /usr/lib/stallion/2681.sys
     /usr/sbin/stlload -b 2 -i /usr/lib/stallion/2681.sys
diff -urN linux-2.2.5-pre2/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- linux-2.2.5-pre2/arch/alpha/kernel/smp.c	Sat Jan 16 17:02:50 1999
+++ linux/arch/alpha/kernel/smp.c	Mon Dec  3 18:36:42 2001
@@ -499,6 +499,7 @@
 			return;
 		}
 		mdelay(1);
+		barrier();
 	}
 	DBGS(("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid));
 }
@@ -541,6 +542,7 @@
 		if (!(hwrpb->txrdy & cpumask))
 			goto ready1;
 		udelay(100);
+		barrier();
 	}
 	goto timeout;
 
@@ -549,6 +551,7 @@
 		if (!(hwrpb->txrdy & cpumask))
 			goto ready2;
 		udelay(100);
+		barrier();
 	}
 	goto timeout;
 
diff -urN linux-2.2.5-pre2/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- linux-2.2.5-pre2/arch/sparc64/kernel/smp.c	Mon Mar 15 16:10:43 1999
+++ linux/arch/sparc64/kernel/smp.c	Mon Dec  3 18:36:42 2001
@@ -347,6 +347,17 @@
 extern unsigned long xcall_tlbcachesync;
 extern unsigned long xcall_flush_cache_all;
 extern unsigned long xcall_report_regs;
+extern unsigned long xcall_receive_signal;
+
+void smp_receive_signal(int cpu)
+{
+	if(smp_processors_ready &&
+	   (cpu_present_map & (1UL<<cpu)) != 0) {
+		u64 pstate, data0 = (((u64)&xcall_receive_signal) & 0xffffffff);
+		__asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
+		xcall_deliver(data0, 0, 0, pstate, cpu);
+	}
+}
 
 void smp_report_regs(void)
 {
diff -urN linux-2.2.5-pre2/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- linux-2.2.5-pre2/arch/sparc64/mm/init.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/mm/init.c	Mon Dec  3 18:36:42 2001
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.124 1999/02/08 07:01:42 ecd Exp $
+/*  $Id: init.c,v 1.125 1999/03/28 08:39:33 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -142,9 +142,9 @@
 	printk("%d reserved pages\n",reserved);
 	printk("%d pages shared\n",shared);
 	printk("%d pages swap cached\n",cached);
-	printk("%ld pages in page table cache\n",pgtable_cache_size);
+	printk("%d pages in page table cache\n",pgtable_cache_size);
 #ifndef __SMP__
-	printk("%ld entries in page dir cache\n",pgd_cache_size);
+	printk("%d entries in page dir cache\n",pgd_cache_size);
 #endif	
 	show_buffers();
 #ifdef CONFIG_NET
diff -urN linux-2.2.5-pre2/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S
--- linux-2.2.5-pre2/arch/sparc64/mm/ultra.S	Mon Nov 16 10:37:28 1998
+++ linux/arch/sparc64/mm/ultra.S	Mon Dec  3 18:36:42 2001
@@ -1,4 +1,4 @@
-/* $Id: ultra.S,v 1.31 1998/11/07 06:39:21 davem Exp $
+/* $Id: ultra.S,v 1.32 1999/03/28 08:39:34 davem Exp $
  * ultra.S: Don't expand these all over the place...
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -260,6 +260,21 @@
 	 nop
 	b,pt		%xcc, rtrap
 	 clr		%l6
+
+	.globl		xcall_receive_signal
+xcall_receive_signal:
+	rdpr		%pstate, %g2
+	wrpr		%g2, PSTATE_IG | PSTATE_AG, %pstate
+	rdpr		%tstate, %g1
+	andcc		%g1, TSTATE_PRIV, %g0
+	/* If we did not trap from user space, just ignore. */
+	bne,pn		%xcc, 99f
+	 sethi		%hi(109f), %g7
+	b,pt		%xcc, etrap
+109:	 or		%g7, %lo(109b), %g7
+	b,pt		%xcc, rtrap
+	 clr		%l6
+99:	retry
 
 	/* These two are not performance critical... */
 	.globl		xcall_flush_tlb_all
diff -urN linux-2.2.5-pre2/drivers/char/istallion.c linux/drivers/char/istallion.c
--- linux-2.2.5-pre2/drivers/char/istallion.c	Tue Dec 29 11:29:54 1998
+++ linux/drivers/char/istallion.c	Mon Dec  3 18:36:42 2001
@@ -3,7 +3,7 @@
 /*
  *	istallion.c  -- stallion intelligent multiport serial driver.
  *
- *	Copyright (C) 1996-1998  Stallion Technologies (support@stallion.oz.au).
+ *	Copyright (C) 1996-1999  Stallion Technologies (support@stallion.oz.au).
  *	Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
  *
  *	This code is loosely based on the Linux serial driver, written by
@@ -27,29 +27,24 @@
 /*****************************************************************************/
 
 #include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/wait.h>
+#include <linux/malloc.h>
 #include <linux/interrupt.h>
-#include <linux/termios.h>
-#include <linux/fcntl.h>
-#include <linux/tty_driver.h>
-#include <linux/tty.h>
 #include <linux/tty_flip.h>
 #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>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <asm/system.h>
+
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
+
 /*****************************************************************************/
 
 /*
@@ -79,6 +74,7 @@
 #define	BRD_ECHPCI	26
 #define	BRD_ECH64PCI	27
 #define	BRD_EASYIOPCI	28
+#define	BRD_ECPPCI	29
 
 #define	BRD_BRUMBY	BRD_BRUMBY4
 
@@ -131,7 +127,7 @@
 } stlconf_t;
 
 static stlconf_t	stli_brdconf[] = {
- 	{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },
+	/*{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },*/
 };
 
 static int	stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t);
@@ -170,7 +166,7 @@
  */
 static char	*stli_drvtitle = "Stallion Intelligent Multiport Serial Driver";
 static char	*stli_drvname = "istallion";
-static char	*stli_drvversion = "5.4.7";
+static char	*stli_drvversion = "5.5.1";
 static char	*stli_serialname = "ttyE";
 static char	*stli_calloutname = "cue";
 
@@ -296,8 +292,110 @@
 	"EC8/32-PCI",
 	"EC8/64-PCI",
 	"EasyIO-PCI",
+	"EC/RA-PCI",
 };
 
+/*****************************************************************************/
+
+#ifdef MODULE
+/*
+ *	Define some string labels for arguments passed from the module
+ *	load line. These allow for easy board definitions, and easy
+ *	modification of the io, memory and irq resoucres.
+ */
+
+static char	*board0[8];
+static char	*board1[8];
+static char	*board2[8];
+static char	*board3[8];
+
+static char	**stli_brdsp[] = {
+	(char **) &board0,
+	(char **) &board1,
+	(char **) &board2,
+	(char **) &board3
+};
+
+/*
+ *	Define a set of common board names, and types. This is used to
+ *	parse any module arguments.
+ */
+
+typedef struct stlibrdtype {
+	char	*name;
+	int	type;
+} stlibrdtype_t;
+
+static stlibrdtype_t	stli_brdstr[] = {
+	{ "stallion", BRD_STALLION },
+	{ "1", BRD_STALLION },
+	{ "brumby", BRD_BRUMBY },
+	{ "brumby4", BRD_BRUMBY },
+	{ "brumby/4", BRD_BRUMBY },
+	{ "brumby-4", BRD_BRUMBY },
+	{ "brumby8", BRD_BRUMBY },
+	{ "brumby/8", BRD_BRUMBY },
+	{ "brumby-8", BRD_BRUMBY },
+	{ "brumby16", BRD_BRUMBY },
+	{ "brumby/16", BRD_BRUMBY },
+	{ "brumby-16", BRD_BRUMBY },
+	{ "2", BRD_BRUMBY },
+	{ "onboard2", BRD_ONBOARD2 },
+	{ "onboard-2", BRD_ONBOARD2 },
+	{ "onboard/2", BRD_ONBOARD2 },
+	{ "onboard-mc", BRD_ONBOARD2 },
+	{ "onboard/mc", BRD_ONBOARD2 },
+	{ "onboard-mca", BRD_ONBOARD2 },
+	{ "onboard/mca", BRD_ONBOARD2 },
+	{ "3", BRD_ONBOARD2 },
+	{ "onboard", BRD_ONBOARD },
+	{ "onboardat", BRD_ONBOARD },
+	{ "4", BRD_ONBOARD },
+	{ "onboarde", BRD_ONBOARDE },
+	{ "onboard-e", BRD_ONBOARDE },
+	{ "onboard/e", BRD_ONBOARDE },
+	{ "onboard-ei", BRD_ONBOARDE },
+	{ "onboard/ei", BRD_ONBOARDE },
+	{ "7", BRD_ONBOARDE },
+	{ "ecp", BRD_ECP },
+	{ "ecpat", BRD_ECP },
+	{ "ec8/64", BRD_ECP },
+	{ "ec8/64-at", BRD_ECP },
+	{ "ec8/64-isa", BRD_ECP },
+	{ "23", BRD_ECP },
+	{ "ecpe", BRD_ECPE },
+	{ "ecpei", BRD_ECPE },
+	{ "ec8/64-e", BRD_ECPE },
+	{ "ec8/64-ei", BRD_ECPE },
+	{ "24", BRD_ECPE },
+	{ "ecpmc", BRD_ECPMC },
+	{ "ec8/64-mc", BRD_ECPMC },
+	{ "ec8/64-mca", BRD_ECPMC },
+	{ "25", BRD_ECPMC },
+	{ "ecppci", BRD_ECPPCI },
+	{ "ec/ra", BRD_ECPPCI },
+	{ "ec/ra-pc", BRD_ECPPCI },
+	{ "ec/ra-pci", BRD_ECPPCI },
+	{ "29", BRD_ECPPCI },
+};
+
+/*
+ *	Define the module agruments.
+ */
+MODULE_AUTHOR("Greg Ungerer");
+MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver");
+
+MODULE_PARM(board0, "1-3s");
+MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]");
+MODULE_PARM(board1, "1-3s");
+MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]");
+MODULE_PARM(board2, "1-3s");
+MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]");
+MODULE_PARM(board3, "1-3s");
+MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]");
+
+#endif
+
 /*
  *	Set up a default memory address table for EISA board probing.
  *	The default addresses are all bellow 1Mbyte, which has to be the
@@ -317,18 +415,34 @@
 static int	stli_eisamempsize = sizeof(stli_eisamemprobeaddrs) / sizeof(unsigned long);
 int		stli_eisaprobe = STLI_EISAPROBE;
 
+/*
+ *	Define the Stallion PCI vendor and device IDs.
+ */
+#ifdef CONFIG_PCI
+#ifndef	PCI_VENDOR_ID_STALLION
+#define	PCI_VENDOR_ID_STALLION		0x124d
+#endif
+#ifndef PCI_DEVICE_ID_ECRA
+#define	PCI_DEVICE_ID_ECRA		0x0004
+#endif
+#endif
+
 /*****************************************************************************/
 
 /*
  *	Hardware configuration info for ECP boards. These defines apply
  *	to the directly accessible io ports of the ECP. There is a set of
- *	defines for each ECP board type, ISA, EISA and MCA.
+ *	defines for each ECP board type, ISA, EISA, MCA and PCI.
  */
 #define	ECP_IOSIZE	4
+
 #define	ECP_MEMSIZE	(128 * 1024)
+#define	ECP_PCIMEMSIZE	(256 * 1024)
+
 #define	ECP_ATPAGESIZE	(4 * 1024)
-#define	ECP_EIPAGESIZE	(64 * 1024)
 #define	ECP_MCPAGESIZE	(4 * 1024)
+#define	ECP_EIPAGESIZE	(64 * 1024)
+#define	ECP_PCIPAGESIZE	(64 * 1024)
 
 #define	STL_EISAID	0x8c4e
 
@@ -377,6 +491,14 @@
 #define	ECP_MCDISABLE	0x00
 
 /*
+ *	Important defines for the PCI class of ECP board.
+ *	(It has a lot in common with the other ECP boards.)
+ */
+#define	ECP_PCIIREG	0
+#define	ECP_PCICONFR	1
+#define	ECP_PCISTOP	0x01
+
+/*
  *	Hardware configuration info for ONboard and Brumby boards. These
  *	defines apply to the directly accessible io ports of these boards.
  */
@@ -516,7 +638,11 @@
 /*
  *	Define some handy local macros...
  */
-#define	MIN(a,b)		(((a) <= (b)) ? (a) : (b))
+#undef MIN
+#define	MIN(a,b)	(((a) <= (b)) ? (a) : (b))
+
+#undef	TOLOWER
+#define	TOLOWER(x)	((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
 
 /*****************************************************************************/
 
@@ -527,6 +653,10 @@
 #ifdef MODULE
 int		init_module(void);
 void		cleanup_module(void);
+static void	stli_argbrds(void);
+static int	stli_parsebrd(stlconf_t *confp, char **argp);
+
+static unsigned long	stli_atol(char *str);
 #endif
 
 int		stli_init(void);
@@ -583,6 +713,7 @@
 static int	stli_getportstruct(unsigned long arg);
 static int	stli_getbrdstruct(unsigned long arg);
 static void	*stli_memalloc(int len);
+static stlibrd_t *stli_allocbrd(void);
 
 static void	stli_ecpinit(stlibrd_t *brdp);
 static void	stli_ecpenable(stlibrd_t *brdp);
@@ -599,6 +730,9 @@
 static void	stli_ecpmcdisable(stlibrd_t *brdp);
 static char	*stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
 static void	stli_ecpmcreset(stlibrd_t *brdp);
+static void	stli_ecppciinit(stlibrd_t *brdp);
+static char	*stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
+static void	stli_ecppcireset(stlibrd_t *brdp);
 
 static void	stli_onbinit(stlibrd_t *brdp);
 static void	stli_onbenable(stlibrd_t *brdp);
@@ -625,6 +759,12 @@
 static inline int	stli_findeisabrds(void);
 static inline int	stli_eisamemprobe(stlibrd_t *brdp);
 static inline int	stli_initports(stlibrd_t *brdp);
+static inline int	stli_getbrdnr(void);
+
+#ifdef	CONFIG_PCI
+static inline int	stli_findpcibrds(void);
+static inline int	stli_initpcibrd(int brdtype, struct pci_dev *devp);
+#endif
 
 /*****************************************************************************/
 
@@ -741,8 +881,7 @@
 		kfree_s(stli_txcookbuf, STLI_TXBUFSIZE);
 
 	for (i = 0; (i < stli_nrbrds); i++) {
-		brdp = stli_brds[i];
-		if (brdp == (stlibrd_t *) NULL)
+		if ((brdp = stli_brds[i]) == (stlibrd_t *) NULL)
 			continue;
 		for (j = 0; (j < STL_MAXPORTS); j++) {
 			portp = brdp->ports[j];
@@ -763,6 +902,114 @@
 	restore_flags(flags);
 }
 
+/*****************************************************************************/
+
+/*
+ *	Check for any arguments passed in on the module load command line.
+ */
+
+static void stli_argbrds()
+{
+	stlconf_t	conf;
+	stlibrd_t	*brdp;
+	int		nrargs, i;
+
+#if DEBUG
+	printk("stli_argbrds()\n");
+#endif
+
+	nrargs = sizeof(stli_brdsp) / sizeof(char **);
+
+	for (i = stli_nrbrds; (i < nrargs); i++) {
+		memset(&conf, 0, sizeof(conf));
+		if (stli_parsebrd(&conf, stli_brdsp[i]) == 0)
+			continue;
+		if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
+			continue;
+		stli_nrbrds = i + 1;
+		brdp->brdnr = i;
+		brdp->brdtype = conf.brdtype;
+		brdp->iobase = conf.ioaddr1;
+		brdp->memaddr = conf.memaddr;
+		stli_brdinit(brdp);
+	}
+}
+
+/*****************************************************************************/
+
+/*
+ *	Convert an ascii string number into an unsigned long.
+ */
+
+static unsigned long stli_atol(char *str)
+{
+	unsigned long	val;
+	int		base, c;
+	char		*sp;
+
+	val = 0;
+	sp = str;
+	if ((*sp == '0') && (*(sp+1) == 'x')) {
+		base = 16;
+		sp += 2;
+	} else if (*sp == '0') {
+		base = 8;
+		sp++;
+	} else {
+		base = 10;
+	}
+
+	for (; (*sp != 0); sp++) {
+		c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
+		if ((c < 0) || (c >= base)) {
+			printk("STALLION: invalid argument %s\n", str);
+			val = 0;
+			break;
+		}
+		val = (val * base) + c;
+	}
+	return(val);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Parse the supplied argument string, into the board conf struct.
+ */
+
+static int stli_parsebrd(stlconf_t *confp, char **argp)
+{
+	char	*sp;
+	int	nrbrdnames, i;
+
+#if DEBUG
+	printk("stli_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
+#endif
+
+	if ((argp[0] == (char *) NULL) || (*argp[0] == 0))
+		return(0);
+
+	for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
+		*sp = TOLOWER(*sp);
+
+	nrbrdnames = sizeof(stli_brdstr) / sizeof(stlibrdtype_t);
+	for (i = 0; (i < nrbrdnames); i++) {
+		if (strcmp(stli_brdstr[i].name, argp[0]) == 0)
+			break;
+	}
+	if (i >= nrbrdnames) {
+		printk("STALLION: unknown board name, %s?\n", argp[0]);
+		return(0);
+	}
+
+	confp->brdtype = stli_brdstr[i].type;
+	if ((argp[1] != (char *) NULL) && (*argp[1] != 0))
+		confp->ioaddr1 = stli_atol(argp[1]);
+	if ((argp[2] != (char *) NULL) && (*argp[2] != 0))
+		confp->memaddr = stli_atol(argp[2]);
+	return(1);
+}
+
 #endif
 
 /*****************************************************************************/
@@ -1433,7 +1680,6 @@
 
 		down(&stli_tmpwritesem);
 		copy_from_user(stli_tmpwritebuf, chbuf, count);
-		up(&stli_tmpwritesem);
 		chbuf = &stli_tmpwritebuf[0];
 	}
 
@@ -1485,8 +1731,10 @@
 		portp->portidx;
 	*bits |= portp->portbit;
 	set_bit(ST_TXBUSY, &portp->state);
-
 	EBRDDISABLE(brdp);
+
+	if (from_user)
+		up(&stli_tmpwritesem);
 	restore_flags(flags);
 
 	return(count);
@@ -3363,6 +3611,60 @@
 /*****************************************************************************/
 
 /*
+ *	The following set of functions act on ECP PCI boards.
+ */
+
+static void stli_ecppciinit(stlibrd_t *brdp)
+{
+#if DEBUG
+	printk("stli_ecppciinit(brdp=%x)\n", (int) brdp);
+#endif
+
+	outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
+	udelay(10);
+	outb(0, (brdp->iobase + ECP_PCICONFR));
+	udelay(500);
+}
+
+/*****************************************************************************/
+
+static char *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+{	
+	void		*ptr;
+	unsigned char	val;
+
+#if DEBUG
+	printk("stli_ecppcigetmemptr(brdp=%x,offset=%x,line=%d)\n",
+		(int) brdp, (int) offset, line);
+#endif
+
+	if (offset > brdp->memsize) {
+		printk("STALLION: shared memory pointer=%x out of range at "
+			"line=%d(%d), board=%d\n", (int) offset, line,
+			__LINE__, brdp->brdnr);
+		ptr = 0;
+		val = 0;
+	} else {
+		ptr = brdp->membase + (offset % ECP_PCIPAGESIZE);
+		val = (offset / ECP_PCIPAGESIZE) << 1;
+	}
+	outb(val, (brdp->iobase + ECP_PCICONFR));
+	return(ptr);
+}
+
+/*****************************************************************************/
+
+static void stli_ecppcireset(stlibrd_t *brdp)
+{	
+	outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
+	udelay(10);
+	outb(0, (brdp->iobase + ECP_PCICONFR));
+	udelay(500);
+}
+
+/*****************************************************************************/
+
+/*
  *	The following routines act on ONboards.
  */
 
@@ -3678,7 +3980,7 @@
 
 	brdp->iosize = ECP_IOSIZE;
 	if (check_region(brdp->iobase, brdp->iosize))
-		printk("STALLION: Warning, unit %d I/O address %x conflicts "
+		printk("STALLION: Warning, board %d I/O address %x conflicts "
 			"with another device\n", brdp->brdnr, brdp->iobase);
 
 /*
@@ -3729,6 +4031,20 @@
 		name = "serial(EC8/64-MCA)";
 		break;
 
+	case BRD_ECPPCI:
+		brdp->membase = (void *) brdp->memaddr;
+		brdp->memsize = ECP_PCIMEMSIZE;
+		brdp->pagesize = ECP_PCIPAGESIZE;
+		brdp->init = stli_ecppciinit;
+		brdp->enable = NULL;
+		brdp->reenable = NULL;
+		brdp->disable = NULL;
+		brdp->getmemptr = stli_ecppcigetmemptr;
+		brdp->intr = stli_ecpintr;
+		brdp->reset = stli_ecppcireset;
+		name = "serial(EC/RA-PCI)";
+		break;
+
 	default:
 		return(-EINVAL);
 	}
@@ -3817,7 +4133,7 @@
 
 	brdp->iosize = ONB_IOSIZE;
 	if (check_region(brdp->iobase, brdp->iosize))
-		printk("STALLION: Warning, unit %d I/O address %x conflicts "
+		printk("STALLION: Warning, board %d I/O address %x conflicts "
 			"with another device\n", brdp->brdnr, brdp->iobase);
 
 /*
@@ -4082,6 +4398,7 @@
 	case BRD_ECP:
 	case BRD_ECPE:
 	case BRD_ECPMC:
+	case BRD_ECPPCI:
 		stli_initecp(brdp);
 		break;
 	case BRD_ONBOARD:
@@ -4104,20 +4421,20 @@
 			stli_brdnames[brdp->brdtype]);
 		return(ENODEV);
 	default:
-		printk("STALLION: unit=%d is unknown board type=%d\n",
+		printk("STALLION: board=%d is unknown board type=%d\n",
 			brdp->brdnr, brdp->brdtype);
 		return(ENODEV);
 	}
 
 	if ((brdp->state & BST_FOUND) == 0) {
-		printk("STALLION: %s board not found, unit=%d io=%x mem=%x\n",
+		printk("STALLION: %s board not found, board=%d io=%x mem=%x\n",
 			stli_brdnames[brdp->brdtype], brdp->brdnr,
 			brdp->iobase, (int) brdp->memaddr);
 		return(ENODEV);
 	}
 
 	stli_initports(brdp);
-	printk("STALLION: %s found, unit=%d io=%x mem=%x "
+	printk("STALLION: %s found, board=%d io=%x mem=%x "
 		"nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype],
 		brdp->brdnr, brdp->iobase, (int) brdp->memaddr,
 		brdp->nrpanels, brdp->nrports);
@@ -4279,29 +4596,13 @@
 			continue;
 
 /*
- *		Check that we have room for this new board in our board
- *		info table.
- */
-		if (stli_nrbrds >= STL_MAXBRDS) {
-			printk("STALLION: no room for more probed boards, "
-				"maximum supported %d\n", STL_MAXBRDS);
-			break;
-		}
-
-/*
  *		We have found a Stallion board and it is not configured already.
  *		Allocate a board structure and initialize it.
  */
-		brdp = (stlibrd_t *) stli_memalloc(sizeof(stlibrd_t));
-		if (brdp == (stlibrd_t *) NULL) {
-			printk("STALLION: failed to allocate memory "
-				"(size=%d)\n", sizeof(stlibrd_t));
+		if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
+			return(-ENOMEM);
+		if ((brdp->brdnr = stli_getbrdnr()) < 0)
 			return(-ENOMEM);
-		}
-		memset(brdp, 0, sizeof(stlibrd_t));
-
-		brdp->magic = STLI_BOARDMAGIC;
-		brdp->brdnr = stli_nrbrds++;
 		eid = inb(iobase + 0xc82);
 		if (eid == ECP_EISAID)
 			brdp->brdtype = BRD_ECPE;
@@ -4322,6 +4623,123 @@
 /*****************************************************************************/
 
 /*
+ *	Find the next available board number that is free.
+ */
+
+static inline int stli_getbrdnr()
+{
+	int	i;
+
+	for (i = 0; (i < STL_MAXBRDS); i++) {
+		if (stli_brds[i] == (stlibrd_t *) NULL) {
+			if (i >= stli_nrbrds)
+				stli_nrbrds = i + 1;
+			return(i);
+		}
+	}
+	return(-1);
+}
+
+/*****************************************************************************/
+
+#ifdef	CONFIG_PCI
+
+/*
+ *	We have a Stallion board. Allocate a board structure and
+ *	initialize it. Read its IO and MEMORY resources from PCI
+ *	configuration space.
+ */
+
+static inline int stli_initpcibrd(int brdtype, struct pci_dev *devp)
+{
+	stlibrd_t	*brdp;
+
+#if DEBUG
+	printk("stli_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
+		dev->bus->number, dev->devfn);
+#endif
+
+	if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
+		return(-ENOMEM);
+	if ((brdp->brdnr = stli_getbrdnr()) < 0) {
+		printk("STALLION: too many boards found, "
+			"maximum supported %d\n", STL_MAXBRDS);
+		return(0);
+	}
+	brdp->brdtype = brdtype;
+
+#if DEBUG
+	printk("%s(%d): BAR[]=%x,%x,%x,%x\n", __FILE__, __LINE__,
+		devp->base_address[0], devp->base_address[1],
+		devp->base_address[2], devp->base_address[3]);
+#endif
+
+/*
+ *	We have all resources from the board, so lets setup the actual
+ *	board structure now.
+ */
+	brdp->iobase = (devp->base_address[3] & PCI_BASE_ADDRESS_IO_MASK);
+	brdp->memaddr = (devp->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK);
+	stli_brdinit(brdp);
+
+	return(0);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Find all Stallion PCI boards that might be installed. Initialize each
+ *	one as it is found.
+ */
+
+static inline int stli_findpcibrds()
+{
+	struct pci_dev	*dev = NULL;
+	int		rc;
+
+#if DEBUG
+	printk("stli_findpcibrds()\n");
+#endif
+
+	if (! pci_present())
+		return(0);
+
+	while ((dev = pci_find_device(PCI_VENDOR_ID_STALLION,
+	    PCI_DEVICE_ID_ECRA, dev))) {
+		if ((rc = stli_initpcibrd(BRD_ECPPCI, dev)))
+			return(rc);
+	}
+
+	return(0);
+}
+
+#endif
+
+/*****************************************************************************/
+
+/*
+ *	Allocate a new board structure. Fill out the basic info in it.
+ */
+
+static stlibrd_t *stli_allocbrd()
+{
+	stlibrd_t	*brdp;
+
+	brdp = (stlibrd_t *) stli_memalloc(sizeof(stlibrd_t));
+	if (brdp == (stlibrd_t *) NULL) {
+		printk("STALLION: failed to allocate memory (size=%d)\n",
+			sizeof(stlibrd_t));
+		return((stlibrd_t *) NULL);
+	}
+
+	memset(brdp, 0, sizeof(stlibrd_t));
+	brdp->magic = STLI_BOARDMAGIC;
+	return(brdp);
+}
+
+/*****************************************************************************/
+
+/*
  *	Scan through all the boards in the configuration and see what we
  *	can find.
  */
@@ -4344,19 +4762,16 @@
 
 /*
  *	Firstly scan the list of static boards configured. Allocate
- *	resources and initialize the boards as found.
+ *	resources and initialize the boards as found. If this is a
+ *	module then let the module args override static configuration.
  */
 	for (i = 0; (i < stli_nrbrds); i++) {
 		confp = &stli_brdconf[i];
-		brdp = (stlibrd_t *) stli_memalloc(sizeof(stlibrd_t));
-		if (brdp == (stlibrd_t *) NULL) {
-			printk("STALLION: failed to allocate memory "
-				"(size=%d)\n", sizeof(stlibrd_t));
+#ifdef MODULE
+		stli_parsebrd(confp, stli_brdsp[i]);
+#endif
+		if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
 			return(-ENOMEM);
-		}
-		memset(brdp, 0, sizeof(stlibrd_t));
-
-		brdp->magic = STLI_BOARDMAGIC;
 		brdp->brdnr = i;
 		brdp->brdtype = confp->brdtype;
 		brdp->iobase = confp->ioaddr1;
@@ -4365,10 +4780,17 @@
 	}
 
 /*
- *	Now go probing for EISA boards if enabled.
+ *	Static configuration table done, so now use dynamic methods to
+ *	see if any more boards should be configured.
  */
+#ifdef MODULE
+	stli_argbrds();
+#endif
 	if (stli_eisaprobe)
 		stli_findeisabrds();
+#ifdef CONFIG_PCI
+	stli_findpcibrds();
+#endif
 
 /*
  *	All found boards are initialized. Now for a little optimization, if
diff -urN linux-2.2.5-pre2/drivers/char/stallion.c linux/drivers/char/stallion.c
--- linux-2.2.5-pre2/drivers/char/stallion.c	Tue Dec 29 11:29:54 1998
+++ linux/drivers/char/stallion.c	Mon Dec  3 18:36:42 2001
@@ -3,7 +3,7 @@
 /*
  *	stallion.c  -- stallion multiport serial driver.
  *
- *	Copyright (C) 1996-1998  Stallion Technologies (support@stallion.oz.au).
+ *	Copyright (C) 1996-1999  Stallion Technologies (support@stallion.oz.au).
  *	Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
  *
  *	This code is loosely based on the Linux serial driver, written by
@@ -27,28 +27,18 @@
 /*****************************************************************************/
 
 #include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
+#include <linux/malloc.h>
 #include <linux/interrupt.h>
-#include <linux/termios.h>
-#include <linux/fcntl.h>
-#include <linux/tty_driver.h>
-#include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
 #include <linux/cd1400.h>
 #include <linux/sc26198.h>
 #include <linux/comstats.h>
 #include <linux/stallion.h>
-#include <linux/string.h>
-#include <linux/malloc.h>
 #include <linux/ioport.h>
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -78,7 +68,7 @@
  *	stl_brdconf[] array is a board. Each line contains io/irq/memory
  *	ranges for that board (as well as what type of board it is).
  *	Some examples:
- *		{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 }
+ *		{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
  *	This line would configure an EasyIO board (4 or 8, no difference),
  *	at io address 2a0 and irq 10.
  *	Another example:
@@ -105,7 +95,7 @@
 } stlconf_t;
 
 static stlconf_t	stl_brdconf[] = {
-	{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
+	/*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/
 };
 
 static int	stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
@@ -144,7 +134,7 @@
  */
 static char	*stl_drvtitle = "Stallion Multiport Serial Driver";
 static char	*stl_drvname = "stallion";
-static char	*stl_drvversion = "5.4.7";
+static char	*stl_drvversion = "5.5.1";
 static char	*stl_serialname = "ttyE";
 static char	*stl_calloutname = "cue";
 
@@ -259,6 +249,85 @@
 
 /*****************************************************************************/
 
+#ifdef MODULE
+/*
+ *	Define some string labels for arguments passed from the module
+ *	load line. These allow for easy board definitions, and easy
+ *	modification of the io, memory and irq resoucres.
+ */
+
+static char	*board0[4];
+static char	*board1[4];
+static char	*board2[4];
+static char	*board3[4];
+
+static char	**stl_brdsp[] = {
+	(char **) &board0,
+	(char **) &board1,
+	(char **) &board2,
+	(char **) &board3
+};
+
+/*
+ *	Define a set of common board names, and types. This is used to
+ *	parse any module arguments.
+ */
+
+typedef struct stlbrdtype {
+	char	*name;
+	int	type;
+} stlbrdtype_t;
+
+static stlbrdtype_t	stl_brdstr[] = {
+	{ "easyio", BRD_EASYIO },
+	{ "eio", BRD_EASYIO },
+	{ "20", BRD_EASYIO },
+	{ "ec8/32", BRD_ECH },
+	{ "ec8/32-at", BRD_ECH },
+	{ "ec8/32-isa", BRD_ECH },
+	{ "ech", BRD_ECH },
+	{ "echat", BRD_ECH },
+	{ "21", BRD_ECH },
+	{ "ec8/32-mc", BRD_ECHMC },
+	{ "ec8/32-mca", BRD_ECHMC },
+	{ "echmc", BRD_ECHMC },
+	{ "echmca", BRD_ECHMC },
+	{ "22", BRD_ECHMC },
+	{ "ec8/32-pc", BRD_ECHPCI },
+	{ "ec8/32-pci", BRD_ECHPCI },
+	{ "26", BRD_ECHPCI },
+	{ "ec8/64-pc", BRD_ECH64PCI },
+	{ "ec8/64-pci", BRD_ECH64PCI },
+	{ "ech-pci", BRD_ECH64PCI },
+	{ "echpci", BRD_ECH64PCI },
+	{ "echpc", BRD_ECH64PCI },
+	{ "27", BRD_ECH64PCI },
+	{ "easyio-pc", BRD_EASYIOPCI },
+	{ "easyio-pci", BRD_EASYIOPCI },
+	{ "eio-pci", BRD_EASYIOPCI },
+	{ "eiopci", BRD_EASYIOPCI },
+	{ "28", BRD_EASYIOPCI },
+};
+
+/*
+ *	Define the module agruments.
+ */
+MODULE_AUTHOR("Greg Ungerer");
+MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
+
+MODULE_PARM(board0, "1-4s");
+MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
+MODULE_PARM(board1, "1-4s");
+MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
+MODULE_PARM(board2, "1-4s");
+MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
+MODULE_PARM(board3, "1-4s");
+MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
+
+#endif
+
+/*****************************************************************************/
+
 /*
  *	Hardware ID bits for the EasyIO and ECH boards. These defines apply
  *	to the directly accessible io ports of these boards (not the uarts -
@@ -399,9 +468,11 @@
 /*
  *	Define some handy local macros...
  */
-#ifndef	MIN
-#define	MIN(a,b)		(((a) <= (b)) ? (a) : (b))
-#endif
+#undef	MIN
+#define	MIN(a,b)	(((a) <= (b)) ? (a) : (b))
+
+#undef	TOLOWER
+#define	TOLOWER(x)	((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
 
 /*****************************************************************************/
 
@@ -412,6 +483,10 @@
 #ifdef MODULE
 int		init_module(void);
 void		cleanup_module(void);
+static void	stl_argbrds(void);
+static int	stl_parsebrd(stlconf_t *confp, char **argp);
+
+static unsigned long stl_atol(char *str);
 #endif
 
 int		stl_init(void);
@@ -459,15 +534,17 @@
 static void	stl_echpci64intr(stlbrd_t *brdp);
 static void	stl_offintr(void *private);
 static void	*stl_memalloc(int len);
+static stlbrd_t *stl_allocbrd(void);
 static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);
 
 static inline int	stl_initbrds(void);
 static inline int	stl_initeio(stlbrd_t *brdp);
 static inline int	stl_initech(stlbrd_t *brdp);
+static inline int	stl_getbrdnr(void);
 
 #ifdef	CONFIG_PCI
 static inline int	stl_findpcibrds(void);
-static inline int	stl_initpcibrd(int brdtype, struct pci_dev *dev);
+static inline int	stl_initpcibrd(int brdtype, struct pci_dev *devp);
 #endif
 
 /*
@@ -747,7 +824,8 @@
 		kfree_s(stl_tmpwritebuf, STL_TXBUFSIZE);
 
 	for (i = 0; (i < stl_nrbrds); i++) {
-		brdp = stl_brds[i];
+		if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
+			continue;
 		for (j = 0; (j < STL_MAXPANELS); j++) {
 			panelp = brdp->panels[j];
 			if (panelp == (stlpanel_t *) NULL)
@@ -779,6 +857,124 @@
 	restore_flags(flags);
 }
 
+/*****************************************************************************/
+
+/*
+ *	Check for any arguments passed in on the module load command line.
+ */
+
+static void stl_argbrds()
+{
+	stlconf_t	conf;
+	stlbrd_t	*brdp;
+	int		nrargs, i;
+
+#if DEBUG
+	printk("stl_argbrds()\n");
+#endif
+
+	nrargs = sizeof(stl_brdsp) / sizeof(char **);
+
+	for (i = stl_nrbrds; (i < nrargs); i++) {
+		memset(&conf, 0, sizeof(conf));
+		if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
+			continue;
+		if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
+			continue;
+		stl_nrbrds = i + 1;
+		brdp->brdnr = i;
+		brdp->brdtype = conf.brdtype;
+		brdp->ioaddr1 = conf.ioaddr1;
+		brdp->ioaddr2 = conf.ioaddr2;
+		brdp->irq = conf.irq;
+		brdp->irqtype = conf.irqtype;
+		stl_brdinit(brdp);
+	}
+}
+
+/*****************************************************************************/
+
+/*
+ *	Convert an ascii string number into an unsigned long.
+ */
+
+static unsigned long stl_atol(char *str)
+{
+	unsigned long	val;
+	int		base, c;
+	char		*sp;
+
+	val = 0;
+	sp = str;
+	if ((*sp == '0') && (*(sp+1) == 'x')) {
+		base = 16;
+		sp += 2;
+	} else if (*sp == '0') {
+		base = 8;
+		sp++;
+	} else {
+		base = 10;
+	}
+
+	for (; (*sp != 0); sp++) {
+		c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
+		if ((c < 0) || (c >= base)) {
+			printk("STALLION: invalid argument %s\n", str);
+			val = 0;
+			break;
+		}
+		val = (val * base) + c;
+	}
+	return(val);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Parse the supplied argument string, into the board conf struct.
+ */
+
+static int stl_parsebrd(stlconf_t *confp, char **argp)
+{
+	char	*sp;
+	int	nrbrdnames, i;
+
+#if DEBUG
+	printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
+#endif
+
+	if ((argp[0] == (char *) NULL) || (*argp[0] == 0))
+		return(0);
+
+	for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
+		*sp = TOLOWER(*sp);
+
+	nrbrdnames = sizeof(stl_brdstr) / sizeof(stlbrdtype_t);
+	for (i = 0; (i < nrbrdnames); i++) {
+		if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
+			break;
+	}
+	if (i >= nrbrdnames) {
+		printk("STALLION: unknown board name, %s?\n", argp[0]);
+		return(0);
+	}
+
+	confp->brdtype = stl_brdstr[i].type;
+
+	i = 1;
+	if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
+		confp->ioaddr1 = stl_atol(argp[i]);
+	i++;
+	if (confp->brdtype == BRD_ECH) {
+		if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
+			confp->ioaddr2 = stl_atol(argp[i]);
+		i++;
+	}
+	if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
+		confp->irq = stl_atol(argp[i]);
+	return(1);
+}
+
 #endif
 
 /*****************************************************************************/
@@ -794,6 +990,28 @@
 
 /*****************************************************************************/
 
+/*
+ *	Allocate a new board structure. Fill out the basic info in it.
+ */
+
+static stlbrd_t *stl_allocbrd()
+{
+	stlbrd_t	*brdp;
+
+	brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t));
+	if (brdp == (stlbrd_t *) NULL) {
+		printk("STALLION: failed to allocate memory (size=%d)\n",
+			sizeof(stlbrd_t));
+		return((stlbrd_t *) NULL);
+	}
+
+	memset(brdp, 0, sizeof(stlbrd_t));
+	brdp->magic = STL_BOARDMAGIC;
+	return(brdp);
+}
+
+/*****************************************************************************/
+
 static int stl_open(struct tty_struct *tty, struct file *filp)
 {
 	stlport_t	*portp;
@@ -1121,7 +1339,6 @@
 		
 		down(&stl_tmpwritesem);
 		copy_from_user(stl_tmpwritebuf, chbuf, count);
-		up(&stl_tmpwritesem);
 		chbuf = &stl_tmpwritebuf[0];
 	}
 
@@ -1154,6 +1371,9 @@
 	clear_bit(ASYI_TXLOW, &portp->istate);
 	stl_startrxtx(portp, -1, 1);
 
+	if (from_user)
+		up(&stl_tmpwritesem);
+
 	return(count);
 }
 
@@ -2185,12 +2405,12 @@
 	}
 
 	if (check_region(brdp->ioaddr1, brdp->iosize1)) {
-		printk("STALLION: Warning, unit %d I/O address %x conflicts "
+		printk("STALLION: Warning, board %d I/O address %x conflicts "
 			"with another device\n", brdp->brdnr, brdp->ioaddr1);
 	}
 	if (brdp->iosize2 > 0) {
 		if (check_region(brdp->ioaddr2, brdp->iosize2)) {
-			printk("STALLION: Warning, unit %d I/O address %x "
+			printk("STALLION: Warning, board %d I/O address %x "
 				"conflicts with another device\n",
 				brdp->brdnr, brdp->ioaddr2);
 		}
@@ -2376,7 +2596,7 @@
 		conflict = check_region(brdp->ioaddr2, brdp->iosize2) ?
 			brdp->ioaddr2 : 0;
 	if (conflict) {
-		printk("STALLION: Warning, unit %d I/O address %x conflicts "
+		printk("STALLION: Warning, board %d I/O address %x conflicts "
 			"with another device\n", brdp->brdnr, conflict);
 	}
 
@@ -2499,14 +2719,14 @@
 		stl_initech(brdp);
 		break;
 	default:
-		printk("STALLION: unit=%d is unknown board type=%d\n",
+		printk("STALLION: board=%d is unknown board type=%d\n",
 			brdp->brdnr, brdp->brdtype);
 		return(ENODEV);
 	}
 
 	stl_brds[brdp->brdnr] = brdp;
 	if ((brdp->state & BRD_FOUND) == 0) {
-		printk("STALLION: %s board not found, unit=%d io=%x irq=%d\n",
+		printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
 			stl_brdnames[brdp->brdtype], brdp->brdnr,
 			brdp->ioaddr1, brdp->irq);
 		return(ENODEV);
@@ -2516,7 +2736,7 @@
 		if (brdp->panels[i] != (stlpanel_t *) NULL)
 			stl_initports(brdp, brdp->panels[i]);
 
-	printk("STALLION: %s found, unit=%d io=%x irq=%d "
+	printk("STALLION: %s found, board=%d io=%x irq=%d "
 		"nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
 		brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
 		brdp->nrports);
@@ -2525,6 +2745,26 @@
 
 /*****************************************************************************/
 
+/*
+ *	Find the next available board number that is free.
+ */
+
+static inline int stl_getbrdnr()
+{
+	int	i;
+
+	for (i = 0; (i < STL_MAXBRDS); i++) {
+		if (stl_brds[i] == (stlbrd_t *) NULL) {
+			if (i >= stl_nrbrds)
+				stl_nrbrds = i + 1;
+			return(i);
+		}
+	}
+	return(-1);
+}
+
+/*****************************************************************************/
+
 #ifdef	CONFIG_PCI
 
 /*
@@ -2533,42 +2773,32 @@
  *	configuration space.
  */
 
-static inline int stl_initpcibrd(int brdtype, struct pci_dev *dev)
+static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp)
 {
-	unsigned int	bar[4];
 	stlbrd_t	*brdp;
-	int		i;
-	unsigned char	irq;
 
 #if DEBUG
-	printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n",
-		brdtype, dev->bus->number, dev->devfn);
+	printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
+		dev->bus->number, dev->devfn);
 #endif
 
-	brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t));
-	if (brdp == (stlbrd_t *) NULL) {
-		printk("STALLION: failed to allocate memory (size=%d)\n",
-			sizeof(stlbrd_t));
+	if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
 		return(-ENOMEM);
+	if ((brdp->brdnr = stl_getbrdnr()) < 0) {
+		printk("STALLION: too many boards found, "
+			"maximum supported %d\n", STL_MAXBRDS);
+		return(0);
 	}
-
-	memset(brdp, 0, sizeof(stlbrd_t));
-	brdp->magic = STL_BOARDMAGIC;
-	brdp->brdnr = stl_nrbrds++;
 	brdp->brdtype = brdtype;
 
 /*
- *	Read in all the BAR registers from this board. Different Stallion
- *	boards use these in different ways, so we just read in the whole
- *	lot and then figure out what is what later.
- */
-	for (i = 0; (i < 4); i++)
-		bar[i] = dev->base_address[i];
-	irq = dev->irq;
-
+ *	Different Stallion boards use the BAR registers in different ways,
+ *	so set up io addresses based on board type.
+ */
 #if DEBUG
 	printk("%s(%d): BAR[]=%x,%x,%x,%x IRQ=%x\n", __FILE__, __LINE__,
-		bar[0], bar[1], bar[2], bar[3], irq);
+		devp->base_address[0], devp->base_address[1],
+		devp->base_address[2], devp->base_address[3], devp->irq);
 #endif
 
 /*
@@ -2577,29 +2807,34 @@
  */
 	switch (brdtype) {
 	case BRD_ECHPCI:
-		brdp->ioaddr2 = (bar[0] & PCI_BASE_ADDRESS_IO_MASK);
-		brdp->ioaddr1 = (bar[1] & PCI_BASE_ADDRESS_IO_MASK);
+		brdp->ioaddr2 = (devp->base_address[0] &
+			PCI_BASE_ADDRESS_IO_MASK);
+		brdp->ioaddr1 = (devp->base_address[1] &
+			PCI_BASE_ADDRESS_IO_MASK);
 		break;
 	case BRD_ECH64PCI:
-		brdp->ioaddr2 = (bar[2] & PCI_BASE_ADDRESS_IO_MASK);
-		brdp->ioaddr1 = (bar[1] & PCI_BASE_ADDRESS_IO_MASK);
+		brdp->ioaddr2 = (devp->base_address[2] &
+			PCI_BASE_ADDRESS_IO_MASK);
+		brdp->ioaddr1 = (devp->base_address[1] &
+			PCI_BASE_ADDRESS_IO_MASK);
 		break;
 	case BRD_EASYIOPCI:
-		brdp->ioaddr1 = (bar[2] & PCI_BASE_ADDRESS_IO_MASK);
-		brdp->ioaddr2 = (bar[1] & PCI_BASE_ADDRESS_IO_MASK);
+		brdp->ioaddr1 = (devp->base_address[2] &
+			PCI_BASE_ADDRESS_IO_MASK);
+		brdp->ioaddr2 = (devp->base_address[1] &
+			PCI_BASE_ADDRESS_IO_MASK);
 		break;
 	default:
 		printk("STALLION: unknown PCI board type=%d\n", brdtype);
 		break;
 	}
 
-	brdp->irq = irq;
+	brdp->irq = devp->irq;
 	stl_brdinit(brdp);
 
 	return(0);
 }
 
-
 /*****************************************************************************/
 
 /*
@@ -2621,17 +2856,8 @@
 		return(0);
 
 	for (i = 0; (i < stl_nrpcibrds); i++)
-		while ((dev = pci_find_device(stl_pcibrds[i].vendid, stl_pcibrds[i].devid, dev))) {
-
-/*
- *			Check that we can handle more boards...
- */
-			if (stl_nrbrds >= STL_MAXBRDS) {
-				printk("STALLION: too many boards found, "
-					"maximum supported %d\n", STL_MAXBRDS);
-				i = stl_nrpcibrds;
-				break;
-			}
+		while ((dev = pci_find_device(stl_pcibrds[i].vendid,
+		    stl_pcibrds[i].devid, dev))) {
 
 /*
  *			Found a device on the PCI bus that has our vendor and
@@ -2680,15 +2906,11 @@
  */
 	for (i = 0; (i < stl_nrbrds); i++) {
 		confp = &stl_brdconf[i];
-		brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t));
-		if (brdp == (stlbrd_t *) NULL) {
-			printk("STALLION: failed to allocate memory "
-				"(size=%d)\n", sizeof(stlbrd_t));
+#ifdef MODULE
+		stl_parsebrd(confp, stl_brdsp[i]);
+#endif
+		if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
 			return(-ENOMEM);
-		}
-		memset(brdp, 0, sizeof(stlbrd_t));
-
-		brdp->magic = STL_BOARDMAGIC;
 		brdp->brdnr = i;
 		brdp->brdtype = confp->brdtype;
 		brdp->ioaddr1 = confp->ioaddr1;
@@ -2698,11 +2920,14 @@
 		stl_brdinit(brdp);
 	}
 
-#ifdef CONFIG_PCI
 /*
- *	If the PCI BIOS support is compiled in then let's go looking for
- *	ECH-PCI boards.
+ *	Find any dynamically supported boards. That is via module load
+ *	line options or auto-detected on the PCI bus.
  */
+#ifdef MODULE
+	stl_argbrds();
+#endif
+#ifdef CONFIG_PCI
 	stl_findpcibrds();
 #endif
 
diff -urN linux-2.2.5-pre2/drivers/char/synclink.c linux/drivers/char/synclink.c
--- linux-2.2.5-pre2/drivers/char/synclink.c	Mon Dec  3 18:36:37 2001
+++ linux/drivers/char/synclink.c	Mon Dec  3 18:36:42 2001
@@ -3626,7 +3626,7 @@
 	}
 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 	
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
+#if 0 && LINUX_VERSION_CODE >= VERSION(2,1,0)
 	ret += sprintf(buf+ret, "irq_spinlock=%08X\n",
 	 		info->irq_spinlock.lock );
 #endif
diff -urN linux-2.2.5-pre2/drivers/fc4/socal.c linux/drivers/fc4/socal.c
--- linux-2.2.5-pre2/drivers/fc4/socal.c	Mon Mar 15 16:11:29 1999
+++ linux/drivers/fc4/socal.c	Mon Dec  3 18:36:42 2001
@@ -73,6 +73,7 @@
 	}
 }
 
+#ifdef HAVE_SOCAL_UCODE
 static void socal_bzero(void *d, int size)
 {
 	u32 *dp = (u32 *)d;
@@ -81,6 +82,7 @@
 		size -= sizeof(u32);
 	}
 }
+#endif
 
 static inline void socal_disable(struct socal *s)
 {
diff -urN linux-2.2.5-pre2/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- linux-2.2.5-pre2/drivers/video/fbcon.c	Sun Mar  7 23:50:49 1999
+++ linux/drivers/video/fbcon.c	Mon Dec  3 18:36:42 2001
@@ -1587,7 +1587,7 @@
         if (CON_IS_VISIBLE(conp) && softback_buf) {
 	    int l = fbcon_softback_size / conp->vc_size_row;
 	    if (l > 5)
-		softback_end += l * conp->vc_size_row;
+		softback_end = softback_buf + l * conp->vc_size_row;
 	    else {
 		/* Smaller scrollback makes no sense, and 0 would screw
 		   the operation totally */
diff -urN linux-2.2.5-pre2/include/asm-i386/timex.h linux/include/asm-i386/timex.h
--- linux-2.2.5-pre2/include/asm-i386/timex.h	Tue Mar 23 13:54:13 1999
+++ linux/include/asm-i386/timex.h	Mon Dec  3 18:36:42 2001
@@ -39,7 +39,7 @@
 #else
 	unsigned long eax, edx;
 
-	__asm__("rdtsc":"=a" (eax), "=d" (edx));
+	__asm__ __volatile__("rdtsc":"=a" (eax), "=d" (edx));
 	return eax;
 #endif
 }
diff -urN linux-2.2.5-pre2/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h
--- linux-2.2.5-pre2/include/asm-sparc64/pgtable.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/pgtable.h	Mon Dec  3 18:36:42 2001
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.102 1999/01/22 16:19:29 jj Exp $
+/* $Id: pgtable.h,v 1.103 1999/03/28 08:40:04 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -333,8 +333,8 @@
 extern struct pgtable_cache_struct {
 	unsigned long *pgd_cache;
 	unsigned long *pte_cache;
-	unsigned long pgcache_size;
-	unsigned long pgdcache_size;
+	unsigned int pgcache_size;
+	unsigned int pgdcache_size;
 } pgt_quicklists;
 #endif
 #define pgd_quicklist		(pgt_quicklists.pgd_cache)
diff -urN linux-2.2.5-pre2/include/asm-sparc64/smp.h linux/include/asm-sparc64/smp.h
--- linux-2.2.5-pre2/include/asm-sparc64/smp.h	Mon Mar 15 16:10:44 1999
+++ linux/include/asm-sparc64/smp.h	Mon Dec  3 18:36:42 2001
@@ -98,8 +98,17 @@
 /* This needn't do anything as we do not sleep the cpu
  * inside of the idler task, so an interrupt is not needed
  * to get a clean fast response.
+ *
+ * Addendum: We do want it to do something for the signal
+ *           delivery case, we detect that by just seeing
+ *           if we are trying to send this to an idler or not.
  */
-extern __inline__ void smp_send_reschedule(int cpu) { }
+extern __inline__ void smp_send_reschedule(int cpu)
+{
+	extern void smp_receive_signal(int);
+	if(cpu_data[cpu].idle_volume == 0)
+		smp_receive_signal(cpu);
+}
 
 /* This is a nop as well because we capture all other cpus
  * anyways when making the PROM active.
diff -urN linux-2.2.5-pre2/include/linux/if_arp.h linux/include/linux/if_arp.h
--- linux-2.2.5-pre2/include/linux/if_arp.h	Mon Dec  3 18:36:37 2001
+++ linux/include/linux/if_arp.h	Mon Dec  3 18:36:42 2001
@@ -70,7 +70,7 @@
 #define ARPHRD_FCPP	784		/* Point to point fibrechanel	*/
 #define ARPHRD_FCAL	785		/* Fibrechannel arbitrated loop */
 #define ARPHRD_FCPL	786		/* Fibrechannel public loop	*/
-#define ARPHRD_FCFABRIC	786		/* Fibrechannel fabric		*/
+#define ARPHRD_FCFABRIC	787		/* Fibrechannel fabric		*/
 	/* 787->799 reserved for fibrechannel media types */
 
 
diff -urN linux-2.2.5-pre2/include/linux/sched.h linux/include/linux/sched.h
--- linux-2.2.5-pre2/include/linux/sched.h	Tue Mar 23 13:54:17 1999
+++ linux/include/linux/sched.h	Mon Dec  3 18:36:42 2001
@@ -113,6 +113,7 @@
  */
 extern rwlock_t tasklist_lock;
 extern spinlock_t scheduler_lock;
+extern spinlock_t runqueue_lock;
 
 extern void sched_init(void);
 extern void show_state(void);
diff -urN linux-2.2.5-pre2/include/net/sock.h linux/include/net/sock.h
--- linux-2.2.5-pre2/include/net/sock.h	Mon Dec  3 18:36:37 2001
+++ linux/include/net/sock.h	Mon Dec  3 18:36:42 2001
@@ -845,6 +845,9 @@
 
 extern __inline__ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
+#ifdef CONFIG_FILTER
+	struct sk_filter *filter;
+#endif
 	/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
 	   number of warnings when compiling with -W --ANK
 	 */
@@ -852,7 +855,7 @@
                 return -ENOMEM;
 
 #ifdef CONFIG_FILTER
-	if (sk->filter && sk_filter(skb, sk->filter))
+	if ((filter = sk->filter) != NULL && sk_filter(skb, filter))
 		return -EPERM;	/* Toss packet */
 #endif /* CONFIG_FILTER */
 
diff -urN linux-2.2.5-pre2/net/core/sock.c linux/net/core/sock.c
--- linux-2.2.5-pre2/net/core/sock.c	Mon Dec  3 18:36:37 2001
+++ linux/net/core/sock.c	Mon Dec  3 18:36:42 2001
@@ -7,7 +7,7 @@
  *		handler for protocols to use and generic option handler.
  *
  *
- * Version:	$Id: sock.c,v 1.78 1999/03/25 10:03:55 davem Exp $
+ * Version:	$Id: sock.c,v 1.79 1999/03/28 10:18:25 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -150,6 +150,9 @@
 		    char *optval, int optlen)
 {
 	struct sock *sk=sock->sk;
+#ifdef CONFIG_FILTER
+	struct sk_filter *filter;
+#endif
 	int val;
 	int valbool;
 	int err;
@@ -341,16 +344,11 @@
 			break;
 
 		case SO_DETACH_FILTER:
-                        if(sk->filter) {
-				struct sk_filter *filter;
-
-				filter = sk->filter;
-
+			filter = sk->filter;
+                        if(filter) {
 				sk->filter = NULL;
 				synchronize_bh();
-				
-				if (filter)
-					sk_filter_release(sk, filter);
+				sk_filter_release(sk, filter);
 				return 0;
 			}
 			return -ENOENT;
@@ -500,22 +498,16 @@
 
 void sk_free(struct sock *sk)
 {
-	if (sk->destruct)
-		sk->destruct(sk);
-
 #ifdef CONFIG_FILTER
-	if (sk->filter) {
-		sk_filter_release(sk, sk->filter);
-		sk->filter = NULL;
-	}
+	struct sk_filter *filter;
 #endif
-
-	if (atomic_read(&sk->omem_alloc))
-		printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc));
+	if (sk->destruct)
+		sk->destruct(sk);
 
 #ifdef CONFIG_FILTER
-	if (sk->filter) {
-		sk_filter_release(sk, sk->filter);
+	filter = sk->filter;
+	if (filter) {
+		sk_filter_release(sk, filter);
 		sk->filter = NULL;
 	}
 #endif
diff -urN linux-2.2.5-pre2/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c
--- linux-2.2.5-pre2/net/ipv4/ipconfig.c	Sun Jan 17 10:00:00 1999
+++ linux/net/ipv4/ipconfig.c	Mon Dec  3 18:36:42 2001
@@ -1,5 +1,5 @@
 /*
- *  $Id: ipconfig.c,v 1.19 1999/01/15 06:54:00 davem Exp $
+ *  $Id: ipconfig.c,v 1.20 1999/03/28 10:18:28 davem Exp $
  *
  *  Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
  *  information to configure own IP address and routes.
@@ -825,9 +825,9 @@
 	 */
 	if (ic_myaddr == INADDR_NONE ||
 #ifdef CONFIG_ROOT_NFS
-	     root_server_addr == INADDR_NONE ||
+	    (root_server_addr == INADDR_NONE && ic_servaddr == INADDR_NONE) ||
 #endif
-	    (ic_first_dev && ic_first_dev->next)) {
+	    ic_first_dev->next) {
 #ifdef CONFIG_IP_PNP_DYNAMIC
 		if (ic_dynamic() < 0) {
 			printk(KERN_ERR "IP-Config: Auto-configuration of network failed.\n");
diff -urN linux-2.2.5-pre2/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- linux-2.2.5-pre2/net/ipv4/tcp_ipv4.c	Sun Mar 21 07:22:00 1999
+++ linux/net/ipv4/tcp_ipv4.c	Mon Dec  3 18:36:42 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.170 1999/03/21 05:22:47 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.171 1999/03/28 10:18:26 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -1305,6 +1305,9 @@
 
 	if(newsk != NULL) {
 		struct tcp_opt *newtp;
+#ifdef CONFIG_FILTER
+		struct sk_filter *filter;
+#endif
 
 		memcpy(newsk, sk, sizeof(*newsk));
 		newsk->sklist_next = NULL;
@@ -1326,8 +1329,8 @@
 		skb_queue_head_init(&newsk->back_log);
 		skb_queue_head_init(&newsk->error_queue);
 #ifdef CONFIG_FILTER
-		if (newsk->filter)
-			sk_filter_charge(newsk, newsk->filter);
+		if ((filter = newsk->filter) != NULL)
+			sk_filter_charge(newsk, filter);
 #endif
 
 		/* Now setup tcp_opt */
@@ -1559,9 +1562,9 @@
 
 int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
 {
-
 #ifdef CONFIG_FILTER
-	if (sk->filter && sk_filter(skb, sk->filter))
+	struct sk_filter *filter = sk->filter;
+	if (filter && sk_filter(skb, filter))
 		goto discard;
 #endif /* CONFIG_FILTER */
 
diff -urN linux-2.2.5-pre2/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- linux-2.2.5-pre2/net/ipv6/tcp_ipv6.c	Sun Mar 21 07:22:00 1999
+++ linux/net/ipv6/tcp_ipv6.c	Mon Dec  3 18:36:42 2001
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.100 1999/03/21 05:22:59 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.101 1999/03/28 10:18:30 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -1181,6 +1181,9 @@
 
 static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
 {
+#ifdef CONFIG_FILTER
+	struct sk_filter *filter;
+#endif
 	int users = 0;
 
 	/* Imagine: socket is IPv6. IPv4 packet arrives,
@@ -1195,7 +1198,8 @@
 		return tcp_v4_do_rcv(sk, skb);
 
 #ifdef CONFIG_FILTER
-	if (sk->filter && sk_filter(skb, sk->filter))
+	filter = sk->filter;
+	if (filter && sk_filter(skb, filter))
 		goto discard;
 #endif /* CONFIG_FILTER */
 
