diff -u --recursive --new-file v1.1.78/linux/MAGIC linux/MAGIC
--- v1.1.78/linux/MAGIC	Tue Aug  9 09:32:59 1994
+++ linux/MAGIC	Tue Jan 10 10:07:09 1995
@@ -25,6 +25,14 @@
 structures following the array have been overwritten.  Using this
 discipline, these cases get detected quickly and safely.
 
+You should also register the magic number used by ioctls in the table
+below.  This allows ioctls on inappropriate devices to fail, rather than
+doing something completely unexpected.  The magic number is the first
+argument to the _IO family of macros (see include/linux/ioctl.h) or
+in general bits 8..15 of the ioctl number.  Where ioctls are done on
+devices with a major device number, it is recommended that you use the
+major device number as the ioctl magic value (e.g. hd, lp).
+
 					Theodore Ts'o
 					31-Mar-94
 
@@ -39,4 +47,27 @@
 SERIAL_MAGIC        0x5301  struct async_struct  include/linux/serial.h
 SLIP_MAGIC          0x5302  struct slip          drivers/net/slip.h
 
+Ioctl	Include File	Comments
+========================================================
+0x00	fd.h
+0x03	hdreg.h
+0x06	lp.h
+0x12	fs.h
+'C'	soundcard.h
+'K'	kd.h
+'M'	soundcard.h
+'P'	soundcard.h
+'Q'	soundcard.h
+'S'	cdrom.h
+'S'	fs.h		subcodes from 0x80, no conflict
+'T'	soundcard.h	conflicts with termios.h
+'T'	termios.h	conflicts with soundcard.h
+'T'	ppp.h		subcodes from 0x90, no conflict
+'V'	vt.h
+'f'	ext2_fs.h
+'m'	mtio.h		conflicts with soundcard.h
+'m'	soundcard.h	conflicts with mtio.h
+'s'	pcsp.h
+'v'	ext2_fs.h
+0x89	sockios.h
 
diff -u --recursive --new-file v1.1.78/linux/Makefile linux/Makefile
--- v1.1.78/linux/Makefile	Mon Jan  9 11:24:19 1995
+++ linux/Makefile	Tue Jan 10 10:09:58 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 78
+SUBLEVEL = 79
 
 ARCH = i386
 
diff -u --recursive --new-file v1.1.78/linux/README linux/README
--- v1.1.78/linux/README	Thu Nov  3 17:08:53 1994
+++ linux/README	Tue Jan 10 17:02:11 1995
@@ -179,12 +179,11 @@
    see which kernel function contains the offending address.
 
    To find out the kernel function name, you'll need to find the system
-   binary associated with the kernel that exhibited the symptom.  In the
-   case of compressed kernels, this will be 'linux/tools/zSystem', while
-   uncompressed kernels use the file 'tools/system'.  To extract the
-   namelist and match it against the EIP from the kernel crash, do:
+   binary associated with the kernel that exhibited the symptom.  This is
+   the file 'linux/vmlinux'.  To extract the namelist and match it against
+   the EIP from the kernel crash, do:
 
-		nm tools/zSystem | sort | less
+		nm vmlinux | sort | less
 
    This will give you a list of kernel addresses sorted in ascending
    order, from which it is simple to find the function that contains the
@@ -208,10 +207,10 @@
    kernel with -g; edit arch/i386/Makefile appropriately, then do a "make
    clean". You'll also need to enable CONFIG_PROC_FS (via "make config").
 
-   After you've rebooted with the new kernel, do "gdb tools/zSystem
-   /proc/kcore". You can now use all the usual gdb commands. The command to
-   look up the point where your system crashed is "l *0xXXXXXXXX". (Replace
-   the XXXes with the EIP value.)
+   After you've rebooted with the new kernel, do "gdb vmlinux /proc/kcore".
+   You can now use all the usual gdb commands. The command to look up the
+   point where your system crashed is "l *0xXXXXXXXX". (Replace the XXXes
+   with the EIP value.)
 
    gdb'ing a non-running kernel currently fails because gdb (wrongly)
    disregards the starting offset for which the kernel is compiled.
diff -u --recursive --new-file v1.1.78/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v1.1.78/linux/arch/alpha/config.in	Mon Jan  9 11:24:19 1995
+++ linux/arch/alpha/config.in	Wed Jan 11 07:55:49 1995
@@ -9,7 +9,7 @@
 bool 'Normal harddisk support' CONFIG_BLK_DEV_HD n
 bool 'XT harddisk support' CONFIG_BLK_DEV_XD n
 bool 'Networking support' CONFIG_NET y
-bool 'System V IPC' CONFIG_SYSVIPC y
+bool 'System V IPC' CONFIG_SYSVIPC n
 bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF y
 
 if [ "$CONFIG_NET" = "y" ]; then
diff -u --recursive --new-file v1.1.78/linux/arch/alpha/lib/Makefile linux/arch/alpha/lib/Makefile
--- v1.1.78/linux/arch/alpha/lib/Makefile	Mon Jan  9 11:24:19 1995
+++ linux/arch/alpha/lib/Makefile	Wed Jan 11 07:55:49 1995
@@ -28,7 +28,6 @@
 	$(CC) -DREM -DINTSIZE -c -o __remlu.o divide.S
 
 dep:
-	$(CPP) -M *.c > .depend
 
 #
 # include a dependency file if one exists
diff -u --recursive --new-file v1.1.78/linux/arch/alpha/lib/divide.S linux/arch/alpha/lib/divide.S
--- v1.1.78/linux/arch/alpha/lib/divide.S	Mon Jan  9 11:24:19 1995
+++ linux/arch/alpha/lib/divide.S	Wed Jan 11 11:41:04 1995
@@ -19,27 +19,39 @@
  * These are not normal C functions: instead of the normal
  * calling sequence, these expect their arguments in registers
  * $24 and $25, and return the result in $27. Register $28 may
- * be clobbered (assembly temprary), anything else must be saved. 
+ * be clobbered (assembly temporary), anything else must be saved. 
  *
- * In short: painful. I'm not going to try to be clever about it:
- * let somebody else optimize it if they will.
+ * In short: painful.
+ *
+ * This is a rather simple bit-at-a-time algorithm: it's very good
+ * at dividing random 64-bit numbers, but the more usual case where
+ * the divisor is small is handled better by the DEC algorithm
+ * using lookup tables. This uses much less memory, though, and is
+ * nicer on the cache.. Besides, I don't know the copyright status
+ * of the DEC code.
  */
 
 /*
  * My temporaries:
  *	$0 - current bit
  *	$1 - shifted divisor
- *	$2 - rest
- *	$3 - compare status
+ *	$2 - modulus/quotient
  *
  *	$23 - return address
  *	$24 - dividend
  *	$25 - divisor
+ *
+ *	$27 - quotient/modulus
+ *	$28 - compare status
  */
 
 /*
  * Select function type and registers
  */
+#define mask	$0
+#define divisor	$1
+#define compare $28
+
 #ifdef DIV
 #define func(x) __div##x
 #define modulus $2
@@ -61,38 +73,44 @@
 #define LONGIFY(x)
 #endif
 
+.set noat
 .globl	function
 .ent	function
 function:
-	lda	$30,-32($30)
+	subq	$30,32,$30
 	stq	$0, 0($30)
 	stq	$1, 8($30)
 	stq	$2,16($30)
-	stq	$3,24($30)
-	bis	$25,$25,$1
+
+	bis	$25,$25,divisor
 	bis	$24,$24,modulus
 	bis	$31,$31,quotient
-	LONGIFY($1)
+	LONGIFY(divisor)
 	LONGIFY(modulus)
-	beq	$1, 9f			/* div by zero */
-	bis	$31,1,$0
-	blt	$1, 2f			/* high bit set */
-1:	cmpult	modulus,$1,$3
-	bne	$3,3f
-	addq	$1,$1,$1
-	addq	$0,$0,$0
-	bge	$1,1b
-2:	cmpult	modulus,$1,$3
-	bne	$3,3f
-	subq	modulus,$1,modulus
-	addq	$0,quotient,quotient
-3:	srl	$0,1,$0
-	srl	$1,1,$1
-	bne	$0,2b
+	beq	divisor, 9f			/* div by zero */
+	bis	$31,1,mask
+
+	/* shift divisor left */
+1:	cmpult	divisor,modulus,compare
+	blt	divisor, 3f
+	addq	divisor,divisor,divisor
+	addq	mask,mask,mask
+	bne	compare,1b
+
+	/* ok, start to go right again.. */
+2:	srl	divisor,1,divisor
+	beq	mask,9f
+	srl	mask,1,mask
+3:	cmpule	divisor,modulus,compare
+	beq	compare,2b
+	addq	quotient,mask,quotient
+	beq	mask,9f
+	subq	modulus,divisor,modulus
+	br	2b
+
 9:	ldq	$0, 0($30)
 	ldq	$1, 8($30)
 	ldq	$2, 16($30)
-	ldq	$3, 32($30)
-	lda	$30,32($30)
+	addq	$30,32,$30
 	ret	$31,($23),1
 	.end	function
diff -u --recursive --new-file v1.1.78/linux/arch/i386/config.in linux/arch/i386/config.in
--- v1.1.78/linux/arch/i386/config.in	Mon Jan  9 07:21:56 1995
+++ linux/arch/i386/config.in	Tue Jan 10 10:07:09 1995
@@ -104,7 +104,7 @@
 bool 'Dummy net driver support' CONFIG_DUMMY n
 bool 'SLIP (serial line) support' CONFIG_SLIP n
 if [ "$CONFIG_SLIP" = "y" ]; then
-  bool ' CSLIP compressed headers' SL_COMPRESSED y
+  bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y
   bool ' 16 channels instead of 4' SL_SLIP_LOTS n
 #  bool ' SLIP debugging on' SL_DUMP y
 fi
diff -u --recursive --new-file v1.1.78/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- v1.1.78/linux/arch/i386/kernel/bios32.c	Mon Jan  9 11:24:20 1995
+++ linux/arch/i386/kernel/bios32.c	Wed Jan 11 08:27:16 1995
@@ -36,9 +36,14 @@
  * CHANGELOG :
  * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
  *	Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard.
+ *
+ * Jan 10, 1995 : Modified to store the information about configured pci
+ *      devices into a list, which can be accessed via /proc/pci by
+ *      Curtis Varner, cvarner@cs.ucr.edu
  */
 
 #include <linux/config.h>
+#include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/bios32.h>
 #include <linux/pci.h>
@@ -57,6 +62,10 @@
 #define PCIBIOS_WRITE_CONFIG_WORD	0xb10c
 #define PCIBIOS_WRITE_CONFIG_DWORD	0xb10d
 
+#ifdef CONFIG_PCI
+extern void add_pci_resource(unsigned char, unsigned char);
+#endif
+
 /* BIOS32 signature: "_32_" */
 #define BIOS32_SIGNATURE	(('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
 
@@ -76,6 +85,15 @@
  * and the PCI BIOS specification.
  */
 
+#ifdef CONFIG_PCI
+typedef struct pci_resource_t
+{
+   unsigned char bus;
+   unsigned char dev_fn;
+   struct pci_resource_t *next;
+} pci_resource_t;
+#endif
+
 union bios32 {
 	struct {
 		unsigned long signature;	/* _32_ */
@@ -106,6 +124,12 @@
  * Returns the entry point for the given service, NULL on error
  */
 
+#define PCI_LIST_SIZE 32
+
+static pci_resource_t pci_list = { 0, 0, NULL };
+static int pci_index = 0;
+static pci_resource_t pci_table[PCI_LIST_SIZE];
+
 static unsigned long bios32_service(unsigned long service)
 {
 	unsigned char return_code;	/* %al */
@@ -424,7 +448,7 @@
 
 /* Returns Interrupt register */
 
-int interrupt_decod(unsigned char bus,unsigned char dev_fn)
+int interrupt_decode(unsigned char bus,unsigned char dev_fn)
 {
 	unsigned char interrupt;
 		pcibios_read_config_byte(
@@ -467,31 +491,26 @@
 		pcibios_read_config_dword(
 			bus, dev_fn, (unsigned char) PCI_CLASS_REVISION, &class);
 		class=class >> 16;
-		for (i=0;i<PCI_CLASS_NUM;i++) 
+		for (i=0;i<PCI_CLASS_NUM;i++)
 			if (class==pci_class[i].class_id) break;
 		return i;
 }
 
 
-
-
 int device_decode(unsigned char bus,unsigned char dev_fn,unsigned short vendor)
 {
 	struct pci_device_type 	pci_device[PCI_DEVICE_NUM+1] = PCI_DEVICE_TYPE;
 	int 			i;
 	unsigned short   	device;
-		pcibios_read_config_word(
-			bus, dev_fn, (unsigned char) PCI_DEVICE_ID, &device);
-		for (i=0;i<PCI_DEVICE_NUM;i++) 
-			if ((device==pci_device[i].device_id) 
-			 && (vendor==pci_device[i].vendor_id)) return i;
-		printk("Device id=%x ",device);
-		return i;
-}
-
-
-
 
+	pcibios_read_config_word(
+		bus, dev_fn, (unsigned char) PCI_DEVICE_ID, &device);
+	for (i=0;i<PCI_DEVICE_NUM;i++)
+		if ((device==pci_device[i].device_id)
+		 && (vendor==pci_device[i].vendor_id)) return i;
+	printk("Device id=%x ",device);
+	return i;
+}
 
 
 int vendor_decode(unsigned char bus,unsigned char dev_fn)
@@ -502,38 +521,14 @@
 
 		pcibios_read_config_word(
 			bus, dev_fn, (unsigned char) PCI_VENDOR_ID, &vendor);
-		for (i=0;i<PCI_VENDOR_NUM;i++) 
+		for (i=0;i<PCI_VENDOR_NUM;i++)
 			if (vendor==pci_vendor[i].vendor_id) return i;
 		printk("Vendor id=%x ",vendor);
 		return i;
 }
 
 
-
-
-/* Call all the information procedures */
-
-void info(unsigned char bus,unsigned char dev_fn)
-{
-	struct	pci_class_type		pci_class[PCI_CLASS_NUM+1] = PCI_CLASS_TYPE;
-	struct	pci_vendor_type		pci_vendor[PCI_VENDOR_NUM+1] = PCI_VENDOR_TYPE;
-	struct	pci_device_type		pci_device[PCI_DEVICE_NUM+1] = PCI_DEVICE_TYPE;
-	int				pr;
-		pr=vendor_decode(bus,dev_fn);
-		printk("       %s : %s %s (rev %d). "
-			,pci_class[class_decode(bus,dev_fn)].class_name
-			,pci_vendor[pr].vendor_name
-			,pci_device[device_decode(bus,dev_fn,pci_vendor[pr].vendor_id)].device_name
-			,revision_decode(bus,dev_fn));
-			
-		if (bist_probe(bus,dev_fn))
-			printk("BIST capable. ");
-		if ((pr=interrupt_decod(bus,dev_fn))!=0)
-			printk("8259's interrupt %d.",pr);
-		printk("\n");
-}
-
-/* In futur version in case we detect a PCI to PCi bridge, we will go 
+/* In future version in case we detect a PCI to PCi bridge, we will go
 for a recursive device search*/
 
 void probe_devices(unsigned char bus)
@@ -542,7 +537,7 @@
 	unsigned char	dev_fn;
 
 /* For a mysterious reason, my PC crash if I try to probe device 31 function 7  */
-/* (i.e. dev_fn=0xff) It can be a bug in my BIOS, or I havn't understood all about */
+/* (i.e. dev_fn=0xff) It can be a bug in my BIOS, or I haven't understood all about */
 /* PCI */
 
 
@@ -554,32 +549,110 @@
 /* Second, we get rid of non multi-function device that seems to be lazy  */
 /* and not fully decode the function number */
 
-			if ((res!=0xffffffff) && 
+			if ((res!=0xffffffff) &&
 				(((dev_fn & 7) == 0) || multi_function(bus,dev_fn))) {
-				printk("Bus %d Device %d Function %d.\n",
-						(int) bus,
-						(int) ((dev_fn & 0xf8) >> 3),
-						(int) (dev_fn & 7));
-				info(bus,dev_fn);
+				add_pci_resource( bus, dev_fn);
 			}
 		}
 }
 
 
+void probe_pci(void)
+{
+	if (pcibios_present()==0) {
+		printk("ProbePci PCI bios not detected.\n");
+		return;
+	}
+	printk( "Probing PCI hardware.\n");
+	probe_devices(0);
+}
+
+
+/*
+ * Function to add a resource to the pci list...
+ */
+void add_pci_resource(unsigned char bus, unsigned char dev_fn)
+{
+	pci_resource_t* new_pci;
+	pci_resource_t* temp;
 
+	/*
+	 * Request and verify allocation of kernel RAM
+	 */
+	if(pci_index > 31)
+	{
+		printk("PCI resource list full.\n");
+		return;
+	}
 
 
+	new_pci = &pci_table[pci_index];
+	pci_index++;
 
+	/*
+	 * Enter the new node into the list....
+	 *
+	 */
+	if(pci_list.next != NULL)
+	{
+		for(temp = pci_list.next; (temp->next); temp = temp->next)
+			/* nothing */;
 
-void probe_pci(void)
+		temp->next = new_pci;
+	}
+	else
+		pci_list.next = new_pci;
+
+	/*
+	 * Set the information for the node
+	 */
+	new_pci->next = NULL;
+	new_pci->bus = bus;
+	new_pci->dev_fn = dev_fn;
+
+	return;
+}
+
+
+int get_pci_list(char* buf)
 {
-	if (pcibios_present()==0) printk("ProbePci PCI bios not detected.\n");
-	 else {
-		printk( "Probing PCI hardware.\n");
-		probe_devices(0);
+	int pr, length;
+	pci_resource_t* temp = pci_list.next;
+	struct	pci_class_type	pci_class[PCI_CLASS_NUM+1] = PCI_CLASS_TYPE;
+	struct	pci_vendor_type	pci_vendor[PCI_VENDOR_NUM+1] = PCI_VENDOR_TYPE;
+	struct	pci_device_type	pci_device[PCI_DEVICE_NUM+1] = PCI_DEVICE_TYPE;
+
+	for (length = 0 ; (temp) && (length<4000); temp = temp->next)
+	{
+		pr=vendor_decode(temp->bus,temp->dev_fn);
+
+		length += sprintf(buf+length, "Bus %2d Device %3d Function %2d.\n",
+			(int)temp->bus,
+			(int)((temp->dev_fn & 0xf8) >> 3),
+			(int) (temp->dev_fn & 7));
+
+		length += sprintf(buf+length, "    %s : %s %s (rev %d). ",
+			pci_class[class_decode(temp->bus, temp->dev_fn)].class_name,
+			pci_vendor[pr].vendor_name,
+			pci_device[device_decode(temp->bus, temp->dev_fn, pci_vendor[pr].vendor_id)].device_name,
+			revision_decode(temp->bus, temp->dev_fn));
+
+		if (bist_probe(temp->bus, temp->dev_fn))
+			length += sprintf(buf+length, "BIST capable. ");
+
+		if ((pr = interrupt_decode(temp->bus, temp->dev_fn)) != 0)
+			length += sprintf(buf+length, "8259's interrupt %d.", pr);
+
+		length += sprintf(buf+length, "\n");
 	}
+
+	if (temp)
+		length += sprintf(buf+length, "4K limit reached!\n");
+
+	return length;
 }
 
+
 #endif
 
 unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end)
@@ -638,3 +711,6 @@
 #endif
 	return memory_start;
 }
+
+
+
diff -u --recursive --new-file v1.1.78/linux/arch/i386/kernel/ioport.c linux/arch/i386/kernel/ioport.c
--- v1.1.78/linux/arch/i386/kernel/ioport.c	Mon Jan  9 11:24:20 1995
+++ linux/arch/i386/kernel/ioport.c	Wed Jan 11 07:55:49 1995
@@ -12,7 +12,6 @@
 #include <linux/ioport.h>
 
 #define IOTABLE_SIZE 32
-#define STR(x) #x
 
 typedef struct resource_entry_t {
 	u_long from, num;
@@ -202,7 +201,7 @@
 }
 
 /*
- * This is for compatibilty with older drivers.
+ * This is for compatibility with older drivers.
  * It can be removed when all driver call the new function.
  */
 void snarf_region(unsigned int from, unsigned int num)
diff -u --recursive --new-file v1.1.78/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v1.1.78/linux/arch/i386/kernel/traps.c	Mon Jan  9 07:21:56 1995
+++ linux/arch/i386/kernel/traps.c	Wed Jan 11 08:11:02 1995
@@ -82,11 +82,23 @@
 asmlinkage void reserved(void);
 asmlinkage void alignment_check(void);
 
+int kstack_depth_to_print = 24;
+
+/*
+ * These constants are for searching for possible module text
+ * segments.  VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
+ * a guess of how much space is likely to be vmalloced.
+ */
+#define VMALLOC_OFFSET (8*1024*1024)
+#define MODULE_RANGE (8*1024*1024)
+
 /*static*/ void die_if_kernel(char * str, struct pt_regs * regs, long err)
 {
 	int i;
 	unsigned long esp;
 	unsigned short ss;
+	unsigned long *stack, addr, module_start, module_end;
+	extern char start_kernel, etext;
 
 	esp = (unsigned long) &regs->esp;
 	ss = KERNEL_DS;
@@ -110,8 +122,38 @@
 		printk("Corrupted stack page\n");
 	printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)\nStack: ",
 		current->comm, current->pid, 0xffff & i, current->kernel_stack_page);
-	for(i=0;i<5;i++)
-		printk("%08lx ", get_seg_long(ss,(i+(unsigned long *)esp)));
+	stack = (unsigned long *) esp;
+	for(i=0; i < kstack_depth_to_print; i++) {
+		if (((long) stack & 4095) == 0)
+			break;
+		if (i && ((i % 8) == 0))
+			printk("\n       ");
+		printk("%08lx ", get_seg_long(ss,stack++));
+	}
+	printk("\nCall Trace: ");
+	stack = (unsigned long *) esp;
+	i = 1;
+	module_start = ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
+	module_end = module_start + MODULE_RANGE;
+	while (((long) stack & 4095) != 0) {
+		addr = get_seg_long(ss, stack++);
+		/*
+		 * If the address is either in the text segment of the
+		 * kernel, or in the region which contains vmalloc'ed
+		 * memory, it *may* be the address of a calling
+		 * routine; if so, print it so that someone tracing
+		 * down the cause of the crash will be able to figure
+		 * out the call path that was taken.
+		 */
+		if (((addr >= (unsigned long) &start_kernel) &&
+		     (addr <= (unsigned long) &etext)) ||
+		    ((addr >= module_start) && (addr <= module_end))) {
+			if (i && ((i % 8) == 0))
+				printk("\n       ");
+			printk("%08lx ", addr);
+			i++;
+		}
+	}
 	printk("\nCode: ");
 	for(i=0;i<20;i++)
 		printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/Makefile linux/arch/sparc/Makefile
--- v1.1.78/linux/arch/sparc/Makefile	Mon Jan  9 07:21:58 1995
+++ linux/arch/sparc/Makefile	Wed Jan 11 09:01:16 1995
@@ -1,7 +1,7 @@
 #
 # sparc/Makefile
 #
-# Makefile for the architecture dependant flags and dependancies on the
+# Makefile for the architecture dependent flags and dependencies on the
 # Sparc.
 #
 # Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
@@ -19,8 +19,8 @@
 
 HEAD := arch/sparc/kernel/head.o
 
-SUBDIRS := $(SUBDIRS) arch/sparc/kernel
-ARCHIVES := arch/sparc/kernel/kernel.o $(ARCHIVES)
+SUBDIRS := $(SUBDIRS) arch/sparc/kernel arch/sparc/lib
+ARCHIVES := arch/sparc/kernel/kernel.o arch/sparc/lib/lib.a $(ARCHIVES)
 
 archclean:
 
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S
--- v1.1.78/linux/arch/sparc/kernel/entry.S	Mon Jan  9 11:24:20 1995
+++ linux/arch/sparc/kernel/entry.S	Wed Jan 11 09:01:41 1995
@@ -9,6 +9,7 @@
  */
 
 #include <asm/head.h>
+#include <asm/asi.h>
 
 /* Here are macros for routines we do often, this allows me to inline this
  * without making the code look real ugly. Well, the macro looks ugly too but
@@ -223,9 +224,9 @@
 		TRAP_WIN_CLEAN
 
 		nop
-		or %%g0, %l3, %o0
+		or %g0, %l3, %o0
 		call _do_hw_interrupt
-		or %%g0, %%g0, %o1
+		or %g0, %g0, %o1
 		wr %l0, 0x20, %psr  ! re-enable traps and reset the condition codes
 		nop
 		nop
@@ -260,7 +261,7 @@
 	ld	[%l6 + THREAD_WIM], %l5
 	and	%l0, 0x1f, %l3
 
-/* I don't know whats worse, the extra comparison here, or an extra load
+/* I don't know what's worse, the extra comparison here, or an extra load
  * from a lookup table, we'll see.
  */
 	cmp	%l5, %l3
@@ -289,7 +290,7 @@
  * was attempted and a trap occurred. Therefore the restore attempt had no
  * effect on window movement and the trap saved, which means it went in the
  * other direction. :-( We are in a trap window which is two restores away
- * from the window we want to un-invalidate sorta speak and three away from
+ * from the window we want to un-invalidate so to speak and three away from
  * the one which will become invalid after this routine. There are probably
  * bugs already this routine. Bugs suck.
  */
@@ -314,14 +315,14 @@
 	ld	[%l1 + %lo(_current)], %l1
 	st	%l0, [%l1 + THREAD_WIM]
 	save	%g0, %g0, %g0		! back to invalid register
-	ldd	%l0, [%sp]		! load the window from stack
-	ldd	%l2, [%sp + 8]
-	ldd	%l4, [%sp + 16]
-	ldd	%l6, [%sp + 24]
-	ldd	%i0, [%sp + 32]
-	ldd	%i2, [%sp + 40]
-	ldd	%i4, [%sp + 48]
-	ldd	%i6, [%sp + 56]
+	ldd	[%sp], %l0		! load the window from stack
+	ldd	[%sp + 8], %l2
+	ldd	[%sp + 16], %l4
+	ldd	[%sp + 24], %l6
+	ldd	[%sp + 32], %i0
+	ldd	[%sp + 40], %i2
+	ldd	[%sp + 48], %i4
+	ldd	[%sp + 56], %i6
 	save	%g0, %g0, %g0		! to window where trap happened
 	save	%g0, %g0, %g0		! back to trap window, so rett works
 	wr	%l0, 0x0, %psr		! load condition codes
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S
--- v1.1.78/linux/arch/sparc/kernel/head.S	Mon Jan  9 11:24:20 1995
+++ linux/arch/sparc/kernel/head.S	Wed Jan 11 09:01:41 1995
@@ -44,6 +44,8 @@
 #include <asm/version.h>
 #include <asm/asi.h>
 #include <asm/contregs.h>
+#include <asm/psr.h>
+#include <asm/page.h>
 
 	.data
 
@@ -52,7 +54,7 @@
         .globl  _intstack
         .globl  _eintstack
 _intstack:
-        .skip   4 * PAGESIZE                ! 16k = 128 128-byte stack frames
+        .skip   4 * PAGE_SIZE                ! 16k = 128 128-byte stack frames
 _eintstack:
 
 
@@ -77,7 +79,7 @@
  */
 
 /* Uh, actually Linus it is I who cannot spell. Too much murky
- * Sparc assembly will does this to ya.
+ * Sparc assembly will do this to ya.
  */
 _cputypvar:
 	.asciz "compatability"
@@ -181,8 +183,8 @@
 	.text
 
         .globl  _msgbuf
-msgbufsize = PAGESIZE                       ! 1 page for msg buffer
-_msgbuf =  PAGESIZE
+msgbufsize = PAGE_SIZE                       ! 1 page for msg buffer
+_msgbuf =  PAGE_SIZE
 
 
 IE_reg_addr = _msgbuf + msgbufsize      ! this page not used; points to IEreg
@@ -191,7 +193,7 @@
 /* Ok, things start to get interesting. We get linked such that 'start'
    is the entry symbol. However, it is real low in kernel address space
    and as such a nifty place to place the trap table. We achieve this goal
-   by just jumping to 'dostart' for the first trap's entry as the sparc
+   by just jumping to 'gokernel' for the first trap's entry as the sparc
    never receives the zero trap as it is real special (hw reset).
 
    Each trap entry point is the size of 4 sparc instructions (or 4 bytes
@@ -494,7 +496,7 @@
    a v0 or v2 prom.
 */
 
-gokernel:	mov	%o0, %g7
+gokernel:	or	%g0, %o0, %g7
 		st	%o0, [_prom_vector_p]   ! we will need it later
 		rd	%psr, %l2
 		rd	%wim, %l3
@@ -502,7 +504,7 @@
 		or	%g0, %o2, %l5		! could be prom magic value...
 	
 #if 0 /* You think I'm nutz? */
-		cmp	%l5, 0x0		! check for magic SMP pointer
+		subcc	%l5, 0x0, %g0		! check for magic SMP pointer
 		bne	nosmp	
 		nop
 		call    %o2			! call smp prom setup 
@@ -519,15 +521,15 @@
 		st	%l3, [%l1 + %lo(_boot_wim)]
 		sethi	%hi(_boot_tbr), %l1
 		st	%l4, [%l1 + %lo(_boot_tbr)]
-		sethi	%hi(_boot_o_two), %l1
+		sethi	%hi(_boot_smp_ptr), %l1
 		st	%l5, [%l1 + %lo(_boot_smp_ptr)]
 
-		mov	%o0, %g7
+		or	%g0, %o0, %g7
 		sethi	%hi(_prom_vector_p), %g5
 		st	%o0, [%g5 + %lo(_prom_vector_p)]   ! we will need it later
 
 		ld	[%g7 + 0x4], %o3
-		cmp	%o3, 2			! a v2 prom?
+		subcc	%o3, 0x2, %g0			! a v2 prom?
 		be	found_v2
 		nop
 
@@ -538,17 +540,19 @@
 */
 
 		sethi	%hi(LOAD_ADDR), %g6
-		cmp	%o0, %g6		! an old sun4?
-		beq	no_sun4_here
+		subcc	%o0, %g6, %g0		! an old sun4?
+		be	no_sun4_here
 		nop
 
-		st	%g0, [_prom_iface_vers]
+		sethi	%hi(_prom_iface_vers), %g1
+		st	%g0, [%g1 + %lo(_prom_iface_vers)]
 		b	not_v2
 		nop
 
 found_v2:
-		or	%%g0, 0x2, %o5
-		st	%o5, [_prom_iface_vers]
+		or	%g0, 0x2, %o5
+		sethi	%hi(_prom_iface_vers), %g1
+		st	%o5, [%g1 + %lo(_prom_iface_vers)]
 
 not_v2:
 
@@ -573,29 +577,32 @@
 		call 	%l0
 		or	%g0, %g0, %o0		! next_node(0) = first_node
 
-		set	_cputypvar, %o1		! first node has cpu-arch
-		set	_cputypval, %o2		! information, the string
+		sethi	%hi(_cputypvar), %o1	! first node has cpu-arch
+		or	%o1, %lo(_cputypvar), %o1
+		sethi	%hi(_cputypval), %o2	! information, the string
+		or	%o2, %lo(_cputypval), %o2
 		ld	[%l1], %l0		! 'compatibility' tells
-		ld	[%l0 + 0x0c], %l0	! that we want 'sun4x' where
+		ld	[%l0 + 0xc], %l0	! that we want 'sun4x' where
 		call	%l0			! x is one of '', 'c', 'm',
 		nop				! 'd' or 'e'. %o2 holds pointer
 						! to a buf where above string
 						! will get stored by the prom.
 
-		set	_cputypval, %o2		! better safe than sorry
-		ldub	[%o2 + 4], %o0
-		cmp	%o0, 'c'		! we already know we are not
-		beq	is_sun4c		! on a plain sun4 because of
+		sethi	%hi(_cputypval), %o2	! better safe than sorry
+		or	%o2, %lo(_cputypval), %o2
+		ldub	[%o2 + 0x4], %o0
+		subcc	%o0, 'c', %g0		! we already know we are not
+		be	is_sun4c		! on a plain sun4 because of
 		nop				! the check for 0x4000 in %o0
-		cmp	%o0, 'm'		! at start:
-		beq	is_sun4m
+		subcc	%o0, 'm', %g0		! at start:
+		be	is_sun4m
 		nop
 		b	no_sun4d_here		! god bless the person who
 		nop				! tried to run this on sun4d
 
 is_sun4m:
 is_sun4c:					! OK, this is a sun4c, yippie
-		mov 	%g7, %g6		! load up the promvec offsets
+		or 	%g0, %g7, %g6		! load up the promvec offsets
 		sethi	%hi(prom_magic), %g5   	! magic mushroom :>
 		st	%g6, [%g5 + %lo(prom_magic)]
 		add	%g7, 0x4, %g6
@@ -639,29 +646,39 @@
  * as the prom expects.
  */
 
-		set	boot_msg, %o0	
-		ld	[prom_printf], %o1
+		sethi	%hi(boot_msg), %o0	
+		or	%o0, %lo(boot_msg), %o0
+		sethi	%hi(prom_printf), %o1
+		ld	[%o1 + %lo(prom_printf)], %o1
 		ld	[%o1], %o1
 		call	%o1  			! print boot message #1
 		nop
 
-_newline:	set	newline, %o0
-		ld	[prom_printf], %o1
+_newline:	sethi	%hi(newline), %o0
+		or	%o0, %lo(newline), %o0
+		sethi	%hi(prom_printf), %o1
+		ld	[%o1 + %lo(prom_printf)], %o1
 		ld	[%o1], %o1
 		call	%o1
 		nop
 
-		set	pstring1, %o0
-		ld	[prom_printf], %o2
+		sethi	%hi(pstring1), %o0
+		or	%o0, %lo(pstring1), %o0
+		sethi	%hi(prom_printf), %o2
+		ld	[%o2 + %lo(prom_printf)], %o2
 		ld	[%o2], %o2
-		ld	[prom_magic], %o1
+		sethi	%hi(prom_magic), %o1
+		ld	[%o1 + %lo(prom_magic)], %o1
 		ld	[%o1], %o1
 		call	%o2
 
-		set	pstring2, %o0
-		ld	[prom_printf], %o2
+		sethi	%hi(pstring2), %o0
+		or	%o0, %lo(pstring2), %o0
+		sethi	%hi(prom_printf), %o2
+		ld	[%o2 + %lo(prom_printf)], %o2
 		ld	[%o2], %o2
-		ld	[_prom_iface_vers], %o1
+		sethi	%hi(_prom_iface_vers), %o1
+		ld	[%o1 + %lo(_prom_iface_vers)], %o1
 		ld	[%o1], %o1
 		call 	%o2
 
@@ -675,9 +692,9 @@
 		nop
 
 rest_of_boot:
-		mov	PAGESHIFT_SUN4C, %g5
+		or	%g0, PAGE_SHIFT, %g5
 
-		set	AC_CONTEXT, %g1		! kernel context, safe now
+		sethi	%hi(AC_CONTEXT), %g1	! kernel context, safe now
 						! the only valid context
 						! until we call paging_init()
 		stba	%g0, [%g1] ASI_CONTROL
@@ -690,7 +707,7 @@
 
 /* Uh, oh, interrupt time. This crap is real confusing. What I want to do is
  * clear all interrupts, map the interrupt enable register which in effect
- * enables non-maskable interrupts (or NMI's). Actuall we take no interrupts
+ * enables non-maskable interrupts (or NMI's). Actually we take no interrupts
  * until we frob with the %tbr (trap base register) which the prom has set 
  * to all its routines which allows some sanity during bootup.
  */
@@ -711,7 +728,8 @@
  * show-time!
  */
 
-		set	1f, %g1
+		sethi	%hi(1f), %g1
+		or	%g1, %lo(1f), %g1
 		jmp	%g1
 		nop
 
@@ -734,26 +752,31 @@
 
 		rd	%psr, %g3
 		andn	%g3, PSR_ET, %g3
-		wr	%g3, 0, %psr		! make sure traps are off
+		wr	%g3, 0x0, %psr		! make sure traps are off
 						! before we play around
-		WRITE_PAUSE			! no guarentees until 3 insns
+		WRITE_PAUSE			! no guarantees until 3 insns
 
 
-		wr	%g0, 0, %wim		! magical invalid window reg
+		wr	%g0, 0x0, %wim		! magical invalid window reg
 		WRITE_PAUSE			! see above
 
 	
 /* I keep the timer interrupt on so that BogoMIPS works and the prom
  * keeps updating it's "jiffies" counter. 100HZ clock on sparcstations.
  */	
-		wr	%g0, (PSR_S | PSR_PS | PSR_PIL), %psr
+
+/* If gas wasn't so dumb, I could use or'd macros in this next
+ * write. ;-( like this (PSR_PS | PSR_S | PSR_PIL)...
+ */
+
+		wr	%g0, (0xfc0), %psr
 		WRITE_PAUSE
 
-		wr	%g0, 2, %wim		! window 1 invalid
+		wr	%g0, 0x2, %wim		! window 1 invalid
 		WRITE_PAUSE
-		mov	1, %g1
-		sethi	%hi(_task + PCB_WIM), %g2
-		st	%g1, [%g2 + %lo(_task + PCB_WIM)]
+		or	%g0, 0x1, %g1
+		sethi	%hi(_current + THREAD_WIM), %g2
+		st	%g1, [%g2 + %lo(_current + THREAD_WIM)]
 
 /* I want a kernel stack NOW! */
 
@@ -765,7 +788,7 @@
 
 
 /*
- * Maybe the prom zero's out our BSS section, maybe it doesn't. I certainly 
+ * Maybe the prom zeroes out our BSS section, maybe it doesn't. I certainly 
  * don't know, do you?
  */
 
@@ -788,12 +811,12 @@
 		sub	%g3, %g4, %g2
 		sethi	%hi(_kernel_data_len), %g3
 		st	%g2, [%g3 + %lo(_kernel_data_len)]
-		clr	%g1
+		or	%g0, %g0, %g1
 
 1:	
 		st	%g0, [%o0]
 		add	%o0, 0x4, %o0
-		cmp	%o0, %o1
+		subcc	%o0, %o1, %g0
 		bl	1b
 		nop
 
@@ -812,7 +835,7 @@
 		or	%g0, 0x0, %g3
 
 1:		srl	%g1, 0x1, %g1			! shift until highest
-		cmp	%g1, 0x0			! bit set
+		subcc	%g1, 0x0, %g0			! bit set
 		bne	1b
 		add	%g3, 0x1, %g3
 		sethi	%hi(_nwindows), %g4
@@ -906,7 +929,7 @@
  * sequence, all sorts of bad things can happen
  */
 
-prom_abort:		.skip 4		! "L1-A" magic cookie
+prom_abort:		.skip 4		! L1-A magic cookie
 					! must be mapped in ALL contexts
 
 /* prom_sync is a place where the kernel should place a pointer to a kernel
@@ -916,7 +939,7 @@
  * executed. Nice feature eh?
  */
 
-prom_sync:		.skip 4			! hook in prom for "sync" func
+prom_sync:		.skip 4			! hook in prom for sync func
 
 	.align 4
 
@@ -930,14 +953,15 @@
 _nwindowsm1:	.skip 4
 
 	.align 4
-/* Boot time priviledged register values, plus magic %o2 value */
+/* Boot time privileged register values, plus magic %o2 value */
 
 	.globl _boot_wim
 	.globl _boot_psr
 	.globl _boot_tbr
-	.globl _boot_o_two
+	.globl _boot_smp_ptr
 _boot_wim:		.skip 4
 _boot_psr:		.skip 4
 _boot_tbr:		.skip 4
 _boot_smp_ptr:		.skip 4
+
 
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- v1.1.78/linux/arch/sparc/kernel/irq.c	Mon Jan  9 11:24:20 1995
+++ linux/arch/sparc/kernel/irq.c	Wed Jan 11 09:01:41 1995
@@ -19,6 +19,11 @@
  * sa_restorer is the unused
  */
 
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <linux/linkage.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
 
 void disable_irq(unsigned int irq_nr)
 {
@@ -87,7 +92,7 @@
 int request_irq(unsigned int irq, void (*handler)(int),
 	unsigned long flags, const char * devname)
 {
-	return irqaction(irq,&sa);
+	return irqaction(irq, (struct sigaction *) 0);
 }
 
 void free_irq(unsigned int irq)
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v1.1.78/linux/arch/sparc/kernel/process.c	Mon Jan  9 07:21:58 1995
+++ linux/arch/sparc/kernel/process.c	Wed Jan 11 09:01:41 1995
@@ -30,8 +30,6 @@
  */
 asmlinkage int sys_idle(void)
 {
-	int i;
-
 	if (current->pid != 0)
 		return -EPERM;
 
@@ -54,7 +52,6 @@
 {
 	regs->sp = sp;
 	regs->fp = fp;
-	regs->psr = psr;
 }
 
 /*
@@ -75,9 +72,8 @@
 	struct pt_regs * childregs;
 
 	childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
-	p->tss.sp = (unsigned long) childregs;
+	p->tss.usp = (unsigned long) childregs;
 	*childregs = *regs;
-	p->tss.back_link = 0;
 	p->tss.psr = regs->psr; /* for condition codes */
 	return clone_flags;
 }
@@ -98,8 +94,8 @@
 	int error;
 	char * filename;
 
-	error = do_execve(filename, (char **) regs.reg_window[0], 
-			  (char **) regs.reg_window[1], &regs);
+	error = do_execve(filename, (char **) regs.u_regs[0], 
+			  (char **) regs.u_regs[1], &regs);
 	putname(filename);
 	return error;
 }
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/kernel/traps.c linux/arch/sparc/kernel/traps.c
--- v1.1.78/linux/arch/sparc/kernel/traps.c	Mon Jan  9 07:21:58 1995
+++ linux/arch/sparc/kernel/traps.c	Wed Jan 11 09:01:41 1995
@@ -8,6 +8,8 @@
  * I hate traps on the sparc, grrr...
  */
 
+#include <linux/sched.h>  /* for jiffies */
+#include <linux/kernel.h>
 
 void do_hw_interrupt(unsigned long type, unsigned long vector)
 {
@@ -23,7 +25,7 @@
   return;
 }
 
-extern unsigned int *trapbase;
+extern unsigned long *trapbase;
 
 void trap_init(void)
 {
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/COPYING.LIB linux/arch/sparc/lib/COPYING.LIB
--- v1.1.78/linux/arch/sparc/lib/COPYING.LIB	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/lib/COPYING.LIB	Wed Jan 11 09:02:26 1995
@@ -0,0 +1,481 @@
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+                    675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+     Appendix: How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/Makefile linux/arch/sparc/lib/Makefile
--- v1.1.78/linux/arch/sparc/lib/Makefile	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/lib/Makefile	Wed Jan 11 09:02:26 1995
@@ -0,0 +1,44 @@
+#
+# Makefile for Sparc library files..
+#
+
+.c.s:
+	$(CC) $(CFLAGS) -S $<
+.s.o:
+	$(AS) -c -o $*.o $<
+.c.o:
+	$(CC) $(CFLAGS) -c $<
+
+OBJS  = mul.o rem.o sdiv.o udiv.o umul.o urem.o
+
+lib.a: $(OBJS)
+	$(AR) rcs lib.a $(OBJS)
+	sync
+
+mul.o: mul.S
+	$(CC) -c -o mul.o mul.S
+
+rem.o: rem.S
+	$(CC) -DST_DIV0=0x2 -c -o rem.o rem.S
+
+sdiv.o: sdiv.S
+	$(CC) -DST_DIV0=0x2 -c -o sdiv.o sdiv.S
+
+udiv.o: udiv.S
+	$(CC) -DST_DIV0=0x2 -c -o udiv.o udiv.S
+
+umul.o: umul.S
+	$(CC) -c -o umul.o umul.S
+
+urem.o: urem.S
+	$(CC) -DST_DIV0=0x2 -c -o urem.o urem.S
+
+dep:
+	$(CPP) -M *.S > .depend
+
+#
+# include a dependency file if one exists
+#
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/mul.S linux/arch/sparc/lib/mul.S
--- v1.1.78/linux/arch/sparc/lib/mul.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/lib/mul.S	Wed Jan 11 09:02:26 1995
@@ -0,0 +1,127 @@
+/* mul.S:       This routine was taken from glibc-1.09 and is covered
+ *              by the GNU Library General Public License Version 2.
+ */
+
+/*
+ * Signed multiply, from Appendix E of the Sparc Version 8
+ * Architecture Manual.
+ */
+
+/*
+ * Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the upper 32 bits of
+ * the 64-bit product).
+ *
+ * This code optimizes short (less than 13-bit) multiplies.
+ */
+
+	.globl .mul
+.mul:
+	mov	%o0, %y		! multiplier -> Y
+	andncc	%o0, 0xfff, %g0	! test bits 12..31
+	be	Lmul_shortway	! if zero, can do it the short way
+	andcc	%g0, %g0, %o4	! zero the partial product and clear N and V
+
+	/*
+	 * Long multiply.  32 steps, followed by a final shift step.
+	 */
+	mulscc	%o4, %o1, %o4	! 1
+	mulscc	%o4, %o1, %o4	! 2
+	mulscc	%o4, %o1, %o4	! 3
+	mulscc	%o4, %o1, %o4	! 4
+	mulscc	%o4, %o1, %o4	! 5
+	mulscc	%o4, %o1, %o4	! 6
+	mulscc	%o4, %o1, %o4	! 7
+	mulscc	%o4, %o1, %o4	! 8
+	mulscc	%o4, %o1, %o4	! 9
+	mulscc	%o4, %o1, %o4	! 10
+	mulscc	%o4, %o1, %o4	! 11
+	mulscc	%o4, %o1, %o4	! 12
+	mulscc	%o4, %o1, %o4	! 13
+	mulscc	%o4, %o1, %o4	! 14
+	mulscc	%o4, %o1, %o4	! 15
+	mulscc	%o4, %o1, %o4	! 16
+	mulscc	%o4, %o1, %o4	! 17
+	mulscc	%o4, %o1, %o4	! 18
+	mulscc	%o4, %o1, %o4	! 19
+	mulscc	%o4, %o1, %o4	! 20
+	mulscc	%o4, %o1, %o4	! 21
+	mulscc	%o4, %o1, %o4	! 22
+	mulscc	%o4, %o1, %o4	! 23
+	mulscc	%o4, %o1, %o4	! 24
+	mulscc	%o4, %o1, %o4	! 25
+	mulscc	%o4, %o1, %o4	! 26
+	mulscc	%o4, %o1, %o4	! 27
+	mulscc	%o4, %o1, %o4	! 28
+	mulscc	%o4, %o1, %o4	! 29
+	mulscc	%o4, %o1, %o4	! 30
+	mulscc	%o4, %o1, %o4	! 31
+	mulscc	%o4, %o1, %o4	! 32
+	mulscc	%o4, %g0, %o4	! final shift
+
+	! If %o0 was negative, the result is
+	!	(%o0 * %o1) + (%o1 << 32))
+	! We fix that here.
+
+#if 0
+	tst	%o0
+	bge	1f
+	rd	%y, %o0
+
+	! %o0 was indeed negative; fix upper 32 bits of result by subtracting 
+	! %o1 (i.e., return %o4 - %o1 in %o1).
+	retl
+	sub	%o4, %o1, %o1
+
+1:
+	retl
+	mov	%o4, %o1
+#else
+	/* Faster code adapted from tege@sics.se's code for umul.S.  */
+	sra	%o0, 31, %o2	! make mask from sign bit
+	and	%o1, %o2, %o2	! %o2 = 0 or %o1, depending on sign of %o0
+	rd	%y, %o0		! get lower half of product
+	retl
+	sub	%o4, %o2, %o1	! subtract compensation 
+				!  and put upper half in place
+#endif
+
+Lmul_shortway:
+	/*
+	 * Short multiply.  12 steps, followed by a final shift step.
+	 * The resulting bits are off by 12 and (32-12) = 20 bit positions,
+	 * but there is no problem with %o0 being negative (unlike above).
+	 */
+	mulscc	%o4, %o1, %o4	! 1
+	mulscc	%o4, %o1, %o4	! 2
+	mulscc	%o4, %o1, %o4	! 3
+	mulscc	%o4, %o1, %o4	! 4
+	mulscc	%o4, %o1, %o4	! 5
+	mulscc	%o4, %o1, %o4	! 6
+	mulscc	%o4, %o1, %o4	! 7
+	mulscc	%o4, %o1, %o4	! 8
+	mulscc	%o4, %o1, %o4	! 9
+	mulscc	%o4, %o1, %o4	! 10
+	mulscc	%o4, %o1, %o4	! 11
+	mulscc	%o4, %o1, %o4	! 12
+	mulscc	%o4, %g0, %o4	! final shift
+
+	/*
+	 *  %o4 has 20 of the bits that should be in the low part of the
+	 * result; %y has the bottom 12 (as %y's top 12).  That is:
+	 *
+	 *	  %o4		    %y
+	 * +----------------+----------------+
+	 * | -12- |   -20-  | -12- |   -20-  |
+	 * +------(---------+------)---------+
+	 *  --hi-- ----low-part----
+	 *
+	 * The upper 12 bits of %o4 should be sign-extended to form the
+	 * high part of the product (i.e., highpart = %o4 >> 20).
+	 */
+
+	rd	%y, %o5
+	sll	%o4, 12, %o0	! shift middle bits left 12
+	srl	%o5, 20, %o5	! shift low bits right 20, zero fill at left
+	or	%o5, %o0, %o0	! construct low part of result
+	retl
+	sra	%o4, 20, %o1	! ... and extract high part of result
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/rem.S linux/arch/sparc/lib/rem.S
--- v1.1.78/linux/arch/sparc/lib/rem.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/lib/rem.S	Wed Jan 11 09:02:26 1995
@@ -0,0 +1,359 @@
+/* rem.S:       This routine was taken from glibc-1.09 and is covered
+ *              by the GNU Library General Public License Version 2.
+ */
+
+
+/* This file is generated from divrem.m4; DO NOT EDIT! */
+/*
+ * Division and remainder, from Appendix E of the Sparc Version 8
+ * Architecture Manual, with fixes from Gordon Irlam.
+ */
+
+/*
+ * Input: dividend and divisor in %o0 and %o1 respectively.
+ *
+ * m4 parameters:
+ *  .rem	name of function to generate
+ *  rem		rem=div => %o0 / %o1; rem=rem => %o0 % %o1
+ *  true		true=true => signed; true=false => unsigned
+ *
+ * Algorithm parameters:
+ *  N		how many bits per iteration we try to get (4)
+ *  WORDSIZE	total number of bits (32)
+ *
+ * Derived constants:
+ *  TOPBITS	number of bits in the top decade of a number
+ *
+ * Important variables:
+ *  Q		the partial quotient under development (initially 0)
+ *  R		the remainder so far, initially the dividend
+ *  ITER	number of main division loop iterations required;
+ *		equal to ceil(log2(quotient) / N).  Note that this
+ *		is the log base (2^N) of the quotient.
+ *  V		the current comparand, initially divisor*2^(ITER*N-1)
+ *
+ * Cost:
+ *  Current estimate for non-large dividend is
+ *	ceil(log2(quotient) / N) * (10 + 7N/2) + C
+ *  A large dividend is one greater than 2^(31-TOPBITS) and takes a
+ *  different path, as the upper bits of the quotient must be developed
+ *  one bit at a time.
+ */
+
+
+	.globl .rem
+.rem:
+	! compute sign of result; if neither is negative, no problem
+	orcc	%o1, %o0, %g0	! either negative?
+	bge	2f			! no, go do the divide
+	xor	%o1, %o0, %g6	! compute sign in any case
+	tst	%o1
+	bge	1f
+	tst	%o0
+	! %o1 is definitely negative; %o0 might also be negative
+	bge	2f			! if %o0 not negative...
+	sub	%g0, %o1, %o1	! in any case, make %o1 nonneg
+1:	! %o0 is negative, %o1 is nonnegative
+	sub	%g0, %o0, %o0	! make %o0 nonnegative
+2:
+
+	! Ready to divide.  Compute size of quotient; scale comparand.
+	orcc	%o1, %g0, %o5
+	bne	1f
+	mov	%o0, %o3
+
+		! Divide by zero trap.  If it returns, return 0 (about as
+		! wrong as possible, but that is what SunOS does...).
+		ta	ST_DIV0
+		retl
+		clr	%o0
+
+1:
+	cmp	%o3, %o5			! if %o1 exceeds %o0, done
+	blu	Lgot_result		! (and algorithm fails otherwise)
+	clr	%o2
+	sethi	%hi(1 << (32 - 4 - 1)), %g1
+	cmp	%o3, %g1
+	blu	Lnot_really_big
+	clr	%o4
+
+	! Here the dividend is >= 2**(31-N) or so.  We must be careful here,
+	! as our usual N-at-a-shot divide step will cause overflow and havoc.
+	! The number of bits in the result here is N*ITER+SC, where SC <= N.
+	! Compute ITER in an unorthodox manner: know we need to shift V into
+	! the top decade: so do not even bother to compare to R.
+	1:
+		cmp	%o5, %g1
+		bgeu	3f
+		mov	1, %g7
+		sll	%o5, 4, %o5
+		b	1b
+		add	%o4, 1, %o4
+
+	! Now compute %g7.
+	2:	addcc	%o5, %o5, %o5
+		bcc	Lnot_too_big
+		add	%g7, 1, %g7
+
+		! We get here if the %o1 overflowed while shifting.
+		! This means that %o3 has the high-order bit set.
+		! Restore %o5 and subtract from %o3.
+		sll	%g1, 4, %g1	! high order bit
+		srl	%o5, 1, %o5		! rest of %o5
+		add	%o5, %g1, %o5
+		b	Ldo_single_div
+		sub	%g7, 1, %g7
+
+	Lnot_too_big:
+	3:	cmp	%o5, %o3
+		blu	2b
+		nop
+		be	Ldo_single_div
+		nop
+	/* NB: these are commented out in the V8-Sparc manual as well */
+	/* (I do not understand this) */
+	! %o5 > %o3: went too far: back up 1 step
+	!	srl	%o5, 1, %o5
+	!	dec	%g7
+	! do single-bit divide steps
+	!
+	! We have to be careful here.  We know that %o3 >= %o5, so we can do the
+	! first divide step without thinking.  BUT, the others are conditional,
+	! and are only done if %o3 >= 0.  Because both %o3 and %o5 may have the high-
+	! order bit set in the first step, just falling into the regular
+	! division loop will mess up the first time around.
+	! So we unroll slightly...
+	Ldo_single_div:
+		subcc	%g7, 1, %g7
+		bl	Lend_regular_divide
+		nop
+		sub	%o3, %o5, %o3
+		mov	1, %o2
+		b	Lend_single_divloop
+		nop
+	Lsingle_divloop:
+		sll	%o2, 1, %o2
+		bl	1f
+		srl	%o5, 1, %o5
+		! %o3 >= 0
+		sub	%o3, %o5, %o3
+		b	2f
+		add	%o2, 1, %o2
+	1:	! %o3 < 0
+		add	%o3, %o5, %o3
+		sub	%o2, 1, %o2
+	2:
+	Lend_single_divloop:
+		subcc	%g7, 1, %g7
+		bge	Lsingle_divloop
+		tst	%o3
+		b,a	Lend_regular_divide
+
+Lnot_really_big:
+1:
+	sll	%o5, 4, %o5
+	cmp	%o5, %o3
+	bleu	1b
+	addcc	%o4, 1, %o4
+	be	Lgot_result
+	sub	%o4, 1, %o4
+
+	tst	%o3	! set up for initial iteration
+Ldivloop:
+	sll	%o2, 4, %o2
+		! depth 1, accumulated bits 0
+	bl	L.1.16
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 2, accumulated bits 1
+	bl	L.2.17
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 3, accumulated bits 3
+	bl	L.3.19
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 7
+	bl	L.4.23
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (7*2+1), %o2
+	
+L.4.23:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (7*2-1), %o2
+	
+	
+L.3.19:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 5
+	bl	L.4.21
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (5*2+1), %o2
+	
+L.4.21:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (5*2-1), %o2
+	
+	
+	
+L.2.17:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 3, accumulated bits 1
+	bl	L.3.17
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 3
+	bl	L.4.19
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (3*2+1), %o2
+	
+L.4.19:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (3*2-1), %o2
+	
+	
+L.3.17:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 1
+	bl	L.4.17
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (1*2+1), %o2
+	
+L.4.17:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (1*2-1), %o2
+	
+	
+	
+	
+L.1.16:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 2, accumulated bits -1
+	bl	L.2.15
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 3, accumulated bits -1
+	bl	L.3.15
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -1
+	bl	L.4.15
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-1*2+1), %o2
+	
+L.4.15:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-1*2-1), %o2
+	
+	
+L.3.15:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -3
+	bl	L.4.13
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-3*2+1), %o2
+	
+L.4.13:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-3*2-1), %o2
+	
+	
+	
+L.2.15:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 3, accumulated bits -3
+	bl	L.3.13
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -5
+	bl	L.4.11
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-5*2+1), %o2
+	
+L.4.11:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-5*2-1), %o2
+	
+	
+L.3.13:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -7
+	bl	L.4.9
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-7*2+1), %o2
+	
+L.4.9:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-7*2-1), %o2
+	
+	
+	
+	
+	9:
+Lend_regular_divide:
+	subcc	%o4, 1, %o4
+	bge	Ldivloop
+	tst	%o3
+	bl,a	Lgot_result
+	! non-restoring fixup here (one instruction only!)
+	add	%o3, %o1, %o3
+
+
+Lgot_result:
+
+	retl
+	mov %o3, %o0
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/sdiv.S linux/arch/sparc/lib/sdiv.S
--- v1.1.78/linux/arch/sparc/lib/sdiv.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/lib/sdiv.S	Wed Jan 11 09:02:26 1995
@@ -0,0 +1,363 @@
+/* sdiv.S:      This routine was taken from glibc-1.09 and is covered
+ *              by the GNU Library General Public License Version 2.
+ */
+
+
+/* This file is generated from divrem.m4; DO NOT EDIT! */
+/*
+ * Division and remainder, from Appendix E of the Sparc Version 8
+ * Architecture Manual, with fixes from Gordon Irlam.
+ */
+
+/*
+ * Input: dividend and divisor in %o0 and %o1 respectively.
+ *
+ * m4 parameters:
+ *  .div	name of function to generate
+ *  div		div=div => %o0 / %o1; div=rem => %o0 % %o1
+ *  true		true=true => signed; true=false => unsigned
+ *
+ * Algorithm parameters:
+ *  N		how many bits per iteration we try to get (4)
+ *  WORDSIZE	total number of bits (32)
+ *
+ * Derived constants:
+ *  TOPBITS	number of bits in the top decade of a number
+ *
+ * Important variables:
+ *  Q		the partial quotient under development (initially 0)
+ *  R		the remainder so far, initially the dividend
+ *  ITER	number of main division loop iterations required;
+ *		equal to ceil(log2(quotient) / N).  Note that this
+ *		is the log base (2^N) of the quotient.
+ *  V		the current comparand, initially divisor*2^(ITER*N-1)
+ *
+ * Cost:
+ *  Current estimate for non-large dividend is
+ *	ceil(log2(quotient) / N) * (10 + 7N/2) + C
+ *  A large dividend is one greater than 2^(31-TOPBITS) and takes a
+ *  different path, as the upper bits of the quotient must be developed
+ *  one bit at a time.
+ */
+
+
+	.globl .div
+.div:
+	! compute sign of result; if neither is negative, no problem
+	orcc	%o1, %o0, %g0	! either negative?
+	bge	2f			! no, go do the divide
+	xor	%o1, %o0, %g6	! compute sign in any case
+	tst	%o1
+	bge	1f
+	tst	%o0
+	! %o1 is definitely negative; %o0 might also be negative
+	bge	2f			! if %o0 not negative...
+	sub	%g0, %o1, %o1	! in any case, make %o1 nonneg
+1:	! %o0 is negative, %o1 is nonnegative
+	sub	%g0, %o0, %o0	! make %o0 nonnegative
+2:
+
+	! Ready to divide.  Compute size of quotient; scale comparand.
+	orcc	%o1, %g0, %o5
+	bne	1f
+	mov	%o0, %o3
+
+		! Divide by zero trap.  If it returns, return 0 (about as
+		! wrong as possible, but that is what SunOS does...).
+		ta	ST_DIV0
+		retl
+		clr	%o0
+
+1:
+	cmp	%o3, %o5			! if %o1 exceeds %o0, done
+	blu	Lgot_result		! (and algorithm fails otherwise)
+	clr	%o2
+	sethi	%hi(1 << (32 - 4 - 1)), %g1
+	cmp	%o3, %g1
+	blu	Lnot_really_big
+	clr	%o4
+
+	! Here the dividend is >= 2**(31-N) or so.  We must be careful here,
+	! as our usual N-at-a-shot divide step will cause overflow and havoc.
+	! The number of bits in the result here is N*ITER+SC, where SC <= N.
+	! Compute ITER in an unorthodox manner: know we need to shift V into
+	! the top decade: so do not even bother to compare to R.
+	1:
+		cmp	%o5, %g1
+		bgeu	3f
+		mov	1, %g7
+		sll	%o5, 4, %o5
+		b	1b
+		add	%o4, 1, %o4
+
+	! Now compute %g7.
+	2:	addcc	%o5, %o5, %o5
+		bcc	Lnot_too_big
+		add	%g7, 1, %g7
+
+		! We get here if the %o1 overflowed while shifting.
+		! This means that %o3 has the high-order bit set.
+		! Restore %o5 and subtract from %o3.
+		sll	%g1, 4, %g1	! high order bit
+		srl	%o5, 1, %o5		! rest of %o5
+		add	%o5, %g1, %o5
+		b	Ldo_single_div
+		sub	%g7, 1, %g7
+
+	Lnot_too_big:
+	3:	cmp	%o5, %o3
+		blu	2b
+		nop
+		be	Ldo_single_div
+		nop
+	/* NB: these are commented out in the V8-Sparc manual as well */
+	/* (I do not understand this) */
+	! %o5 > %o3: went too far: back up 1 step
+	!	srl	%o5, 1, %o5
+	!	dec	%g7
+	! do single-bit divide steps
+	!
+	! We have to be careful here.  We know that %o3 >= %o5, so we can do the
+	! first divide step without thinking.  BUT, the others are conditional,
+	! and are only done if %o3 >= 0.  Because both %o3 and %o5 may have the high-
+	! order bit set in the first step, just falling into the regular
+	! division loop will mess up the first time around.
+	! So we unroll slightly...
+	Ldo_single_div:
+		subcc	%g7, 1, %g7
+		bl	Lend_regular_divide
+		nop
+		sub	%o3, %o5, %o3
+		mov	1, %o2
+		b	Lend_single_divloop
+		nop
+	Lsingle_divloop:
+		sll	%o2, 1, %o2
+		bl	1f
+		srl	%o5, 1, %o5
+		! %o3 >= 0
+		sub	%o3, %o5, %o3
+		b	2f
+		add	%o2, 1, %o2
+	1:	! %o3 < 0
+		add	%o3, %o5, %o3
+		sub	%o2, 1, %o2
+	2:
+	Lend_single_divloop:
+		subcc	%g7, 1, %g7
+		bge	Lsingle_divloop
+		tst	%o3
+		b,a	Lend_regular_divide
+
+Lnot_really_big:
+1:
+	sll	%o5, 4, %o5
+	cmp	%o5, %o3
+	bleu	1b
+	addcc	%o4, 1, %o4
+	be	Lgot_result
+	sub	%o4, 1, %o4
+
+	tst	%o3	! set up for initial iteration
+Ldivloop:
+	sll	%o2, 4, %o2
+		! depth 1, accumulated bits 0
+	bl	L.1.16
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 2, accumulated bits 1
+	bl	L.2.17
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 3, accumulated bits 3
+	bl	L.3.19
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 7
+	bl	L.4.23
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (7*2+1), %o2
+	
+L.4.23:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (7*2-1), %o2
+	
+	
+L.3.19:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 5
+	bl	L.4.21
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (5*2+1), %o2
+	
+L.4.21:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (5*2-1), %o2
+	
+	
+	
+L.2.17:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 3, accumulated bits 1
+	bl	L.3.17
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 3
+	bl	L.4.19
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (3*2+1), %o2
+	
+L.4.19:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (3*2-1), %o2
+	
+	
+L.3.17:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 1
+	bl	L.4.17
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (1*2+1), %o2
+	
+L.4.17:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (1*2-1), %o2
+	
+	
+	
+	
+L.1.16:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 2, accumulated bits -1
+	bl	L.2.15
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 3, accumulated bits -1
+	bl	L.3.15
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -1
+	bl	L.4.15
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-1*2+1), %o2
+	
+L.4.15:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-1*2-1), %o2
+	
+	
+L.3.15:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -3
+	bl	L.4.13
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-3*2+1), %o2
+	
+L.4.13:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-3*2-1), %o2
+	
+	
+	
+L.2.15:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 3, accumulated bits -3
+	bl	L.3.13
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -5
+	bl	L.4.11
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-5*2+1), %o2
+	
+L.4.11:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-5*2-1), %o2
+	
+	
+L.3.13:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -7
+	bl	L.4.9
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-7*2+1), %o2
+	
+L.4.9:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-7*2-1), %o2
+	
+	
+	
+	
+	9:
+Lend_regular_divide:
+	subcc	%o4, 1, %o4
+	bge	Ldivloop
+	tst	%o3
+	bl,a	Lgot_result
+	! non-restoring fixup here (one instruction only!)
+	sub	%o2, 1, %o2
+
+
+Lgot_result:
+	! check to see if answer should be < 0
+	tst	%g6
+	bl,a	1f
+	sub %g0, %o2, %o2
+1:
+	retl
+	mov %o2, %o0
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/udiv.S linux/arch/sparc/lib/udiv.S
--- v1.1.78/linux/arch/sparc/lib/udiv.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/lib/udiv.S	Wed Jan 11 09:02:26 1995
@@ -0,0 +1,346 @@
+/* udiv.S:      This routine was taken from glibc-1.09 and is covered
+ *              by the GNU Library General Public License Version 2.
+ */
+
+
+/* This file is generated from divrem.m4; DO NOT EDIT! */
+/*
+ * Division and remainder, from Appendix E of the Sparc Version 8
+ * Architecture Manual, with fixes from Gordon Irlam.
+ */
+
+/*
+ * Input: dividend and divisor in %o0 and %o1 respectively.
+ *
+ * m4 parameters:
+ *  .udiv	name of function to generate
+ *  div		div=div => %o0 / %o1; div=rem => %o0 % %o1
+ *  false		false=true => signed; false=false => unsigned
+ *
+ * Algorithm parameters:
+ *  N		how many bits per iteration we try to get (4)
+ *  WORDSIZE	total number of bits (32)
+ *
+ * Derived constants:
+ *  TOPBITS	number of bits in the top decade of a number
+ *
+ * Important variables:
+ *  Q		the partial quotient under development (initially 0)
+ *  R		the remainder so far, initially the dividend
+ *  ITER	number of main division loop iterations required;
+ *		equal to ceil(log2(quotient) / N).  Note that this
+ *		is the log base (2^N) of the quotient.
+ *  V		the current comparand, initially divisor*2^(ITER*N-1)
+ *
+ * Cost:
+ *  Current estimate for non-large dividend is
+ *	ceil(log2(quotient) / N) * (10 + 7N/2) + C
+ *  A large dividend is one greater than 2^(31-TOPBITS) and takes a
+ *  different path, as the upper bits of the quotient must be developed
+ *  one bit at a time.
+ */
+
+
+	.globl .udiv
+.udiv:
+
+	! Ready to divide.  Compute size of quotient; scale comparand.
+	orcc	%o1, %g0, %o5
+	bne	1f
+	mov	%o0, %o3
+
+		! Divide by zero trap.  If it returns, return 0 (about as
+		! wrong as possible, but that is what SunOS does...).
+		ta	ST_DIV0
+		retl
+		clr	%o0
+
+1:
+	cmp	%o3, %o5			! if %o1 exceeds %o0, done
+	blu	Lgot_result		! (and algorithm fails otherwise)
+	clr	%o2
+	sethi	%hi(1 << (32 - 4 - 1)), %g1
+	cmp	%o3, %g1
+	blu	Lnot_really_big
+	clr	%o4
+
+	! Here the dividend is >= 2**(31-N) or so.  We must be careful here,
+	! as our usual N-at-a-shot divide step will cause overflow and havoc.
+	! The number of bits in the result here is N*ITER+SC, where SC <= N.
+	! Compute ITER in an unorthodox manner: know we need to shift V into
+	! the top decade: so do not even bother to compare to R.
+	1:
+		cmp	%o5, %g1
+		bgeu	3f
+		mov	1, %g7
+		sll	%o5, 4, %o5
+		b	1b
+		add	%o4, 1, %o4
+
+	! Now compute %g7.
+	2:	addcc	%o5, %o5, %o5
+		bcc	Lnot_too_big
+		add	%g7, 1, %g7
+
+		! We get here if the %o1 overflowed while shifting.
+		! This means that %o3 has the high-order bit set.
+		! Restore %o5 and subtract from %o3.
+		sll	%g1, 4, %g1	! high order bit
+		srl	%o5, 1, %o5		! rest of %o5
+		add	%o5, %g1, %o5
+		b	Ldo_single_div
+		sub	%g7, 1, %g7
+
+	Lnot_too_big:
+	3:	cmp	%o5, %o3
+		blu	2b
+		nop
+		be	Ldo_single_div
+		nop
+	/* NB: these are commented out in the V8-Sparc manual as well */
+	/* (I do not understand this) */
+	! %o5 > %o3: went too far: back up 1 step
+	!	srl	%o5, 1, %o5
+	!	dec	%g7
+	! do single-bit divide steps
+	!
+	! We have to be careful here.  We know that %o3 >= %o5, so we can do the
+	! first divide step without thinking.  BUT, the others are conditional,
+	! and are only done if %o3 >= 0.  Because both %o3 and %o5 may have the high-
+	! order bit set in the first step, just falling into the regular
+	! division loop will mess up the first time around.
+	! So we unroll slightly...
+	Ldo_single_div:
+		subcc	%g7, 1, %g7
+		bl	Lend_regular_divide
+		nop
+		sub	%o3, %o5, %o3
+		mov	1, %o2
+		b	Lend_single_divloop
+		nop
+	Lsingle_divloop:
+		sll	%o2, 1, %o2
+		bl	1f
+		srl	%o5, 1, %o5
+		! %o3 >= 0
+		sub	%o3, %o5, %o3
+		b	2f
+		add	%o2, 1, %o2
+	1:	! %o3 < 0
+		add	%o3, %o5, %o3
+		sub	%o2, 1, %o2
+	2:
+	Lend_single_divloop:
+		subcc	%g7, 1, %g7
+		bge	Lsingle_divloop
+		tst	%o3
+		b,a	Lend_regular_divide
+
+Lnot_really_big:
+1:
+	sll	%o5, 4, %o5
+	cmp	%o5, %o3
+	bleu	1b
+	addcc	%o4, 1, %o4
+	be	Lgot_result
+	sub	%o4, 1, %o4
+
+	tst	%o3	! set up for initial iteration
+Ldivloop:
+	sll	%o2, 4, %o2
+		! depth 1, accumulated bits 0
+	bl	L.1.16
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 2, accumulated bits 1
+	bl	L.2.17
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 3, accumulated bits 3
+	bl	L.3.19
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 7
+	bl	L.4.23
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (7*2+1), %o2
+	
+L.4.23:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (7*2-1), %o2
+	
+	
+L.3.19:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 5
+	bl	L.4.21
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (5*2+1), %o2
+	
+L.4.21:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (5*2-1), %o2
+	
+	
+	
+L.2.17:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 3, accumulated bits 1
+	bl	L.3.17
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 3
+	bl	L.4.19
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (3*2+1), %o2
+	
+L.4.19:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (3*2-1), %o2
+	
+	
+L.3.17:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 1
+	bl	L.4.17
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (1*2+1), %o2
+	
+L.4.17:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (1*2-1), %o2
+	
+	
+	
+	
+L.1.16:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 2, accumulated bits -1
+	bl	L.2.15
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 3, accumulated bits -1
+	bl	L.3.15
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -1
+	bl	L.4.15
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-1*2+1), %o2
+	
+L.4.15:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-1*2-1), %o2
+	
+	
+L.3.15:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -3
+	bl	L.4.13
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-3*2+1), %o2
+	
+L.4.13:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-3*2-1), %o2
+	
+	
+	
+L.2.15:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 3, accumulated bits -3
+	bl	L.3.13
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -5
+	bl	L.4.11
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-5*2+1), %o2
+	
+L.4.11:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-5*2-1), %o2
+	
+	
+L.3.13:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -7
+	bl	L.4.9
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-7*2+1), %o2
+	
+L.4.9:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-7*2-1), %o2
+	
+	
+	
+	
+	9:
+Lend_regular_divide:
+	subcc	%o4, 1, %o4
+	bge	Ldivloop
+	tst	%o3
+	bl,a	Lgot_result
+	! non-restoring fixup here (one instruction only!)
+	sub	%o2, 1, %o2
+
+
+Lgot_result:
+
+	retl
+	mov %o2, %o0
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/umul.S linux/arch/sparc/lib/umul.S
--- v1.1.78/linux/arch/sparc/lib/umul.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/lib/umul.S	Wed Jan 11 09:02:26 1995
@@ -0,0 +1,158 @@
+/* umul.S:      This routine was taken from glibc-1.09 and is covered
+ *              by the GNU Library General Public License Version 2.
+ */
+
+
+/*
+ * Unsigned multiply.  Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the
+ * upper 32 bits of the 64-bit product).
+ *
+ * This code optimizes short (less than 13-bit) multiplies.  Short
+ * multiplies require 25 instruction cycles, and long ones require
+ * 45 instruction cycles.
+ *
+ * On return, overflow has occurred (%o1 is not zero) if and only if
+ * the Z condition code is clear, allowing, e.g., the following:
+ *
+ *	call	.umul
+ *	nop
+ *	bnz	overflow	(or tnz)
+ */
+
+	.globl .umul
+.umul:
+	or	%o0, %o1, %o4
+	mov	%o0, %y		! multiplier -> Y
+	andncc	%o4, 0xfff, %g0	! test bits 12..31 of *both* args
+	be	Lmul_shortway	! if zero, can do it the short way
+	andcc	%g0, %g0, %o4	! zero the partial product and clear N and V
+
+	/*
+	 * Long multiply.  32 steps, followed by a final shift step.
+	 */
+	mulscc	%o4, %o1, %o4	! 1
+	mulscc	%o4, %o1, %o4	! 2
+	mulscc	%o4, %o1, %o4	! 3
+	mulscc	%o4, %o1, %o4	! 4
+	mulscc	%o4, %o1, %o4	! 5
+	mulscc	%o4, %o1, %o4	! 6
+	mulscc	%o4, %o1, %o4	! 7
+	mulscc	%o4, %o1, %o4	! 8
+	mulscc	%o4, %o1, %o4	! 9
+	mulscc	%o4, %o1, %o4	! 10
+	mulscc	%o4, %o1, %o4	! 11
+	mulscc	%o4, %o1, %o4	! 12
+	mulscc	%o4, %o1, %o4	! 13
+	mulscc	%o4, %o1, %o4	! 14
+	mulscc	%o4, %o1, %o4	! 15
+	mulscc	%o4, %o1, %o4	! 16
+	mulscc	%o4, %o1, %o4	! 17
+	mulscc	%o4, %o1, %o4	! 18
+	mulscc	%o4, %o1, %o4	! 19
+	mulscc	%o4, %o1, %o4	! 20
+	mulscc	%o4, %o1, %o4	! 21
+	mulscc	%o4, %o1, %o4	! 22
+	mulscc	%o4, %o1, %o4	! 23
+	mulscc	%o4, %o1, %o4	! 24
+	mulscc	%o4, %o1, %o4	! 25
+	mulscc	%o4, %o1, %o4	! 26
+	mulscc	%o4, %o1, %o4	! 27
+	mulscc	%o4, %o1, %o4	! 28
+	mulscc	%o4, %o1, %o4	! 29
+	mulscc	%o4, %o1, %o4	! 30
+	mulscc	%o4, %o1, %o4	! 31
+	mulscc	%o4, %o1, %o4	! 32
+	mulscc	%o4, %g0, %o4	! final shift
+
+
+	/*
+	 * Normally, with the shift-and-add approach, if both numbers are
+	 * positive you get the correct result.  With 32-bit two's-complement
+	 * numbers, -x is represented as
+	 *
+	 *		  x		    32
+	 *	( 2  -  ------ ) mod 2  *  2
+	 *		   32
+	 *		  2
+	 *
+	 * (the `mod 2' subtracts 1 from 1.bbbb).  To avoid lots of 2^32s,
+	 * we can treat this as if the radix point were just to the left
+	 * of the sign bit (multiply by 2^32), and get
+	 *
+	 *	-x  =  (2 - x) mod 2
+	 *
+	 * Then, ignoring the `mod 2's for convenience:
+	 *
+	 *   x *  y	= xy
+	 *  -x *  y	= 2y - xy
+	 *   x * -y	= 2x - xy
+	 *  -x * -y	= 4 - 2x - 2y + xy
+	 *
+	 * For signed multiplies, we subtract (x << 32) from the partial
+	 * product to fix this problem for negative multipliers (see mul.s).
+	 * Because of the way the shift into the partial product is calculated
+	 * (N xor V), this term is automatically removed for the multiplicand,
+	 * so we don't have to adjust.
+	 *
+	 * But for unsigned multiplies, the high order bit wasn't a sign bit,
+	 * and the correction is wrong.  So for unsigned multiplies where the
+	 * high order bit is one, we end up with xy - (y << 32).  To fix it
+	 * we add y << 32.
+	 */
+#if 0
+	tst	%o1
+	bl,a	1f		! if %o1 < 0 (high order bit = 1),
+	add	%o4, %o0, %o4	! %o4 += %o0 (add y to upper half)
+1:	rd	%y, %o0		! get lower half of product
+	retl
+	addcc	%o4, %g0, %o1	! put upper half in place and set Z for %o1==0
+#else
+	/* Faster code from tege@sics.se.  */
+	sra	%o1, 31, %o2	! make mask from sign bit
+	and	%o0, %o2, %o2	! %o2 = 0 or %o0, depending on sign of %o1
+	rd	%y, %o0		! get lower half of product
+	retl
+	addcc	%o4, %o2, %o1	! add compensation and put upper half in place
+#endif
+
+Lmul_shortway:
+	/*
+	 * Short multiply.  12 steps, followed by a final shift step.
+	 * The resulting bits are off by 12 and (32-12) = 20 bit positions,
+	 * but there is no problem with %o0 being negative (unlike above),
+	 * and overflow is impossible (the answer is at most 24 bits long).
+	 */
+	mulscc	%o4, %o1, %o4	! 1
+	mulscc	%o4, %o1, %o4	! 2
+	mulscc	%o4, %o1, %o4	! 3
+	mulscc	%o4, %o1, %o4	! 4
+	mulscc	%o4, %o1, %o4	! 5
+	mulscc	%o4, %o1, %o4	! 6
+	mulscc	%o4, %o1, %o4	! 7
+	mulscc	%o4, %o1, %o4	! 8
+	mulscc	%o4, %o1, %o4	! 9
+	mulscc	%o4, %o1, %o4	! 10
+	mulscc	%o4, %o1, %o4	! 11
+	mulscc	%o4, %o1, %o4	! 12
+	mulscc	%o4, %g0, %o4	! final shift
+
+	/*
+	 * %o4 has 20 of the bits that should be in the result; %y has
+	 * the bottom 12 (as %y's top 12).  That is:
+	 *
+	 *	  %o4		    %y
+	 * +----------------+----------------+
+	 * | -12- |   -20-  | -12- |   -20-  |
+	 * +------(---------+------)---------+
+	 *	   -----result-----
+	 *
+	 * The 12 bits of %o4 left of the `result' area are all zero;
+	 * in fact, all top 20 bits of %o4 are zero.
+	 */
+
+	rd	%y, %o5
+	sll	%o4, 12, %o0	! shift middle bits left 12
+	srl	%o5, 20, %o5	! shift low bits right 20
+	or	%o5, %o0, %o0
+	retl
+	addcc	%g0, %g0, %o1	! %o1 = zero, and set Z
diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/urem.S linux/arch/sparc/lib/urem.S
--- v1.1.78/linux/arch/sparc/lib/urem.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/lib/urem.S	Wed Jan 11 09:02:26 1995
@@ -0,0 +1,344 @@
+/* urem.S:      This routine was taken from glibc-1.09 and is covered
+ *              by the GNU Library General Public License Version 2.
+ */
+
+/* This file is generated from divrem.m4; DO NOT EDIT! */
+/*
+ * Division and remainder, from Appendix E of the Sparc Version 8
+ * Architecture Manual, with fixes from Gordon Irlam.
+ */
+
+/*
+ * Input: dividend and divisor in %o0 and %o1 respectively.
+ *
+ * m4 parameters:
+ *  .urem	name of function to generate
+ *  rem		rem=div => %o0 / %o1; rem=rem => %o0 % %o1
+ *  false		false=true => signed; false=false => unsigned
+ *
+ * Algorithm parameters:
+ *  N		how many bits per iteration we try to get (4)
+ *  WORDSIZE	total number of bits (32)
+ *
+ * Derived constants:
+ *  TOPBITS	number of bits in the top decade of a number
+ *
+ * Important variables:
+ *  Q		the partial quotient under development (initially 0)
+ *  R		the remainder so far, initially the dividend
+ *  ITER	number of main division loop iterations required;
+ *		equal to ceil(log2(quotient) / N).  Note that this
+ *		is the log base (2^N) of the quotient.
+ *  V		the current comparand, initially divisor*2^(ITER*N-1)
+ *
+ * Cost:
+ *  Current estimate for non-large dividend is
+ *	ceil(log2(quotient) / N) * (10 + 7N/2) + C
+ *  A large dividend is one greater than 2^(31-TOPBITS) and takes a
+ *  different path, as the upper bits of the quotient must be developed
+ *  one bit at a time.
+ */
+
+	.globl .urem
+.urem:
+
+	! Ready to divide.  Compute size of quotient; scale comparand.
+	orcc	%o1, %g0, %o5
+	bne	1f
+	mov	%o0, %o3
+
+		! Divide by zero trap.  If it returns, return 0 (about as
+		! wrong as possible, but that is what SunOS does...).
+		ta	ST_DIV0
+		retl
+		clr	%o0
+
+1:
+	cmp	%o3, %o5			! if %o1 exceeds %o0, done
+	blu	Lgot_result		! (and algorithm fails otherwise)
+	clr	%o2
+	sethi	%hi(1 << (32 - 4 - 1)), %g1
+	cmp	%o3, %g1
+	blu	Lnot_really_big
+	clr	%o4
+
+	! Here the dividend is >= 2**(31-N) or so.  We must be careful here,
+	! as our usual N-at-a-shot divide step will cause overflow and havoc.
+	! The number of bits in the result here is N*ITER+SC, where SC <= N.
+	! Compute ITER in an unorthodox manner: know we need to shift V into
+	! the top decade: so do not even bother to compare to R.
+	1:
+		cmp	%o5, %g1
+		bgeu	3f
+		mov	1, %g7
+		sll	%o5, 4, %o5
+		b	1b
+		add	%o4, 1, %o4
+
+	! Now compute %g7.
+	2:	addcc	%o5, %o5, %o5
+		bcc	Lnot_too_big
+		add	%g7, 1, %g7
+
+		! We get here if the %o1 overflowed while shifting.
+		! This means that %o3 has the high-order bit set.
+		! Restore %o5 and subtract from %o3.
+		sll	%g1, 4, %g1	! high order bit
+		srl	%o5, 1, %o5		! rest of %o5
+		add	%o5, %g1, %o5
+		b	Ldo_single_div
+		sub	%g7, 1, %g7
+
+	Lnot_too_big:
+	3:	cmp	%o5, %o3
+		blu	2b
+		nop
+		be	Ldo_single_div
+		nop
+	/* NB: these are commented out in the V8-Sparc manual as well */
+	/* (I do not understand this) */
+	! %o5 > %o3: went too far: back up 1 step
+	!	srl	%o5, 1, %o5
+	!	dec	%g7
+	! do single-bit divide steps
+	!
+	! We have to be careful here.  We know that %o3 >= %o5, so we can do the
+	! first divide step without thinking.  BUT, the others are conditional,
+	! and are only done if %o3 >= 0.  Because both %o3 and %o5 may have the high-
+	! order bit set in the first step, just falling into the regular
+	! division loop will mess up the first time around.
+	! So we unroll slightly...
+	Ldo_single_div:
+		subcc	%g7, 1, %g7
+		bl	Lend_regular_divide
+		nop
+		sub	%o3, %o5, %o3
+		mov	1, %o2
+		b	Lend_single_divloop
+		nop
+	Lsingle_divloop:
+		sll	%o2, 1, %o2
+		bl	1f
+		srl	%o5, 1, %o5
+		! %o3 >= 0
+		sub	%o3, %o5, %o3
+		b	2f
+		add	%o2, 1, %o2
+	1:	! %o3 < 0
+		add	%o3, %o5, %o3
+		sub	%o2, 1, %o2
+	2:
+	Lend_single_divloop:
+		subcc	%g7, 1, %g7
+		bge	Lsingle_divloop
+		tst	%o3
+		b,a	Lend_regular_divide
+
+Lnot_really_big:
+1:
+	sll	%o5, 4, %o5
+	cmp	%o5, %o3
+	bleu	1b
+	addcc	%o4, 1, %o4
+	be	Lgot_result
+	sub	%o4, 1, %o4
+
+	tst	%o3	! set up for initial iteration
+Ldivloop:
+	sll	%o2, 4, %o2
+		! depth 1, accumulated bits 0
+	bl	L.1.16
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 2, accumulated bits 1
+	bl	L.2.17
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 3, accumulated bits 3
+	bl	L.3.19
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 7
+	bl	L.4.23
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (7*2+1), %o2
+	
+L.4.23:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (7*2-1), %o2
+	
+	
+L.3.19:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 5
+	bl	L.4.21
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (5*2+1), %o2
+	
+L.4.21:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (5*2-1), %o2
+	
+	
+	
+L.2.17:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 3, accumulated bits 1
+	bl	L.3.17
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 3
+	bl	L.4.19
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (3*2+1), %o2
+	
+L.4.19:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (3*2-1), %o2
+	
+	
+L.3.17:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits 1
+	bl	L.4.17
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (1*2+1), %o2
+	
+L.4.17:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (1*2-1), %o2
+	
+	
+	
+	
+L.1.16:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 2, accumulated bits -1
+	bl	L.2.15
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 3, accumulated bits -1
+	bl	L.3.15
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -1
+	bl	L.4.15
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-1*2+1), %o2
+	
+L.4.15:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-1*2-1), %o2
+	
+	
+L.3.15:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -3
+	bl	L.4.13
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-3*2+1), %o2
+	
+L.4.13:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-3*2-1), %o2
+	
+	
+	
+L.2.15:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 3, accumulated bits -3
+	bl	L.3.13
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -5
+	bl	L.4.11
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-5*2+1), %o2
+	
+L.4.11:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-5*2-1), %o2
+	
+	
+L.3.13:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+			! depth 4, accumulated bits -7
+	bl	L.4.9
+	srl	%o5,1,%o5
+	! remainder is positive
+	subcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-7*2+1), %o2
+	
+L.4.9:
+	! remainder is negative
+	addcc	%o3,%o5,%o3
+		b	9f
+		add	%o2, (-7*2-1), %o2
+	
+	
+	
+	
+	9:
+Lend_regular_divide:
+	subcc	%o4, 1, %o4
+	bge	Ldivloop
+	tst	%o3
+	bl,a	Lgot_result
+	! non-restoring fixup here (one instruction only!)
+	add	%o3, %o1, %o3
+
+
+Lgot_result:
+
+	retl
+	mov %o3, %o0
diff -u --recursive --new-file v1.1.78/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v1.1.78/linux/drivers/block/floppy.c	Mon Jan  9 07:22:01 1995
+++ linux/drivers/block/floppy.c	Wed Jan 11 08:11:02 1995
@@ -2998,7 +2998,7 @@
 	}
 
 	/* Allow ioctls if we have write-permissions even if read-only open */
-	if ((filp->f_mode & 2) || permission(inode,2))
+	if ((filp->f_mode & 2) || (permission(inode,2) == 0))
 		filp->f_mode |= IOCTL_MODE_BIT;
 	if (filp->f_mode & 2)
 		filp->f_mode |= OPEN_WRITE_BIT;
diff -u --recursive --new-file v1.1.78/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v1.1.78/linux/drivers/block/ide.c	Mon Jan  9 11:24:20 1995
+++ linux/drivers/block/ide.c	Tue Jan 10 10:07:20 1995
@@ -82,13 +82,16 @@
  *  Version 3.4 BETA	removed "444" debug message
  *  (sent to Linus)
  *  Version 3.5		correct the bios_cyl field if it's too small
- *  (linux 1.1.76!)	 (to help fdisk with brain-dead BIOSs)
+ *  (linux 1.1.76)	 (to help fdisk with brain-dead BIOSs)
  *  Version 3.6		cosmetic corrections to comments and stuff
- *			reorganise probing code to make it understandable
+ *  (linux 1.1.77)	reorganise probing code to make it understandable
  *			added halfway retry to probing for drive identification
  *			added "hdx=noprobe" command line option
  *			allow setting multmode even when identification fails
- *
+ *  Version 3.7		move set_geometry=1 from do_identify() to ide_init()
+ *			increase DRQ_WAIT to eliminate nuisance messages
+ *			wait for DRQ_STAT instead of DATA_READY during probing
+ *			  (courtesy of Gary Thomas gary@efland.UU.NET)
  *  To do:
  *	- special 32-bit controller-type detection & support
  *	- figure out why two WD drives on one i/f sometimes don't identify
@@ -234,7 +237,7 @@
 /*
  * Timeouts for various operations:
  */
-#define WAIT_DRQ	3	/* 30msec - spec allows up to 20ms */
+#define WAIT_DRQ	5	/* 50msec - spec allows up to 20ms */
 #define WAIT_READY	3	/* 30msec - should be instantaneous */
 #define WAIT_PIDENTIFY	100	/* 1sec   - should be less than 3ms (?) */
 #define WAIT_WORSTCASE	3000	/* 30sec  - worst case when spinning up */
@@ -1624,10 +1627,6 @@
 #endif	/* CONFIG_BLK_DEV_IDECD */
 		return;
 	}
-	/*
-	 * for Quantum drives, and also for drives not known to the BIOS:
-	 */
-	dev->special.b.set_geometry = 1;
 
 	/*
 	 * Gather up the geometry info.
@@ -1738,7 +1737,7 @@
 	for (timer = jiffies + (timeout / 2); timer > jiffies;) {
 		if ((IN_BYTE(HD_ALTSTATUS,DEV_HWIF) & BUSY_STAT) == 0) {
 			delay_10ms();		/* wait for IRQ & DATA_READY */
-			if (OK_STAT(GET_STAT(DEV_HWIF),DATA_READY,BAD_RW_STAT)){
+			if (OK_STAT(GET_STAT(DEV_HWIF),DRQ_STAT,BAD_RW_STAT)){
 				cli();			/* some sys need this */
 				do_identify(dev);	/* drive returned ID */
 				rc = 0;
@@ -1770,7 +1769,7 @@
 /*
  * This routine has the difficult job of finding a drive if it exists,
  * without getting hung up if it doesn't exist, and without leaving any IRQs
- * dangling to haunt us later.  The last point actually occured in v2.3, and
+ * dangling to haunt us later.  The last point actually occurred in v2.3, and
  * is the reason for the slightly complex exit sequence.  If a drive is "known"
  * to exist (from CMOS or kernel parameters), but does not respond right away,
  * the probe will "hang in there" for the maximum wait time (about 30 seconds).
@@ -2041,6 +2040,7 @@
 		dev->wqueue			= NULL;
 		dev->special.all		= 0;
 		dev->special.b.recalibrate	= 1;
+		dev->special.b.set_geometry	= 1;
 		dev->keep_settings		= 0;
 		ide_hd[hwif][drive<<PARTN_BITS].start_sect = 0;
 		dev->name = ide_devname[hwif][drive];
diff -u --recursive --new-file v1.1.78/linux/drivers/block/sbpcd.c linux/drivers/block/sbpcd.c
--- v1.1.78/linux/drivers/block/sbpcd.c	Mon Jan  9 11:24:20 1995
+++ linux/drivers/block/sbpcd.c	Tue Jan 10 10:07:08 1995
@@ -4004,7 +4004,7 @@
 static int config_spea(void)
 {
   int n_ports=0x10; /* 2:0x00, 8:0x10, 16:0x20, 32:0x30 */
-/* What is n_ports? Number of adresses or base address offset? */
+/* What is n_ports? Number of addresses or base address offset? */
   int irq_number=0; /* 2:0x01, 7:0x03, 12:0x05, 15:0x07, OFF:0x00 */
   int dma_channel=0; /* 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68, 7:0x78, OFF: 0x00 */
   int dack_polarity=0; /* L:0x00, H:0x80 */
diff -u --recursive --new-file v1.1.78/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v1.1.78/linux/drivers/char/Makefile	Mon Jan  9 11:24:21 1995
+++ linux/drivers/char/Makefile	Tue Jan 10 17:02:17 1995
@@ -95,7 +95,6 @@
 dep:
 	$(CPP) -M $(SRCS) > .depend
 
-modules:
 dummy:
 
 #
diff -u --recursive --new-file v1.1.78/linux/drivers/char/console.c linux/drivers/char/console.c
--- v1.1.78/linux/drivers/char/console.c	Mon Jan  9 07:22:01 1995
+++ linux/drivers/char/console.c	Wed Jan 11 07:55:50 1995
@@ -293,15 +293,15 @@
 #define vcmode		(vt_cons[currcons]->vc_mode)
 #define structsize	(sizeof(struct vc_data) + sizeof(struct vt_struct))
 
-static void * memsetw(void * s, unsigned short c, unsigned int count)
+static void memsetw(void * s, unsigned short c, unsigned int count)
 {
-__asm__("cld\n\t"
-	"rep\n\t"
-	"stosw"
-	: /* no output */
-	:"a" (c),"D" (s),"c" (count/2)
-	:"cx","di");
-return s;
+	unsigned short * addr = (unsigned short *) s;
+
+	count /= 2;
+	while (count) {
+		count--;
+		*(addr++) = c;
+	}
 }
 
 int vc_cons_allocated(unsigned int i)
@@ -681,67 +681,72 @@
 		pos += video_size_row;
 		scr_end += video_size_row;
 		if (scr_end > video_mem_end) {
-			__asm__("cld\n\t"
-				"rep\n\t"
-				"movsl\n\t"
-				"movl _video_num_columns,%1\n\t"
-				"rep\n\t"
-				"stosw"
-				: /* no output */
-				:"a" (video_erase_char),
-				"c" ((video_num_lines-1)*video_num_columns>>1),
-				"D" (video_mem_start),
-				"S" (origin)
-				:"cx","di","si");
+			unsigned short * d = (unsigned short *) video_mem_start;
+			unsigned short * s = (unsigned short *) origin;
+			unsigned int count;
+
+			count = (video_num_lines-1)*video_num_columns;
+			while (count) {
+				count--;
+				*(d++) = *(s++);
+			}
+			count = video_num_columns;
+			while (count) {
+				count--;
+				*(d++) = video_erase_char;
+			}
 			scr_end -= origin-video_mem_start;
 			pos -= origin-video_mem_start;
 			origin = video_mem_start;
 			has_scrolled = 1;
 		} else {
-			__asm__("cld\n\t"
-				"rep\n\t"
-				"stosw"
-				: /* no output */
-				:"a" (video_erase_char),
-				"c" (video_num_columns),
-				"D" (scr_end-video_size_row)
-				:"cx","di");
+			unsigned short * d;
+			unsigned int count;
+
+			d = (unsigned short *) (scr_end - video_size_row);
+			count = video_num_columns;
+			while (count) {
+				count--;
+				*(d++) = video_erase_char;
+			}
 		}
 		set_origin(currcons);
 	} else {
-		__asm__("cld\n\t"
-			"rep\n\t"
-			"movsl\n\t"
-			"movl _video_num_columns,%%ecx\n\t"
-			"rep\n\t"
-			"stosw"
-			: /* no output */
-			:"a" (video_erase_char),
-			"c" ((b-t-1)*video_num_columns>>1),
-			"D" (origin+video_size_row*t),
-			"S" (origin+video_size_row*(t+1))
-			:"cx","di","si");
+		unsigned short * d = (unsigned short *) (origin+video_size_row*t);
+		unsigned short * s = (unsigned short *) (origin+video_size_row*(t+1));
+		unsigned int count = (b-t-1) * video_num_columns;
+
+		while (count) {
+			count--;
+			*(d++) = *(s++);
+		}
+		count = video_num_columns;
+		while (count) {
+			count--;
+			*(d++) = video_erase_char;
+		}
 	}
 }
 
 static void scrdown(int currcons, unsigned int t, unsigned int b)
 {
+	unsigned short *d, *s;
+	unsigned int count;
+
 	if (b > video_num_lines || t >= b)
 		return;
-	__asm__("std\n\t"
-		"rep\n\t"
-		"movsl\n\t"
-		"addl $2,%%edi\n\t"	/* %edi has been decremented by 4 */
-		"movl _video_num_columns,%%ecx\n\t"
-		"rep\n\t"
-		"stosw\n\t"
-		"cld"
-		: /* no output */
-		:"a" (video_erase_char),
-		"c" ((b-t-1)*video_num_columns>>1),
-		"D" (origin+video_size_row*b-4),
-		"S" (origin+video_size_row*(b-1)-4)
-		:"ax","cx","di","si");
+	d = (unsigned short *) origin+video_size_row*b;
+	s = (unsigned short *) origin+video_size_row*(b-1);
+	count = (b-t-1)*video_num_columns;
+	while (count) {
+		count--;
+		*(--d) = *(--s);
+	}
+	count = video_num_columns;
+	while (count) {
+		count--;
+		*(--d) = video_erase_char;
+	}
 	has_scrolled = 1;
 }
 
@@ -796,83 +801,74 @@
 static void csi_J(int currcons, int vpar)
 {
 	unsigned long count;
-	unsigned long start;
+	unsigned short * start;
 
 	switch (vpar) {
 		case 0:	/* erase from cursor to end of display */
 			count = (scr_end-pos)>>1;
-			start = pos;
+			start = (unsigned short *) pos;
 			break;
 		case 1:	/* erase from start to cursor */
 			count = ((pos-origin)>>1)+1;
-			start = origin;
+			start = (unsigned short *) origin;
 			break;
 		case 2: /* erase whole display */
 			count = video_num_columns * video_num_lines;
-			start = origin;
+			start = (unsigned short *) origin;
 			break;
 		default:
 			return;
 	}
-	__asm__("cld\n\t"
-		"rep\n\t"
-		"stosw\n\t"
-		: /* no output */
-		:"c" (count),
-		"D" (start),"a" (video_erase_char)
-		:"cx","di");
+	while (count) {
+		count--;
+		*(start++) = video_erase_char;
+	}
 	need_wrap = 0;
 }
 
 static void csi_K(int currcons, int vpar)
 {
-	long count;
-	long start;
+	unsigned long count;
+	unsigned short * start;
 
 	switch (vpar) {
 		case 0:	/* erase from cursor to end of line */
 			count = video_num_columns-x;
-			start = pos;
+			start = (unsigned short *) pos;
 			break;
 		case 1:	/* erase from start of line to cursor */
-			start = pos - (x<<1);
+			start = (unsigned short *) (pos - (x<<1));
 			count = x+1;
 			break;
 		case 2: /* erase whole line */
-			start = pos - (x<<1);
+			start = (unsigned short *) (pos - (x<<1));
 			count = video_num_columns;
 			break;
 		default:
 			return;
 	}
-	__asm__("cld\n\t"
-		"rep\n\t"
-		"stosw\n\t"
-		: /* no output */
-		:"c" (count),
-		"D" (start),"a" (video_erase_char)
-		:"cx","di");
+	while (count) {
+		count--;
+		*(start++) = video_erase_char;
+	}
 	need_wrap = 0;
 }
 
 static void csi_X(int currcons, int vpar) /* erase the following vpar positions */
 {					  /* not vt100? */
-	long count;
-	long start;
+	unsigned long count;
+	unsigned short * start;
 
 	if (!vpar)
 		vpar++;
 
-	start=pos;
-	count=(vpar > video_num_columns-x) ? (video_num_columns-x) : vpar;
+	start = (unsigned short *) pos;
+	count = (vpar > video_num_columns-x) ? (video_num_columns-x) : vpar;
 
-	__asm__("cld\n\t"
-		"rep\n\t"
-		"stosw\n\t"
-		: /* no output */
-		:"c" (count),
-		"D" (start),"a" (video_erase_char)
-		:"cx","di");
+	while (count) {
+		count--;
+		*(start++) = video_erase_char;
+	}
 	need_wrap = 0;
 }
 
diff -u --recursive --new-file v1.1.78/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v1.1.78/linux/drivers/char/keyboard.c	Mon Jan  9 07:22:02 1995
+++ linux/drivers/char/keyboard.c	Wed Jan 11 07:55:50 1995
@@ -74,8 +74,11 @@
 extern void scrollfront(int);
 extern int vc_cons_allocated(unsigned int);
 
-#define fake_keyboard_interrupt() \
-__asm__ __volatile__("int $0x21")
+#ifdef __i386__
+#define fake_keyboard_interrupt() __asm__ __volatile__("int $0x21")
+#else
+#define fake_keyboard_interrupt() do ; while (0)
+#endif
 
 unsigned char kbd_read_mask = 0x01;	/* modified by psaux.c */
 
@@ -611,6 +614,7 @@
 
 static void show_ptregs(void)
 {
+#ifdef __i386__
 	if (!pt_regs)
 		return;
 	printk("\n");
@@ -625,6 +629,7 @@
 	printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
 		0xffff & pt_regs->ds,0xffff & pt_regs->es,
 		0xffff & pt_regs->fs,0xffff & pt_regs->gs);
+#endif
 }
 
 static void hold(void)
@@ -1176,7 +1181,9 @@
 				/* nothing */;
 			outb(0xfe,0x64);	 /* pulse reset low */
 		}
+#ifdef __i386__
 		__asm__("\tlidt _no_idt");
+#endif
 	}
 }
 
diff -u --recursive --new-file v1.1.78/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v1.1.78/linux/drivers/char/lp.c	Mon Jan  9 11:24:21 1995
+++ linux/drivers/char/lp.c	Tue Jan 10 17:02:17 1995
@@ -37,6 +37,9 @@
 #ifdef MODULE
 #include <linux/module.h>
 #include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
 #endif
 
 /* Test if printer is ready (and optionally has no error conditions) */
@@ -48,6 +51,15 @@
    (status & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
       (LP_PBUSY|LP_PSELECD|LP_PERRORP) 
 
+/* Allow old versions of tunelp to continue to work */
+#define OLD_LPCHAR   0x0001
+#define OLD_LPTIME   0x0002
+#define OLD_LPABORT  0x0004
+#define OLD_LPSETIRQ 0x0005
+#define OLD_LPGETIRQ 0x0006
+#define OLD_LPWAIT   0x0008
+#define OLD_IOCTL_MAX 8
+
 /* 
  * All my debugging code assumes that you debug with only one printer at
  * a time. RWWH
@@ -320,6 +332,8 @@
 	if (LP_F(minor) & LP_BUSY)
 		return -EBUSY;
 
+	MOD_INC_USE_COUNT;
+
 	/* If ABORTOPEN is set and the printer is offline or out of paper,
 	   we may still want to open it to perform ioctl()s.  Therefore we
 	   have commandeered O_NONBLOCK, even though it is being used in
@@ -329,34 +343,37 @@
 		int status = LP_S(minor);
 		if (status & LP_POUTPA) {
 			printk(KERN_INFO "lp%d out of paper\n", minor);
+			MOD_DEC_USE_COUNT;
 			return -ENOSPC;
 		} else if (!(status & LP_PSELECD)) {
 			printk(KERN_INFO "lp%d off-line\n", minor);
+			MOD_DEC_USE_COUNT;
 			return -EIO;
 		} else if (!(status & LP_PERRORP)) {
 			printk(KERN_ERR "lp%d printer error\n", minor);
+			MOD_DEC_USE_COUNT;
 			return -EIO;
 		}
 	}
 
 	if ((irq = LP_IRQ(minor))) {
 		lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
-		if (!lp_table[minor].lp_buffer)
+		if (!lp_table[minor].lp_buffer) {
+			MOD_DEC_USE_COUNT;
 			return -ENOMEM;
+		}
 
 		ret = request_irq(irq, lp_interrupt, SA_INTERRUPT, "printer");
 		if (ret) {
 			kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
 			lp_table[minor].lp_buffer = NULL;
 			printk("lp%d unable to use interrupt %d, error %d\n", minor, irq, ret);
+			MOD_DEC_USE_COUNT;
 			return ret;
 		}
 	}
 
 	LP_F(minor) |= LP_BUSY;
-#ifdef MODULE
-	MOD_INC_USE_COUNT;
-#endif	
 	return 0;
 }
 
@@ -372,9 +389,7 @@
 	}
 
 	LP_F(minor) &= ~LP_BUSY;
-#ifdef MODULE
 	MOD_DEC_USE_COUNT;
-#endif		
 }
 
 
@@ -391,13 +406,19 @@
 		return -ENODEV;
 	if ((LP_F(minor) & LP_EXIST) == 0)
 		return -ENODEV;
+	if (cmd <= OLD_IOCTL_MAX)
+		printk(KERN_NOTICE "lp%d: warning: obsolete ioctl %#x (perhaps you need a new tunelp)\n",
+		    minor, cmd);
 	switch ( cmd ) {
+		case OLD_LPTIME:
 		case LPTIME:
 			LP_TIME(minor) = arg;
 			break;
+		case OLD_LPCHAR:
 		case LPCHAR:
 			LP_CHAR(minor) = arg;
 			break;
+		case OLD_LPABORT:
 		case LPABORT:
 			if (arg)
 				LP_F(minor) |= LP_ABORT;
@@ -416,9 +437,11 @@
 			else
 				LP_F(minor) &= ~LP_CAREFUL;
 			break;
+		case OLD_LPWAIT:
 		case LPWAIT:
 			LP_WAIT(minor) = arg;
 			break;
+		case OLD_LPSETIRQ:
 		case LPSETIRQ: {
 			int oldirq;
 			int newirq = arg;
@@ -462,11 +485,28 @@
 			lp_reset(minor);
 			break;
 		}
-		case LPGETIRQ:
+		case OLD_LPGETIRQ:
 			retval = LP_IRQ(minor);
 			break;
+		case LPGETIRQ:
+			retval = verify_area(VERIFY_WRITE, (void *) arg,
+			    sizeof(int));
+		    	if (retval)
+		    		return retval;
+			memcpy_tofs((int *) arg, &LP_IRQ(minor), sizeof(int));
+			break;
 		case LPGETSTATUS:
-			retval = LP_S(minor);	/* in range 0..255 */
+			retval = verify_area(VERIFY_WRITE, (void *) arg,
+			    sizeof(int));
+		    	if (retval)
+		    		return retval;
+			else {
+				int status = LP_S(minor);
+				memcpy_tofs((int *) arg, &status, sizeof(int));
+			}
+			break;
+		case LPRESET:
+			lp_reset(minor);
 			break;
 		default:
 			retval = -EINVAL;
diff -u --recursive --new-file v1.1.78/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v1.1.78/linux/drivers/char/mem.c	Thu Oct 13 14:07:06 1994
+++ linux/drivers/char/mem.c	Wed Jan 11 07:55:50 1995
@@ -87,8 +87,10 @@
 {
 	if (vma->vm_offset & ~PAGE_MASK)
 		return -ENXIO;
+#ifdef __i386__
 	if (x86 > 3 && vma->vm_offset >= high_memory)
 		vma->vm_page_prot |= PAGE_PCD;
+#endif
 	if (remap_page_range(vma->vm_start, vma->vm_offset, vma->vm_end - vma->vm_start, vma->vm_page_prot))
 		return -EAGAIN;
 	vma->vm_inode = inode;
diff -u --recursive --new-file v1.1.78/linux/drivers/net/3c501.c linux/drivers/net/3c501.c
--- v1.1.78/linux/drivers/net/3c501.c	Mon Jan  9 11:24:21 1995
+++ linux/drivers/net/3c501.c	Tue Jan 10 10:07:07 1995
@@ -51,7 +51,7 @@
     like (eg touching a register at the wrong time).
     
     	The driver is less efficient than it could be. It switches through
-    recieve mode even if more transmits are queued. If this worries you buy
+    receive mode even if more transmits are queued. If this worries you buy
     a real ethernet card.
     
     	The combination of slow receive restart and no real multicast
@@ -564,7 +564,7 @@
 	skb->dev = dev;
 
 	/*
-	 *	The read incrememts through the bytes. The interrupt
+	 *	The read increments through the bytes. The interrupt
 	 *	handler will fix the pointer when it returns to 
 	 *	receive mode.
 	 */
diff -u --recursive --new-file v1.1.78/linux/drivers/net/atp.c linux/drivers/net/atp.c
--- v1.1.78/linux/drivers/net/atp.c	Mon Jan  9 11:24:21 1995
+++ linux/drivers/net/atp.c	Tue Jan 10 10:07:08 1995
@@ -113,7 +113,7 @@
 
 #ifndef HAVE_PORTRESERVE
 #define check_region(ioaddr, size)		0
-#define request_region(ioaddr, size,name);		do ; while (0)
+#define request_region(ioaddr, size,name)	do ; while (0)
 #endif
 
 /* use 0 for production, 1 for verification, >2 for debug */
diff -u --recursive --new-file v1.1.78/linux/drivers/net/ni52.c linux/drivers/net/ni52.c
--- v1.1.78/linux/drivers/net/ni52.c	Mon Jan  9 11:24:22 1995
+++ linux/drivers/net/ni52.c	Tue Jan 10 10:07:08 1995
@@ -181,7 +181,7 @@
 
 #ifndef HAVE_PORTRESERVE
 #define check_region(ioaddr, size) 		0
-#define	request_region(ioaddr, size,name);		do ; while (0)
+#define	request_region(ioaddr, size,name)	do ; while (0)
 #endif
 
 #define NI52_TOTAL_SIZE 16
diff -u --recursive --new-file v1.1.78/linux/drivers/net/ni65.c linux/drivers/net/ni65.c
--- v1.1.78/linux/drivers/net/ni65.c	Mon Jan  9 11:24:22 1995
+++ linux/drivers/net/ni65.c	Tue Jan 10 10:07:09 1995
@@ -54,7 +54,7 @@
 
 #ifndef HAVE_PORTRESERVE
 #define check_region(ioaddr, size)              0
-#define request_region(ioaddr, size,name);             do ; while (0)
+#define request_region(ioaddr, size,name)       do ; while (0)
 #endif
 
 #ifndef NET_DEBUG
diff -u --recursive --new-file v1.1.78/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c
--- v1.1.78/linux/drivers/net/sk_g16.c	Mon Jan  9 11:24:22 1995
+++ linux/drivers/net/sk_g16.c	Tue Jan 10 10:07:09 1995
@@ -329,7 +329,7 @@
 #ifndef HAVE_PORTRESERVE
 
 #define check_region(ioaddr, size)              0
-#define request_region(ioaddr, size,name);             do ; while (0)
+#define request_region(ioaddr, size,name)       do ; while (0)
 
 #endif
 
diff -u --recursive --new-file v1.1.78/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v1.1.78/linux/drivers/net/slip.c	Mon Jan  9 07:22:06 1995
+++ linux/drivers/net/slip.c	Tue Jan 10 10:07:09 1995
@@ -46,12 +46,6 @@
 #define SL_CHECK_TRANSMIT
 #include <linux/config.h>
 
-#ifdef SL_COMPRESSED
-/* I think following lines must be in the <linux/config.h>
- *         14 Oct 1994 Dmitry Gorodchanin
- */
-#define CONFIG_SLIP_COMPRESSED
-#endif
 /* Undef this, if you don't need 6bit encapsulation code in the driver */
 #define CONFIG_SLIP_MODE_SLIP6
 
diff -u --recursive --new-file v1.1.78/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v1.1.78/linux/drivers/scsi/Makefile	Mon Jan  9 11:24:22 1995
+++ linux/drivers/scsi/Makefile	Tue Jan 10 10:07:08 1995
@@ -2,7 +2,7 @@
 # Makefile for kernel/blk_drv/scsi
 #
 # Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DONT put your own dependencies here
+# removes any old dependencies. DON'T put your own dependencies here
 # unless its something special (ie not a .c file).
 #
 
diff -u --recursive --new-file v1.1.78/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v1.1.78/linux/drivers/scsi/sr.c	Mon Jan  9 07:22:07 1995
+++ linux/drivers/scsi/sr.c	Tue Jan 10 17:02:09 1995
@@ -284,7 +284,7 @@
  *     
  *   - TOSHIBA: setting density is done here now, mounting PhotoCD's should
  *              work now without running the program "set_density"
- *              People reported, that it is nessesary to eject and reinsert
+ *              People reported that it is necessary to eject and reinsert
  *              the CD after the set-density call to get this working for
  *              old drives.
  *              And some very new drives don't need this call any more...
@@ -302,10 +302,10 @@
   int             rc;
 
   if (!suser()) {
-    /* I'm not the superuser, so SCSI_IOCTL_SEND_COMMAND is'nt allowed for me.
-     * That's why mpcd_sector will be initialized with zero, becauce I'm not
-     * able to get the right value. Nessesary only if access_count is 1, else
-     * no disk change happend since the last call of this function and we can
+    /* I'm not the superuser, so SCSI_IOCTL_SEND_COMMAND isn't allowed for me.
+     * That's why mpcd_sector will be initialized with zero, because I'm not
+     * able to get the right value. Necessary only if access_count is 1, else
+     * no disk change happened since the last call of this function and we can
      * keep the old value.
      */
     if (1 == scsi_CDs[MINOR(inode->i_rdev)].device->access_count)
@@ -328,7 +328,7 @@
     rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
 			   SCSI_IOCTL_SEND_COMMAND, buf);
     if (rc != 0) {
-      printk("sr_photocd: ioctl error: %i\n",rc);
+      printk("sr_photocd: ioctl error (NEC): 0x%x\n",rc);
       sector = 0;
     } else {
       min   = (unsigned long)buf[8+15]/16*10 + (unsigned long)buf[8+15]%16;
@@ -361,7 +361,7 @@
     rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
 			   SCSI_IOCTL_SEND_COMMAND, buf);
     if (rc != 0) {
-      printk("sr_photocd: ioctl error: %i\n",rc);
+      printk("sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc);
     }
 
     /* ... and then I ask, if there is a multisession-Disk */
@@ -370,8 +370,10 @@
     *((unsigned long*)buf+1) = 4;
     buf[8+0] = 0xc7;
     buf[8+1] = 3;
+    rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
+			   SCSI_IOCTL_SEND_COMMAND, buf);
     if (rc != 0) {
-      printk("sr_photocd: ioctl error: %i\n",rc);
+      printk("sr_photocd: ioctl error (TOSHIBA #2): 0x%x\n",rc);
       sector = 0;
     } else {
       min   = (unsigned long)buf[8+1]/16*10 + (unsigned long)buf[8+1]%16;
@@ -574,7 +576,7 @@
 
 #if 1
 	/* Here we redirect the volume descriptor block of the CD-ROM.
-	 * Nessesary for multisession CD's, until the isofs-rotines
+	 * Necessary for multisession CD's, until the isofs-routines
 	 * handle this via the CDROMMULTISESSION_SYS call
 	 */
 	if (block >= 64 && block < 68) {
diff -u --recursive --new-file v1.1.78/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v1.1.78/linux/drivers/scsi/sr_ioctl.c	Mon Jan  9 07:22:07 1995
+++ linux/drivers/scsi/sr_ioctl.c	Tue Jan 10 17:02:09 1995
@@ -421,14 +421,9 @@
 			}
 
 		case CDROMMULTISESSION_SYS: /* tell start-of-last-session to kernel */
-			{
-			  long *p_lba;
-			  
-			  if(!suser()) return -EACCES;
-			  p_lba =(long*)arg;
-			  *p_lba=scsi_CDs[target].mpcd_sector;
-			  return (0);
-			}
+			if(!suser()) return -EACCES;
+			*((unsigned int *)arg)=scsi_CDs[target].mpcd_sector;
+			return (0);
 			
 		case BLKRASET:
 			if(!suser())  return -EACCES;
diff -u --recursive --new-file v1.1.78/linux/fs/exec.c linux/fs/exec.c
--- v1.1.78/linux/fs/exec.c	Mon Jan  9 07:22:08 1995
+++ linux/fs/exec.c	Wed Jan 11 08:11:02 1995
@@ -535,7 +535,7 @@
 	flush_thread();
 
 	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 
-	    !permission(bprm->inode,MAY_READ))
+	    permission(bprm->inode,MAY_READ))
 		current->dumpable = 0;
 	current->signal = 0;
 	for (i=0 ; i<32 ; i++) {
@@ -605,8 +605,9 @@
 		bprm.e_uid = (i & S_ISUID) ? bprm.inode->i_uid : current->euid;
 		bprm.e_gid = (i & S_ISGID) ? bprm.inode->i_gid : current->egid;
 	}
-	if (!permission(bprm.inode, MAY_EXEC) ||
-	    (!(bprm.inode->i_mode & 0111) && fsuser())) {
+	if ((retval = permission(bprm.inode, MAY_EXEC)) != 0)
+		goto exec_error2;
+	if (!(bprm.inode->i_mode & 0111) && fsuser()) {
 		retval = -EACCES;
 		goto exec_error2;
 	}
diff -u --recursive --new-file v1.1.78/linux/fs/ext/namei.c linux/fs/ext/namei.c
--- v1.1.78/linux/fs/ext/namei.c	Sat Oct 22 16:41:35 1994
+++ linux/fs/ext/namei.c	Wed Jan 11 08:11:02 1995
@@ -810,8 +810,7 @@
 		retval = -EEXIST;
 		if (new_bh)
 			goto end_rename;
-		retval = -EACCES;
-		if (!permission(old_inode, MAY_WRITE))
+		if ((retval = permission(old_inode, MAY_WRITE)) != 0)
 			goto end_rename;
 		retval = -EINVAL;
 		if (subdir(new_dir, old_inode))
diff -u --recursive --new-file v1.1.78/linux/fs/ext2/acl.c linux/fs/ext2/acl.c
--- v1.1.78/linux/fs/ext2/acl.c	Mon Aug 15 15:53:47 1994
+++ linux/fs/ext2/acl.c	Wed Jan 11 08:11:02 1995
@@ -30,12 +30,12 @@
 	 * Nobody gets write access to an immutable file
 	 */
 	if ((mask & S_IWOTH) && IS_IMMUTABLE(inode))
-		return 0;
+		return -EACCES;
 	/*
 	 * Special case, access is always granted for root
 	 */
 	if (fsuser())
-		return 1;
+		return 0;
 	/*
 	 * If no ACL, checks using the file mode
 	 */
@@ -44,7 +44,7 @@
 	else if (in_group_p (inode->i_gid))
 		mode >>= 3;
 	if (((mode & mask & S_IRWXO) == mask))
-		return 1;
-	else
 		return 0;
+	else
+		return -EACCES;
 }
diff -u --recursive --new-file v1.1.78/linux/fs/isofs/Makefile linux/fs/isofs/Makefile
--- v1.1.78/linux/fs/isofs/Makefile	Mon Jan  9 11:24:23 1995
+++ linux/fs/isofs/Makefile	Tue Jan 10 17:02:17 1995
@@ -20,6 +20,8 @@
 	$(LD) -r -o isofs.o $(OBJS)
 
 modules: isofs.o
+	ln -sf ../fs/isofs/isofs.o $(TOPDIR)/modules
+
 dep:
 	$(CPP) -M *.c > .depend
 
diff -u --recursive --new-file v1.1.78/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v1.1.78/linux/fs/isofs/inode.c	Mon Jan  9 11:24:23 1995
+++ linux/fs/isofs/inode.c	Tue Jan 10 17:02:18 1995
@@ -24,6 +24,9 @@
 #ifdef MODULE
 #include <linux/module.h>
 #include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
 #endif
 
 #ifdef LEAK_CHECK
@@ -41,9 +44,7 @@
 #endif
 	sb->s_dev = 0;
 	unlock_super(sb);
-#ifdef MODULE
 	MOD_DEC_USE_COUNT;
-#endif
 	return;
 }
 
@@ -166,8 +167,11 @@
 
 	struct iso9660_options opt;
 
+	MOD_INC_USE_COUNT;
+
 	if (!parse_options((char *) data,&opt)) {
 		s->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 
@@ -219,6 +223,7 @@
 			printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n",
 			       dev, iso_blknum);
 			unlock_super(s);
+			MOD_DEC_USE_COUNT;
 			return NULL;
 		}
 
@@ -256,6 +261,7 @@
 			printk("Unable to identify CD-ROM format.\n");
 		s->s_dev = 0;
 		unlock_super(s);
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	};
 	
@@ -340,19 +346,18 @@
 	if (!(s->s_mounted)) {
 		s->s_dev=0;
 		printk("get root inode failed\n");
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 
 	if(!check_disk_change(s->s_dev)) {
-#ifdef MODULE
-	  MOD_INC_USE_COUNT;
-#endif
 	  return s;
 	}
  out: /* Kick out for various error conditions */
 	brelse(bh);
 	s->s_dev = 0;
 	unlock_super(s);
+	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
@@ -766,12 +771,7 @@
 
 void cleanup_module(void)
 {
-	if (MOD_IN_USE)
-		printk("ne: device busy, remove delayed\n");
-	else
-	{
-		unregister_filesystem(&iso9660_fs_type);
-	}
+	unregister_filesystem(&iso9660_fs_type);
 }
 
 #endif
diff -u --recursive --new-file v1.1.78/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v1.1.78/linux/fs/minix/inode.c	Mon Jan  9 07:22:08 1995
+++ linux/fs/minix/inode.c	Tue Jan 10 17:02:18 1995
@@ -130,12 +130,14 @@
 
 	if (32 != sizeof (struct minix_inode))
 		panic("bad i-node size");
+	MOD_INC_USE_COUNT;
 	lock_super(s);
 	set_blocksize(dev, BLOCK_SIZE);
 	if (!(bh = bread(dev,1,BLOCK_SIZE))) {
 		s->s_dev=0;
 		unlock_super(s);
 		printk("MINIX-fs: unable to read superblock\n");
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	ms = (struct minix_super_block *) bh->b_data;
@@ -164,6 +166,7 @@
 		brelse(bh);
 		if (!silent)
 			printk("VFS: Can't find a minix filesystem on dev 0x%04x.\n", dev);
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	for (i=0;i < MINIX_I_MAP_SLOTS;i++)
@@ -190,6 +193,7 @@
 		unlock_super(s);
 		brelse(bh);
 		printk("MINIX-fs: bad superblock or unable to read bitmaps\n");
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	set_bit(0,s->u.minix_sb.s_imap[0]->b_data);
@@ -203,6 +207,7 @@
 		s->s_dev = 0;
 		brelse(bh);
 		printk("MINIX-fs: get root inode failed\n");
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	if (!(s->s_flags & MS_RDONLY)) {
@@ -216,7 +221,6 @@
  	else if (s->u.minix_sb.s_mount_state & MINIX_ERROR_FS)
 		printk ("MINIX-fs: mounting file system with errors, "
 			"running fsck is recommended.\n");
-	MOD_INC_USE_COUNT;
 	return s;
 }
 
@@ -538,12 +542,7 @@
 
 void cleanup_module(void)
 {
-	if (MOD_IN_USE)
-		printk("ne: device busy, remove delayed\n");
-	else
-	{
-		unregister_filesystem(&minix_fs_type);
-	}
+	unregister_filesystem(&minix_fs_type);
 }
 
 #endif
diff -u --recursive --new-file v1.1.78/linux/fs/msdos/Makefile linux/fs/msdos/Makefile
--- v1.1.78/linux/fs/msdos/Makefile	Mon Jan  9 11:24:23 1995
+++ linux/fs/msdos/Makefile	Tue Jan 10 17:02:18 1995
@@ -20,6 +20,8 @@
 	$(LD) -r -o msdos.o $(OBJS)
 
 modules: msdos.o
+	ln -sf ../fs/msdos/msdos.o $(TOPDIR)/modules
+
 dep:
 	$(CPP) -M *.c > .depend
 
diff -u --recursive --new-file v1.1.78/linux/fs/msdos/inode.c linux/fs/msdos/inode.c
--- v1.1.78/linux/fs/msdos/inode.c	Tue Dec 27 08:37:13 1994
+++ linux/fs/msdos/inode.c	Tue Jan 10 17:02:18 1995
@@ -19,8 +19,11 @@
 #include "msbuffer.h"
 
 #ifdef MODULE
-	#include <linux/module.h>
-	#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
 #endif
 
 #include <asm/segment.h>
@@ -62,9 +65,7 @@
 	lock_super(sb);
 	sb->s_dev = 0;
 	unlock_super(sb);
-	#ifdef MODULE
-		MOD_DEC_USE_COUNT;
-	#endif
+	MOD_DEC_USE_COUNT;
 	return;
 }
 
@@ -177,6 +178,8 @@
 	gid_t gid;
 	int umask;
 	int blksize = 512;
+
+	MOD_INC_USE_COUNT;
 	if (hardsect_size[MAJOR(sb->s_dev)] != NULL){
 		blksize = hardsect_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)];
 		if (blksize != 512){
@@ -187,6 +190,7 @@
 	    &debug,&fat,&quiet,&blksize)
 		|| (blksize != 512 && blksize != 1024)) {
 		sb->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	cache_init();
@@ -200,6 +204,7 @@
 		brelse (bh);
 		sb->s_dev = 0;
 		printk("MSDOS bread failed\n");
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	b = (struct msdos_boot_sector *) bh->b_data;
@@ -279,6 +284,7 @@
 			printk("VFS: Can't find a valid MSDOS filesystem on dev 0x%04x.\n",
 				   sb->s_dev);
 		sb->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	sb->s_magic = MSDOS_SUPER_MAGIC;
@@ -297,11 +303,9 @@
 	if (!(sb->s_mounted = iget(sb,MSDOS_ROOT_INO))) {
 		sb->s_dev = 0;
 		printk("get root inode failed\n");
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
-	#ifdef MODULE
-		MOD_INC_USE_COUNT;
-	#endif
 	return sb;
 }
 
@@ -514,12 +518,7 @@
 
 void cleanup_module(void)
 {
-	if (MOD_IN_USE)
-		printk("msdos: device busy, remove delayed\n");
-	else
-	{
-		unregister_filesystem(&msdos_fs_type);
-	}
+	unregister_filesystem(&msdos_fs_type);
 }
 
 #endif
diff -u --recursive --new-file v1.1.78/linux/fs/namei.c linux/fs/namei.c
--- v1.1.78/linux/fs/namei.c	Sun Nov 20 21:50:47 1994
+++ linux/fs/namei.c	Wed Jan 11 08:11:02 1995
@@ -107,14 +107,14 @@
 	if (inode->i_op && inode->i_op->permission)
 		return inode->i_op->permission(inode, mask);
 	else if ((mask & S_IWOTH) && IS_IMMUTABLE(inode))
-		return 0; /* Nobody gets write access to an immutable file */
+		return -EACCES; /* Nobody gets write access to an immutable file */
 	else if (current->fsuid == inode->i_uid)
 		mode >>= 6;
 	else if (in_group_p(inode->i_gid))
 		mode >>= 3;
 	if (((mode & mask & 0007) == mask) || fsuser())
-		return 1;
-	return 0;
+		return 0;
+	return -EACCES;
 }
 
 /*
@@ -182,9 +182,9 @@
 		iput(dir);
 		return -ENOTDIR;
 	}
- 	if (!perm) {
+ 	if (perm != 0) {
 		iput(dir);
-		return -EACCES;
+		return perm;
 	}
 	if (!len) {
 		*result = dir;
@@ -352,9 +352,9 @@
 			return -EISDIR;
 		}
 		/* thanks to Paul Pluzhnikov for noticing this was missing.. */
-		if (!permission(dir,ACC_MODE(flag))) {
+		if ((error = permission(dir,ACC_MODE(flag))) != 0) {
 			iput(dir);
-			return -EACCES;
+			return error;
 		}
 		*res_inode=dir;
 		return 0;
@@ -368,8 +368,8 @@
 				iput(inode);
 				error = -EEXIST;
 			}
-		} else if (!permission(dir,MAY_WRITE | MAY_EXEC))
-			error = -EACCES;
+		} else if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0)
+			;	/* error is already set! */
 		else if (!dir->i_op || !dir->i_op->create)
 			error = -EACCES;
 		else if (IS_RDONLY(dir))
@@ -395,9 +395,9 @@
 		iput(inode);
 		return -EISDIR;
 	}
-	if (!permission(inode,ACC_MODE(flag))) {
+	if ((error = permission(inode,ACC_MODE(flag))) != 0) {
 		iput(inode);
-		return -EACCES;
+		return error;
 	}
 	if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
 		if (IS_NODEV(inode)) {
@@ -460,9 +460,9 @@
 		iput(dir);
 		return -EROFS;
 	}
-	if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
+	if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) {
 		iput(dir);
-		return -EACCES;
+		return error;
 	}
 	if (!dir->i_op || !dir->i_op->mknod) {
 		iput(dir);
@@ -517,9 +517,9 @@
 		iput(dir);
 		return -EROFS;
 	}
-	if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
+	if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) {
 		iput(dir);
-		return -EACCES;
+		return error;
 	}
 	if (!dir->i_op || !dir->i_op->mkdir) {
 		iput(dir);
@@ -563,9 +563,9 @@
 		iput(dir);
 		return -EROFS;
 	}
-	if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
+	if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) {
 		iput(dir);
-		return -EACCES;
+		return error;
 	}
 	/*
 	 * A subdirectory cannot be removed from an append-only directory
@@ -611,9 +611,9 @@
 		iput(dir);
 		return -EROFS;
 	}
-	if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
+	if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) {
 		iput(dir);
-		return -EACCES;
+		return error;
 	}
 	/*
 	 * A file cannot be removed from an append-only directory
@@ -659,9 +659,9 @@
 		iput(dir);
 		return -EROFS;
 	}
-	if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
+	if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) {
 		iput(dir);
-		return -EACCES;
+		return error;
 	}
 	if (!dir->i_op || !dir->i_op->symlink) {
 		iput(dir);
@@ -718,10 +718,10 @@
 		iput(oldinode);
 		return -EXDEV;
 	}
-	if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
+	if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) {
 		iput(dir);
 		iput(oldinode);
-		return -EACCES;
+		return error;
 	}
 	/*
 	 * A link to an append-only or immutable file cannot be created
@@ -772,9 +772,9 @@
 	error = dir_namei(oldname,&old_len,&old_base,NULL,&old_dir);
 	if (error)
 		return error;
-	if (!permission(old_dir,MAY_WRITE | MAY_EXEC)) {
+	if ((error = permission(old_dir,MAY_WRITE | MAY_EXEC)) != 0) {
 		iput(old_dir);
-		return -EACCES;
+		return error;
 	}
 	if (!old_len || (old_base[0] == '.' &&
 	    (old_len == 1 || (old_base[1] == '.' &&
@@ -787,10 +787,10 @@
 		iput(old_dir);
 		return error;
 	}
-	if (!permission(new_dir,MAY_WRITE | MAY_EXEC)) {
+	if ((error = permission(new_dir,MAY_WRITE | MAY_EXEC)) != 0){
 		iput(old_dir);
 		iput(new_dir);
-		return -EACCES;
+		return error;
 	}
 	if (!new_len || (new_base[0] == '.' &&
 	    (new_len == 1 || (new_base[1] == '.' &&
diff -u --recursive --new-file v1.1.78/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v1.1.78/linux/fs/nfs/inode.c	Mon Jan  9 07:22:08 1995
+++ linux/fs/nfs/inode.c	Tue Jan 10 17:02:18 1995
@@ -79,9 +79,11 @@
 	struct file *filp;
 	dev_t dev = sb->s_dev;
 
+	MOD_INC_USE_COUNT;
 	if (!data) {
 		printk("nfs_read_super: missing data argument\n");
 		sb->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	fd = data->fd;
@@ -92,11 +94,13 @@
 	if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) {
 		printk("nfs_read_super: invalid file descriptor\n");
 		sb->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	if (!S_ISSOCK(filp->f_inode->i_mode)) {
 		printk("nfs_read_super: not a socket\n");
 		sb->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	filp->f_count++;
@@ -133,9 +137,9 @@
 	if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) {
 		sb->s_dev = 0;
 		printk("nfs_read_super: get root inode failed\n");
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
-	MOD_INC_USE_COUNT;
 	return sb;
 }
 
@@ -264,23 +268,12 @@
 
 int init_module(void)
 {
-	int i;
-
 	register_filesystem(&nfs_fs_type);
-
 	return 0;
 }
 
 void cleanup_module(void)
 {
-	int i;
-
-	if (MOD_IN_USE) 
-	{
-		printk("NFS cannot be removed, currently in use\n");
-		return;
-	}
-
 	unregister_filesystem(&nfs_fs_type);
 }
 
diff -u --recursive --new-file v1.1.78/linux/fs/open.c linux/fs/open.c
--- v1.1.78/linux/fs/open.c	Tue Dec 20 15:09:11 1994
+++ linux/fs/open.c	Wed Jan 11 08:11:02 1995
@@ -74,10 +74,14 @@
 	error = namei(path,&inode);
 	if (error)
 		return error;
-	if (S_ISDIR(inode->i_mode) || !permission(inode,MAY_WRITE)) {
+	if (S_ISDIR(inode->i_mode)) {
 		iput(inode);
 		return -EACCES;
 	}
+	if ((error = permission(inode,MAY_WRITE)) != 0) {
+		iput(inode);
+		return error;
+	}
 	if (IS_RDONLY(inode)) {
 		iput(inode);
 		return -EROFS;
@@ -157,9 +161,9 @@
 		newattrs.ia_ctime = CURRENT_TIME;
 		flags = ATTR_ATIME_SET | ATTR_MTIME_SET;
 	} else {
-		if (!permission(inode,MAY_WRITE)) {
+		if ((error = permission(inode,MAY_WRITE)) != 0) {
 			iput(inode);
-			return -EACCES;
+			return error;
 		}
 		actime = modtime = newattrs.ia_ctime = CURRENT_TIME;
 	}
@@ -190,8 +194,7 @@
 	current->fsgid = current->gid;
 	res = namei(filename,&inode);
 	if (!res) {
-		if (!permission(inode, mode))
-			res = -EACCES;
+		res = permission(inode, mode);
 		iput(inode);
 	}
 	current->fsuid = old_fsuid;
@@ -211,9 +214,9 @@
 		iput(inode);
 		return -ENOTDIR;
 	}
-	if (!permission(inode,MAY_EXEC)) {
+	if ((error = permission(inode,MAY_EXEC)) != 0) {
 		iput(inode);
-		return -EACCES;
+		return error;
 	}
 	iput(current->fs->pwd);
 	current->fs->pwd = inode;
@@ -224,6 +227,7 @@
 {
 	struct inode * inode;
 	struct file * file;
+	int error;
 
 	if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 		return -EBADF;
@@ -231,8 +235,8 @@
 		return -ENOENT;
 	if (!S_ISDIR(inode->i_mode))
 		return -ENOTDIR;
-	if (!permission(inode,MAY_EXEC))
-		return -EACCES;
+	if ((error = permission(inode,MAY_EXEC)) != 0)
+		return error;
 	iput(current->fs->pwd);
 	current->fs->pwd = inode;
 	inode->i_count++;
diff -u --recursive --new-file v1.1.78/linux/fs/proc/array.c linux/fs/proc/array.c
--- v1.1.78/linux/fs/proc/array.c	Mon Jan  9 11:24:23 1995
+++ linux/fs/proc/array.c	Wed Jan 11 08:54:36 1995
@@ -605,6 +605,7 @@
 extern int get_irq_list(char *);
 extern int get_dma_list(char *);
 extern int get_cpuinfo(char *);
+extern int get_pci_list(char*);
 
 static int get_root_array(char * page, int type)
 {
@@ -618,6 +619,11 @@
 		case PROC_MEMINFO:
 			return get_meminfo(page);
 
+#ifdef CONFIG_PCI
+  	        case PROC_PCI:
+			return get_pci_list(page);
+#endif
+			
 		case PROC_CPUINFO:
 			return get_cpuinfo(page);
 
diff -u --recursive --new-file v1.1.78/linux/fs/proc/inode.c linux/fs/proc/inode.c
--- v1.1.78/linux/fs/proc/inode.c	Mon Jan  9 07:22:08 1995
+++ linux/fs/proc/inode.c	Tue Jan 10 17:02:18 1995
@@ -44,6 +44,37 @@
 	NULL
 };
 
+
+static int parse_options(char *options,uid_t *uid,gid_t *gid)
+{
+	char *this_char,*value;
+
+	*uid = current->uid;
+	*gid = current->gid;
+	if (!options) return 1;
+	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
+		if ((value = strchr(this_char,'=')) != NULL)
+			*value++ = 0;
+		if (!strcmp(this_char,"uid")) {
+			if (!value || !*value)
+				return 0;
+			*uid = simple_strtoul(value,&value,0);
+			if (*value)
+				return 0;
+		}
+		else if (!strcmp(this_char,"gid")) {
+			if (!value || !*value)
+				return 0;
+			*gid = simple_strtoul(value,&value,0);
+			if (*value)
+				return 0;
+		}
+		else return 0;
+	}
+	return 1;
+}
+
+
 struct super_block *proc_read_super(struct super_block *s,void *data, 
 				    int silent)
 {
@@ -58,6 +89,7 @@
 		printk("get root inode failed\n");
 		return NULL;
 	}
+	parse_options(data, &s->s_mounted->i_uid, &s->s_mounted->i_gid);
 	return s;
 }
 
@@ -117,7 +149,7 @@
 	if (!pid) {
 		switch (ino) {
 			case PROC_KMSG:
-				inode->i_mode = S_IFREG | S_IRUGO;
+				inode->i_mode = S_IFREG | S_IRUSR;
 				inode->i_op = &proc_kmsg_inode_operations;
 				break;
 			case PROC_NET:
diff -u --recursive --new-file v1.1.78/linux/fs/proc/link.c linux/fs/proc/link.c
--- v1.1.78/linux/fs/proc/link.c	Thu Oct 20 09:54:33 1994
+++ linux/fs/proc/link.c	Wed Jan 11 08:11:02 1995
@@ -103,16 +103,16 @@
 	unsigned int pid, ino;
 	struct task_struct * p;
 	struct inode * new_inode;
-	int i;
+	int i, error;
 
 	*res_inode = NULL;
 	if (dir)
 		iput(dir);
 	if (!inode)
 		return -ENOENT;
-	if (!permission(inode, MAY_EXEC)) {
+	if ((error = permission(inode, MAY_EXEC)) != 0){
 		iput(inode);
-		return -EACCES;
+		return error;
 	}
 	ino = inode->i_ino;
 	pid = ino >> 16;
diff -u --recursive --new-file v1.1.78/linux/fs/proc/net.c linux/fs/proc/net.c
--- v1.1.78/linux/fs/proc/net.c	Mon Jan  9 11:24:23 1995
+++ linux/fs/proc/net.c	Wed Jan 11 08:03:11 1995
@@ -42,6 +42,7 @@
 /* the get_*_info() functions are in the net code, and are configured
    in via the standard mechanism... */
 extern int unix_get_info(char *, char **, off_t, int);
+extern int afinet_get_info(char *, char **, off_t, int);
 #ifdef CONFIG_INET
 extern int tcp_get_info(char *, char **, off_t, int);
 extern int udp_get_info(char *, char **, off_t, int);
@@ -144,6 +145,7 @@
 	{ PROC_NET_NR,		2, "nr" },
 #endif /* CONFIG_NETROM */
 #endif /* CONFIG_AX25 */
+	{ PROC_NET_SOCKSTAT,	8, "sockstat" },
 	{ 0, 0, NULL }
 };
 
@@ -230,6 +232,9 @@
 		{
 			case PROC_NET_UNIX:
 				length = unix_get_info(page,&start,file->f_pos,thistime);
+				break;
+			case PROC_NET_SOCKSTAT:
+				length = afinet_get_info(page,&start,file->f_pos,thistime);
 				break;
 #ifdef CONFIG_INET
 			case PROC_NET_ARP:
diff -u --recursive --new-file v1.1.78/linux/fs/proc/root.c linux/fs/proc/root.c
--- v1.1.78/linux/fs/proc/root.c	Mon Dec 12 20:13:07 1994
+++ linux/fs/proc/root.c	Wed Jan 11 08:55:07 1995
@@ -59,6 +59,9 @@
 	{ PROC_MEMINFO,		7, "meminfo" },
 	{ PROC_KMSG,		4, "kmsg" },
 	{ PROC_VERSION,		7, "version" },
+#ifdef CONFIG_PCI
+	{ PROC_PCI,             3, "pci"  },
+#endif
 	{ PROC_CPUINFO,		7, "cpuinfo" },
 	{ PROC_SELF,		4, "self" },	/* will change inode # */
 	{ PROC_NET,		3, "net" },
@@ -74,7 +77,9 @@
    	{ PROC_KSYMS,		5, "ksyms" },
    	{ PROC_DMA,		3, "dma" },
 	{ PROC_IOPORTS,		7, "ioports"},
-	{ PROC_PROFILE,     7, "profile"},
+#ifdef CONFIG_PROFILE
+	{ PROC_PROFILE,		7, "profile"},
+#endif
 };
 
 #define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0])))
diff -u --recursive --new-file v1.1.78/linux/fs/sysv/Makefile linux/fs/sysv/Makefile
--- v1.1.78/linux/fs/sysv/Makefile	Mon Jan  9 11:24:23 1995
+++ linux/fs/sysv/Makefile	Tue Jan 10 17:02:18 1995
@@ -21,6 +21,8 @@
 	$(LD) -r -o sysv.o $(OBJS)
 
 modules: sysv.o
+	ln -sf ../fs/sysv/sysv.o $(TOPDIR)/modules
+
 dep:
 	$(CPP) -M *.c > .depend
 
diff -u --recursive --new-file v1.1.78/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v1.1.78/linux/fs/sysv/inode.c	Mon Jan  9 11:24:23 1995
+++ linux/fs/sysv/inode.c	Tue Jan 10 17:18:08 1995
@@ -1000,11 +1000,6 @@
 {
 	int i;
 
-	if (MOD_IN_USE) {
-		printk("SysV FS cannot be removed, currently in use\n");
-		return;
-	}
-
 	for (i = 0; i < 3; i++)
 		unregister_filesystem(&sysv_fs_type[i]);
 }
diff -u --recursive --new-file v1.1.78/linux/fs/umsdos/Makefile linux/fs/umsdos/Makefile
--- v1.1.78/linux/fs/umsdos/Makefile	Mon Jan  9 11:24:23 1995
+++ linux/fs/umsdos/Makefile	Tue Jan 10 17:02:18 1995
@@ -21,6 +21,7 @@
 	$(LD) -r -o umsdos.o $(OBJS)
 
 modules: umsdos.o
+	ln -sf ../fs/umsdos/umsdos.o $(TOPDIR)/modules
 
 clean:
 	rm -f core *.o *.a *.s
diff -u --recursive --new-file v1.1.78/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- v1.1.78/linux/fs/umsdos/inode.c	Tue Dec 27 08:37:13 1994
+++ linux/fs/umsdos/inode.c	Tue Jan 10 17:02:18 1995
@@ -13,13 +13,15 @@
 #include <linux/errno.h>
 #include <asm/segment.h>
 #include <linux/string.h>
-#include <linux/ctype.h>
 #include <linux/stat.h>
 #include <linux/umsdos_fs.h>
 
 #ifdef MODULE
-	#include <linux/module.h>
-	#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
 #endif
 
 struct inode *pseudo_root=NULL;		/* Useful to simulate the pseudo DOS */
@@ -55,9 +57,7 @@
 void UMSDOS_put_super(struct super_block *sb)
 {
 	msdos_put_super(sb);
-	#ifdef MODULE
-		MOD_DEC_USE_COUNT;
-	#endif
+	MOD_DEC_USE_COUNT;
 }
 
 
@@ -404,7 +404,9 @@
 		which do not have an EMD file. They behave like normal
 		msdos directory, with all limitation of msdos.
 	*/
-	struct super_block *sb = msdos_read_super(s,data,silent);
+	struct super_block *sb;
+	MOD_INC_USE_COUNT;
+	sb = msdos_read_super(s,data,silent);
 	printk ("UMSDOS Beta 0.6 (compatibility level %d.%d, fast msdos)\n"
 		,UMSDOS_VERSION,UMSDOS_RELEASE);
 	if (sb != NULL){
@@ -473,9 +475,8 @@
 			}
 			iput (pseudo);
 		}
-		#ifdef MODULE
-			MOD_INC_USE_COUNT;
-		#endif
+	} else {
+		MOD_DEC_USE_COUNT;
 	}
 	return sb;
 }
@@ -497,12 +498,7 @@
 
 void cleanup_module(void)
 {
-	if (MOD_IN_USE)
-		printk("Umsdos: file system in use, remove delayed\n");
-	else
-	{
-		unregister_filesystem(&umsdos_fs_type);
-	}
+	unregister_filesystem(&umsdos_fs_type);
 }
 
 #endif
diff -u --recursive --new-file v1.1.78/linux/fs/xiafs/Makefile linux/fs/xiafs/Makefile
--- v1.1.78/linux/fs/xiafs/Makefile	Mon Jan  9 11:24:23 1995
+++ linux/fs/xiafs/Makefile	Tue Jan 10 17:02:18 1995
@@ -21,6 +21,7 @@
 	$(LD) -r -o xiafs.o $(OBJS)
 
 modules: xiafs.o
+	ln -sf ../fs/xiafs/xiafs.o $(TOPDIR)/modules
 
 dep:
 	$(CPP) -M *.c > .depend
diff -u --recursive --new-file v1.1.78/linux/fs/xiafs/inode.c linux/fs/xiafs/inode.c
--- v1.1.78/linux/fs/xiafs/inode.c	Tue Dec  6 12:39:35 1994
+++ linux/fs/xiafs/inode.c	Tue Jan 10 17:02:18 1995
@@ -535,10 +535,6 @@
 
 void cleanup_module(void)
 {
-	if (MOD_IN_USE) {
-		printk("XIA-FS cannot be removed, currently in use\n");
-		return;
-	}
 	unregister_filesystem(&xiafs_fs_type);
 }
 
diff -u --recursive --new-file v1.1.78/linux/fs/xiafs/namei.c linux/fs/xiafs/namei.c
--- v1.1.78/linux/fs/xiafs/namei.c	Thu Aug 11 17:11:07 1994
+++ linux/fs/xiafs/namei.c	Wed Jan 11 08:11:02 1995
@@ -758,8 +758,7 @@
         retval = -EEXIST;
 	if (new_bh)
 	    goto end_rename;
-	retval = -EACCES;
-	if (!permission(old_inode, MAY_WRITE))
+	if ((retval = permission(old_inode, MAY_WRITE)) != 0)
 	    goto end_rename;
 	retval = -EINVAL;
 	if (subdir(new_dir, old_inode))
diff -u --recursive --new-file v1.1.78/linux/include/asm-alpha/byteorder.h linux/include/asm-alpha/byteorder.h
--- v1.1.78/linux/include/asm-alpha/byteorder.h	Mon Jan  9 07:22:09 1995
+++ linux/include/asm-alpha/byteorder.h	Tue Jan 10 10:07:07 1995
@@ -20,7 +20,7 @@
  * The constant and non-constant versions here are the same.
  * Maybe I'll come up with an alpha-optimized routine for the
  * non-constant ones (the constant ones don't need it: gcc
- * will optimze it to the correct constant)
+ * will optimize it to the correct constant)
  */
 
 extern __inline__ unsigned long int
diff -u --recursive --new-file v1.1.78/linux/include/asm-sparc/byteorder.h linux/include/asm-sparc/byteorder.h
--- v1.1.78/linux/include/asm-sparc/byteorder.h	Mon Jan  9 07:22:10 1995
+++ linux/include/asm-sparc/byteorder.h	Wed Jan 11 09:00:53 1995
@@ -20,7 +20,7 @@
  * The constant and non-constant versions here are the same.
  * Maybe I'll come up with an alpha-optimized routine for the
  * non-constant ones (the constant ones don't need it: gcc
- * will optimze it to the correct constant)
+ * will optimize it to the correct constant)
  */
 
 extern __inline__ unsigned long int
diff -u --recursive --new-file v1.1.78/linux/include/asm-sparc/page.h linux/include/asm-sparc/page.h
--- v1.1.78/linux/include/asm-sparc/page.h	Mon Jan  9 07:22:10 1995
+++ linux/include/asm-sparc/page.h	Wed Jan 11 09:00:53 1995
@@ -19,7 +19,7 @@
 
 #define PAGE_SHIFT   12             /* This is the virtual page... */
 #define PGDIR_SHIFT  18             /* This is the virtual segment */
-#define PAGE_SIZE    (1UL << PAGE_SHIFT)
+#define PAGE_SIZE    4096
 #define PGDIR_SIZE   (1UL << PGDIR_SHIFT)
 
 #ifdef __KERNEL__
@@ -65,6 +65,7 @@
  * with the following macro
  */
 
+#ifndef __ASSEMBLY__ /* for head.S */
 extern __inline__ unsigned long get_segmap(unsigned long addr)
 {
   register unsigned long entry;
@@ -122,6 +123,8 @@
 
   return ctx;
 }
+
+#endif /* !(__ASSEMBLY__) */
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v1.1.78/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h
--- v1.1.78/linux/include/asm-sparc/processor.h	Mon Jan  9 11:24:24 1995
+++ linux/include/asm-sparc/processor.h	Wed Jan 11 09:00:53 1995
@@ -48,7 +48,7 @@
 	unsigned long npc;          /* next program counter */
 
 /* 8 local registers + 8 in registers * 24 register windows.
- * Most sparc's I know of only have 8 windows implemented,
+ * Most sparcs I know of only have 8 windows implemented,
  * we determine how many at boot time and store that value
  * in nwindows.
  */
@@ -58,8 +58,7 @@
 };
 
 #define INIT_TSS  { \
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-        0, 0, 0, 0, 0, 0, 0, 0, \
+	0, 0, 0, 0, 0, 0, \
         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
@@ -84,7 +83,9 @@
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
-	0, 0, 0, 0, \
+	0, 0, 0, 0, 0, 0, 0, 0, 0, \
+        { 0, 0, 0, 0, 0, 0, 0, 0, }, \
+        0, \
         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
diff -u --recursive --new-file v1.1.78/linux/include/asm-sparc/psr.h linux/include/asm-sparc/psr.h
--- v1.1.78/linux/include/asm-sparc/psr.h	Mon Jan  2 15:26:45 1995
+++ linux/include/asm-sparc/psr.h	Wed Jan 11 09:00:53 1995
@@ -10,6 +10,7 @@
 #ifndef __LINUX_SPARC_PSR_H
 #define __LINUX_SPARC_PSR_H
 
+#define __LINUX_SPARC_V8  /* duh */
 
 #ifdef __LINUX_SPARC_V8
 
diff -u --recursive --new-file v1.1.78/linux/include/asm-sparc/segment.h linux/include/asm-sparc/segment.h
--- v1.1.78/linux/include/asm-sparc/segment.h	Mon Jan  2 15:26:45 1995
+++ linux/include/asm-sparc/segment.h	Wed Jan 11 09:07:01 1995
@@ -8,6 +8,7 @@
 #define USER_DS     0x1
 
 #include <linux/string.h>
+#include <asm/vac-ops.h>
 
 static inline unsigned char get_user_byte(const char * addr)
 {
diff -u --recursive --new-file v1.1.78/linux/include/asm-sparc/string.h linux/include/asm-sparc/string.h
--- v1.1.78/linux/include/asm-sparc/string.h	Mon Jan  9 07:22:10 1995
+++ linux/include/asm-sparc/string.h	Wed Jan 11 09:00:53 1995
@@ -166,7 +166,7 @@
   return retval;
 }
 
-extern __inline__ char *strchr(const char *src, char c)
+extern __inline__ char *strchr(const char *src, int c)
 {
   register char temp;
   register char *trick;
@@ -271,7 +271,7 @@
 }
 	
 
-extern __inline__ void *memset(void *src, char c, size_t count)
+extern __inline__ void *memset(void *src, int c, size_t count)
 {
   register void *retval;
 
diff -u --recursive --new-file v1.1.78/linux/include/linux/lp.h linux/include/linux/lp.h
--- v1.1.78/linux/include/linux/lp.h	Thu Dec 29 20:13:17 1994
+++ linux/include/linux/lp.h	Tue Jan 10 10:07:09 1995
@@ -53,20 +53,21 @@
 #define LP_INIT_TIME 2
 
 /* IOCTL numbers */
-#define LPCHAR   0x0001  /* corresponds to LP_INIT_CHAR */
-#define LPTIME   0x0002  /* corresponds to LP_INIT_TIME */
-#define LPABORT  0x0004  /* call with TRUE arg to abort on error,
+#define LPCHAR   0x0601  /* corresponds to LP_INIT_CHAR */
+#define LPTIME   0x0602  /* corresponds to LP_INIT_TIME */
+#define LPABORT  0x0604  /* call with TRUE arg to abort on error,
 			    FALSE to retry.  Default is retry.  */
-#define LPSETIRQ 0x0005  /* call with new IRQ number,
+#define LPSETIRQ 0x0605  /* call with new IRQ number,
 			    or 0 for polling (no IRQ) */
-#define LPGETIRQ 0x0006  /* get the current IRQ number */
-#define LPWAIT   0x0008  /* corresponds to LP_INIT_WAIT */
-#define LPCAREFUL   0x0009  /* call with TRUE arg to require out-of-paper, off-
+#define LPGETIRQ 0x0606  /* get the current IRQ number */
+#define LPWAIT   0x0608  /* corresponds to LP_INIT_WAIT */
+#define LPCAREFUL   0x0609  /* call with TRUE arg to require out-of-paper, off-
 			    line, and error indicators good on all writes,
 			    FALSE to ignore them.  Default is ignore. */
-#define LPABORTOPEN 0x000a  /* call with TRUE arg to abort open() on error,
+#define LPABORTOPEN 0x060a  /* call with TRUE arg to abort open() on error,
 			    FALSE to ignore error.  Default is ignore.  */
-#define LPGETSTATUS 0x000b  /* return LP_S(minor) */
+#define LPGETSTATUS 0x060b  /* return LP_S(minor) */
+#define LPRESET     0x060c  /* reset printer */
 
 /* timeout for printk'ing a timeout, in jiffies (100ths of a second).
    This is also used for re-checking error conditions if LP_ABORT is
diff -u --recursive --new-file v1.1.78/linux/include/linux/net.h linux/include/linux/net.h
--- v1.1.78/linux/include/linux/net.h	Mon Jan  9 07:22:10 1995
+++ linux/include/linux/net.h	Wed Jan 11 08:03:11 1995
@@ -23,7 +23,7 @@
 #include <linux/socket.h>
 
 
-#define NSOCKETS	128		/* should be dynamic, later...	*/
+#define NSOCKETS	2000		/* Dynamic, this is MAX LIMIT	*/
 #define NPROTO		16		/* should be enough for now..	*/
 
 
@@ -80,6 +80,8 @@
   struct wait_queue	**wait;		/* ptr to place to wait on	*/
   struct inode		*inode;
   struct fasync_struct  *fasync_list;	/* Asynchronous wake up list	*/
+  struct socket		*nextsock;	/* next on the allocated socks	*/
+  struct socket		*prevsock;	/* precious on the allocated socks */
 };
 
 #define SOCK_INODE(S)	((S)->inode)
diff -u --recursive --new-file v1.1.78/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v1.1.78/linux/include/linux/proc_fs.h	Mon Jan  9 07:22:11 1995
+++ linux/include/linux/proc_fs.h	Wed Jan 11 08:11:02 1995
@@ -15,6 +15,7 @@
 	PROC_KMSG,
 	PROC_VERSION,
 	PROC_CPUINFO,
+	PROC_PCI,
 	PROC_SELF,	/* will change inode # */
 	PROC_NET,
 #ifdef CONFIG_DEBUG_MALLOC
@@ -87,6 +88,7 @@
 	PROC_NET_NR,
 #endif
 #endif
+	PROC_NET_SOCKSTAT,
 	PROC_NET_LAST
 };
 
diff -u --recursive --new-file v1.1.78/linux/include/linux/sysv_fs.h linux/include/linux/sysv_fs.h
--- v1.1.78/linux/include/linux/sysv_fs.h	Sat Nov  5 13:32:13 1994
+++ linux/include/linux/sysv_fs.h	Tue Jan 10 17:02:10 1995
@@ -136,7 +136,7 @@
 	char	       s_fname[6];	/* file system volume name */
 	char	       s_fpack[6];	/* file system pack name */
 	long	       s_fill[12];
-	long	       s_state;		/* file system state */
+	long	       s_state;		/* file system state: 0x7c269d38-s_time means clean */
 	long	       s_magic;		/* version of file system */
 	long	       s_type;		/* type of file system: 1 for 512 byte blocks
 								2 for 1024 byte blocks */
@@ -170,7 +170,7 @@
 	char	       s_fname[6];	/* file system volume name */
 	char	       s_fpack[6];	/* file system pack name */
 	long	       s_fill[14];
-	long	       s_state;		/* file system state */
+	long	       s_state;		/* file system state: 0xcb096f43 means clean */
 	long	       s_magic;		/* version of file system */
 	long	       s_type;		/* type of file system: 1 for 512 byte blocks
 								2 for 1024 byte blocks */
diff -u --recursive --new-file v1.1.78/linux/include/linux/sysv_fs_sb.h linux/include/linux/sysv_fs_sb.h
--- v1.1.78/linux/include/linux/sysv_fs_sb.h	Mon Jan  9 07:22:11 1995
+++ linux/include/linux/sysv_fs_sb.h	Tue Jan 10 17:02:11 1995
@@ -57,7 +57,7 @@
 	unsigned long  *s_sb_flc_blocks; /* pointer to s_sbd->s_free */
 	unsigned long  *s_sb_total_free_blocks;/* pointer to s_sbd->s_tfree */
 	unsigned long  *s_sb_time;	/* pointer to s_sbd->s_time */
-	unsigned long  *s_sb_state;	/* pointer to s_sbd->s_state */
+	unsigned long  *s_sb_state;	/* pointer to s_sbd->s_state, only FSTYPE_SYSV */
 	/* We keep those superblock entities that don't change here;
 	   this saves us an indirection and perhaps a conversion. */
 	unsigned long  s_firstinodezone; /* index of first inode zone */
diff -u --recursive --new-file v1.1.78/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.1.78/linux/kernel/ksyms.c	Mon Jan  9 11:24:24 1995
+++ linux/kernel/ksyms.c	Tue Jan 10 10:08:21 1995
@@ -188,6 +188,11 @@
 	X(request_dma),
 	X(free_dma),
 
+	/* IO port handling */
+	X(check_region),
+	X(request_region),
+	X(release_region),
+
 	/* process management */
 	X(wake_up),
 	X(wake_up_interruptible),
@@ -246,9 +251,6 @@
 	X(alloc_skb),
 	X(kfree_skb),
 	X(dev_kfree_skb),
-	X(snarf_region),
-	X(request_region),
-	X(release_region),
 	X(netif_rx),
 	X(dev_rint),
 	X(dev_tint),
diff -u --recursive --new-file v1.1.78/linux/net/inet/af_inet.c linux/net/inet/af_inet.c
--- v1.1.78/linux/net/inet/af_inet.c	Mon Jan  9 11:24:24 1995
+++ linux/net/inet/af_inet.c	Wed Jan 11 08:03:11 1995
@@ -154,20 +154,27 @@
 	struct sock *sk1;
 	struct sock *sk2;
 	int mask;
+	unsigned long flags;
 
 	sk->num = num;
 	sk->next = NULL;
 	num = num &(SOCK_ARRAY_SIZE -1);
 
 	/* We can't have an interrupt re-enter here. */
+	save_flags(flags);
 	cli();
+
+	sk->prot->inuse += 1;
+	if (sk->prot->highestinuse < sk->prot->inuse)
+		sk->prot->highestinuse = sk->prot->inuse;
+
 	if (sk->prot->sock_array[num] == NULL) 
 	{
 		sk->prot->sock_array[num] = sk;
-		sti();
+		restore_flags(flags);
 		return;
 	}
-	sti();
+	restore_flags(flags);
 	for(mask = 0xff000000; mask != 0xffffffff; mask = (mask >> 8) | mask) 
 	{
 		if ((mask & sk->saddr) &&
@@ -211,6 +218,7 @@
 static void remove_sock(struct sock *sk1)
 {
 	struct sock *sk2;
+	unsigned long flags;
 
 	if (!sk1->prot) 
 	{
@@ -219,12 +227,14 @@
 	}
 
 	/* We can't have this changing out from under us. */
+	save_flags(flags);
 	cli();
 	sk2 = sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)];
 	if (sk2 == sk1) 
 	{
+		sk1->prot->inuse -= 1;
 		sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)] = sk1->next;
-		sti();
+		restore_flags(flags);
 		return;
 	}
 
@@ -235,11 +245,12 @@
 
 	if (sk2) 
 	{
+		sk1->prot->inuse -= 1;
 		sk2->next = sk1->next;
-		sti();
+		restore_flags(flags);
 		return;
 	}
-	sti();
+	restore_flags(flags);
 }
 
 /*
@@ -1502,6 +1513,12 @@
 		udp_prot.sock_array[i] = NULL;
 		raw_prot.sock_array[i] = NULL;
   	}
+	tcp_prot.inuse = 0;
+	tcp_prot.highestinuse = 0;
+	udp_prot.inuse = 0;
+	udp_prot.highestinuse = 0;
+	raw_prot.inuse = 0;
+	raw_prot.highestinuse = 0;
 
 	printk("IP Protocols: ");
 	for(p = inet_protocol_base; p != NULL;) 
diff -u --recursive --new-file v1.1.78/linux/net/inet/dev.c linux/net/inet/dev.c
--- v1.1.78/linux/net/inet/dev.c	Mon Jan  9 07:22:12 1995
+++ linux/net/inet/dev.c	Tue Jan 10 10:07:07 1995
@@ -281,7 +281,7 @@
 	return notifier_chain_register(&netdev_chain, nb);
 }
 
-int unregister_netdevice_notifer(struct notifier_block *nb)
+int unregister_netdevice_notifier(struct notifier_block *nb)
 {
 	return notifier_chain_unregister(&netdev_chain,nb);
 }
@@ -611,7 +611,7 @@
 {
 	struct sk_buff *skb;
 	struct packet_type *ptype;
-	struct packet_type *pt_prev=NULL;
+	struct packet_type *pt_prev;
 	unsigned short type;
 
 	/*
@@ -684,7 +684,7 @@
 		 *	here is minimal but no doubt adds up at the 4,000+ pkts/second
 		 *	rate we can hit flat out]
 		 */
-		 
+		pt_prev = NULL;
 		for (ptype = ptype_base; ptype != NULL; ptype = ptype->next) 
 		{
 			if ((ptype->type == type || ptype->type == htons(ETH_P_ALL)) && (!ptype->dev || ptype->dev==skb->dev))
diff -u --recursive --new-file v1.1.78/linux/net/inet/ipx.c linux/net/inet/ipx.c
--- v1.1.78/linux/net/inet/ipx.c	Mon Jan  9 07:22:13 1995
+++ linux/net/inet/ipx.c	Tue Jan 10 10:07:20 1995
@@ -32,6 +32,7 @@
  *			Small correction to promisc mode error fix <Alan Cox>
  *			Asynchronous I/O support.
  *			Changed to use notifiers and the newer packet_type stuff.
+ *			Assorted major fixes <Alejandro Liu>
  */
   
 #include <linux/config.h>
@@ -432,7 +433,6 @@
 	}
 }
 
-/* Called from proc fs */
 int ipx_rt_get_info(char *buffer, char **start, off_t offset, int length)
 {
 	ipx_route *rt;
@@ -440,12 +440,13 @@
 	off_t pos=0;
 	off_t begin=0;
 
-	len += sprintf (buffer,"Net      Router                Flags Dev\n");
+	len += sprintf (buffer,"Net      Router                Flags Dev   Frame\n");
 	for (rt = ipx_router_list; rt != NULL; rt = rt->next)
 	{
-		len += sprintf (buffer+len,"%08lX %08lX:%02X%02X%02X%02X%02X%02X %02X    %s\n", ntohl(rt->net),
+		len += sprintf (buffer+len,"%08lX %08lX:%02X%02X%02X%02X%02X%02X %02X    %s  %d\n", ntohl(rt->net),
 			ntohl(rt->router_net), rt->router_node[0], rt->router_node[1], rt->router_node[2],
-			rt->router_node[3], rt->router_node[4], rt->router_node[5], rt->flags, rt->dev->name);
+			rt->router_node[3], rt->router_node[4], rt->router_node[5], rt->flags, rt->dev->name,
+			ntohs(rt->dlink_type));
 		pos=begin+len;
 		if(pos<offset)
 		{
@@ -806,6 +807,50 @@
 	return(0);
 }
 
+#if 0
+/*
+ * User to dump IPX packets (debugging)
+ */
+void dump_data(char *str,unsigned char *d) {
+  static char h2c[] = "0123456789ABCDEF";
+  int l,i;
+  char *p, b[64];
+  for (l=0;l<16;l++) {
+    p = b;
+    for (i=0; i < 8 ; i++) {
+      *(p++) = h2c[d[i] & 0x0f];
+      *(p++) = h2c[(d[i] >> 4) & 0x0f];
+      *(p++) = ' ';
+    }
+    *(p++) = '-';
+    *(p++) = ' ';
+    for (i=0; i < 8 ; i++)  *(p++) = ' '<= d[i] && d[i]<'\177' ? d[i] : '.';
+    *p = '\000';
+    d += i;
+    printk("%s-%04X: %s\n",str,l*8,b);
+  }
+}
+
+void dump_addr(char *str,ipx_address *p) {
+  printk("%s: %08X:%02X%02X%02X%02X%02X%02X:%04X\n",
+   str,ntohl(p->net),p->node[0],p->node[1],p->node[2],
+   p->node[3],p->node[4],p->node[5],ntohs(p->sock));
+}
+
+void dump_hdr(char *str,ipx_packet *p) {
+  printk("%s: CHKSUM=%04X SIZE=%d (%04X) HOPS=%d (%02X) TYPE=%02X\n",
+   str,p->ipx_checksum,ntohs(p->ipx_pktsize),ntohs(p->ipx_pktsize),
+   p->ipx_tctrl,p->ipx_tctrl,p->ipx_type);
+  dump_addr("  IPX-DST",&p->ipx_dest);
+  dump_addr("  IPX-SRC",&p->ipx_source);
+}
+
+void dump_pkt(char *str,ipx_packet *p) {
+  dump_hdr(str,p);
+  dump_data(str,(unsigned char *)p);
+}
+#endif
+
 int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 {
 	/* NULL here for pt means the packet was looped back */
@@ -885,6 +930,18 @@
 			return(0);
 		}
 
+		/*
+		 *	Ok, before we forward, make sure this is not a local packet on the 
+		 *	other network 
+		 */
+		if (rt->router_net == 0) 
+		{
+			memset(IPXaddr,'\0',6);
+			memcpy(IPXaddr+(6-rt->dev->addr_len),rt->dev->dev_addr,rt->dev->addr_len);
+			if (memcmp(IPXaddr,ipx->ipx_dest.node,6) == 0) 
+				goto DELIVER;
+		}
+	
 		/* Check for differences in outgoing and incoming packet size */
 		incoming_size = skb->len - ntohs(ipx->ipx_pktsize);
 		outgoing_size = rt->datalink->header_length + rt->dev->hard_header_len;
@@ -900,15 +957,20 @@
 				return 0;
 			}
 			free_it=1;
-			skb2->free=1;
 			skb2->len=ntohs(ipx->ipx_pktsize) + outgoing_size;
 			skb2->mem_addr = skb2;
-			skb2->arp = 1;
 			skb2->sk = NULL;
+			skb2->free = 1;
+			skb2->arp = 1;
+			skb2->len = ntohs(ipx->ipx_pktsize) + outgoing_size;
 
-			/* Need to copy with appropriate offsets */
-			memcpy((char *)(skb2+1)+outgoing_size,
-				(char *)(skb+1)+incoming_size,
+			/*
+        		 *	NOTE: src arg for memcpy used to be (skb+1)+insize
+			 *	however, that doesn't work... (dunno why)
+			 *	it should though...
+ 			 */
+ 			
+ 			memcpy((char *)(skb2+1)+outgoing_size,ipx,
 				ntohs(ipx->ipx_pktsize));
 		}
 		else
@@ -931,7 +993,7 @@
 		return(0);
 	}
 	/************ End of router: Now sanity check stuff for us ***************/
-	
+DELIVER:	
 	/* Ok its for us ! */
 	if (ln->net == 0L) {
 /*		printk("IPX: Registering local net %lx\n", ipx->ipx_dest.net);*/
@@ -1319,6 +1381,7 @@
 /* Called by ddi.c on kernel start up */
 
 static struct packet_type ipx_8023_packet_type = 
+
 {
 	0,	/* MUTTER ntohs(ETH_P_8023),*/
 	0,		/* copy */
diff -u --recursive --new-file v1.1.78/linux/net/inet/packet.c linux/net/inet/packet.c
--- v1.1.78/linux/net/inet/packet.c	Mon Jan  9 07:22:13 1995
+++ linux/net/inet/packet.c	Wed Jan 11 08:03:11 1995
@@ -404,5 +404,6 @@
 	128,
 	0,
 	{NULL,},
-	"PACKET"
+	"PACKET",
+	0, 0
 };
diff -u --recursive --new-file v1.1.78/linux/net/inet/proc.c linux/net/inet/proc.c
--- v1.1.78/linux/net/inet/proc.c	Wed Dec 28 09:43:32 1994
+++ linux/net/inet/proc.c	Wed Jan 11 08:03:11 1995
@@ -145,6 +145,34 @@
 }
 
 
+/*
+ *	Report socket allocation statistics [mea@utu.fi]
+ */
+int afinet_get_info(char *buffer, char **start, off_t offset, int length)
+{
+	/* From  net/socket.c  */
+	extern int socket_get_info(char *, char **, off_t, int);
+	extern struct proto packet_prot;
+
+	int len  = socket_get_info(buffer,start,offset,length);
+
+	len += sprintf(buffer+len,"SOCK_ARRAY_SIZE=%d\n",SOCK_ARRAY_SIZE);
+	len += sprintf(buffer+len,"TCP: inuse %d highest %d\n",
+		       tcp_prot.inuse, tcp_prot.highestinuse);
+	len += sprintf(buffer+len,"UDP: inuse %d highest %d\n",
+		       udp_prot.inuse, udp_prot.highestinuse);
+	len += sprintf(buffer+len,"RAW: inuse %d highest %d\n",
+		       raw_prot.inuse, raw_prot.highestinuse);
+	len += sprintf(buffer+len,"PAC: inuse %d highest %d\n",
+		       packet_prot.inuse, packet_prot.highestinuse);
+	*start = buffer + offset;
+	len -= offset;
+	if (len > length)
+		len = length;
+	return len;
+}
+
+
 /* 
  *	Called from the PROCfs module. This outputs /proc/net/snmp.
  */
diff -u --recursive --new-file v1.1.78/linux/net/inet/raw.c linux/net/inet/raw.c
--- v1.1.78/linux/net/inet/raw.c	Mon Dec 12 21:01:10 1994
+++ linux/net/inet/raw.c	Wed Jan 11 08:03:11 1995
@@ -314,5 +314,6 @@
 	128,
 	0,
 	{NULL,},
-	"RAW"
+	"RAW",
+	0, 0
 };
diff -u --recursive --new-file v1.1.78/linux/net/inet/sock.h linux/net/inet/sock.h
--- v1.1.78/linux/net/inet/sock.h	Mon Jan  9 07:22:13 1995
+++ linux/net/inet/sock.h	Wed Jan 11 08:03:11 1995
@@ -91,6 +91,7 @@
   unsigned long		        lingertime;
   int				proc;
   struct sock			*next;
+  struct sock			*prev; /* Doubdly linked chain.. */
   struct sock			*pair;
   struct sk_buff		* volatile send_head;
   struct sk_buff		* volatile send_tail;
@@ -245,6 +246,7 @@
   unsigned long		retransmits;
   struct sock *		sock_array[SOCK_ARRAY_SIZE];
   char			name[80];
+  int			inuse, highestinuse;
 };
 
 #define TIME_WRITE	1
diff -u --recursive --new-file v1.1.78/linux/net/inet/tcp.c linux/net/inet/tcp.c
--- v1.1.78/linux/net/inet/tcp.c	Mon Jan  9 11:24:24 1995
+++ linux/net/inet/tcp.c	Wed Jan 11 08:03:11 1995
@@ -555,7 +555,7 @@
 	if (sk->inuse || in_bh) 
 	{
 		sk->retransmit_timer.expires = 10;
-		add_timer(&sk->timer);
+		add_timer(&sk->retransmit_timer);
 		sti();
 		return;
 	}
@@ -4821,5 +4821,6 @@
 	128,
 	0,
 	{NULL,},
-	"TCP"
+	"TCP",
+	0, 0
 };
diff -u --recursive --new-file v1.1.78/linux/net/inet/udp.c linux/net/inet/udp.c
--- v1.1.78/linux/net/inet/udp.c	Mon Jan  9 07:22:13 1995
+++ linux/net/inet/udp.c	Wed Jan 11 08:03:11 1995
@@ -599,7 +599,12 @@
 
 	if (uh->check && udp_check(uh, len, saddr, daddr)) 
 	{
-		printk("UDP: bad checksum.\n");
+		/* <mea@utu.fi> wants to know, who sent it, to
+		   go and stomp on the garbage sender... */
+		printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n",
+		       ntohl(saddr),ntohs(uh->source),
+		       ntohl(daddr),ntohs(uh->dest),
+		       ulen);
 		udp_statistics.UdpInErrors++;
 		kfree_skb(skb, FREE_WRITE);
 		return(0);
@@ -724,6 +729,7 @@
 	128,
 	0,
 	{NULL,},
-	"UDP"
+	"UDP",
+	0, 0
 };
 
diff -u --recursive --new-file v1.1.78/linux/net/socket.c linux/net/socket.c
--- v1.1.78/linux/net/socket.c	Mon Jan  9 07:22:13 1995
+++ linux/net/socket.c	Wed Jan 11 08:03:11 1995
@@ -21,7 +21,12 @@
  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
  *					tty drivers).
  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
- *		Jeff Uphoff	:	Made max number of sockets command-line configurable.
+ *		Jeff Uphoff	:	Made max number of sockets command-line
+ *					configurable.
+ *		Matti Aarnio	:	Made the number of sockets dynamic,
+ *					to be allocated when needed, and mr.
+ *					Uphoff's max is used as max to be
+ *					allowed to allocate.
  *
  *
  *		This program is free software; you can redistribute it and/or
@@ -90,9 +95,14 @@
 };
 
 /*
- *	The list of sockets -- allocated in sock_init().
+ *	The lists of sockets
  */
-static struct socket *sockets = NULL;
+
+static struct socket *freesockets = NULL;	/* List of free sockets,
+						   pick the first */
+static struct socket *usedsockets = NULL;	/* Doubly-linked list of the
+						   active sockets */
+
 /*
  *	Used to wait for a socket.
  */
@@ -104,16 +114,23 @@
 /*      
  *	Maximum number of sockets -- override-able on command-line.
  */
-static int nsockets = NSOCKETS;
-
-#define last_socket	(sockets + nsockets - 1)
+static int maxnsockets = NSOCKETS;
+/*
+ *	Number of sockets allocated
+ */
+static int nsockets = 0;
+/*
+ *	Statistics counters of the free/used lists
+ */
+static int sockets_in_use  = 0;
+static int sockets_in_free = 0;
 
 /*      
  *	Overrides default max number of sockets if supplied on command-line.
  */
 void sock_setup(char *str, int *ints)
 {
-	nsockets = ints[0] ? ints[1] : NSOCKETS;
+	maxnsockets = ints[0] ? ints[1] : NSOCKETS;
 }
 
 
@@ -214,7 +231,7 @@
 			return sock;
 		printk("socket.c: uhhuh. stale inode->i_socket pointer\n");
 	}
-	for (sock = sockets; sock <= last_socket; ++sock)
+	for (sock = usedsockets; sock != NULL; sock = sock->nextsock)
 		if (sock->state != SS_FREE && SOCK_INODE(sock) == inode) 
 		{
 			printk("socket.c: uhhuh. Found socket despite no inode->i_socket pointer\n");
@@ -247,48 +264,116 @@
 static struct socket *sock_alloc(int wait)
 {
 	struct socket *sock;
+	int i;
 
 	while (1) 
 	{
+		if (freesockets == NULL)
+		{
+			/* Lets see if we can allocate some more */
+			cli();
+			/* Alloc them from same memory page, if possible.
+			   Nothing SHOULD prevent us from allocing one at
+			   the time.. */
+			for (i = 0; i < 16 && nsockets < maxnsockets; ++i)
+			{
+				sock = (struct socket*)kmalloc(sizeof(struct socket),GFP_KERNEL);
+				if (sock == NULL) break; /* Ah well.. */
+				sock->state = SS_FREE;
+				sock->nextsock = freesockets;
+				sock->prevsock = NULL;
+				freesockets = sock;
+				++sockets_in_free;
+				++nsockets;
+			}
+			sti();
+printk("sock_alloc: Alloced some more, now %d sockets\n", nsockets);
+		}
+
+
 		cli();
-		for (sock = sockets; sock <= last_socket; ++sock) 
+		sock = freesockets;
+		if (sock != NULL) /* Freelist, we pick
+				     the first -- or only */
 		{
-			if (sock->state == SS_FREE) 
+		/*
+		 * Move it to the `usedsockets' linked-list
+		 * at its FRONT (thus  ->prevsock = NULL)
+		 */
+			freesockets = sock->nextsock;
+			sock->nextsock = usedsockets;
+			sock->prevsock = NULL;
+			/* Is there something in there already ? */
+			if (usedsockets != NULL)
+			  /* Yes, attach the `previous' pointer */
+			  usedsockets->prevsock = sock;
+			usedsockets = sock;
+
+			--sockets_in_free;
+			++sockets_in_use;
+			sti();
+		/*
+		 *	Got one..
+		 */
+			sock->state = SS_UNCONNECTED;
+			sock->flags = 0;
+			sock->ops = NULL;
+			sock->data = NULL;
+			sock->conn = NULL;
+			sock->iconn = NULL;
+			sock->fasync_list = NULL;
+		/*
+		 * This really shouldn't be necessary, but everything
+		 * else depends on inodes, so we grab it.
+		 * Sleeps are also done on the i_wait member of this
+		 * inode.  The close system call will iput this inode
+		 * for us.
+		 */
+			if (!(SOCK_INODE(sock) = get_empty_inode())) 
 			{
+				printk("NET: sock_alloc: no more inodes\n");
 			/*
-			 *	Got one..
+			 * Roll-back the linkage
 			 */
-				sock->state = SS_UNCONNECTED;
+				cli();
+				/* Not the last ? */
+				if (sock->nextsock != NULL)
+				  sock->nextsock->prevsock = sock->prevsock;
+				/* Not the first ? */
+				if (sock->prevsock != NULL)
+				  sock->prevsock->nextsock = sock->nextsock;
+				else
+				  /* It is the first, update the head-handle */
+				  usedsockets = sock->nextsock;
+				/* Link it back to the free-list */
+				sock->nextsock = freesockets;
+				sock->prevsock = NULL; /* Not used, but .. */
+				freesockets = sock;
+				++sockets_in_free;
+				--sockets_in_use;
 				sti();
-				sock->flags = 0;
-				sock->ops = NULL;
-				sock->data = NULL;
-				sock->conn = NULL;
-				sock->iconn = NULL;
-				sock->fasync_list = NULL;
-			/*
-			 * This really shouldn't be necessary, but everything
-			 * else depends on inodes, so we grab it.
-			 * Sleeps are also done on the i_wait member of this
-			 * inode.  The close system call will iput this inode
-			 * for us.
-			 */
-				if (!(SOCK_INODE(sock) = get_empty_inode())) 
-				{
-					printk("NET: sock_alloc: no more inodes\n");
-					sock->state = SS_FREE;
-					return(NULL);
-				}
-				SOCK_INODE(sock)->i_mode = S_IFSOCK;
-				SOCK_INODE(sock)->i_uid = current->uid;
-				SOCK_INODE(sock)->i_gid = current->gid;
-				SOCK_INODE(sock)->i_socket = sock;
-
-				sock->wait = &SOCK_INODE(sock)->i_wait;
-				return(sock);
+				sock->state = SS_FREE;
+				return(NULL);
 			}
+			SOCK_INODE(sock)->i_mode = S_IFSOCK;
+			SOCK_INODE(sock)->i_uid = current->euid;
+			SOCK_INODE(sock)->i_gid = current->egid;
+			SOCK_INODE(sock)->i_socket = sock;
+
+			sock->wait = &SOCK_INODE(sock)->i_wait;
+
+			return(sock);
 		}
 		sti();
+
+		/*
+		 * The rest of these are in fact vestigal from the previous
+		 * version, which didn't have growing list of sockets.
+		 * These may become necessary if there are 2000 (or whatever
+		 * the hard limit is set to) sockets already in system,
+		 * but then the system itself is quite catatonic.. IMO [mea]
+		 */
+
 		/*
 		 *	If its a 'now or never request' then return.
 		 */
@@ -325,6 +410,7 @@
 	int oldstate;
 	struct inode *inode;
 	struct socket *peersock, *nextsock;
+	unsigned long flags;
 
 	if ((oldstate = sock->state) != SS_UNCONNECTED)
 		sock->state = SS_DISCONNECTING;
@@ -350,7 +436,28 @@
 	if (peersock)
 		sock_release_peer(peersock);
 	inode = SOCK_INODE(sock);
+	/*
+	 * Remove this `sock' from the doubly-linked chain.
+	 */
+	save_flags(flags);
+	cli();
 	sock->state = SS_FREE;		/* this really releases us */
+	/* Not the last ? */
+	if (sock->nextsock != NULL)
+	  sock->nextsock->prevsock = sock->prevsock;
+	/* Not the first ? */
+	if (sock->prevsock != NULL)
+	  sock->prevsock->nextsock = sock->nextsock;
+	else
+	  /* It is the first, update the head-handle */
+	  usedsockets = sock->nextsock;
+	/* Link it back to the free-list */
+	sock->nextsock = freesockets;
+	sock->prevsock = NULL; /* Not really used, but.. */
+	freesockets = sock;
+	--sockets_in_use;	/* Bookkeeping.. */
+	++sockets_in_free;
+	restore_flags(flags);
 	
 	/*
 	 *	This will wake anyone waiting for a free socket.
@@ -698,8 +805,9 @@
 
 	if (!(sock = sock_alloc(1))) 
 	{
-		printk("sock_socket: no more sockets\n");
-		return(-EAGAIN);
+		printk("NET: sock_socket: no more sockets\n");
+		return(-ENOSR);	/* Was: EAGAIN, but we are out of
+				   system resources! */
 	}
 
 	sock->type = type;
@@ -871,7 +979,8 @@
 	if (!(newsock = sock_alloc(0))) 
 	{
 		printk("NET: sock_accept: no more sockets\n");
-		return(-EAGAIN);
+		return(-ENOSR);	/* Was: EGAIN, but we are out of system
+				   resources! */
 	}
 	newsock->type = sock->type;
 	newsock->ops = sock->ops;
@@ -1406,23 +1515,11 @@
 
 void sock_init(void)
 {
-	struct socket *sock;
 	int i;
 
 	printk("Swansea University Computer Society NET3.019\n");
 
 	/*
-	 *	The list of sockets.
-	 */
-	sockets = (struct socket *)kmalloc(sizeof(struct socket) * nsockets, GFP_KERNEL);
-	printk("Allocated %d sockets.\n", nsockets);
-	/*
-	 *	Release all sockets. 
-	 */
-	for (sock = sockets; sock <= last_socket; ++sock)
-		sock->state = SS_FREE;
-
-	/*
 	 *	Initialize all address (protocol) families. 
 	 */
 	 
@@ -1447,5 +1544,22 @@
 
 	bh_base[NET_BH].routine= net_bh;
 #endif  
-  
+}
+
+int socket_get_info(char *buffer, char **start, off_t offset, int length)
+{
+	int len = sprintf(buffer,
+			  "sockets: used %d free %d alloced %d highlimit %d\n",
+			  sockets_in_use, sockets_in_free,
+			  nsockets, maxnsockets);
+	if (offset >= len)
+	{
+		*start = buffer;
+		return 0;
+	}
+	*start = buffer + offset;
+	len -= offset;
+	if (len > length)
+		len = length;
+	return len;
 }
