diff -u --recursive --new-file v1.1.94/linux/Makefile linux/Makefile
--- v1.1.94/linux/Makefile	Wed Feb 22 16:53:03 1995
+++ linux/Makefile	Thu Feb 23 13:32:28 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 94
+SUBLEVEL = 95
 
 ARCH = i386
 
diff -u --recursive --new-file v1.1.94/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v1.1.94/linux/arch/alpha/kernel/entry.S	Wed Feb 22 16:53:03 1995
+++ linux/arch/alpha/kernel/entry.S	Sun Feb 26 20:27:20 1995
@@ -63,7 +63,7 @@
 .text
 .set noat
 
-.align 5
+.align 3
 .globl	entInt
 .ent	entInt
 entInt:
@@ -74,7 +74,6 @@
 	addq	$1,1,$1
 	stq	$1,0($0)
 /* set up the arguments to the C interrupt handler */
-	bis	$30,$30,$19
 	lda	$27,do_entInt
 	jsr	$26,($27),do_entInt
 /* ok, check if we need to do software interrupts */
@@ -91,73 +90,128 @@
 2:	stq	$1,0($0)
 	RESTORE_ALL
 	rti
-.align 5
+.align 3
 3:	lda	$27,do_bottom_half
 	jsr	$26,($27),do_bottom_half
 	br	$31,1b
 .end entInt
 
-.align 5
+.align 3
 .globl	entMM
 .ent	entMM
 entMM:
 	SAVE_ALL
-	bis	$30,$30,$19
 	lda	$27,do_page_fault
 	jsr	$26,($27),do_page_fault
 	RESTORE_ALL
 	rti
 .end entMM
 
-.align 5
+.align 3
 .globl	entArith
 .ent	entArith
 entArith:
 	SAVE_ALL
-	bis	$30,$30,$19
 	lda	$27,do_entArith
 	jsr	$26,($27),do_entArith
 	RESTORE_ALL
 	rti
 .end entArith
 
-.align 5
+.align 3
 .globl	entIF
 .ent	entIF
 entIF:
 	SAVE_ALL
-	bis	$30,$30,$19
 	lda	$27,do_entIF
 	jsr	$26,($27),do_entIF
 	RESTORE_ALL
 	rti
 .end entIF
 
-.align 5
+.align 3
 .globl	entUna
 .ent	entUna
 entUna:
 	SAVE_ALL
-	bis	$30,$30,$19
 	lda	$27,do_entUna
 	jsr	$26,($27),do_entUna
 	RESTORE_ALL
 	rti
 .end entUna
 
-.align 5
+/*
+ * Fork() is one of the special system calls: it needs to
+ * save the callee-saved regs so that the regs can be found
+ * for the new process.. We save them in the "context switch"
+ * stack format (see arch/alpha/kernel/process.c).
+ *
+ * Also, for the kernel fork, we need to fake the system call
+ * stack buildup, as we can't do system calls from kernel space.
+ */
+.align 3
+.globl	kernel_fork
+.ent	kernel_fork
+kernel_fork:
+	subq $30,6*8,$30
+	stq $31,0($30)
+	stq $26,8($30)
+	stq $29,16($30)
+	stq $16,24($30)
+	stq $17,32($30)
+	stq $18,40($30)
+	SAVE_ALL
+	lda $27,sys_fork
+	jsr $26,($27),sys_fork
+	br ret_from_sys_call
+.end	kernel_fork
+
+.align 3
+.globl	sys_fork
+.ent	sys_fork
+sys_fork:
+	subq $30,64,$30
+	stq  $9,0($30)
+	stq $10,8($30)
+	stq $11,16($30)
+	stq $12,24($30)
+	stq $13,32($30)
+	stq $14,40($30)
+	stq $15,48($30)
+	stq $26,56($30)
+
+	bis $30,$30,$16
+	lda $27,alpha_fork
+	jsr $26,($27),alpha_fork
+	
+	ldq  $9,0($30)
+	ldq $10,8($30)
+	ldq $11,16($30)
+	ldq $12,24($30)
+	ldq $13,32($30)
+	ldq $14,40($30)
+	ldq $15,48($30)
+	ldq $26,56($30)
+	ldq $0,64($30)
+	addq $30,64,$30
+	ret $31,($26),1
+.end	sys_fork
+
+.align 3
 .globl	entSys
+.globl	ret_from_sys_call
 .ent	entSys
 entSys:
 	SAVE_ALL
-	bis	$30,$30,$19
 	lda	$27,do_entSys
 	jsr	$26,($27),do_entSys
+	stq	$0,0($30)
+ret_from_sys_call:
 	RESTORE_ALL
 	rti
 .end entSys
 
-	.align 5
+	.align 3
 	.globl sys_call_table
 sys_call_table:
 	.quad 0
diff -u --recursive --new-file v1.1.94/linux/arch/alpha/kernel/head.S linux/arch/alpha/kernel/head.S
--- v1.1.94/linux/arch/alpha/kernel/head.S	Sun Feb  5 19:31:50 1995
+++ linux/arch/alpha/kernel/head.S	Sun Feb 26 16:45:26 1995
@@ -59,7 +59,7 @@
 	ret ($26)
 	.end rdusp
 
-.align 5
+.align 9
 .globl floppy_track_buffer
 floppy_track_buffer:
 	.space 512*2*MAX_BUFFER_SECTORS,1
diff -u --recursive --new-file v1.1.94/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v1.1.94/linux/arch/alpha/kernel/irq.c	Sun Feb  5 19:31:50 1995
+++ linux/arch/alpha/kernel/irq.c	Sun Feb 26 20:27:20 1995
@@ -22,6 +22,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/bitops.h>
+#include <asm/dma.h>
 
 static unsigned char cache_21 = 0xff;
 static unsigned char cache_A1 = 0xff;
@@ -374,8 +375,9 @@
 	printk("Machine check\n");
 }
 
-asmlinkage void do_entInt(unsigned long type, unsigned long vector,
-	unsigned long la_ptr, struct pt_regs *regs)
+asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
+	unsigned long a3, unsigned long a4, unsigned long a5,
+	struct pt_regs regs)
 {
 	switch (type) {
 		case 0:
@@ -383,13 +385,13 @@
 			break;
 		case 1:
 			/* timer interrupt.. */
-			handle_irq(0, regs);
+			handle_irq(0, &regs);
 			return;
 		case 2:
-			machine_check(vector, la_ptr, regs);
+			machine_check(vector, la_ptr, &regs);
 			break;
 		case 3:
-			device_interrupt(vector, regs);
+			device_interrupt(vector, &regs);
 			return;
 		case 4:
 			printk("Performance counter interrupt\n");
@@ -397,7 +399,7 @@
 		default:
 			printk("Hardware intr %ld %lx? Huh?\n", type, vector);
 	}
-	printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
+	printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
 }
 
 extern asmlinkage void entInt(void);
@@ -405,4 +407,8 @@
 void init_IRQ(void)
 {
 	wrent(entInt, 0);
+	dma_outb(0, DMA1_RESET_REG);
+	dma_outb(0, DMA2_RESET_REG);
+	dma_outb(0, DMA1_CLR_MASK_REG);
+	dma_outb(0, DMA2_CLR_MASK_REG);
 }
diff -u --recursive --new-file v1.1.94/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v1.1.94/linux/arch/alpha/kernel/process.c	Wed Feb 22 16:53:03 1995
+++ linux/arch/alpha/kernel/process.c	Fri Feb 24 16:41:00 1995
@@ -43,7 +43,8 @@
 
 void show_regs(struct pt_regs * regs)
 {
-	printk("\nPS: %04lx PC: %016lx\n", regs->ps, regs->pc);
+	printk("\nps: %04lx pc: %016lx\n", regs->ps, regs->pc);
+	printk("rp: %04lx sp: %p\n", regs->r26, regs+1);
 }
 
 /*
@@ -51,28 +52,88 @@
  */
 void exit_thread(void)
 {
-	halt();
 }
 
 void flush_thread(void)
 {
-	halt();
 }
 
+struct alpha_switch_stack {
+	unsigned long r9;
+	unsigned long r10;
+	unsigned long r11;
+	unsigned long r12;
+	unsigned long r13;
+	unsigned long r14;
+	unsigned long r15;
+	unsigned long r26;
+};
+
+/*
+ * "alpha_switch_to()".. Done completely in assembly, due to the
+ * fact that we obviously don't returns to the caller directly.
+ * Also, we have to save the regs that the C compiler expects to be
+ * saved across a function call.. (9-15)
+ *
+ * NOTE! The stack switches from under us when we do the swpctx call:
+ * this *looks* like it restores the same registers that it just saved,
+ * but it actually restores the new context regs and return address.
+ */
+__asm__(".align 3\n\t"
+	".globl alpha_switch_to\n\t"
+	".ent alpha_switch_to\n"
+	"alpha_switch_to:\n\t"
+	"subq $30,64,$30\n\t"
+	"stq  $9,0($30)\n\t"
+	"stq $10,8($30)\n\t"
+	"stq $11,16($30)\n\t"
+	"stq $12,24($30)\n\t"
+	"stq $13,32($30)\n\t"
+	"stq $14,40($30)\n\t"
+	"stq $15,48($30)\n\t"
+	"stq $26,56($30)\n\t"
+	"call_pal 48\n\t"
+	"ldq  $9,0($30)\n\t"
+	"ldq $10,8($30)\n\t"
+	"ldq $11,16($30)\n\t"
+	"ldq $12,24($30)\n\t"
+	"ldq $13,32($30)\n\t"
+	"ldq $14,40($30)\n\t"
+	"ldq $15,48($30)\n\t"
+	"ldq $26,56($30)\n\t"
+	"addq $30,64,$30\n\t"
+	"ret $31,($26),1\n\t"
+	".end alpha_switch_to");
+
 /*
- * This needs some work still..
+ * "alpha_fork()".. By the time we get here, the
+ * non-volatile registers have also been saved on the
+ * stack. We do some ugly pointer stuff here.. (see
+ * also copy_thread)
+ */
+int alpha_fork(struct alpha_switch_stack * swstack)
+{
+	return do_fork(COPYVM | SIGCHLD, 0, (struct pt_regs *) (swstack+1));
+}
+
+/*
+ * Copy an alpha thread..
  */
 void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 	struct task_struct * p, struct pt_regs * regs)
 {
 	struct pt_regs * childregs;
+	struct alpha_switch_stack * childstack, *stack;
 
-	p->tss.usp = usp;
 	childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
 	*childregs = *regs;
-	p->tss.ksp = (unsigned long) childregs;
-/*	p->tss.pc = XXXX; */
-	panic("copy_thread not implemented");
+	childregs->r0 = 0;
+	regs->r0 = p->pid;
+	stack = ((struct alpha_switch_stack *) regs) - 1;
+	childstack = ((struct alpha_switch_stack *) childregs) - 1;
+	*childstack = *stack;
+	p->tss.usp = usp;
+	p->tss.ksp = (unsigned long) childstack;
 }
 
 /*
@@ -108,16 +169,9 @@
 }
 
 /*
- * sys_fork() does the obvious thing, but not the obvious way.
- * See sys_execve() above.
+ * This doesn't actually work correctly like this: we need to do the
+ * same stack setups that fork() does first.
  */
-asmlinkage int sys_fork(unsigned long a0, unsigned long a1, unsigned long a2,
-	unsigned long a3, unsigned long a4, unsigned long a5,
-	struct pt_regs regs)
-{
-	return do_fork(COPYVM | SIGCHLD, rdusp(), &regs);
-}
-
 asmlinkage int sys_clone(unsigned long a0, unsigned long a1, unsigned long a2,
 	unsigned long a3, unsigned long a4, unsigned long a5,
 	struct pt_regs regs)
diff -u --recursive --new-file v1.1.94/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v1.1.94/linux/arch/alpha/kernel/setup.c	Sun Feb  5 19:31:50 1995
+++ linux/arch/alpha/kernel/setup.c	Fri Feb 24 16:41:00 1995
@@ -74,6 +74,7 @@
 	static char cmdline[] = "";
 	extern int _end;
 
+	ROOT_DEV = 0x0200;	/* fd0 */
 	aux_device_present = 0xaa;
 	*cmdline_p = cmdline;
 	*memory_start_p = (unsigned long) &_end;
diff -u --recursive --new-file v1.1.94/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v1.1.94/linux/arch/alpha/kernel/traps.c	Wed Feb 22 16:53:03 1995
+++ linux/arch/alpha/kernel/traps.c	Sun Feb 26 20:27:20 1995
@@ -15,27 +15,34 @@
 	unsigned long i;
 
 	printk("%s %ld\n", str, err);
-	printk("PC = %016lx PS = %04lx\n", regs->pc, regs->ps);
+	printk("pc = %016lx ps = %04lx\n", regs->pc, regs->ps);
+	printk("rp = %016lx sp = %p\n", regs->r26, regs+1);
 	for (i = 0 ; i < 5000000000 ; i++)
 		/* pause */;
 	halt();
 }
 
-asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask, unsigned long a2, struct pt_regs * regs)
+asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask,
+	unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5,
+	struct pt_regs regs)
 {
 	printk("Arithmetic trap: %02lx %016lx\n", summary, write_mask);
-	die_if_kernel("Arithmetic fault", regs, 0);
+	die_if_kernel("Arithmetic fault", &regs, 0);
 }
 
-asmlinkage void do_entIF(unsigned long type, unsigned long a1, unsigned long a2, struct pt_regs * regs)
+asmlinkage void do_entIF(unsigned long type, unsigned long a1, unsigned long a2,
+	unsigned long a3, unsigned long a4, unsigned long a5,
+	struct pt_regs regs)
 {
-	die_if_kernel("Instruction fault", regs, type);
+	die_if_kernel("Instruction fault", &regs, type);
 }
 
-asmlinkage void do_entUna(unsigned long va, unsigned long opcode, unsigned long reg, struct pt_regs * regs)
+asmlinkage void do_entUna(unsigned long va, unsigned long opcode, unsigned long reg,
+	unsigned long a3, unsigned long a4, unsigned long a5,
+	struct pt_regs regs)
 {
 	printk("Unaligned trap: %016lx %ld %ld\n", va, opcode, reg);
-	die_if_kernel("Unaligned", regs, 0);
+	die_if_kernel("Unaligned", &regs, 0);
 }
 
 /*
@@ -49,10 +56,11 @@
  * are a thinko. DEC palcode is strange. The PAL-code designers probably
  * got terminally tainted by VMS at some point.
  */
-asmlinkage void do_entSys(unsigned long sysnr, unsigned long arg1, unsigned long arg2, struct pt_regs *regs)
+asmlinkage void do_entSys(unsigned long a0, unsigned long a1, unsigned long a2,
+	unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs regs)
 {
-	printk("System call %ld(%ld,%ld)\n", sysnr, arg1, arg2);
-	die_if_kernel("Syscall", regs, 0);
+	printk("System call %ld(%ld,%ld)\n", regs.r0, a0, a1);
+	die_if_kernel("Syscall", &regs, 0);
 }
 
 extern asmlinkage void entMM(void);
diff -u --recursive --new-file v1.1.94/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c
--- v1.1.94/linux/arch/alpha/mm/fault.c	Wed Feb  1 09:23:04 1995
+++ linux/arch/alpha/mm/fault.c	Thu Mar  2 09:04:40 1995
@@ -24,12 +24,11 @@
 
 /*
  * This routine handles page faults.  It determines the address,
- * and the problem, and then passes it off to one of the appropriate
- * routines.
+ * and the problem, and then passes it off to handle_mm_fault().
  *
  * mmcsr:
- *	0 = translation not valid (= do_no_page())
- *	1 = access violation (= user tries to access kernel pages)
+ *	0 = translation not valid
+ *	1 = access violation
  *	2 = fault-on-read
  *	3 = fault-on-execute
  *	4 = fault-on-write
@@ -39,13 +38,12 @@
  *	0 = load
  *	1 = store
  */
-asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
-	long cause, struct pt_regs * regs)
+asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr, long cause,
+	unsigned long a3, unsigned long a4, unsigned long a5,
+	struct pt_regs regs)
 {
 	struct vm_area_struct * vma;
 
-	if (mmcsr == 1)
-		goto bad_area;
 	vma = find_vma(current, address);
 	if (!vma)
 		goto bad_area;
@@ -73,11 +71,7 @@
 			goto bad_area;
 	}
 
-	if (mmcsr) {
-		do_wp_page(vma, address, cause > 0);
-		return;
-	}
-	do_no_page(vma, address, cause > 0);
+	handle_mm_fault(vma, address, cause > 0);
 	return;
 
 /*
@@ -85,7 +79,7 @@
  * Fix it, but check if it's kernel or user first..
  */
 bad_area:
-	if (user_mode(regs)) {
+	if (user_mode(&regs)) {
 		send_sig(SIGSEGV, current, 1);
 		return;
 	}
@@ -94,6 +88,6 @@
  * terminate things with extreme prejudice.
  */
 	printk(KERN_ALERT "Unable to handle kernel paging request at virtual address %08lx\n",address);
-	die_if_kernel("Oops", regs, cause);
+	die_if_kernel("Oops", &regs, cause);
 	do_exit(SIGKILL);
 }
diff -u --recursive --new-file v1.1.94/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v1.1.94/linux/arch/i386/Makefile	Fri Jan 13 10:12:22 1995
+++ linux/arch/i386/Makefile	Sat Feb 25 15:55:27 1995
@@ -52,6 +52,12 @@
 DRIVERS := $(DRIVERS) arch/i386/math-emu/math.a
 endif
 
+arch/i386/kernel: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=arch/i386/kernel
+
+arch/i386/mm: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=arch/i386/mm
+
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
 zImage: vmlinux
diff -u --recursive --new-file v1.1.94/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v1.1.94/linux/arch/i386/kernel/irq.c	Mon Jan 16 14:18:13 1995
+++ linux/arch/i386/kernel/irq.c	Thu Mar  2 08:39:22 1995
@@ -20,6 +20,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
 
@@ -360,4 +361,6 @@
 		printk("Unable to get IRQ2 for cascade\n");
 	if (request_irq(13,math_error_irq, 0, "math error"))
 		printk("Unable to get IRQ13 for math-error handler\n");
-}
+	request_region(0x20,0x20,"pic1");
+	request_region(0xa0,0x20,"pic2");
+} 
diff -u --recursive --new-file v1.1.94/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v1.1.94/linux/arch/i386/kernel/process.c	Wed Feb 22 16:53:03 1995
+++ linux/arch/i386/kernel/process.c	Wed Mar  1 08:43:07 1995
@@ -105,7 +105,7 @@
 		printk(" ESP: %04x:%08lx",0xffff & regs->ss,regs->esp);
 	printk(" EFLAGS: %08lx\n",regs->eflags);
 	printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
-		regs->orig_eax,regs->ebx,regs->ecx,regs->edx);
+		regs->eax,regs->ebx,regs->ecx,regs->edx);
 	printk("ESI: %08lx EDI: %08lx EBP: %08lx",
 		regs->esi, regs->edi, regs->ebp);
 	printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
@@ -237,6 +237,7 @@
 
 asmlinkage int sys_clone(struct pt_regs regs)
 {
+#ifdef CLONE_ACTUALLY_WORKS_OK
 	unsigned long clone_flags;
 	unsigned long newsp;
 
@@ -247,6 +248,9 @@
 	if (newsp == regs.esp)
 		clone_flags |= COPYVM;
 	return do_fork(clone_flags, newsp, &regs);
+#else
+	return -ENOSYS;
+#endif
 }
 
 /*
diff -u --recursive --new-file v1.1.94/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v1.1.94/linux/arch/i386/kernel/ptrace.c	Wed Feb 22 16:53:03 1995
+++ linux/arch/i386/kernel/ptrace.c	Sat Feb 25 15:36:18 1995
@@ -155,7 +155,7 @@
 	}
 	pgmiddle = pmd_offset(pgdir, addr);
 	if (pmd_none(*pgmiddle)) {
-		do_no_page(vma, addr, 0);
+		do_no_page(vma, addr, 1);
 		goto repeat;
 	}
 	if (pmd_bad(*pgmiddle)) {
diff -u --recursive --new-file v1.1.94/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v1.1.94/linux/arch/i386/kernel/setup.c	Mon Jan 30 06:41:55 1995
+++ linux/arch/i386/kernel/setup.c	Thu Feb 23 13:31:58 1995
@@ -20,6 +20,7 @@
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
+#include <linux/ioport.h>
 
 #include <asm/segment.h>
 #include <asm/system.h>
@@ -122,4 +123,12 @@
 	*cmdline_p = command_line;
 	*memory_start_p = memory_start;
 	*memory_end_p = memory_end;
+	/* request io space for devices used on all i[345]86 PC'S */
+	request_region(0x00,0x20,"dma1");
+	request_region(0x40,0x20,"timer");
+	request_region(0x70,0x10,"rtc");
+	request_region(0x80,0x20,"dma page reg");
+	request_region(0xc0,0x20,"dma2");
+	request_region(0xf0,0x2,"npu");
+	request_region(0xf8,0x8,"npu");
 }
diff -u --recursive --new-file v1.1.94/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v1.1.94/linux/arch/sparc/config.in	Fri Feb 17 11:20:11 1995
+++ linux/arch/sparc/config.in	Sun Feb 26 20:46:20 1995
@@ -13,6 +13,8 @@
 
 bool 'Sparc V8 kernel' CONFIG_SPARC_V8 y
 bool 'Sparc SMP support' CONFIG_LINUX_SMP n
+bool 'Sparc SUN4M support' CONFIG_SUN4M n
+bool 'Sparc Reference MMU' CONFIG_SRMMU n
 bool 'Networking support' CONFIG_NET n
 bool 'Limit memory to low 16MB' CONFIG_MAX_16M n
 bool 'System V IPC' CONFIG_SYSVIPC y
diff -u --recursive --new-file v1.1.94/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S
--- v1.1.94/linux/arch/sparc/kernel/head.S	Mon Feb 20 21:34:54 1995
+++ linux/arch/sparc/kernel/head.S	Sun Feb 26 20:46:20 1995
@@ -155,13 +155,13 @@
 boot_msg:	
 	.ascii "Booting Sparc-Linux V0.00PRE-ALPHA "
 	.ascii WHO_COMPILED_ME 
-	.asciz " \n"
+	.ascii "\r\n"
 	.align 4
 
 	.globl boot_msg2
 
 boot_msg2:
-	.asciz "Booting Sparclinux V0.00 PRE-ALPHA on a (SUN4C)\n\n"
+	.asciz "Booting Sparclinux V0.00 PRE-ALPHA on a (SUN4C)\r\n\n"
 
 	.align 4
 
@@ -250,20 +250,20 @@
 
 /* Level'd interrupt entry points, see macro defs above */
 
-        TRAP_ENTRY_INTERRUPT_SOFT(1, 0x101) /* Interrupt Level 1  */
-        TRAP_ENTRY_INTERRUPT(2)             /* Interrupt Level 2  */
-        TRAP_ENTRY_INTERRUPT(3)             /* Interrupt Level 3  */
-        TRAP_ENTRY_INTERRUPT_SOFT(4, 0x104) /* Interrupt Level 4  */
-        TRAP_ENTRY_INTERRUPT(5)             /* Interrupt Level 5  */
-        TRAP_ENTRY_INTERRUPT_SOFT(6, 0x106) /* Interrupt Level 6  */
-        TRAP_ENTRY_INTERRUPT(7)             /* Interrupt Level 7  */
-        TRAP_ENTRY_INTERRUPT(8)             /* Interrupt Level 8  */
-        TRAP_ENTRY_INTERRUPT(9)             /* Interrupt Level 9  */
-        TRAP_ENTRY_INTERRUPT(10)            /* Interrupt Level 10 */
-        TRAP_ENTRY_INTERRUPT(11)            /* Interrupt Level 11 */
-        TRAP_ENTRY_INTERRUPT(12)            /* Interrupt Level 12 */
-        TRAP_ENTRY_INTERRUPT(13)            /* Interrupt Level 13 */
-        TRAP_ENTRY_TIMER                    /* Interrupt Level 14 */
+        TRAP_ENTRY_INTERRUPT_SOFT(1, 0x101) /* IRQ Software/SBUS Level 1  */
+        TRAP_ENTRY_INTERRUPT(2)             /* IRQ SBUS Level 2           */
+        TRAP_ENTRY_INTERRUPT(3)             /* IRQ SCSI/DMA/SBUS Level 3  */
+        TRAP_ENTRY_INTERRUPT_SOFT(4, 0x104) /* IRQ Software Level 4       */
+        TRAP_ENTRY_INTERRUPT(5)             /* IRQ SBUS/Ethernet Level 5  */
+        TRAP_ENTRY_INTERRUPT_SOFT(6, 0x106) /* IRQ Software Level 6       */
+        TRAP_ENTRY_INTERRUPT(7)             /* IRQ Video/SBUS Level 5     */
+        TRAP_ENTRY_INTERRUPT(8)             /* IRQ SBUS Level 6           */
+        TRAP_ENTRY_INTERRUPT(9)             /* IRQ SBUS Level 7           */
+        TRAP_ENTRY_INTERRUPT(10)            /* IRQ Timer #1               */
+        TRAP_ENTRY_INTERRUPT(11)            /* IRQ Floppy Intr.           */
+        TRAP_ENTRY_INTERRUPT(12)            /* IRQ Zilog serial chip      */
+        TRAP_ENTRY_INTERRUPT(13)            /* IRQ Audio Intr.            */
+        TRAP_ENTRY_TIMER                    /* IRQ Timer #2 (one we use)  */
         TRAP_ENTRY_INTERRUPT_NMI(15, linux_trap_nmi) /* Level 15 (nmi) */
 
 	TRAP_ENTRY(0x20, my_trap_handler)   /* General Register Access Error */
@@ -541,6 +541,15 @@
 		be	found_v2
 		nop
 
+		/* paul@sfe.com.au */
+		subcc	%o3, 0x3, %g0			! a v3 prom?
+		or	%g0, 0x3, %o5
+		sethi	%hi(C_LABEL(prom_iface_vers) ), %g1
+		st	%o5, [%g1 + %lo( C_LABEL(prom_iface_vers) )]
+		be	not_v2
+		nop
+
+
 /* Old sun4's pass our load address into %o0 instead of the prom
    pointer. On sun4's you have to hard code the romvec pointer into
    your code. Sun probably still does that because they don't even
@@ -654,6 +663,15 @@
  * as the prom expects.
  */
 
+/* paul@sfe.com.au */
+/* V3 doesnt have printf.. And I dont really feel like doing the formatting
+ * myself.. So we miss out on some messages (for now).
+ */
+		ld	[%g7 + 0x4], %o0
+		subcc	%o3, 0x3, %g0
+		be	v3_bootmsg
+		nop
+
 		sethi	%hi(boot_msg), %o0	
 		or	%o0, %lo(boot_msg), %o0
 		sethi	%hi(prom_printf), %o1
@@ -687,6 +705,28 @@
 		b	rest_of_boot
 		nop
 
+v3_bootmsg:
+		ld	[%g7 + 0x94], %o0
+		ld	[%o0], %o0
+		sethi	%hi(boot_msg), %o1
+		or	%o1, %lo(boot_msg), %o1
+		mov	BOOT_MSG_LEN, %o2
+		ld	[%g7 + 0xb8], %o4
+		call	%o4
+		nop
+ 
+		ld	[%g7 + 0x94], %o0
+		ld	[%o0], %o0
+		sethi	%hi(boot_msg2), %o1
+		or	%o1, %lo(boot_msg2), %o1
+		mov	BOOT_MSG2_LEN, %o2
+		ld	[%g7 + 0xb8], %o4
+		call	%o4
+		nop
+		b	rest_of_boot
+		nop
+
+
 no_sun4_here:
 		ld	[%g7 + 0x68], %o1
 		set	sun4_notsup, %o0
@@ -723,7 +763,9 @@
 		srl	%l2, %g5, %l2
 		or	%l2, %l3, %l1		
 
+#ifndef CONFIG_SRMMU
 		sta	%l1, [%l0] ASI_PTE
+#endif
 	
 		or	%g0, 0x1, %l1
 		stb	%l1, [%l0]
@@ -856,9 +898,13 @@
 
 /* Here we go */
 
+#ifndef CONFIG_SUN4M
+		/* paul@sfe.com.au */
+		/* Look into traps later :( */
 		set	C_LABEL(trapbase), %g3
 		wr	%g3, 0x0, %tbr
 		WRITE_PAUSE
+#endif
 
 
 /* First we call init_prom() to set up romvec, then off to start_kernel() */
diff -u --recursive --new-file v1.1.94/linux/arch/sparc/kernel/probe.c linux/arch/sparc/kernel/probe.c
--- v1.1.94/linux/arch/sparc/kernel/probe.c	Mon Feb 20 21:34:54 1995
+++ linux/arch/sparc/kernel/probe.c	Wed Mar  1 09:12:33 1995
@@ -4,11 +4,13 @@
 */
 
 #include <linux/kernel.h>
+#include <linux/string.h>
 #include <asm/vac-ops.h>
 #include <asm/io.h>
 #include <asm/vaddrs.h>
 #include <asm/param.h>
 #include <asm/clock.h>
+#include <asm/system.h>
 
 /* #define DEBUG_PROBING */
 
@@ -83,7 +85,7 @@
   { 2, 0, "Bipolar Integrated Technology - B5010"},
   { 3, 0, "LSI Logic Corporation - unknown-type"},
   { 4, 0, "Texas Instruments, Inc. - unknown"},
-  { 4, 1, "Texas Instruments, Inc. - unknown"},
+  { 4, 1, "Texas Instruments, Inc. - Sparc Classic"},
   { 4, 2, "Texas Instruments, Inc. - unknown"},
   { 4, 3, "Texas Instruments, Inc. - unknown"},
   { 4, 4, "Texas Instruments, Inc. - unknown"},
@@ -119,7 +121,10 @@
 void
 probe_cpu(void)
 {
-  register int psr_impl, psr_vers, fpu_vers, i;
+  register int psr_impl=0;
+  register int psr_vers = 0;
+  register int fpu_vers = 0;
+  register int i = 0;
   unsigned int tmp_fsr;
 
   &tmp_fsr;   /* GCC grrr... */
@@ -195,6 +200,7 @@
 {
   register unsigned int x,y;
 
+#ifndef CONFIG_SRMMU
   vac_size = find_vac_size();
   vac_linesize = find_vac_linesize();
   vac_do_hw_vac_flushes = find_vac_hwflushes();
@@ -223,6 +229,7 @@
 
   x=enable_vac();
   printk("ENABLED\n");
+#endif
 
   return;
 }
@@ -233,7 +240,7 @@
   find_mmu_num_segmaps();
   find_mmu_num_contexts();
 
-  printk("\nMMU segmaps: %d     MMU contexts: %d\n", num_segmaps, 
+  printk("MMU segmaps: %d     MMU contexts: %d\n", num_segmaps, 
 	 num_contexts);
 
   return;
@@ -275,7 +282,7 @@
 	}
     }
 
-  printk("%s\n", node_str);
+  printk("Mostek %s\n", node_str);
   printk("At OBIO address: 0x%x Virtual address: 0x%x\n",
 	 (unsigned int) TIMER_PHYSADDR, (unsigned int) TIMER_STRUCT);
 
@@ -299,49 +306,13 @@
   printk("\nProbing ESP:\n");
   lbuf = get_str_from_prom(nd, "name", promstr_buf);
 
-  printk("\nProperty length for %s: 0x%x\n", "name", 
-	 *get_int_from_prom(nd, "name", promint_buf));
-
   if(*get_int_from_prom(nd, "name", promint_buf) != 0)
-  printk("Node: 0x%x Name: %s", nd, lbuf);
-
-  lbuf = get_str_from_prom(nd, "device-type", promstr_buf);
-
-  printk("\nProperty length for %s: 0x%x\n", "device_type", 
-	 *get_int_from_prom(nd, "device_type", promint_buf));
-
-  if(*get_int_from_prom(nd, "device-type", promint_buf) != 0)
-    printk("Device-Type: %s ", lbuf);
-  
-  lbuf = get_str_from_prom(nd, "model", promstr_buf);
-
-  printk("\nProperty length for %s: 0x%x\n", "model", 
-	 *get_int_from_prom(nd, "model", promint_buf));
-
-  if(*get_int_from_prom(nd, "model", promint_buf) != 0)
-    printk("Model: %s", lbuf);
-
-  printk("\n");
-
-  while((nd = node_get_sibling(nd)) != 0)
-    {
-      lbuf = get_str_from_prom(nd, "name", promstr_buf);
-
-      if(*get_int_from_prom(nd, "name", promint_buf) != 0)
-      printk("Node: 0x%x Name: %s ", nd, lbuf);
-
-      lbuf = get_str_from_prom(nd, "device-type", promstr_buf);
-
-      if(*get_int_from_prom(nd, "device-type", promint_buf) != 0)
-      printk("Device-Type: %s ", lbuf);
-
-      lbuf = get_str_from_prom(nd, "model", promstr_buf);
-
-      if(*get_int_from_prom(nd, "model", promint_buf) != 0)
-      printk("Model: %s", lbuf);
+  printk("Node: 0x%x Name: %s\n", nd, lbuf);
 
-      printk("\n");
-    }
+  while((nd = node_get_sibling(nd)) != 0) {
+    lbuf = get_str_from_prom(nd, "name", promstr_buf);
+    printk("Node: 0x%x Name: %s\n", nd, lbuf);
+  }
 
   printk("\n");
 
@@ -358,40 +329,44 @@
 
   lbuf = (char *) 0;
 
-  while((nd = node_get_sibling(nd)) != 0)
-    {
-      lbuf = get_str_from_prom(nd, "name", promstr_buf);
-      if(lbuf[0]=='s' && lbuf[1]=='b' && lbuf[2]=='u' && lbuf[3]=='s')
-	break;
-    }
+  while((nd = node_get_sibling(nd)) != 0) {
+    lbuf = get_str_from_prom(nd, "name", promstr_buf);
+    if(strcmp(lbuf, "sbus") == 0)
+      break;
+  };
+
   nd = node_get_child(nd);
 
   printk("Node: 0x%x Name: %s\n", nd,
 	 get_str_from_prom(nd, "name", promstr_buf));
 
-  if(lbuf[0]=='e' && lbuf[1]=='s' && lbuf[2]=='p')
+  if(strcmp(lbuf, "esp") == 0) {
     probe_esp(nd);
+  };
 
-  while((nd = node_get_sibling(nd)) != 0)
-    {
-      printk("Node: 0x%x Name: %s\n", nd,
-	     get_str_from_prom(nd, "name", promstr_buf));
-
-	  if(lbuf[0]=='e' && lbuf[1]=='s' && lbuf[2]=='p')
-	    {
-	      savend = nd;
-	      probe_esp(nd);
-	      nd = savend;
-	    }
-    }
+  while((nd = node_get_sibling(nd)) != 0) {
+    printk("Node: 0x%x Name: %s\n", nd,
+	   lbuf = get_str_from_prom(nd, "name", promstr_buf));
+    
+    if(strcmp(lbuf, "esp") == 0) {
+      savend = nd;
+      probe_esp(nd);
+      nd = savend;
+    };
+  };
 
+  printk("\n");
   return;
 }
 
+extern unsigned long probe_memory(void);
+extern struct sparc_phys_banks sp_banks[14];
+unsigned int phys_bytes_of_ram, end_of_phys_memory;
+
 void
 probe_devices(void)
 {
-  register int nd;
+  register int nd, i;
   register char* str;
 
   nd = prom_node_root;
@@ -399,15 +374,18 @@
   printk("PROBING DEVICES:\n");
 
   str = get_str_from_prom(nd, "device_type", promstr_buf);
-  printk("Root Node: 0x%x ", nd);
+  if(strcmp(str, "cpu") == 0) {
+    printk("Found CPU root prom device tree node.\n");
+  } else {
+    printk("Root node in device tree was not 'cpu' cannot continue.\n");
+    halt();
+  };
 
 #ifdef DEBUG_PROBING
   printk("String address for d_type: 0x%x\n", (unsigned int) str);
   printk("str[0] = %c  str[1] = %c  str[2] = %c \n", str[0], str[1], str[2]);
 #endif
 
-  printk("Device Type: %s ", str);
-
   str = get_str_from_prom(nd, "name", promstr_buf);
 
 #ifdef DEBUG_PROBING
@@ -421,29 +399,34 @@
 
 
 /* Ok, here will go a call to each specific device probe. We can
-   call these now that we have the 'root' node and the child of
-   this node to send to the routines. ORDER IS IMPORTANT!
-*/
+ * call these now that we have the 'root' node and the child of
+ * this node to send to the routines. ORDER IS IMPORTANT!
+ */
 
   probe_cpu();
   probe_vac();
   probe_mmu();
+  phys_bytes_of_ram = probe_memory();
+
+  printk("Physical Memory: %d bytes\n", (int) phys_bytes_of_ram);
+  for(i=0; sp_banks[i].num_bytes != 0; i++) {
+    printk("Bank %d:  base 0x%x  bytes %d\n", i,
+	   (unsigned int) sp_banks[i].base_addr, 
+	   (int) sp_banks[i].num_bytes);
+    end_of_phys_memory = sp_banks[i].base_addr + sp_banks[i].num_bytes;
+  }
 
-/*
   printk("PROM Root Child Node: 0x%x Name: %s \n", nd,
 	 get_str_from_prom(nd, "name", promstr_buf));
 
-  while((nd = node_get_sibling(nd)) != 0)
-    {
-
-      printk("Node: 0x%x Name: %s\n", nd,
-	     get_str_from_prom(nd, "name", promstr_buf));
-
-    }
+  while((nd = node_get_sibling(nd)) != 0) {
+    printk("Node: 0x%x Name: %s", nd,
+	   get_str_from_prom(nd, "name", promstr_buf));
+    printk("\n");
+  };
 
   printk("\nProbing SBUS:\n");
   probe_sbus(first_descent);
-*/
 
   return;
 }
diff -u --recursive --new-file v1.1.94/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v1.1.94/linux/arch/sparc/kernel/process.c	Sun Feb  5 19:31:51 1995
+++ linux/arch/sparc/kernel/process.c	Sun Feb 26 20:46:20 1995
@@ -76,15 +76,16 @@
   halt();
 }
 
-unsigned long copy_thread(int nr, unsigned long clone_flags, struct task_struct * p, struct pt_regs * regs)
+void copy_thread(int nr, unsigned long clone_flags, unsigned long sp, struct task_struct * p, struct pt_regs * regs)
 {
 	struct pt_regs * childregs;
 
 	childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
 	p->tss.usp = (unsigned long) childregs;
 	*childregs = *regs;
+	childregs->sp = sp;
 	p->tss.psr = regs->psr; /* for condition codes */
-	return clone_flags;
+	return;
 }
 
 /*
@@ -93,6 +94,11 @@
 void dump_thread(struct pt_regs * regs, struct user * dump)
 {
   return; /* solaris does this enough */
+}
+
+asmlinkage int sys_fork(struct pt_regs regs)
+{
+	return do_fork(COPYVM | SIGCHLD, regs.sp, &regs);
 }
 
 /*
diff -u --recursive --new-file v1.1.94/linux/arch/sparc/kernel/promops.c linux/arch/sparc/kernel/promops.c
--- v1.1.94/linux/arch/sparc/kernel/promops.c	Sun Feb  5 19:31:51 1995
+++ linux/arch/sparc/kernel/promops.c	Sun Feb 26 20:46:20 1995
@@ -9,7 +9,7 @@
 #include <asm/openprom.h>
 
 /* #define DEBUG_PROMOPS */
-#define MAX_PR_LEN   16           /* exotic hardware probably overshoots this */
+#define MAX_PR_LEN   64           /* exotic hardware probably overshoots this */
 
 int prom_node_root;               /* initialized in init_prom */
 
@@ -37,12 +37,14 @@
  * the default return value is -1 is the prom has nothing interesting.
  */
 
+unsigned int prom_int_null;
+
 unsigned int *
 get_int_from_prom(int node, char *nd_prop, unsigned int *value)
 {
   unsigned int pr_len;
 
-  *value = 0;    /* duh, I was returning -1 as an unsigned int, prom_panic() */
+  *value = &prom_int_null;    /* duh, I was returning -1 as an unsigned int, prom_panic() */
 
   pr_len = romvec->pv_nodeops->no_proplen(node, nd_prop);
   if(pr_len > MAX_PR_LEN)
@@ -99,6 +101,7 @@
 {
   romvec = r_ptr;
   prom_node_root = romvec->pv_nodeops->no_nextnode(0);
+  prom_int_null = 0;
   
   return;
 }
diff -u --recursive --new-file v1.1.94/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c
--- v1.1.94/linux/arch/sparc/kernel/setup.c	Mon Feb 20 21:34:54 1995
+++ linux/arch/sparc/kernel/setup.c	Sun Feb 26 20:46:20 1995
@@ -52,7 +52,8 @@
 }
 
 /* Lame prom console routines, gets registered below. Thanks for the
- * tip Linus.
+ * tip Linus.  First comes the V0 prom routine, then the V3 version
+ * writen by Paul Hatchman (paul@sfe.com.au).
  */
 
 void sparc_console_print(const char * p)
@@ -69,6 +70,24 @@
 
 }
 
+/* paul@sfe.com.au */
+/* V3 prom console printing routines */
+void sparc_console_print_v3 (const char *p)
+{
+       unsigned char c;
+
+       while ((c = *(p++)) != 0)
+       {
+               if (c == '\n') romvec->pv_v2devops.v2_dev_write 
+                       ((*romvec->pv_v2bootargs.fd_stdout), "\r", 1);
+               romvec->pv_v2devops.v2_dev_write 
+                       ((*romvec->pv_v2bootargs.fd_stdout), &c, 1);
+       }
+
+       return;
+}
+
+
 /* This routine will in the future do all the nasty prom stuff
  * to probe for the mmu type and it's parameters, etc. This will
  * also be where SMP things happen plus the Sparc specific memory
@@ -76,23 +95,23 @@
  */
 
 extern void register_console(void (*proc)(const char *));
+extern unsigned int prom_iface_vers, end_of_phys_memory;
 
 void setup_arch(char **cmdline_p,
 	unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
-	extern int _end;
-
-	register_console(sparc_console_print);
+	if(romvec->pv_romvers == 0) {
+	  register_console(sparc_console_print);
+	} else {
+	  register_console(sparc_console_print_v3);
+	};
 
 	printk("Sparc PROM-Console registered...\n");
-
-	printk("calling get_idprom...\n");
 	get_idprom();     /* probe_devices expects this to be done */
-
-	printk("calling probe_devices...\n");
 	probe_devices();  /* cpu/fpu, mmu probes */
 
 	*memory_start_p = (((unsigned long) &end));
+	*memory_end_p = (((unsigned long) end_of_phys_memory));
 }
 
 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
diff -u --recursive --new-file v1.1.94/linux/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c
--- v1.1.94/linux/arch/sparc/mm/fault.c	Wed Feb 22 16:53:03 1995
+++ linux/arch/sparc/mm/fault.c	Sun Feb 26 20:46:20 1995
@@ -12,6 +12,8 @@
 #include <asm/pgtable.h>
 
 extern unsigned long pg0[1024];		/* page table for 0-4MB for everybody */
+extern struct sparc_phys_banks sp_banks[14];
+
 extern void die_if_kernel(char *,struct pt_regs *,long);
 
 struct linux_romvec *romvec;
@@ -49,28 +51,30 @@
 {
   register struct linux_romvec *lprom;
   register struct linux_mlist_v0 *mlist;
-  register unsigned long bytes, base_paddr;
+  register unsigned long bytes, base_paddr, tally;
   register int i;
 
-  bytes = 0;
+  bytes = tally = 0;
   base_paddr = 0;
+  i=0;
   lprom = romvec;
   switch(lprom->pv_romvers)
     {
     case 0:
       mlist=(*(lprom->pv_v0mem.v0_totphys));
-      bytes=mlist->num_bytes;
+      bytes = tally = mlist->num_bytes;
       base_paddr = (unsigned long) mlist->start_adr;
-      printk("Bank 1: starting at 0x%x holding %d bytes\n", 
-	     (unsigned int) base_paddr, (int) bytes);
-      i=1;
-      if(mlist->theres_more != (void *)0)
-	{
+
+      sp_banks[0].base_addr = base_paddr;
+      sp_banks[0].num_bytes = bytes;
+
+      if(mlist->theres_more != (void *)0) {
 	  i++;
 	  mlist=mlist->theres_more;
-	  bytes+=mlist->num_bytes;
-	  printk("Bank %d: starting at 0x%x holding %d bytes\n", i,
-		 (unsigned int) mlist->start_adr, (int) mlist->num_bytes);
+	  bytes=mlist->num_bytes;
+	  tally += bytes;
+	  sp_banks[i].base_addr = (unsigned long) mlist->start_adr;
+	  sp_banks[i].num_bytes = mlist->num_bytes;
 	}
       break;
     case 2:
@@ -78,10 +82,12 @@
       (*(lprom->pv_halt))();
       break;
     }
-  printk("Physical memory: %d bytes  starting at va 0x%x\n",
-	 (unsigned int) bytes, (int) base_paddr);
 
-  return bytes;
+  i++;
+  sp_banks[i].base_addr = 0xdeadbeef;
+  sp_banks[i].num_bytes = 0;
+
+  return tally;
 }
 
 /* Sparc routine to reserve the mapping of the open boot prom */
diff -u --recursive --new-file v1.1.94/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- v1.1.94/linux/arch/sparc/mm/init.c	Wed Feb 22 16:53:03 1995
+++ linux/arch/sparc/mm/init.c	Wed Mar  1 09:12:33 1995
@@ -29,6 +29,8 @@
 
 extern int map_the_prom(int);
 
+struct sparc_phys_banks sp_banks[14];
+unsigned long *sun4c_mmu_table;
 extern int invalid_segment, num_segmaps, num_contexts;
 
 /*
@@ -102,8 +104,11 @@
 
 unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
 {
-	int pg_segmap = 0;
 	unsigned long i, a, b, mask=0;
+	unsigned long curseg, curpte, num_inval;
+	unsigned long address;
+	pte_t *pg_table;
+
 	register int num_segs, num_ctx;
 	register char * c;
 
@@ -113,6 +118,8 @@
 	num_segs -= 1;
 	invalid_segment = num_segs;
 
+	start_mem = free_area_init(start_mem, end_mem);
+
 /* On the sparc we first need to allocate the segmaps for the
  * PROM's virtual space, and make those segmaps unusable. We
  * map the PROM in ALL contexts therefore the break key and the
@@ -125,11 +132,82 @@
 
 	start_mem = PAGE_ALIGN(start_mem);
 
+	/* Set up static page tables in kernel space, this will be used
+	 * so that the low-level page fault handler can fill in missing
+	 * TLB entries since all mmu entries cannot be loaded at once
+	 * on the sun4c.
+	 */
+
+#if 0
+	/* ugly debugging code */
+	for(i=0; i<40960; i+=PAGE_SIZE)
+	  printk("address=0x%x  vseg=%d  pte=0x%x\n", (unsigned int) i,
+		 (int) get_segmap(i), (unsigned int) get_pte(i));
+#endif
+
+	printk("Setting up kernel static mmu table... bounce bounce\n");
+
+	address = 0; /* ((unsigned long) &end) + 524288; */
+	sun4c_mmu_table = (unsigned long *) start_mem;
+	pg_table = (pte_t *) start_mem;
+	curseg = curpte = num_inval = 0;
+	while(address < end_mem) {
+	  if(curpte == 0)
+	    put_segmap((address&PGDIR_MASK), curseg);
+	  for(i=0; sp_banks[i].num_bytes != 0; i++)
+	    if((address >= sp_banks[i].base_addr) && 
+	       (address <= (sp_banks[i].base_addr + sp_banks[i].num_bytes)))
+	      goto good_address;
+	  /* No physical memory here, so set the virtual segment to
+	   * the invalid one, and put an invalid pte in the static
+	   * kernel table.
+	   */
+	  *pg_table = mk_pte((address >> PAGE_SHIFT), PAGE_INVALID);
+	  pg_table++; curpte++; num_inval++;
+	  if(curpte > 63) {
+	    if(curpte == num_inval) {
+	      put_segmap((address&PGDIR_MASK), invalid_segment);
+	    } else {
+	      put_segmap((address&PGDIR_MASK), curseg);
+	      curseg++;
+	    }
+	    curpte = num_inval = 0;
+	  }
+	  address += PAGE_SIZE;
+	  continue;
+
+	  good_address:
+	  /* create pte entry */
+	  if(address < (((unsigned long) &end) + 524288)) {
+	    pte_val(*pg_table) = get_pte(address);
+	  } else {
+	    *pg_table = mk_pte((address >> PAGE_SHIFT), PAGE_KERNEL);
+	    put_pte(address, pte_val(*pg_table));
+	  }
+
+	  pg_table++; curpte++;
+	  if(curpte > 63) {
+	    put_segmap((address&PGDIR_MASK), curseg);
+	    curpte = num_inval = 0;
+	    curseg++;
+	  }
+	  address += PAGE_SIZE;
+	}	  
+
+	start_mem = (unsigned long) pg_table;
 	/* ok, allocate the kernel pages, map them in all contexts
 	 * (with help from the prom), and lock them. Isn't the sparc
 	 * fun kiddies? TODO
 	 */
 
+#if 0
+	/* ugly debugging code */
+	for(i=0x1a3000; i<(0x1a3000+40960); i+=PAGE_SIZE)
+	  printk("address=0x%x  vseg=%d  pte=0x%x\n", (unsigned int) i,
+		 (int) get_segmap(i), (unsigned int) get_pte(i));
+	halt();
+#endif
+
 	b=PGDIR_ALIGN(start_mem)>>18;
 	c= (char *)0x0;
 
@@ -163,9 +241,6 @@
 	a= (unsigned long) &etext;
 	mask=~(PTE_NC|PTE_W);    /* make cacheable + not writable */
 
-	printk("changing kernel text perms...\n");
-
-
 	/* must do for every segment since kernel uses all contexts
 	 * and unlike some sun kernels I know of, we can't hard wire
 	 * context 0 just for the kernel, that is unnecessary.
@@ -191,34 +266,79 @@
 	    switch_to_context(i);
 	    printk("%d ", (int) i);
 	  }
+	printk("\n");
 
 	switch_to_context(0);
 
-	/* invalidate all user segmaps for virt addrs 0-KERNBASE */
-
-	/* WRONG, now I just let the kernel sit in low addresses only
-         * from 0 -- end_kernel just like i386-linux. This will make
-         * mem-code a bit easier to cope with.
-	 */
-
-	printk("\ninvalidating user segmaps\n");
-	for(i = 0; i<8; i++)
-	  {
-	    switch_to_context(i);
-	    a=((unsigned long) &end);
-	    for(a+=524288, pg_segmap=0; ++pg_segmap<=3584; a+=(1<<18))
-	      put_segmap((unsigned long *) a, (invalid_segment&0x7f));
-	  }
-
-	printk("wheee! have I sold out yet?\n");
-
 	invalidate();
-	return free_area_init(start_mem, end_mem);
+	return start_mem;
 }
 
 void mem_init(unsigned long start_mem, unsigned long end_mem)
 {
-	return;
+  unsigned long start_low_mem = PAGE_SIZE;
+  int codepages = 0;
+  int reservedpages = 0;
+  int datapages = 0;
+  int i = 0;
+  unsigned long tmp, limit, tmp2, addr;
+  extern char etext;
+
+  end_mem &= PAGE_MASK;
+  high_memory = end_mem;
+
+  start_low_mem = PAGE_ALIGN(start_low_mem);
+  start_mem = PAGE_ALIGN(start_mem);
+
+  for(i = 0; sp_banks[i].num_bytes != 0; i++) {
+    tmp = sp_banks[i].base_addr;
+    limit = (sp_banks[i].base_addr + sp_banks[i].num_bytes);
+    if(tmp<start_mem) {
+      if(limit>start_mem)
+	tmp = start_mem;
+      else continue;
+    }
+
+    while(tmp<limit) {
+      mem_map[MAP_NR(tmp)] = 0;
+      tmp += PAGE_SIZE;
+    }
+    if(sp_banks[i+1].num_bytes != 0)
+      while(tmp < sp_banks[i+1].base_addr) {
+	mem_map[MAP_NR(tmp)] = MAP_PAGE_RESERVED;
+	tmp += PAGE_SIZE;
+      }
+  }
+
+#ifdef CONFIG_SCSI
+  scsi_mem_init(high_memory);
+#endif
+
+  for (addr = 0; addr < high_memory; addr += PAGE_SIZE) {
+    if(mem_map[MAP_NR(addr)]) {
+      if (addr < (unsigned long) &etext)
+	codepages++;
+      else if(addr < start_mem)
+	datapages++;
+      else
+	reservedpages++;
+      continue;
+    }
+    mem_map[MAP_NR(addr)] = 1;
+    free_page(addr);
+  }
+
+  tmp2 = nr_free_pages << PAGE_SHIFT;
+
+  printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
+	 tmp2 >> 10,
+	 high_memory >> 10,
+	 codepages << (PAGE_SHIFT-10),
+	 reservedpages << (PAGE_SHIFT-10),
+	 datapages << (PAGE_SHIFT-10));
+
+  invalidate();
+  return;
 }
 
 void si_meminfo(struct sysinfo *val)
diff -u --recursive --new-file v1.1.94/linux/drivers/block/README.ide linux/drivers/block/README.ide
--- v1.1.94/linux/drivers/block/README.ide	Mon Feb 20 21:34:54 1995
+++ linux/drivers/block/README.ide	Fri Feb 24 21:38:27 1995
@@ -1,4 +1,4 @@
-README.ide -- Information regarding ide.c and ide-cd.c (IDE driver in 1.1.93)
+README.ide -- Information regarding ide.c and ide-cd.c (IDE driver in 1.1.95)
 ================================================================================
 Supported by:  mlord@bnr.ca           -- disks, interfaces, probing
                snyder@fnald0.fnal.gov -- cdroms, ATAPI, audio
@@ -26,6 +26,7 @@
 
 	- support for interface speed selection on jumperless interfaces
 	- improved detection of non-standard IDE ATAPI cdrom drives
+	- support for non-standard 3rd/4th drive interface on Promise cards
 
 To access devices on the second interface, device entries must first be
 created in /dev for them.  To create such entries, simply run the included
diff -u --recursive --new-file v1.1.94/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v1.1.94/linux/drivers/block/floppy.c	Wed Feb 15 10:36:37 1995
+++ linux/drivers/block/floppy.c	Sun Feb 26 16:45:26 1995
@@ -240,6 +240,8 @@
 #define R_SECTOR (reply_buffer[5])
 #define R_SIZECODE (reply_buffer[6])
 
+#define SEL_DLY (2*HZ/100)
+
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof( (x)[0] ))
 /*
  * this struct defines the different floppy drive types.
@@ -254,38 +256,38 @@
   |     |   Head load time, msec
   |     |   |   Head unload time, msec (not used)
   |     |   |   |     Step rate interval, usec
-  |     |   |   |     |    Time needed for spinup time (jiffies)
-  |     |   |   |     |    |    Timeout for spinning down (jiffies)
-  |     |   |   |     |    |    |   Spindown offset (where disk stops)
-  |     |   |   |     |    |    |   |  Select delay
-  |     |   |   |     |    |    |   |  |  RPS
-  |     |   |   |     |    |    |   |  |  |    Max number of tracks
-  |     |   |   |     |    |    |   |  |  |    |     Interrupt timeout
-  |     |   |   |     |    |    |   |  |  |    |     |   Max nonintlv. sectors
-  |     |   |   |     |    |    |   |  |  |    |     |   | -Max Errors- flags */
-{{0,  500, 16, 16, 8000, 100, 300,  0, 2, 5,  80, 3*HZ, 20, {3,1,2,0,2}, 0,
-      0, { 7, 4, 8, 2, 1, 5, 3,10}, 150, 0 }, "unknown" },
-
-{{1,  300, 16, 16, 8000, 100, 300,  0, 2, 5,  40, 3*HZ, 17, {3,1,2,0,2}, 0,
-      0, { 1, 0, 0, 0, 0, 0, 0, 0}, 150, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/
-
-{{2,  500, 16, 16, 6000,  40, 300, 14, 2, 6,  83, 3*HZ, 17, {3,1,2,0,2}, 0,
-      0, { 2, 5, 6,23,10,20,11, 0}, 150, 2 }, "1.2M" }, /*5 1/4 HD AT*/
-
-{{3,  250, 16, 16, 3000, 100, 300,  0, 2, 5,  83, 3*HZ, 20, {3,1,2,0,2}, 0,
-      0, { 4,22,21,30, 3, 0, 0, 0}, 150, 4 }, "720k" }, /*3 1/2 DD*/
-
-{{4,  500, 16, 16, 4000,  40, 300, 10, 2, 5,  83, 3*HZ, 20, {3,1,2,0,2}, 0,
-      0, { 7, 4,25,22,31,21,29,11}, 150, 7 }, "1.44M" }, /*3 1/2 HD*/
-
-{{5, 1000, 15,  8, 3000,  40, 300, 10, 2, 5,  83, 3*HZ, 40, {3,1,2,0,2}, 0,
-      0, { 7, 8, 4,25,28,22,31,21}, 150, 8 }, "2.88M AMI BIOS" }, /*3 1/2 ED*/
-
-{{6, 1000, 15,  8, 3000,  40, 300, 10, 2, 5,  83, 3*HZ, 40, {3,1,2,0,2}, 0,
-      0, { 7, 8, 4,25,28,22,31,21}, 150, 8 }, "2.88M" } /*3 1/2 ED*/
-/*    |  ---autodetected formats--   |   |      |
-      read_track                     |   |    Name printed when booting
-                                     |  Native format
+  |     |   |   |     |       Time needed for spinup time (jiffies)
+  |     |   |   |     |       |      Timeout for spinning down (jiffies)
+  |     |   |   |     |       |      |   Spindown offset (where disk stops)
+  |     |   |   |     |       |      |   |     Select delay
+  |     |   |   |     |       |      |   |     |     RPS
+  |     |   |   |     |       |      |   |     |     |    Max number of tracks
+  |     |   |   |     |       |      |   |     |     |    |     Interrupt timeout
+  |     |   |   |     |       |      |   |     |     |    |     |   Max nonintlv. sectors
+  |     |   |   |     |       |      |   |     |     |    |     |   | -Max Errors- flags */
+{{0,  500, 16, 16, 8000,    1*HZ, 3*HZ,  0, SEL_DLY, 5,  80, 3*HZ, 20, {3,1,2,0,2}, 0,
+      0, { 7, 4, 8, 2, 1, 5, 3,10}, 3*HZ/2, 0 }, "unknown" },
+
+{{1,  300, 16, 16, 8000,    1*HZ, 3*HZ,  0, SEL_DLY, 5,  40, 3*HZ, 17, {3,1,2,0,2}, 0,
+      0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/
+
+{{2,  500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6,  83, 3*HZ, 17, {3,1,2,0,2}, 0,
+      0, { 2, 5, 6,23,10,20,11, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/
+
+{{3,  250, 16, 16, 3000,    1*HZ, 3*HZ,  0, SEL_DLY, 5,  83, 3*HZ, 20, {3,1,2,0,2}, 0,
+      0, { 4,22,21,30, 3, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/
+
+{{4,  500, 16, 16, 4000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5,  83, 3*HZ, 20, {3,1,2,0,2}, 0,
+      0, { 7, 4,25,22,31,21,29,11}, 3*HZ/2, 7 }, "1.44M" }, /*3 1/2 HD*/
+
+{{5, 1000, 15,  8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5,  83, 3*HZ, 40, {3,1,2,0,2}, 0,
+      0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M AMI BIOS" }, /*3 1/2 ED*/
+
+{{6, 1000, 15,  8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5,  83, 3*HZ, 40, {3,1,2,0,2}, 0,
+      0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M" } /*3 1/2 ED*/
+/*    |  ---autodetected formats--   |      |      |
+      read_track                     |      |    Name printed when booting
+                                     |     Native format
                                    Frequency of disk change checks */
 };
 
@@ -3228,7 +3230,7 @@
 			default_drive_params[i].params.select_delay = 0;
 			default_drive_params[i].params.flags |= FD_SILENT_DCL_CLEAR;
 		} else {
-			default_drive_params[i].params.select_delay = 2;
+			default_drive_params[i].params.select_delay = 2*HZ/100;
 			default_drive_params[i].params.flags &= ~FD_SILENT_DCL_CLEAR;
 		}
 	}
diff -u --recursive --new-file v1.1.94/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v1.1.94/linux/drivers/block/ide.c	Mon Feb 20 21:34:54 1995
+++ linux/drivers/block/ide.c	Fri Feb 24 21:38:28 1995
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c	Version 3.12  February 19, 1995
+ *  linux/drivers/block/ide.c	Version 3.13  February 23, 1995
  *
  *  Copyright (C) 1994, 1995  Linus Torvalds & authors (see below)
  */
@@ -103,11 +103,12 @@
  *  Version 3.11	fix mis-identification of old WD disks as cdroms
  *  Version 3,12	simplify logic for selecting initial mult_count
  *			  (fixes problems with buggy WD drives)
+ *  Version 3.13	remove excess "multiple mode disabled" messages
  *
  *  To do:
  *	- special 32-bit controller-type detection & support
- *	- figure out why two WD drives on one i/f sometimes don't identify
  *	- figure out how to support oddball "intelligent" caching cards
+ *	- reverse-engineer 3/4 drive support on fancy "Promise" cards
  */
 
 #include <linux/config.h>
@@ -1701,7 +1702,8 @@
 		dev->mult_req = INITIAL_MULT_COUNT;
 		if (dev->mult_req > id->max_multsect)
 			dev->mult_req = id->max_multsect;
-		dev->special.b.set_multmode = 1;
+		if (dev->mult_req || ((id->multsect_valid & 1) && id->multsect))
+			dev->special.b.set_multmode = 1;
 		printk(", MaxMult=%d", id->max_multsect);
 	}
 	printk("\n");
diff -u --recursive --new-file v1.1.94/linux/drivers/block/sonycd535.c linux/drivers/block/sonycd535.c
--- v1.1.94/linux/drivers/block/sonycd535.c	Wed Feb 22 16:53:04 1995
+++ linux/drivers/block/sonycd535.c	Thu Feb 23 13:31:40 1995
@@ -1556,7 +1556,7 @@
 			sony535_irq_used = tmp_irq;
 #ifndef MODULE
 /* This code is not in MODULEs by default, since the autoirq stuff might
- * not be in the module-accessable symbol table.
+ * not be in the module-accessible symbol table.
  */
 			/* A negative sony535_irq_used will attempt an autoirq. */
 			if (sony535_irq_used < 0) {
diff -u --recursive --new-file v1.1.94/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog
--- v1.1.94/linux/drivers/char/ChangeLog	Wed Feb 22 16:53:04 1995
+++ linux/drivers/char/ChangeLog	Thu Feb 23 13:31:41 1995
@@ -13,7 +13,7 @@
 
 	* serial.c (rs_init, set_serial_info, get_serial_info, rs_close):
 		Remove support for closing_wait2.  Instead, set
-		tty->closing and rely on the line dispcline to prevent
+		tty->closing and rely on the line discipline to prevent
 		echo wars.
 
 	* n_tty.c (n_tty_receive_char):  IEXTEN does not need to be
@@ -30,7 +30,7 @@
 
 	* serial.c (rs_interrupt_multi, startup, shutdown, rs_ioctl,
 		set_multiport_struct, get_multiport_struct): Add
-		provisions for a new type of interrutp service routine,
+		provisions for a new type of interrupt service routine,
 		which better supports multiple serial ports on a single
 		IRQ.  
 
@@ -61,7 +61,7 @@
 
 		The default is to wait 30 seconds; in the case of a
 		very slow device, the close_wait timeout should be
-		lengthed.  If it is set to 0, the kernel will wait
+		lengthened.  If it is set to 0, the kernel will wait
 		forever for all of the data to be transmitted.
 
 Thu Jan 17 01:17:20 1995  Theodore Y. Ts'o  (tytso@rt-11)
diff -u --recursive --new-file v1.1.94/linux/drivers/char/console.c linux/drivers/char/console.c
--- v1.1.94/linux/drivers/char/console.c	Fri Feb 17 11:20:12 1995
+++ linux/drivers/char/console.c	Thu Mar  2 09:31:10 1995
@@ -96,6 +96,7 @@
 #include <linux/malloc.h>
 #include <linux/major.h>
 #include <linux/mm.h>
+#include <linux/ioport.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -1002,7 +1003,7 @@
 	else
 		while (count--) {
 			unsigned short old = scr_readw(p);
-			scr_writew(old ^ ((old & 0x0700 == 0x0100)
+			scr_writew(old ^ (((old & 0x0700) == 0x0100)
 					  ? 0x7000 : 0x7700), p);
 		}
 }
@@ -1915,12 +1916,16 @@
 			video_type = VIDEO_TYPE_EGAM;
 			video_mem_term = 0xb8000;
 			display_desc = "EGA+";
+			request_region(0x3b4,2,"ega+");
 		}
 		else
 		{
 			video_type = VIDEO_TYPE_MDA;
 			video_mem_term = 0xb2000;
 			display_desc = "*MDA";
+			request_region(0x3b4,2,"mda");
+			request_region(0x3b8,1,"mda");
+			request_region(0x3bf,1,"mda");
 		}
 	}
 	else				/* If not, it is color. */
@@ -1934,12 +1939,14 @@
 			video_type = VIDEO_TYPE_EGAC;
 			video_mem_term = 0xc0000;
 			display_desc = "EGA+";
+			request_region(0x3d4,2,"ega+");
 		}
 		else
 		{
 			video_type = VIDEO_TYPE_CGA;
 			video_mem_term = 0xba000;
 			display_desc = "*CGA";
+			request_region(0x3d4,2,"cga");
 		}
 	}
 	
diff -u --recursive --new-file v1.1.94/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v1.1.94/linux/drivers/char/cyclades.c	Thu Feb  9 10:18:50 1995
+++ linux/drivers/char/cyclades.c	Thu Feb 23 13:31:40 1995
@@ -2457,7 +2457,7 @@
     memset(&cy_serial_driver, 0, sizeof(struct tty_driver));
     cy_serial_driver.magic = TTY_DRIVER_MAGIC;
     cy_serial_driver.name = "ttyC";
-    cy_serial_driver.major = 19 /* TTY_MAJOR */;
+    cy_serial_driver.major = CYCLADES_MAJOR;
     cy_serial_driver.minor_start = 32;
     cy_serial_driver.num = NR_PORTS;
     cy_serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
@@ -2492,7 +2492,7 @@
      */
     cy_callout_driver = cy_serial_driver;
     cy_callout_driver.name = "cub";
-    cy_callout_driver.major = 20 /* TTYAUX_MAJOR */;
+    cy_callout_driver.major = CYCLADESAUX_MAJOR;
     cy_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
 
     if (tty_register_driver(&cy_serial_driver))
diff -u --recursive --new-file v1.1.94/linux/drivers/char/defkeymap.c linux/drivers/char/defkeymap.c
--- v1.1.94/linux/drivers/char/defkeymap.c	Thu Oct 13 14:07:05 1994
+++ linux/drivers/char/defkeymap.c	Fri Feb 24 21:38:27 1995
@@ -33,7 +33,7 @@
 	0xf022,	0xf07e,	0xf700,	0xf07c,	0xfb5a,	0xfb58,	0xfb43,	0xfb56,
 	0xfb42,	0xfb4e,	0xfb4d,	0xf03c,	0xf03e,	0xf03f,	0xf700,	0xf30c,
 	0xf703,	0xf020,	0xf207,	0xf10a,	0xf10b,	0xf10c,	0xf10d,	0xf10e,
-	0xf10f,	0xf110,	0xf111,	0xf112,	0xf113,	0xf208,	0xf203,	0xf307,
+	0xf10f,	0xf110,	0xf111,	0xf112,	0xf113,	0xf213,	0xf203,	0xf307,
 	0xf308,	0xf309,	0xf30b,	0xf304,	0xf305,	0xf306,	0xf30a,	0xf301,
 	0xf302,	0xf303,	0xf300,	0xf310,	0xf206,	0xf200,	0xf03e,	0xf10a,
 	0xf10b,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
diff -u --recursive --new-file v1.1.94/linux/drivers/char/defkeymap.map linux/drivers/char/defkeymap.map
--- v1.1.94/linux/drivers/char/defkeymap.map	Thu Oct 13 14:07:05 1994
+++ linux/drivers/char/defkeymap.map	Fri Feb 24 21:38:27 1995
@@ -160,7 +160,8 @@
 	control keycode  68 = F10             
 	alt     keycode  68 = Console_10      
 	control alt     keycode  68 = Console_10      
-keycode  69 = Num_Lock        
+keycode  69 = Num_Lock
+	shift   keycode  69 = Bare_Num_Lock
 keycode  70 = Scroll_Lock      Show_Memory      Show_Registers  
 	control keycode  70 = Show_State      
 	alt     keycode  70 = Scroll_Lock     
diff -u --recursive --new-file v1.1.94/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v1.1.94/linux/drivers/char/keyboard.c	Fri Feb 17 11:20:12 1995
+++ linux/drivers/char/keyboard.c	Thu Mar  2 08:38:43 1995
@@ -26,6 +26,7 @@
 #include <linux/ptrace.h>
 #include <linux/signal.h>
 #include <linux/string.h>
+#include <linux/ioport.h>
 
 #include <asm/bitops.h>
 
@@ -136,14 +137,14 @@
 
 static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
 	num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
-	SAK, decr_console, incr_console, spawn_console;
+	SAK, decr_console, incr_console, spawn_console, bare_num;
 
 static void_fnp spec_fn_table[] = {
 	do_null,	enter,		show_ptregs,	show_mem,
 	show_state,	send_intr,	lastcons,	caps_toggle,
 	num,		hold,		scroll_forw,	scroll_back,
 	boot_it,	caps_on,	compose,	SAK,
-	decr_console,	incr_console,	spawn_console
+	decr_console,	incr_console,	spawn_console,	bare_num
 };
 
 /* maximum values each key_handler can handle */
@@ -643,11 +644,21 @@
 
 static void num(void)
 {
-	if (vc_kbd_mode(kbd,VC_APPLIC)) {
+	if (vc_kbd_mode(kbd,VC_APPLIC))
 		applkey('P', 1);
-		return;
-	}
-	if (!rep)	/* no autorepeat for numlock, ChN */
+	else
+		bare_num();
+}
+
+/*
+ * Bind this to Shift-NumLock if you work in application keypad mode
+ * but want to be able to change the NumLock flag.
+ * Bind this to NumLock if you prefer that the NumLock key always
+ * changes the NumLock flag.
+ */
+static void bare_num(void)
+{
+	if (!rep)
 		chg_vc_kbd_led(kbd,VC_NUMLOCK);
 }
 
@@ -1170,6 +1181,8 @@
 
 	bh_base[KEYBOARD_BH].routine = kbd_bh;
 	request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard");
+	request_region(0x60,1,"kbd");
+	request_region(0x64,1,"kbd");
 #ifdef __alpha__
 	/* enable keyboard interrupts, PC/AT mode */
 	kb_wait();
diff -u --recursive --new-file v1.1.94/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v1.1.94/linux/drivers/char/serial.c	Wed Feb 22 16:53:04 1995
+++ linux/drivers/char/serial.c	Thu Feb 23 13:31:40 1995
@@ -2003,8 +2003,8 @@
 	if (info->flags & ASYNC_CALLOUT_ACTIVE)
 		info->callout_termios = *tty->termios;
 	/*
-	 * Now we wait for the trnasmit buffer to clear; and we notify 
-	 * the line discpline only process XON/XOFF characters.
+	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * the line discipline to only process XON/XOFF characters.
 	 */
 	tty->closing = 1;
 	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
diff -u --recursive --new-file v1.1.94/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
--- v1.1.94/linux/drivers/net/3c503.c	Mon Jan  9 11:24:21 1995
+++ linux/drivers/net/3c503.c	Mon Feb 27 11:06:24 1995
@@ -330,7 +330,7 @@
 {
     if (ei_debug > 1) {
 	printk("%s: Resetting the 3c503 board...", dev->name);
-	printk("%#x=%#02x %#x=%#02x %#x=%#02x...", E33G_IDCFR, inb(E33G_IDCFR),
+	printk("%#lx=%#02x %#lx=%#02x %#lx=%#02x...", E33G_IDCFR, inb(E33G_IDCFR),
 	       E33G_CNTRL, inb(E33G_CNTRL), E33G_GACFR, inb(E33G_GACFR));
     }
     outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL);
diff -u --recursive --new-file v1.1.94/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v1.1.94/linux/drivers/net/Makefile	Wed Feb 15 10:36:38 1995
+++ linux/drivers/net/Makefile	Thu Feb 23 13:51:27 1995
@@ -231,6 +231,8 @@
 
 ifdef CONFIG_ARCNET
 NETDRV_OBJS := $(NETDRV_OBJS) arcnet.o
+else
+MODULES := $(MODULES) arcnet.o
 endif
 
 ifdef CONFIG_PI
diff -u --recursive --new-file v1.1.94/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
--- v1.1.94/linux/drivers/net/arcnet.c	Mon Jan 16 14:18:19 1995
+++ linux/drivers/net/arcnet.c	Thu Feb 23 13:53:58 1995
@@ -1,47 +1,64 @@
-/*
-	arcnet.c written 1994 by Avery Pennarun, derived from skeleton.c
-	by Donald Becker.
-	
+/* arcnet.c
+	Written 1994-95 by Avery Pennarun, derived from skeleton.c by
+        Donald Becker.
+
 	Contact Avery at: apenwarr@tourism.807-city.on.ca or
 	RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
 	
-	!!! This is a dangerous alpha version !!!
-	
 	**********************
 
 	skeleton.c Written 1993 by Donald Becker.
-	Copyright 1993 United States Government as represented by the Director,
-	National Security Agency.  This software may only be used and distributed
-	according to the terms of the GNU Public License as modified by SRC,
-	incorporated herein by reference.
-
-        The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-         Center of Excellence in Space Data and Information Sciences
-         Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	Copyright 1993 United States Government as represented by the
+        Director, National Security Agency.  This software may only be used
+        and distributed according to the terms of the GNU Public License as
+        modified by SRC, incorporated herein by reference.
          
 	**********************
+
+
+	v1.0 (95/02/15)
+	  - Initial non-alpha release.
 	
          
 	TO DO:
 	
-         - Polled transmits probably take a lot more CPU time than needed.
-           Perhaps use the system timer?  A better solution would be to
-           just figure out how to get both xmit and receive IRQ's working
-           at the same time.  No luck yet...
-         - I'd also like to get ping-pong TX buffers working.
          - Test in systems with NON-ARCnet network cards, just to see if
            autoprobe kills anything.  With any luck, it won't.  (It's pretty
-           strict and careful.)
+           careful.)
+           	- Except some unfriendly NE2000's die. (0.40)
          - cards with shared memory that can be "turned off?"
-         	- examine TRXNET for information about this
+         - NFS mount freezes after several megabytes to SOSS for DOS. 
+ 	   unmount/remount works.  Is this arcnet-specific?  I don't know.
+ 	 - Add support for the various stupid bugs ("I didn't read the RFC"
+ 	   syndrome) in MS Windows for Workgroups and LanMan.
+ 	   
+ 	 - get the net people to probe last for arcnet, and first for ne2000
+ 	   in Space.c...  
  */
  
 /**************************************************************************/
+
+/* define this if you want to use the new but possibly dangerous ioprobe
+ * If you get lockups right after status5, you probably need
+ * to undefine this.  It should make more cards probe correctly,
+ * I hope.
+ */
+#define DANGER_PROBE
+
+/* define this if you want to use the "extra delays" which were removed
+ * in 0.41 since they seemed needless.
+ */
+#undef EXTRA_DELAYS
+
+/* undefine this if you want to use the non-IRQ-driven transmitter. (possibly
+ * safer, although it takes more CPU time and IRQ_XMIT seems fine right now)
+ */
+#define IRQ_XMIT
  
 /* define this for "careful" transmitting.  Try with and without if you have
- * problems.
+ * problems.  If you use IRQ_XMIT, do NOT define this.
  */
-#define CAREFUL_XMIT
+#undef CAREFUL_XMIT
 
 /* define this for an extra-careful memory detect.  This should work all
  * the time now, but you never know.
@@ -70,11 +87,7 @@
 /**************************************************************************/
  
 static char *version =
- "arcnet.c:v0.32 ALPHA 94/12/26 Avery Pennarun <apenwarr@tourism.807-city.on.ca>\n";
-
-/* Always include 'config.h' first in case the user wants to turn on
-   or override something. */
-#include <linux/config.h>
+ "arcnet.c:v1.00 95/02/15 Avery Pennarun <apenwarr@tourism.807-city.on.ca>\n";
 
 /*
   Sources:
@@ -86,8 +99,17 @@
 	...I sure wish I had the ARCnet data sheets right about now!
 	RFC's 1201 and 1051 (mostly 1201) - re: ARCnet IP packets
 	net/inet/eth.c (from kernel 1.1.50) for header-building info...
+	Alternate Linux ARCnet source by V.Shergin <vsher@sao.stavropol.su>
+	Textual information and more alternate source from Joachim Koenig
+		<jojo@repas.de>
 */
 
+#include <linux/config.h>
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#endif /* MODULE */
+
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -100,6 +122,7 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -111,6 +134,7 @@
 #include <linux/skbuff.h>
 #include "arp.h"
 
+
 /* debug levels:
  * D_OFF	production
  * D_NORMAL	verification
@@ -143,7 +167,7 @@
 
 #ifndef HAVE_PORTRESERVE
 #define check_region(ioaddr, size) 		0
-#define	snarf_region(ioaddr, size);		do ; while (0)
+#define	request_region(ioaddr, size)		do ; while (0)
 #endif
 
 /* macro to simplify debug checking */
@@ -162,8 +186,8 @@
 
 	/* time needed for various things (in clock ticks, 1/100 sec) */
 #define RESETtime 40		/* reset */
-#define XMITtime 10		/* send */
-#define ACKtime 10		/* acknowledge */
+#define XMITtime 10		/* send (?) */
+#define ACKtime 10		/* acknowledge (?) */
 
 	/* these are the max/min lengths of packet data. (including
 	 * ClientData header)
@@ -220,12 +244,15 @@
 	/* buffers (4 total) used for receive and xmit.
 	 */
 #define EnableReceiver()	outb(RXcmd|(recbuf<<3)|RXbcasts,COMMAND)
-#define TXbuf		2
+/*#define TXbuf		2 (Obsoleted by ping-pong xmits) */
 
 	/* Protocol ID's */
 #define ARC_P_IP	212		/* 0xD4 */
 #define ARC_P_ARP	213		/* 0xD5 */
 #define ARC_P_RARP	214		/* 0xD6 */
+#define ARC_P_IPX	250		/* 0xFA */
+#define ARC_P_LANSOFT	251		/* 0xFB */
+#define ARC_P_ATALK	0xDD
 
 	/* Length of time between "stuck" checks */
 #define TIMERval	(HZ/8)		/* about 1/8 second */
@@ -283,39 +310,65 @@
 	u_short sequence;		/* sequence number of assembly	  */
 };
 
+struct Outgoing
+{
+	struct sk_buff *skb;		/* buffer from upper levels */
+	struct ClientData *hdr;		/* clientdata of last packet */
+	u_char *data;			/* pointer to data in packet */
+	short length,			/* bytes total */
+	      dataleft,			/* bytes left */
+	      segnum,			/* segment being sent */
+	      numsegs,			/* number of segments */
+	      seglen;			/* length of segment */
+};
+
 
 /* Information that needs to be kept for each board. */
 struct arcnet_local {
 	struct enet_statistics stats;
 	u_char arcnum;		/* arcnet number - our 8-bit address */
 	u_short sequence;	/* sequence number (incs with each packet) */
-	u_char recbuf;		/* receive buffer # (0 or 1) */
-	int intx;		/* in TX routine? */
+	u_char recbuf,		/* receive buffer # (0 or 1) */
+	       txbuf,		/* transmit buffer # (2 or 3) */
+	       txready;		/* buffer where a packet is ready to send */
+	short intx,		/* in TX routine? */
+	      in_txhandler,	/* in TX_IRQ handler? */
+	      sending;		/* transmit in progress? */
+	short tx_left;		/* segments of split packet left to TX */
 	struct timer_list timer; /* the timer interrupt struct */
 	struct Incoming incoming[256];	/* one from each address */
+	struct Outgoing outgoing; /* packet currently being sent */
 };
 
 
 /* Index to functions, as function prototypes. */
-
 extern int arcnet_probe(struct device *dev);
+#ifndef MODULE
 static int arcnet_memprobe(struct device *dev,u_char *addr);
 static int arcnet_ioprobe(struct device *dev, short ioaddr);
+#endif
 
 static int arcnet_open(struct device *dev);
 static int arcnet_close(struct device *dev);
 
 static int arcnet_send_packet(struct sk_buff *skb, struct device *dev);
-static void careful_xmit_wait(struct device *dev);
-static int arcnet_tx(struct device *dev,struct ClientData *hdr,short length,
-			char *data);
+#ifdef CAREFUL_XMIT
+ static void careful_xmit_wait(struct device *dev);
+#else
+ #define careful_xmit_wait(dev)
+#endif
+static void arcnet_continue_tx(struct device *dev);
+static void arcnet_prepare_tx(struct device *dev,struct ClientData *hdr,
+		short length,char *data);
+static void arcnet_go_tx(struct device *dev);
 
-static void arcnet_interrupt(int irq, struct pt_regs *regs);
+static void arcnet_interrupt(int irq,struct pt_regs *regs);
 static void arcnet_inthandler(struct device *dev);
 static void arcnet_rx(struct device *dev,int recbuf);
 
-
+#ifdef USE_TIMER_HANDLER
 static void arcnet_timer(unsigned long arg);
+#endif
 
 static struct enet_statistics *arcnet_get_stats(struct device *dev);
 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
@@ -327,10 +380,26 @@
 		struct sk_buff *skb);
 unsigned short arc_type_trans(struct sk_buff *skb,struct device *dev);
 
+static int arcnet_reset(struct device *dev);
+
+#ifdef MODULE
+int  init_module(void);
+void cleanup_module(void);
+#endif
 
 #define tx_done(dev) 1
-#define JIFFER(time) for (delayval=jiffies+(time); delayval>=jiffies;);
-static int arcnet_reset(struct device *dev);
+
+/*
+#define JIFFER(time) for (delayval=jiffies+(time); delayval>jiffies;);
+*/
+#define JIFFER(time) for (delayval=0; delayval<(time*10); delayval++) \
+		udelay(1000);
+
+#ifdef EXTRA_DELAYS
+ #define XJIFFER(time) JIFFER(time)
+#else
+ #define XJIFFER(time)
+#endif
 
 
 /* Check for a network adaptor of this type, and return '0' if one exists.
@@ -342,6 +411,7 @@
 int
 arcnet_probe(struct device *dev)
 {
+#ifndef MODULE
 	/* I refuse to probe anything less than 0x200, because anyone using
 	 * an address like that should probably be shot.
 	 */
@@ -351,10 +421,10 @@
 			      0x200,0x210,0x220,0x230,0x240,0x250,0x260,0x270,
 			      0x280,0x290,0x2a0,0x2b0,0x2c0,
 			            0x310,0x320,0x330,0x340,0x350,0x360,0x370,
-			      0x380,0x390,0x3a0,0x3b0,0x3c0,0x3d0,0x3e0,0x3f0,
+			      0x380,0x390,0x3a0,/* video ports, */0x3e0,0x3f0,
 			      /* a null ends the list */
 			      0};
-	/* I'm not going to probe under 0xA0000 either, for similar reasons.
+	/* I'm not going to probe below 0xA0000 either, for similar reasons.
 	 */
 	unsigned long *addr, addrs[] = {0xD0000,0xE0000,0xA0000,0xB0000,
 					0xC0000,0xF0000,
@@ -366,15 +436,24 @@
 					0xC9000,0xC8000,0xC5000,0xC4000,
 					/* terminator */
 					0};
-	int base_addr=dev->base_addr, status=0,delayval;
+	int base_addr=dev->base_addr, status=0;
+#endif /* MODULE */
+	int delayval;
 	struct arcnet_local *lp;
 
-	if (net_debug) printk(version);
+	if (net_debug)
+	{
+		printk(version);
+		printk("arcnet: ***\n");
+		printk("arcnet: * Read linux/drivers/net/README.arcnet for important release notes!\n");
+		printk("arcnet: ***\n");
+	}
 	
 	BUGLVL(D_INIT)
-		printk("arcnet: given: base %Xh, IRQ %Xh, shmem %lXh\n",
+		printk("arcnet: given: base %lXh, IRQ %Xh, shmem %lXh\n",
 			dev->base_addr,dev->irq,dev->mem_start);
-		
+			
+#ifndef MODULE
 	if (base_addr > 0x1ff)		/* Check a single specified location. */
 		status=arcnet_ioprobe(dev, base_addr);
 	else if (base_addr > 0)		/* Don't probe at all. */
@@ -395,7 +474,7 @@
 	}
 	
 	if (status) return status;
-	
+
 	/* ioprobe turned out okay.  Now give it a couple seconds to finish
 	 * initializing...
 	 */
@@ -421,21 +500,32 @@
 		
 		if (status) return status;
 	}
-
+#else /* MODULE */
+	if (!dev->base_addr || !dev->irq || !dev->mem_start 
+		|| !dev->rmem_start)
+	{
+		printk("arcnet: loadable modules can't autoprobe!\n");
+		printk("arcnet:  try using io=, irqnum=, and shmem= on the insmod line.\n");
+		printk("arcnet:  you may also need num= to change the device name. (ie. num=1 for arc1)\n");
+		return ENODEV;
+	}
+#endif
 	/* now reserve the irq... */
-	{	 int irqval = request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet");
-		 if (irqval) {
-			 printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
-					 dev->irq, irqval);
-			 return EAGAIN;
+	{	
+		int irqval = request_irq(dev->irq, &arcnet_interrupt, 0,
+			"arcnet");
+		if (irqval) {
+			printk("%s: unable to get IRQ %d (irqval=%d).\n",
+				dev->name,dev->irq, irqval);
+			return EAGAIN;
 		 }
 	 }
 	 
 	/* Grab the region so we can find another board if autoIRQ fails. */
-	snarf_region(dev->base_addr, ETHERCARD_TOTAL_SIZE);
-
-	printk("%s: ARCnet card found at %03Xh, IRQ %d, ShMem at %lXh.\n", dev->name,
-		dev->base_addr, dev->irq, dev->mem_start);
+	request_region(dev->base_addr, ETHERCARD_TOTAL_SIZE,"arcnet");
+	
+	printk("%s: ARCnet card found at %03lXh, IRQ %d, ShMem at %lXh.\n", 
+		dev->name, dev->base_addr, dev->irq, dev->mem_start);
 
 	/* Initialize the device structure. */
 	dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
@@ -484,13 +574,14 @@
 	lp->recbuf=0;
 
 	dev->hard_header        = arc_header;
-/*	dev->add_arp            = arc_add_arp;  AVE unavailable in 1.1.51?! */
 	dev->rebuild_header     = arc_rebuild_header;
 	dev->type_trans         = arc_type_trans;
 
 	return 0;
 }
 
+#ifndef MODULE
+
 int arcnet_ioprobe(struct device *dev, short ioaddr)
 {
 	int delayval,airq;
@@ -506,7 +597,7 @@
 	 * no irq, it's not an ARCnet.  We can also kill two birds with
 	 * one stone because we detect the IRQ at the same time :)
 	 */
-
+	 
 	/* reset the card by reading the reset port */
 	inb(RESET);
 	JIFFER(RESETtime);
@@ -545,7 +636,7 @@
 
 	/* now we turn the reset bit off so we can IRQ next reset... */
 	outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND);
-	JIFFER(ACKtime);
+	XJIFFER(ACKtime);
 	if (inb(STATUS) & RESETflag) /* reset flag STILL on */
 	{
 		BUGLVL(D_INIT)
@@ -557,7 +648,7 @@
 	/* set up automatic IRQ detection */
 	autoirq_setup(0);
 	
-	/* enable reset IRQ's (shouldn't be necessary, but hey) */
+	/* enable reset IRQ's (shouldn't be necessary, but worth a try) */
 	outb(RESETflag,INTMASK);
 
 	/* now reset it again to generate an IRQ */
@@ -567,16 +658,16 @@
 	BUGLVL(D_INIT)
 		printk("arcnet:  status3=%Xh\n",inb(STATUS));
 
-	/* enable reset IRQ's again */
-	outb(RESETflag,INTMASK);
-
 	/* and turn the reset flag back off */
 	outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND);
-	JIFFER(ACKtime);
+	XJIFFER(ACKtime);
 
 	BUGLVL(D_INIT)
 		printk("arcnet:  status4=%Xh\n",inb(STATUS));
 
+	/* enable reset IRQ's again */
+	outb(RESETflag,INTMASK);
+
 	/* now reset it again to generate an IRQ */
 	inb(RESET);
 	JIFFER(RESETtime);
@@ -584,6 +675,23 @@
 	BUGLVL(D_INIT)
 		printk("arcnet:  status5=%Xh\n",inb(STATUS));
 
+	/* if we do this, we're sure to get an IRQ since the card has
+	 * just reset and the NORXflag is on until we tell it to start
+	 * receiving.
+	 *
+	 * However, this could, theoretically, cause a lockup.  Maybe I'm just
+	 * not very good at theory! :)
+	 */
+#ifdef DANGER_PROBE
+	outb(NORXflag,INTMASK);
+	JIFFER(RESETtime);
+	outb(0,INTMASK);
+#endif
+
+	/* and turn the reset flag back off */
+	outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND);
+	XJIFFER(ACKtime);
+
 	airq = autoirq_report(0);
 	if (net_debug>=D_INIT && airq)
 		printk("arcnet:  autoirq is %d\n", airq);
@@ -604,7 +712,7 @@
 	{
 		/* now we turn the reset bit off */
 		outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND);
-		JIFFER(ACKtime);
+		XJIFFER(ACKtime);
 	}
 	
 	if (inb(STATUS) & RESETflag) /* reset flag STILL on */
@@ -631,11 +739,12 @@
 	}
 
 	BUGLVL(D_INIT)
-		printk("arcnet: irq and base address seem okay. (%Xh, IRQ %d)\n",
+		printk("arcnet: irq and base address seem okay. (%lXh, IRQ %d)\n",
 			dev->base_addr,dev->irq);
 	return 0;
 }
 
+
 /* A memory probe that is called after the card is reset.
  * It checks for the official TESTvalue in byte 0 and makes sure the buffer
  * has certain characteristics of an ARCnet...
@@ -685,6 +794,8 @@
 	return 0;
 }
 
+#endif /* MODULE */
+
 
 /* Open/initialize the board.  This is called (in the current kernel)
    sometime after booting when the 'ifconfig' program is run.
@@ -699,6 +810,12 @@
 	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
 /*	int ioaddr = dev->base_addr;*/
 
+	if (dev->metric>=10)
+	{
+		net_debug=dev->metric-10;
+		dev->metric=1;
+	}
+
 	if (net_debug) printk(version);
 
 #if 0	/* Yup, they're hardwired in arcnets */
@@ -713,25 +830,34 @@
 
 	/* Reset the hardware here. */
 	BUGLVL(D_EXTRA) printk("arcnet: arcnet_open: resetting card.\n");
-	if (arcnet_reset(dev)) return -ENODEV;
+	
+	/* try to reset - twice if it fails the first time */
+	if (arcnet_reset(dev) && arcnet_reset(dev))
+		return -ENODEV;
 	
 /*	chipset_init(dev, 1);*/
 /*	outb(0x00, ioaddr);*/
 
 /*	lp->open_time = jiffies;*/
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	dev->tbusy=0;
+	dev->interrupt=0;
+	dev->start=1;
+	lp->intx=0;
+	lp->in_txhandler=0;
 
+#ifdef USE_TIMER_HANDLER
 	/* grab a timer handler to recover from any missed IRQ's */
 	init_timer(&lp->timer);
 	lp->timer.expires = TIMERval;         /* length of time */
 	lp->timer.data = (unsigned long)dev;  /* pointer to "dev" structure */
 	lp->timer.function = &arcnet_timer;    /* timer handler */
-#ifdef USE_TIMER_HANDLER
 	add_timer(&lp->timer);
 #endif
+
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
                                  	
 	return 0;
 }
@@ -742,7 +868,10 @@
 arcnet_close(struct device *dev)
 {
 	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-	int ioaddr = dev->base_addr, delayval;
+	int ioaddr = dev->base_addr;
+#ifdef EXTRA_DELAYS
+	int delayval;
+#endif
 
 /*	lp->open_time = 0;*/
 
@@ -758,17 +887,14 @@
 
 	outb(0,INTMASK);	/* no IRQ's */
 	outb(NOTXcmd,COMMAND);  /* disable transmit */
-	JIFFER(ACKtime);
+	XJIFFER(ACKtime);
 	outb(NORXcmd,COMMAND);	/* disable receive */
 
-#if 0	/* we better not do this - hard wired IRQ's */
-	/* If not IRQ jumpered, free up the line. */
-	outw(0x00, ioaddr+0);		/* Release the physical interrupt line. */
-	free_irq(dev->irq);
-	irq2dev_map[dev->irq] = 0;
-#endif
-
 	/* Update the statistics here. */
+	
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
 
 	return 0;
 }
@@ -778,16 +904,16 @@
 arcnet_send_packet(struct sk_buff *skb, struct device *dev)
 {
 	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-	int ioaddr=dev->base_addr,stat=0;
+	int ioaddr=dev->base_addr;
 /*	short daddr;*/
 
 	lp->intx++;
-	
+
 	BUGLVL(D_DURING)
 		printk("arcnet: transmit requested (status=%Xh, inTX=%d)\n",
 			inb(STATUS),lp->intx);
 
-	if (dev->tbusy)
+	if (dev->tbusy || lp->in_txhandler)
 	{
 		/* If we get here, some higher level has decided we are broken.
 		   There should really be a "kick me" function call instead. */
@@ -795,7 +921,28 @@
 		int recbuf=lp->recbuf;
 		int status=inb(STATUS);
 		
-		if (tickssofar < 5) return 1;
+		/* resume any stopped tx's */
+#if 0
+		if (lp->txready && (inb(STATUS)&TXFREEflag))
+		{
+			printk("arcnet: kickme: starting a TX (status=%Xh)\n",
+				inb(STATUS));
+			arcnet_go_tx(dev);
+			lp->intx--;
+			return 1;
+		}
+#endif
+		
+		if (tickssofar < 5) 
+		{
+			BUGLVL(D_DURING)
+				printk("arcnet: premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n",
+					status,tickssofar,lp->outgoing.skb,
+					lp->outgoing.numsegs,
+					lp->outgoing.segnum);
+			lp->intx--;
+			return 1;
+		}
 
 		BUGLVL(D_INIT)
 			printk("arcnet: transmit timed out (status=%Xh, inTX=%d, tickssofar=%d)\n",
@@ -806,10 +953,19 @@
 		
 		if (status&NORXflag) EnableReceiver();
 		if (!(status&TXFREEflag)) outb(NOTXcmd,COMMAND);
+		dev->trans_start = jiffies;
+
+		if (lp->outgoing.skb)
+			dev_kfree_skb(lp->outgoing.skb,FREE_WRITE);
+		lp->outgoing.skb=NULL;
+
 		dev->tbusy=0;
 		mark_bh(NET_BH);
-		dev->trans_start = jiffies;
-		lp->intx--;
+		lp->intx=0;
+		lp->in_txhandler=0;
+		lp->txready=0;
+		lp->sending=0;
+
 		return 1;
 	}
 
@@ -824,90 +980,174 @@
 		lp->intx--;
 		return 0;
 	}
+	
+	if (lp->txready)	/* transmit already in progress! */
+	{
+		printk("arcnet: trying to start new packet while busy!\n");
+		printk("arcnet: marking as not ready.\n");
+		lp->txready=0;
+		return 1;
+	}
 
 	/* Block a timer-based transmit from overlapping.  This could better be
 	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
         if (set_bit(0, (void*)&dev->tbusy) != 0)
         {
-            printk("arcnet: Transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
+            printk("arcnet: transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
             		inb(STATUS),lp->intx,jiffies-dev->trans_start);
-            stat=-EBUSY;
+            lp->intx--;
+            return -EBUSY;
         }
 	else {
-		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-		struct ClientData *hdr=(struct ClientData*)skb->data;
+		struct Outgoing *out=&(lp->outgoing);
+		out->length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+		out->hdr=(struct ClientData*)skb->data;
+		out->skb=skb;
+
+#ifdef IRQ_XMIT
+		if (lp->txready && inb(STATUS)&TXFREEflag)
+			arcnet_go_tx(dev);
+#endif
+
 		
-		if (length<=XMTU)	/* fits in one packet? */
+		if (out->length<=XMTU)	/* fits in one packet? */
 		{
 			BUGLVL(D_TX) printk("arcnet: not splitting %d-byte packet. (split_flag=%d)\n",
-					length,hdr->split_flag);
-			BUGLVL(D_INIT) if (hdr->split_flag)
+					out->length,out->hdr->split_flag);
+			BUGLVL(D_INIT) if (out->hdr->split_flag)
 				printk("arcnet: short packet has split_flag set?! (split_flag=%d)\n",
-					hdr->split_flag);
-			stat=arcnet_tx(dev,hdr,
-				length-sizeof(struct ClientData),
+					out->hdr->split_flag);
+			out->numsegs=1;
+			out->segnum=1;
+			arcnet_prepare_tx(dev,out->hdr,
+				out->length-sizeof(struct ClientData),
 				((char *)skb->data)+sizeof(struct ClientData));
+			careful_xmit_wait(dev);
+
+			/* done right away */
+			dev_kfree_skb(out->skb,FREE_WRITE);
+			out->skb=NULL;
+					
+			if (!lp->sending)
+			{
+				arcnet_go_tx(dev);
+				
+				/* inform upper layers */
+				dev->tbusy=0;
+				mark_bh(NET_BH);
+			}
 		}
 		else			/* too big for one - split it */
 		{
-			u_char *data=(u_char *)skb->data
+			int maxsegsize=XMTU-sizeof(struct ClientData);
+
+			out->data=(u_char *)skb->data
 					+ sizeof(struct ClientData);
-			int dataleft=length-sizeof(struct ClientData),
-				maxsegsize=XMTU-sizeof(struct ClientData),
-				numsegs=(dataleft+maxsegsize-1)/maxsegsize,
-				seglen,segnum=0;
+			out->dataleft=out->length-sizeof(struct ClientData);
+			out->numsegs=(out->dataleft+maxsegsize-1)/maxsegsize;
+				
+			out->segnum=0;
 				
 			BUGLVL(D_TX) printk("arcnet: packet (%d bytes) split into %d fragments:\n",
-				length,numsegs);
+				out->length,out->numsegs);
 
-			while (!stat && dataleft)
-			{
-				if (!segnum)	/* first packet */
-					hdr->split_flag=((numsegs-2)<<1)+1;
-				else
-					hdr->split_flag=segnum<<1;
+#ifdef IRQ_XMIT
+			/* if a packet waiting, launch it */
+			if (lp->txready && inb(STATUS)&TXFREEflag)
+				arcnet_go_tx(dev);
 
-				seglen=maxsegsize;
-				if (seglen>dataleft) seglen=dataleft;
-					
-				BUGLVL(D_TX) printk("arcnet: packet #%d (%d bytes) of %d (%d total), splitflag=%d\n",
-					segnum+1,seglen,numsegs,length,hdr->split_flag);
-
-				stat=arcnet_tx(dev,hdr,seglen,data);
-				
-				dataleft-=seglen;
-				data+=seglen;
-				segnum++;
-				
-#if 0	/* sequence # should not update here... I think! */
-				/* sequence number goes up on each packet */
-				hdr->sequence++;
-				lp->sequence++;
-#endif
+			if (!lp->txready)
+			{
+				/* prepare a packet, launch it and prepare
+                                 * another.
+                                 */
+				arcnet_continue_tx(dev);
+				if (!lp->sending)
+				{
+					arcnet_go_tx(dev);
+					arcnet_continue_tx(dev);
+					if (!lp->sending)
+						arcnet_go_tx(dev);
+				}
 			}
-		}
 			
-		/* I don't know if this should be in or out of these braces,
-		 * but freeing it too often seems worse than too little.
-		 * (maybe?)  (v0.30)
-		 */
-		if (!stat) dev_kfree_skb(skb, FREE_WRITE);
-		
-		/* we're done now */
-		if (stat!=-EBUSY)
-		{
-			dev->tbusy=0;
-			mark_bh(NET_BH);	/* Inform upper layers. */
-			/* this should be on an IRQ, but can't
-			 * because ARCnets (at least mine) are stupid.
+			/* if segnum==numsegs, the transmission is finished;
+			 * free the skb right away.
 			 */
+			if (out->segnum==out->numsegs)
+			{
+				/* transmit completed */
+				out->segnum++;
+				if (out->skb)
+					dev_kfree_skb(out->skb,FREE_WRITE);
+				out->skb=NULL;
+#if 0
+				/* inform upper layers */
+				dev->tbusy=0;
+				mark_bh(NET_BH);
+#endif
+			}
+			
+#else /* non-irq xmit */
+			while (out->segnum<out->numsegs)
+			{
+				arcnet_continue_tx(dev);
+				careful_xmit_wait(dev);
+				arcnet_go_tx(dev);
+				dev->trans_start=jiffies;
+			}
+
+			dev_kfree_skb(out->skb,FREE_WRITE);
+			out->skb=NULL;
+
+			/* inform upper layers */
+			dev->tbusy = 0;
+			mark_bh(NET_BH);
+#endif
 		}
 	}
-	
+
 	lp->intx--;
+	lp->stats.tx_packets++;
+	dev->trans_start=jiffies;
+	return 0;
+}
+
+static void arcnet_continue_tx(struct device *dev)
+{
+	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+	int maxsegsize=XMTU-sizeof(struct ClientData);
+	struct Outgoing *out=&(lp->outgoing);
+	
+	if (lp->txready)
+	{
+		printk("arcnet: continue_tx: called with packet in buffer!\n");
+		return;
+	}
+
+	if (out->segnum>=out->numsegs)
+	{
+		printk("arcnet: continue_tx: building segment %d of %d!\n",
+			out->segnum+1,out->numsegs);
+	}
+
+	if (!out->segnum)	/* first packet */
+		out->hdr->split_flag=((out->numsegs-2)<<1)+1;
+	else
+		out->hdr->split_flag=out->segnum<<1;
 
-	if (!stat) lp->stats.tx_packets++;
-	return stat;
+	out->seglen=maxsegsize;
+	if (out->seglen>out->dataleft) out->seglen=out->dataleft;
+			
+	BUGLVL(D_TX) printk("arcnet: building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n",
+		out->segnum+1,out->seglen,out->numsegs,
+		out->length,out->hdr->split_flag);
+
+	arcnet_prepare_tx(dev,out->hdr,out->seglen,out->data);
+		
+	out->dataleft-=out->seglen;
+	out->data+=out->seglen;
+	out->segnum++;
 }
 
 #ifdef CAREFUL_XMIT
@@ -935,49 +1175,30 @@
 }
 #endif
 
-static int
-arcnet_tx(struct device *dev,struct ClientData *hdr,short length,
+static void
+arcnet_prepare_tx(struct device *dev,struct ClientData *hdr,short length,
 		char *data)
 {
-	int ioaddr = dev->base_addr;
-#if 0
+/*	int ioaddr = dev->base_addr;*/
 	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-#endif
 	struct ClientData *arcsoft;
 	union ArcPacket *arcpacket = 
-		(union ArcPacket *)(dev->mem_start+512*TXbuf);
+		(union ArcPacket *)(dev->mem_start+512*(lp->txbuf^1));
 	u_char pkttype;
 	int offset;
 	short daddr;
 	
+	lp->txbuf=lp->txbuf^1;	/* XOR with 1 to alternate between 2 and 3 */
+	
 	length+=sizeof(struct ClientData);
 
 	BUGLVL(D_TX)
-		printk("arcnet: arcnet_tx: hdr:%ph, length:%d, data:%ph\n",
+		printk("arcnet: arcnet_prep_tx: hdr:%ph, length:%d, data:%ph\n",
 			hdr,length,data);
 
-#if 0
-	/* make sure transmitter is available before sending */
-	if (! (inb(STATUS) & TXFREEflag))
-	{
-		BUGLVL(D_TX)
-			printk("arcnet: transmitter in use! (status=%Xh)\n",
-				inb(STATUS));
-		return -EBUSY;
-	}
-#endif
-	/* <blah> Gruesome hack because tx+rx irq's don't work at
-	 * the same time (or so it seems to me)
-	 *
-	 * Our transmits just won't be interrupt driven, I guess. (ugh)
-	 */		
-#ifdef CAREFUL_XMIT
-	careful_xmit_wait(dev);
-#endif
-
 	/* clean out the page to make debugging make more sense :) */
 	BUGLVL(D_DURING)
-		memset((void *)dev->mem_start+TXbuf*512,0x42,512);
+		memset((void *)dev->mem_start+lp->txbuf*512,0x42,512);
 
 	daddr=arcpacket->hardheader.destination=hdr->daddr;
 
@@ -1051,15 +1272,6 @@
 		
 		printk("\n");
 	}
-	
-
-	/* start sending */
-	outb(TXcmd|(TXbuf<<3),COMMAND);
-
-	dev->trans_start = jiffies;
-
-	BUGLVL(D_TX) printk("arcnet: transmit started successfully. (status=%Xh)\n",
-				inb(STATUS));
 #ifdef CAREFUL_XMIT
  #if 0
 	careful_xmit_wait(dev);
@@ -1078,15 +1290,44 @@
 	}
  #endif
 #endif
+	lp->txready=lp->txbuf;	/* packet is ready for sending */
 
-	return 0;
+#if 0
+#ifdef IRQ_XMIT
+	if (inb(STATUS)&TXFREEflag) arcnet_go_tx(dev);
+#endif
+#endif
+}
+
+static void
+arcnet_go_tx(struct device *dev)
+{
+	struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
+	int ioaddr=dev->base_addr;
+
+	BUGLVL(D_DURING)
+		printk("arcnet: go_tx: status=%Xh\n",
+			inb(STATUS));
+	
+	if (!(inb(STATUS)&TXFREEflag) || !lp->txready) return;
+
+	/* start sending */
+	outb(TXcmd|(lp->txready<<3),COMMAND);
+
+#ifdef IRQ_XMIT
+	outb(TXFREEflag|NORXflag,INTMASK);
+#endif
+
+	dev->trans_start = jiffies;
+	lp->txready=0;
+	lp->sending++;
 }
 
 
 /* The typical workload of the driver:
    Handle the network interface interrupts. */
 static void
-arcnet_interrupt(int irq, struct pt_regs *regs)
+arcnet_interrupt(int irq,struct pt_regs *regs)
 {
 	struct device *dev = (struct device *)(irq2dev_map[irq]);
 
@@ -1103,12 +1344,17 @@
 arcnet_inthandler(struct device *dev)
 {	
 	struct arcnet_local *lp;
-	int ioaddr, status, boguscount = 20;
-
+	int ioaddr, status, boguscount = 3, didsomething;
+	
 	dev->interrupt = 1;
+	sti();
 
 	ioaddr = dev->base_addr;
 	lp = (struct arcnet_local *)dev->priv;
+
+#ifdef IRQ_XMIT
+	outb(0,INTMASK);
+#endif
 	
 	BUGLVL(D_DURING)
 		printk("arcnet: in net_interrupt (status=%Xh)\n",inb(STATUS));
@@ -1116,13 +1362,19 @@
 	do
 	{
 		status = inb(STATUS);
+		didsomething=0;
 	
 		if (!dev->start)
 		{
 			BUGLVL(D_EXTRA)
 				printk("arcnet: ARCnet not yet initialized.  irq ignored. (status=%Xh)\n",
-					inb(STATUS));
-			break;
+					status);
+#ifdef IRQ_XMIT
+			if (!(status&NORXflag))
+				outb(NORXflag,INTMASK);
+#endif
+			dev->interrupt=0;
+			return;
 		}
 	
 		/* RESET flag was enabled - card is resetting and if RX
@@ -1133,7 +1385,8 @@
 			BUGLVL(D_INIT)
 				printk("arcnet: reset irq (status=%Xh)\n",
 					status);
-			break;
+			dev->interrupt=0;
+			return;
 		}
 
 #if 1	/* yes, it's silly to disable this part but it makes good testing */
@@ -1151,40 +1404,99 @@
 		
 			/* Got a packet. */
 			arcnet_rx(dev,!recbuf);
+			
+			didsomething++;
 		}
 #endif
-		
-#if 0  /* this doesn't actually work, and will now zonk everything. leave
-	* disabled until I fix it.
-	*/
-		/* it can only be a xmit-done irq if we're xmitting :) */
-		else if (dev->tbusy && status&TXFREEflag)
+#ifdef IRQ_XMIT
+		/* it can only be an xmit-done irq if we're xmitting :) */
+		if (status&TXFREEflag && !lp->in_txhandler && lp->sending)
 		{
+			struct Outgoing *out=&(lp->outgoing);
+			
+			lp->in_txhandler++;
+			lp->sending--;
+			
 			BUGLVL(D_DURING)
-				printk("arcnet: transmit IRQ?!? (status=%Xh)\n",
-					status);
+				printk("arcnet: TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
+					status,out->numsegs,out->segnum,out->skb);
+					
+			/* send packet if there is one */
+			if (lp->txready)
+			{
+				arcnet_go_tx(dev);
+				didsomething++;
+			}
+			
+			if (lp->intx)
+			{
+				lp->in_txhandler--;
+				continue;
+			}
+
+			if (!lp->outgoing.skb)
+			{
+				BUGLVL(D_DURING)
+					printk("arcnet: TX IRQ done: no split to continue.\n");
+				
+				/* inform upper layers */
+				if (!lp->txready && dev->tbusy)
+				{
+					dev->tbusy=0;
+					mark_bh(NET_BH);
+				}
+				
+				lp->in_txhandler--;
+				continue;
+			}
 			
 			/*lp->stats.tx_packets++;*/
-			dev->tbusy = 0;
-			mark_bh(NET_BH);	/* Inform upper layers. */
 			
-			break;
+			/* if more than one segment, and not all segments
+			 * are done, then continue xmit.
+			 */
+			if (out->segnum<out->numsegs)
+				arcnet_continue_tx(dev);
+			if (lp->txready && !lp->sending)
+				arcnet_go_tx(dev);
+
+			/* if segnum==numsegs, the transmission is finished;
+			 * free the skb.
+			 */
+			if (out->segnum>=out->numsegs)
+			{
+				/* transmit completed */
+				out->segnum++;
+				if (out->skb)
+					dev_kfree_skb(out->skb,FREE_WRITE);
+				out->skb=NULL;
+
+				/* inform upper layers */
+				if (!lp->txready && dev->tbusy)
+				{
+					dev->tbusy=0;
+					mark_bh(NET_BH);
+				}
+			}
+			didsomething++;
+			
+			lp->in_txhandler--;
 		}
-		else
-			break;
-#endif
+#endif /* IRQ_XMIT */
+	} while (--boguscount && didsomething);
 
-#if 0
-		break;	/* delete me */
-#endif
-	} while (--boguscount);
-	
 	BUGLVL(D_DURING)
 		printk("arcnet: net_interrupt complete (status=%Xh)\n",
 			inb(STATUS));
-	
+
+#ifdef IRQ_XMIT
+	if (dev->start && lp->sending )
+		outb(NORXflag|TXFREEflag,INTMASK);
+	else
+		outb(NORXflag,INTMASK);
+#endif
+
 	dev->interrupt=0;
-	return;
 }
 
 /* A packet has arrived; grab it from the buffers and possibly unsplit it.
@@ -1350,9 +1662,9 @@
 	          * process should be aborted.
 	          *
 	          * The RFC also mentions "it is possible for successfully
-	          * received packets to be retransmitted."  I'm hoping this
-	          * means only the most recent one, which is the only one
-	          * currently allowed.
+	          * received packets to be retransmitted."  As of 0.40 all
+	          * previously received packets are allowed, not just the
+	          * most recent one.
 	          *
 	          * We allow multiple assembly processes, one for each
 	          * ARCnet card possible on the network.  Seems rather like
@@ -1372,7 +1684,6 @@
 	        	kfree_skb(in->skb,FREE_WRITE);
 	        	in->skb=NULL;
 	        	in->lastpacket=in->numpackets=0;
-	        	return;
 	        }
 	          
 	        if (arcsoft->split_flag & 1)	/* first packet in split */
@@ -1449,7 +1760,7 @@
 	        	if (packetnum!=in->lastpacket) /* not the right flag! */
 	        	{
 				/* harmless duplicate? ignore. */
-				if (packetnum==in->lastpacket-1)
+				if (packetnum<=in->lastpacket-1)
 				{
 					BUGLVL(D_INIT) printk("arcnet: duplicate splitpacket ignored! (splitflag=%d)\n",
 						arcsoft->split_flag);
@@ -1519,7 +1830,7 @@
 }
 
 
-
+#ifdef USE_TIMER_HANDLER
 /* this function is called every once in a while to make sure the ARCnet
  * isn't stuck.
  *
@@ -1553,7 +1864,7 @@
 	lp->timer.expires=TIMERval;
 	add_timer(&lp->timer);
 }
-
+#endif
 
 /* Get the current statistics.	This may be called with the card open or
    closed. */
@@ -1601,7 +1912,8 @@
 	inb(RESET);		/* Reset by reading this port */
 	JIFFER(RESETtime);
 
-	outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND); /* clear flags & end reset */
+	outb(CFLAGScmd|RESETclear, COMMAND); /* clear flags & end reset */
+	outb(CFLAGScmd|CONFIGclear,COMMAND);
 
 	/* after a reset, the first byte of shared mem is TESTvalue and the
 	 * second byte is our 8-bit ARCnet address
@@ -1619,18 +1931,12 @@
 	
 	/* clear out status variables */
 	recbuf=lp->recbuf=0;
-	dev->tbusy=0;
-
-	/* enable IRQ's on completed receive
-	 * I messed around for a long time, but I couldn't get tx and rx
-	 * irq's to work together.  It looks like one or the other but not
-	 * both... <sigh>.  The Crynwr driver uses only rx, and so do I now.
-	 */
-	outb(NORXflag,INTMASK);
+	lp->txbuf=2;
+	/*dev->tbusy=0;*/
 
 	/* enable extended (512-byte) packets */
 	outb(CONFIGcmd|EXTconf,COMMAND);
-	JIFFER(ACKtime);
+	XJIFFER(ACKtime);
 	
 	/* clean out all the memory to make debugging make more sense :) */
 	BUGLVL(D_DURING)
@@ -1638,6 +1944,9 @@
 	
 	/* and enable receive of our first packet to the first buffer */
 	EnableReceiver();
+
+	/* re-enable interrupts */
+	outb(NORXflag,INTMASK);
 	
 	/* done!  return success. */
 	return 0;
@@ -1668,6 +1977,9 @@
 	case ETH_P_RARP:
 		head->protocol_id=ARC_P_RARP;
 		break;
+	case ETH_P_IPX:
+		head->protocol_id=ARC_P_IPX;
+		break;
 	default:
 		printk("arcnet: I don't understand protocol %d (%Xh)\n",
 			type,type);
@@ -1782,12 +2094,12 @@
 	/* now return the protocol number */
 	switch (head->protocol_id)
 	{
-	case ARC_P_IP:		return htons(ETH_P_IP); /* what the heck is
-							 an htons, anyway? */
+	case ARC_P_IP:		return htons(ETH_P_IP);
 	case ARC_P_ARP:		return htons(ETH_P_ARP);
 	case ARC_P_RARP:	return htons(ETH_P_RARP);
-	case 0xFA:		/* IPX */
-	case 0xDD:		/* Appletalk */
+	case ARC_P_IPX:		return htons(ETH_P_IPX);
+	case ARC_P_LANSOFT: /* don't understand.  fall through. */
+	case ARC_P_ATALK:   /* appletalk - don't understand.  fall through. */
 	default:
 		BUGLVL(D_DURING)
 			printk("arcnet: received packet of unknown protocol id %d (%Xh)\n",
@@ -1811,6 +2123,59 @@
 
 	return htons(ETH_P_IP);
 }
+
+#ifdef MODULE
+char kernel_version[] = UTS_RELEASE;
+static struct device thisARCnet = {
+  "      ",/* if blank, device name inserted by /linux/drivers/net/net_init.c */
+  0, 0, 0, 0,
+  0, 0,  /* I/O address, IRQ */
+  0, 0, 0, NULL, arcnet_probe };
+	
+	
+int io=0x0;	/* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
+int irqnum=0;	/* or use the insmod io= irq= shmem= options */
+int shmem=0;
+int num=0;	/* number of device (ie for arc0, arc1, arc2...) */
+
+int
+init_module(void)
+{
+	sprintf(thisARCnet.name,"arc%d",num);
+
+	thisARCnet.base_addr=io;
+
+	thisARCnet.irq=irqnum;
+	if (thisARCnet.irq==2) thisARCnet.irq=9;
+
+	if (shmem)
+	{
+		thisARCnet.mem_start=shmem;
+		thisARCnet.mem_end=thisARCnet.mem_start+512*4-1;
+		thisARCnet.rmem_start=thisARCnet.mem_start+512*0;
+		thisARCnet.rmem_end=thisARCnet.mem_start+512*2-1;
+	}
+
+	if (register_netdev(&thisARCnet) != 0)
+		return -EIO;
+	return 0;
+}
+
+void
+cleanup_module(void)
+{
+  if (MOD_IN_USE) {
+    printk("%s: device busy, remove delayed\n",thisARCnet.name);
+  } else {
+    if (thisARCnet.start) arcnet_close(&thisARCnet);
+    if (thisARCnet.irq) free_irq(thisARCnet.irq);
+    if (thisARCnet.base_addr) release_region(thisARCnet.base_addr,
+    						ETHERCARD_TOTAL_SIZE);
+    unregister_netdev(&thisARCnet);
+  }
+}
+
+#endif /* MODULE */
 
 
 
diff -u --recursive --new-file v1.1.94/linux/drivers/net/depca.c linux/drivers/net/depca.c
--- v1.1.94/linux/drivers/net/depca.c	Wed Feb 15 10:36:38 1995
+++ linux/drivers/net/depca.c	Thu Feb 23 10:51:12 1995
@@ -171,11 +171,13 @@
       0.38axp 15-sep-94   Special version for Alpha AXP Linux V1.0.
       0.381   12-dec-94   Added DE101 recognition, fix multicast bug.
       0.382    9-feb-95   Fix recognition bug reported by <bkm@star.rl.ac.uk>.
+      0.383   22-feb-95   Fix for conflict with VESA SCSI reported by
+                          <stromain@alf.dec.com>
 
     =========================================================================
 */
 
-static char *version = "depca.c:v0.382 2/9/94 davies@wanton.lkg.dec.com\n";
+static char *version = "depca.c:v0.383 2/22/94 davies@wanton.lkg.dec.com\n";
 
 #include <linux/config.h>
 #ifdef MODULE
@@ -333,15 +335,16 @@
 /*
 ** Private functions
 */
-static int depca_probe1(struct device *dev, short ioaddr);
+static int  depca_probe1(struct device *dev, short ioaddr);
 static void depca_init_ring(struct device *dev);
-static int depca_rx(struct device *dev);
-static int depca_tx(struct device *dev);
+static int  depca_rx(struct device *dev);
+static int  depca_tx(struct device *dev);
 
 static void LoadCSRs(struct device *dev);
-static int InitRestartDepca(struct device *dev);
+static int  InitRestartDepca(struct device *dev);
 static char *DepcaSignature(unsigned long mem_addr);
-static int DevicePresent(short ioaddr);
+static int  DevicePresent(short ioaddr);
+static int  EISA_signature(short iobase);
 #ifdef HAVE_MULTICAST
 static void SetMulticastFilter(int num_addrs, char *addrs, char *multicast_table);
 #endif
@@ -1346,7 +1349,7 @@
   ioaddr+=0x1000;                         /* get the first slot address */
   for (status = -ENODEV, i=1; i<MAX_EISA_SLOTS; i++, ioaddr+=0x1000) {
 
-    if (DevicePresent(ioaddr) == 0) {
+    if (EISA_signature(DEPCA_EISA_ID) == 0) {
       if (num_depcas > 0) {        /* only gets here in autoprobe */
 	dev = alloc_device(dev, ioaddr);
       } else {
@@ -1501,6 +1504,40 @@
   }
 
   return status;
+}
+
+/*
+** Look for a particular board name in the EISA configuration space
+*/
+static int EISA_signature(short iobase)
+{
+  unsigned long i;
+  int status;
+  char *signatures[] = DEPCA_SIGNATURE;
+  char ManCode[8];
+  union {
+    u_long ID;
+    u_char Id[4];
+  } Eisa;
+
+  for (i=0; i<4; i++) {
+    Eisa.Id[i] = inb(iobase + i);
+  }
+
+  ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40);
+  ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40);
+  ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30);
+  ManCode[3]=((Eisa.Id[2]&0x0f)+0x30);
+  ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30);
+  ManCode[5]='\0';
+
+  for (status = -ENXIO, i=0;*signatures[i] != '\0' && status;i++) {
+    if (strstr(ManCode, signatures[i]) != NULL) {
+      status = 0;
+    }
+  }
+  
+  return status;                            /* return the device name string */
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v1.1.94/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v1.1.94/linux/drivers/net/ppp.c	Fri Feb 17 11:20:13 1995
+++ linux/drivers/net/ppp.c	Thu Feb 23 13:19:17 1995
@@ -1463,7 +1463,6 @@
   case PPPIOCSASYNCMAP:
     error = verify_area (VERIFY_READ, (void *) l, sizeof (temp_i));
     if (error == 0) {
-      memset (ppp->xmit_async_map, 0, sizeof (ppp->xmit_async_map));
       ppp->xmit_async_map[0] = get_fs_long (l);
       bset (ppp->xmit_async_map, PPP_FLAG);
       bset (ppp->xmit_async_map, PPP_ESC);
diff -u --recursive --new-file v1.1.94/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v1.1.94/linux/drivers/net/slip.c	Sun Feb  5 19:31:53 1995
+++ linux/drivers/net/slip.c	Thu Feb 23 13:27:11 1995
@@ -35,6 +35,7 @@
  *      Dmitry Gorodchanin      :       Even more cleanups. Preserve CSLIP
  *                                      statistics. Include CSLIP code only
  *                                      if it really needed.
+ *		Alan Cox	:	Free slhc buffers in the right place.
  *
  *
  *
@@ -116,6 +117,32 @@
 static inline void
 sl_free(struct slip *sl)
 {
+	/* Free all SLIP frame buffers. */
+	if (sl->rbuff)  {
+		kfree(sl->rbuff);
+	}
+	sl->rbuff = NULL;
+	if (sl->xbuff)  {
+		kfree(sl->xbuff);
+	}
+	sl->xbuff = NULL;
+#ifdef SL_INCLUDE_CSLIP
+	/* Save CSLIP statistics */
+	if (sl->slcomp)  {
+		sl->rx_compressed += sl->slcomp->sls_i_compressed;
+		sl->rx_dropped    += sl->slcomp->sls_i_tossed;
+		sl->tx_compressed += sl->slcomp->sls_o_compressed;
+		sl->tx_misses     += sl->slcomp->sls_o_misses;
+	}
+	if (sl->cbuff)  {
+		kfree(sl->cbuff);
+	}
+	sl->cbuff = NULL;
+	if(sl->slcomp)
+		slhc_free(sl->slcomp);
+	sl->slcomp = NULL;
+#endif
+
 	if (!clear_bit(SLF_INUSE, &sl->flags)) {
 		printk("%s: sl_free for already free unit.\n", sl->dev->name);
 	}
@@ -581,30 +608,6 @@
 	
 /*	dev->flags &= ~IFF_UP; */
 
-	/* Free all SLIP frame buffers. */
-	if (sl->rbuff)  {
-		kfree(sl->rbuff);
-	}
-	sl->rbuff = NULL;
-	if (sl->xbuff)  {
-		kfree(sl->xbuff);
-	}
-	sl->xbuff = NULL;
-#ifdef SL_INCLUDE_CSLIP
-	/* Save CSLIP statistics */
-	if (sl->slcomp)  {
-		sl->rx_compressed += sl->slcomp->sls_i_compressed;
-		sl->rx_dropped    += sl->slcomp->sls_i_tossed;
-		sl->tx_compressed += sl->slcomp->sls_o_compressed;
-		sl->tx_misses     += sl->slcomp->sls_o_misses;
-	}
-	if (sl->cbuff)  {
-		kfree(sl->cbuff);
-	}
-	sl->cbuff = NULL;
-	slhc_free(sl->slcomp);
-	sl->slcomp = NULL;
-#endif
 	return 0;
 }
 
diff -u --recursive --new-file v1.1.94/linux/drivers/scsi/qlogic.c linux/drivers/scsi/qlogic.c
--- v1.1.94/linux/drivers/scsi/qlogic.c	Mon Feb 20 21:34:55 1995
+++ linux/drivers/scsi/qlogic.c	Thu Feb 23 13:32:05 1995
@@ -18,7 +18,7 @@
    Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994
    (you can reference it, but it is incomplete and inaccurate in places)
 
-   Version 0.40a
+   Version 0.41
 
    Functions as standalone, loadable, and PCMCIA driver, the latter from
    Dave Hind's PCMCIA package.
@@ -37,6 +37,9 @@
    again, 0 tends to be slower, but more stable.  */
 #define QL_TURBO_PDMA 1
 
+/* This should be 1 to enable parity detection */
+#define QL_ENABLE_PARITY 1
+
 /* This will reset all devices when the driver is initialized (during bootup).
    The other linux drivers don't do this, but the DOS drivers do, and after
    using DOS or some kind of crash or lockup this will bring things back
@@ -45,31 +48,42 @@
    recognized when this was set. */
 #define QL_RESET_AT_START 0
 
-/* crystal frequency in megahertz (for offset 5 and 9) */
+/* crystal frequency in megahertz (for offset 5 and 9)
+   Please set this for your card.  Most Qlogic cards are 40 Mhz.  The
+   Control Concepts ISA (not VLB) is 24 Mhz */
 #define XTALFREQ	40
 
-/*****/
-/* offset 0xc */
-/* This will set fast (10Mhz) synchronous timing when set to 1
-   FASTCLK must also be 0 */
-#define FASTSCSI  0
-
-/* This when set to 1 will set a faster sync transfer rate */
-#define FASTCLK   0
+/**********/
+/* DANGER! modify these at your own risk */
+/* SLOWCABLE can usually be reset to zero if you have a clean setup and
+   proper termination.  The rest are for synchronous transfers and other
+   advanced features if your device can transfer faster than 5Mb/sec.
+   If you are really curious, email me for a quick howto until I have
+   something official */
+/**********/
 
 /*****/
 /* config register 1 (offset 8) options */
 /* This needs to be set to 1 if your cabling is long or noisy */
-#define SLOWCABLE 0
+#define SLOWCABLE 1
 
-/* This should be 1 to enable parity detection */
-#define QL_ENABLE_PARITY 1
+/*****/
+/* offset 0xc */
+/* This will set fast (10Mhz) synchronous timing when set to 1
+   For this to have an effect, FASTCLK must also be 1 */
+#define FASTSCSI 0
+
+/* This when set to 1 will set a faster sync transfer rate */
+#define FASTCLK 0
+/*(XTALFREQ>25?1:0)*/
 
 /*****/
 /* offset 6 */
-/* This is the sync transfer divisor, 40Mhz/X will be the data rate
-	The power on default is 5, the maximum normal value is 5 */
+/* This is the sync transfer divisor, XTALFREQ/X will be the maximum
+   achievable data rate (assuming the rest of the system is capable
+   and set properly) */
 #define SYNCXFRPD 4
+/*(XTALFREQ/5)*/
 
 /*****/
 /* offset 7 */
@@ -164,6 +178,7 @@
 	j = 0;
 	if (phase & 1) {	/* in */
 #if QL_TURBO_PDMA
+rtrc(4)
 		/* empty fifo in large chunks */
 		if( reqlen >= 128 && (inb( qbase + 8 ) & 2) ) { /* full */
 			insl( qbase + 4, request, 32 );
@@ -183,6 +198,7 @@
 		}
 #endif
 		/* until both empty and int (or until reclen is 0) */
+rtrc(7)
 		j = 0;
 		while( reqlen && !( (j & 0x10) && (j & 0xc0) ) ) {
 			/* while bytes to receive and not empty */
@@ -198,6 +214,7 @@
 	}
 	else {	/* out */
 #if QL_TURBO_PDMA
+rtrc(4)
 		if( reqlen >= 128 && inb( qbase + 8 ) & 0x10 ) { /* empty */
 			outsl(qbase + 4, request, 32 );
 			reqlen -= 128;
@@ -216,6 +233,7 @@
 		}
 #endif
 		/* until full and int (or until reclen is 0) */
+rtrc(7)
 		j = 0;
 		while( reqlen && !( (j & 2) && (j & 0xc0) ) ) {
 			/* while bytes to send and not full */
@@ -308,6 +326,7 @@
 struct scatterlist	*sglist;	/* scatter-gather list pointer */
 unsigned int	sgcount;		/* sg counter */
 
+rtrc(1)
 	j = inb(qbase + 6);
 	i = inb(qbase + 5);
 	if (i == 0x20) {
@@ -336,7 +355,7 @@
 	reqlen = cmd->request_bufflen;
 /* note that it won't work if transfers > 16M are requested */
 	if (reqlen && !((phase = inb(qbase + 4)) & 6)) {	/* data phase */
-rtrc(1)
+rtrc(2)
 		outb(reqlen, qbase);			/* low-mid xfer cnt */
 		outb(reqlen >> 8, qbase+1);			/* low-mid xfer cnt */
 		outb(reqlen >> 16, qbase + 0xe);	/* high xfer cnt */
@@ -367,7 +386,6 @@
 	}
 /*** Enter Status (and Message In) Phase ***/
 	k = jiffies + WATCHDOG;
-rtrc(4)
 	while ( k > jiffies && !qabort && !(inb(qbase + 4) & 6));	/* wait for status phase */
 	if ( k <= jiffies ) {
 		ql_zap();
@@ -389,7 +407,7 @@
 		result = DID_ERROR;
 	}
 	outb(0x12, qbase + 3);	/* done, disconnect */
-rtrc(3)
+rtrc(1)
 	if ((k = ql_wai()))
 		return (k << 16);
 /* should get bus service interrupt and disconnect interrupt */
@@ -573,7 +591,7 @@
 	if( qlirq != -1 )
 		hreg->irq = qlirq;
 
-	sprintf(qinfo, "Qlogic Driver version 0.40a, chip %02X at %03X, IRQ %d, TPdma:%d",
+	sprintf(qinfo, "Qlogic Driver version 0.41, chip %02X at %03X, IRQ %d, TPdma:%d",
 	    qltyp, qbase, qlirq, QL_TURBO_PDMA );
 	host->name = qinfo;
 
diff -u --recursive --new-file v1.1.94/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c
--- v1.1.94/linux/drivers/scsi/seagate.c	Mon Feb 20 21:34:55 1995
+++ linux/drivers/scsi/seagate.c	Thu Feb 23 13:31:41 1995
@@ -283,7 +283,7 @@
  *	First, we try for the manual override.
  */
 #ifdef DEBUG 
-	printk("Autodetecting seagate ST0x\n");
+	printk("Autodetecting ST0x / TMC-8xx\n");
 #endif
 	
 	if (hostno != -1)
@@ -357,39 +357,40 @@
 		borken_init();
 #endif
 		
-		return 1;
-		}
-	else
-		{
-#ifdef DEBUG
-		printk("ST0x not detected.\n");
-#endif
-		return 0;
-		}
-	}
-	 
-const char *seagate_st0x_info(struct Scsi_Host * shpnt) {
-      static char buffer[256];
-        sprintf(buffer, "scsi%d : %s at irq %d address %p options :"
+		printk("%s options:"
 #ifdef ARBITRATE
-" ARBITRATE"
+		" ARBITRATE"
 #endif
 #ifdef SLOW_HANDSHAKE
-" SLOW_HANDSHAKE"
+		" SLOW_HANDSHAKE"
 #endif
 #ifdef FAST
 #ifdef FAST32
-" FAST32"
+		" FAST32"
 #else
-" FAST"
+		" FAST"
 #endif
 #endif
- 
 #ifdef LINKED
-" LINKED"
+		" LINKED"
 #endif
-              "\n", hostno, (controller_type == SEAGATE) ? ST0X_ID_STR : 
-              FD_ID_STR, irq, base_address);
+              "\n", tpnt->name);
+		return 1;
+		}
+	else
+		{
+#ifdef DEBUG
+		printk("ST0x / TMC-8xx not detected.\n");
+#endif
+		return 0;
+		}
+	}
+	 
+const char *seagate_st0x_info(struct Scsi_Host * shpnt) {
+      static char buffer[64];
+        sprintf(buffer, "%s at irq %d, address 0x%05X", 
+		(controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR,
+		irq, (unsigned int)base_address);
         return buffer;
 }
 
diff -u --recursive --new-file v1.1.94/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v1.1.94/linux/drivers/scsi/sr.c	Mon Feb 20 21:34:55 1995
+++ linux/drivers/scsi/sr.c	Thu Feb 23 13:31:41 1995
@@ -352,7 +352,7 @@
       break;
     }
     if (rec[14] != 0 && rec[14] != 0xb0) {
-      printk("sr_photocd: Hmm, seems the CDROM does'nt support multisession CD's\n");
+      printk("sr_photocd: Hmm, seems the CDROM doesn't support multisession CD's\n");
       no_multi = 1;
       break;
     }
@@ -385,13 +385,13 @@
     if (rc != 0) {
       if (rc == 0x28000002) {
 	/* Got a "not ready" - error. No chance to find out if this is
-	   becauce there is no CD in the drive or becauce the drive
+	   because there is no CD in the drive or because the drive
 	   don't knows multisession CD's. So I need to do an extra check... */
 	if (kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
 			      SCSI_IOCTL_TEST_UNIT_READY, NULL)) {
 	  printk("sr_photocd: drive not ready\n");
 	} else {
-	  printk("sr_photocd: Hmm, seems the CDROM does'nt support multisession CD's\n");
+	  printk("sr_photocd: Hmm, seems the CDROM doesn't support multisession CD's\n");
 	  no_multi = 1;
 	}
       } else
diff -u --recursive --new-file v1.1.94/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- v1.1.94/linux/fs/ext2/balloc.c	Wed Nov 30 21:47:39 1994
+++ linux/fs/ext2/balloc.c	Sun Feb 26 18:52:02 1995
@@ -75,7 +75,7 @@
 		ext2_panic (sb, "read_block_bitmap",
 			    "Cannot read block bitmap - "
 			    "block_group = %d, block_bitmap = %lu",
-			    block_group, gdp->bg_block_bitmap);
+			    block_group, (unsigned long) gdp->bg_block_bitmap);
 	sb->u.ext2_sb.s_block_bitmap_number[bitmap_nr] = block_group;
 	sb->u.ext2_sb.s_block_bitmap[bitmap_nr] = bh;
 }
@@ -249,8 +249,8 @@
  * bitmap, and then for any free bit if that fails.
  */
 int ext2_new_block (struct super_block * sb, unsigned long goal,
-		    unsigned long * prealloc_count,
-		    unsigned long * prealloc_block)
+		    u32 * prealloc_count,
+		    u32 * prealloc_block)
 {
 	struct buffer_head * bh;
 	struct buffer_head * bh2;
@@ -577,6 +577,6 @@
 		ext2_error (sb, "ext2_check_blocks_bitmap",
 			    "Wrong free blocks count in super block, "
 			    "stored = %lu, counted = %lu",
-			    es->s_free_blocks_count, bitmap_count);
+			    (unsigned long) es->s_free_blocks_count, bitmap_count);
 	unlock_super (sb);
 }
diff -u --recursive --new-file v1.1.94/linux/fs/ext2/dir.c linux/fs/ext2/dir.c
--- v1.1.94/linux/fs/ext2/dir.c	Fri Oct 21 09:39:35 1994
+++ linux/fs/ext2/dir.c	Sun Feb 26 18:52:02 1995
@@ -92,7 +92,7 @@
 	if (error_msg != NULL)
 		ext2_error (dir->i_sb, function, "bad directory entry: %s\n"
 			    "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
-			    error_msg, offset, de->inode, de->rec_len,
+			    error_msg, offset, (unsigned long) de->inode, de->rec_len,
 			    de->name_len);
 	return error_msg == NULL ? 1 : 0;
 }
diff -u --recursive --new-file v1.1.94/linux/fs/ext2/fsync.c linux/fs/ext2/fsync.c
--- v1.1.94/linux/fs/ext2/fsync.c	Fri Dec 31 11:59:48 1993
+++ linux/fs/ext2/fsync.c	Sun Feb 26 18:52:02 1995
@@ -27,7 +27,7 @@
 #define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
 #define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
 
-static int sync_block (struct inode * inode, unsigned long * block, int wait)
+static int sync_block (struct inode * inode, u32 * block, int wait)
 {
 	struct buffer_head * bh;
 	int tmp;
@@ -55,7 +55,7 @@
 	return 0;
 }
 
-static int sync_iblock (struct inode * inode, unsigned long * iblock, 
+static int sync_iblock (struct inode * inode, u32 * iblock, 
 			struct buffer_head ** bh, int wait) 
 {
 	int rc, tmp;
@@ -94,8 +94,7 @@
 	return err;
 }
 
-static int sync_indirect (struct inode * inode, unsigned long * iblock,
-			  int wait)
+static int sync_indirect (struct inode * inode, u32 * iblock, int wait)
 {
 	int i;
 	struct buffer_head * ind_bh;
@@ -107,7 +106,7 @@
 	
 	for (i = 0; i < addr_per_block; i++) {
 		rc = sync_block (inode, 
-				 ((unsigned long *) ind_bh->b_data) + i,
+				 ((u32 *) ind_bh->b_data) + i,
 				 wait);
 		if (rc > 0)
 			break;
@@ -118,8 +117,7 @@
 	return err;
 }
 
-static int sync_dindirect (struct inode * inode, unsigned long * diblock,
-			   int wait)
+static int sync_dindirect (struct inode * inode, u32 * diblock, int wait)
 {
 	int i;
 	struct buffer_head * dind_bh;
@@ -131,7 +129,7 @@
 	
 	for (i = 0; i < addr_per_block; i++) {
 		rc = sync_indirect (inode,
-				    ((unsigned long *) dind_bh->b_data) + i,
+				    ((u32 *) dind_bh->b_data) + i,
 				    wait);
 		if (rc > 0)
 			break;
@@ -142,8 +140,7 @@
 	return err;
 }
 
-static int sync_tindirect (struct inode * inode, unsigned long * tiblock, 
-			   int wait)
+static int sync_tindirect (struct inode * inode, u32 * tiblock, int wait)
 {
 	int i;
 	struct buffer_head * tind_bh;
@@ -155,7 +152,7 @@
 	
 	for (i = 0; i < addr_per_block; i++) {
 		rc = sync_dindirect (inode,
-				     ((unsigned long *) tind_bh->b_data) + i,
+				     ((u32 *) tind_bh->b_data) + i,
 				     wait);
 		if (rc > 0)
 			break;
diff -u --recursive --new-file v1.1.94/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c
--- v1.1.94/linux/fs/ext2/ialloc.c	Wed Nov 30 21:47:39 1994
+++ linux/fs/ext2/ialloc.c	Sun Feb 26 18:52:02 1995
@@ -74,7 +74,7 @@
 		ext2_panic (sb, "read_inode_bitmap",
 			    "Cannot read inode bitmap - "
 			    "block_group = %lu, inode_bitmap = %lu",
-			    block_group, gdp->bg_inode_bitmap);
+			    block_group, (unsigned long) gdp->bg_inode_bitmap);
 	sb->u.ext2_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
 	sb->u.ext2_sb.s_inode_bitmap[bitmap_nr] = bh;
 }
@@ -549,6 +549,6 @@
 		ext2_error (sb, "ext2_check_inodes_bitmap",
 			    "Wrong free inodes count in super block, "
 			    "stored = %lu, counted = %lu",
-			    es->s_free_inodes_count, bitmap_count);
+			    (unsigned long) es->s_free_inodes_count, bitmap_count);
 	unlock_super (sb);
 }
diff -u --recursive --new-file v1.1.94/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v1.1.94/linux/fs/ext2/inode.c	Thu Jan 26 07:49:07 1995
+++ linux/fs/ext2/inode.c	Sun Feb 26 18:52:02 1995
@@ -46,7 +46,7 @@
 
 	if (!bh)
 		return 0;
-	tmp = ((unsigned long *) bh->b_data)[nr];
+	tmp = ((u32 *) bh->b_data)[nr];
 	brelse (bh);
 	return tmp;
 }
@@ -182,8 +182,8 @@
 static struct buffer_head * inode_getblk (struct inode * inode, int nr,
 					  int create, int new_block, int * err)
 {
+	u32 * p;
 	int tmp, goal = 0;
-	unsigned long * p;
 	struct buffer_head * result;
 	int blocks = inode->i_sb->s_blocksize / 512;
 
@@ -250,7 +250,7 @@
 					  int new_block, int * err)
 {
 	int tmp, goal = 0;
-	unsigned long * p;
+	u32 * p;
 	struct buffer_head * result;
 	int blocks = inode->i_sb->s_blocksize / 512;
 
@@ -264,7 +264,7 @@
 			return NULL;
 		}
 	}
-	p = (unsigned long *) bh->b_data + nr;
+	p = (u32 *) bh->b_data + nr;
 repeat:
 	tmp = *p;
 	if (tmp) {
@@ -287,8 +287,8 @@
 		goal = inode->u.ext2_i.i_next_alloc_goal;
 	if (!goal) {
 		for (tmp = nr - 1; tmp >= 0; tmp--) {
-			if (((unsigned long *) bh->b_data)[tmp]) {
-				goal = ((unsigned long *)bh->b_data)[tmp];
+			if (((u32 *) bh->b_data)[tmp]) {
+				goal = ((u32 *)bh->b_data)[tmp];
 				break;
 			}
 		}
@@ -325,7 +325,7 @@
 					  int nr,
 					  int blocksize)
 {
-	unsigned long * p;
+	u32 * p;
 	int firstblock = 0;
 	int result = 0;
 	int i;
@@ -338,7 +338,7 @@
 	if(nr + 3 > EXT2_ADDR_PER_BLOCK(inode->i_sb)) goto out;
 
 	for(i=0; i< (PAGE_SIZE / inode->i_sb->s_blocksize); i++) {
-	  p = (unsigned long *) bh->b_data + nr + i;
+	  p = (u32 *) bh->b_data + nr + i;
 	  
 	  /* All blocks in cluster must already be allocated */
 	  if(*p == 0) goto out;
@@ -346,9 +346,9 @@
 	  /* See if aligned correctly */
 	  if(i==0) firstblock = *p;
 	  else if(*p != firstblock + i) goto out;
-	};
+	}
 	
-	p = (unsigned long *) bh->b_data + nr;
+	p = (u32 *) bh->b_data + nr;
 	result = generate_cluster(bh->b_dev, (int *) p, blocksize);
 
       out:
diff -u --recursive --new-file v1.1.94/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v1.1.94/linux/fs/ext2/super.c	Fri Nov  4 12:38:45 1994
+++ linux/fs/ext2/super.c	Sun Feb 26 18:52:02 1995
@@ -360,7 +360,7 @@
 			ext2_error (sb, "ext2_check_descriptors",
 				    "Block bitmap for group %d"
 				    " not in group (block %lu)!",
-				    i, gdp->bg_block_bitmap);
+				    i, (unsigned long) gdp->bg_block_bitmap);
 			return 0;
 		}
 		if (gdp->bg_inode_bitmap < block ||
@@ -369,7 +369,7 @@
 			ext2_error (sb, "ext2_check_descriptors",
 				    "Inode bitmap for group %d"
 				    " not in group (block %lu)!",
-				    i, gdp->bg_inode_bitmap);
+				    i, (unsigned long) gdp->bg_inode_bitmap);
 			return 0;
 		}
 		if (gdp->bg_inode_table < block ||
@@ -379,7 +379,7 @@
 			ext2_error (sb, "ext2_check_descriptors",
 				    "Inode table for group %d"
 				    " not in group (block %lu)!",
-				    i, gdp->bg_inode_table);
+				    i, (unsigned long) gdp->bg_inode_table);
 			return 0;
 		}
 		block += EXT2_BLOCKS_PER_GROUP(sb);
diff -u --recursive --new-file v1.1.94/linux/fs/ext2/truncate.c linux/fs/ext2/truncate.c
--- v1.1.94/linux/fs/ext2/truncate.c	Fri Aug 19 13:42:54 1994
+++ linux/fs/ext2/truncate.c	Sun Feb 26 18:52:02 1995
@@ -45,8 +45,8 @@
 
 static int trunc_direct (struct inode * inode)
 {
+	u32 * p;
 	int i, tmp;
-	unsigned long * p;
 	struct buffer_head * bh;
 	unsigned long block_to_free = 0;
 	unsigned long free_count = 0;
@@ -102,12 +102,12 @@
 	return retry;
 }
 
-static int trunc_indirect (struct inode * inode, int offset, unsigned long * p)
+static int trunc_indirect (struct inode * inode, int offset, u32 * p)
 {
 	int i, tmp;
 	struct buffer_head * bh;
 	struct buffer_head * ind_bh;
-	unsigned long * ind;
+	u32 * ind;
 	unsigned long block_to_free = 0;
 	unsigned long free_count = 0;
 	int retry = 0;
@@ -134,7 +134,7 @@
 			i = 0;
 		if (i < indirect_block)
 			goto repeat;
-		ind = i + (unsigned long *) ind_bh->b_data;
+		ind = i + (u32 *) ind_bh->b_data;
 		tmp = *ind;
 		if (!tmp)
 			continue;
@@ -176,7 +176,7 @@
 	}
 	if (free_count > 0)
 		ext2_free_blocks (inode->i_sb, block_to_free, free_count);
-	ind = (unsigned long *) ind_bh->b_data;
+	ind = (u32 *) ind_bh->b_data;
 	for (i = 0; i < addr_per_block; i++)
 		if (*(ind++))
 			break;
@@ -199,11 +199,11 @@
 }
 
 static int trunc_dindirect (struct inode * inode, int offset,
-			    unsigned long * p)
+			    u32 * p)
 {
 	int i, tmp;
 	struct buffer_head * dind_bh;
-	unsigned long * dind;
+	u32 * dind;
 	int retry = 0;
 	int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
 	int blocks = inode->i_sb->s_blocksize / 512;
@@ -228,7 +228,7 @@
 			i = 0;
 		if (i < dindirect_block)
 			goto repeat;
-		dind = i + (unsigned long *) dind_bh->b_data;
+		dind = i + (u32 *) dind_bh->b_data;
 		tmp = *dind;
 		if (!tmp)
 			continue;
@@ -236,7 +236,7 @@
 					  dind);
 		mark_buffer_dirty(dind_bh, 1);
 	}
-	dind = (unsigned long *) dind_bh->b_data;
+	dind = (u32 *) dind_bh->b_data;
 	for (i = 0; i < addr_per_block; i++)
 		if (*(dind++))
 			break;
@@ -262,7 +262,7 @@
 {
 	int i, tmp;
 	struct buffer_head * tind_bh;
-	unsigned long * tind, * p;
+	u32 * tind, * p;
 	int retry = 0;
 	int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
 	int blocks = inode->i_sb->s_blocksize / 512;
@@ -289,13 +289,13 @@
 			i = 0;
 		if (i < tindirect_block)
 			goto repeat;
-		tind = i + (unsigned long *) tind_bh->b_data;
+		tind = i + (u32 *) tind_bh->b_data;
 		retry |= trunc_dindirect(inode, EXT2_NDIR_BLOCKS +
 			addr_per_block + (i + 1) * addr_per_block * addr_per_block,
 			tind);
 		mark_buffer_dirty(tind_bh, 1);
 	}
-	tind = (unsigned long *) tind_bh->b_data;
+	tind = (u32 *) tind_bh->b_data;
 	for (i = 0; i < addr_per_block; i++)
 		if (*(tind++))
 			break;
@@ -331,10 +331,10 @@
 		down(&inode->i_sem);
 		retry = trunc_direct(inode);
 		retry |= trunc_indirect (inode, EXT2_IND_BLOCK,
-			(unsigned long *) &inode->u.ext2_i.i_data[EXT2_IND_BLOCK]);
+			(u32 *) &inode->u.ext2_i.i_data[EXT2_IND_BLOCK]);
 		retry |= trunc_dindirect (inode, EXT2_IND_BLOCK +
 			EXT2_ADDR_PER_BLOCK(inode->i_sb),
-			(unsigned long *) &inode->u.ext2_i.i_data[EXT2_DIND_BLOCK]);
+			(u32 *) &inode->u.ext2_i.i_data[EXT2_DIND_BLOCK]);
 		retry |= trunc_tindirect (inode);
 		up(&inode->i_sem);
 		if (!retry)
diff -u --recursive --new-file v1.1.94/linux/fs/msdos/inode.c linux/fs/msdos/inode.c
--- v1.1.94/linux/fs/msdos/inode.c	Thu Jan 26 07:49:08 1995
+++ linux/fs/msdos/inode.c	Sun Feb 26 18:52:02 1995
@@ -275,7 +275,7 @@
 		    MSDOS_SB(sb)->fats,MSDOS_SB(sb)->fat_start,MSDOS_SB(sb)->
 		    fat_length,MSDOS_SB(sb)->dir_start,MSDOS_SB(sb)->dir_entries,
 		    MSDOS_SB(sb)->data_start,CF_LE_W(*(unsigned short *) &b->
-		    sectors),b->total_sect,logical_sector_size);
+		    sectors),(unsigned long)b->total_sect,logical_sector_size);
 		printk ("Transaction block size = %d\n",blksize);
 	}
 	if (error) {
diff -u --recursive --new-file v1.1.94/linux/fs/proc/array.c linux/fs/proc/array.c
--- v1.1.94/linux/fs/proc/array.c	Fri Feb 17 11:20:16 1995
+++ linux/fs/proc/array.c	Thu Feb 23 13:31:41 1995
@@ -277,7 +277,7 @@
 {
 #ifdef __i386__
 	char *model[2][9]={{"DX","SX","DX/2","4","SX/2","6",
-				"7","DX/4"},
+				"DX/2-WB","DX/4"},
 			{"Pentium 60/66","Pentium 90/100","3",
 				"4","5","6","7","8"}};
 	char mask[2];
diff -u --recursive --new-file v1.1.94/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h
--- v1.1.94/linux/include/asm-alpha/pgtable.h	Wed Feb 22 16:53:05 1995
+++ linux/include/asm-alpha/pgtable.h	Thu Mar  2 09:04:40 1995
@@ -22,10 +22,12 @@
 /*
  * entries per page directory level: the alpha is three-level, with
  * all levels having a one-page page table.
+ *
+ * The PGD is special: the last entry is reserved for self-mapping.
  */
 #define PTRS_PER_PTE	(1UL << (PAGE_SHIFT-3))
 #define PTRS_PER_PMD	(1UL << (PAGE_SHIFT-3))
-#define PTRS_PER_PGD	(1UL << (PAGE_SHIFT-3))
+#define PTRS_PER_PGD	((1UL << (PAGE_SHIFT-3))-1)
 
 /* the no. of pointers that fit on a page: this will go away */
 #define PTRS_PER_PAGE	(1UL << (PAGE_SHIFT-3))
@@ -158,7 +160,7 @@
 
 extern inline int pte_none(pte_t pte)		{ return !pte_val(pte); }
 extern inline int pte_present(pte_t pte)	{ return pte_val(pte) & _PAGE_VALID; }
-extern inline int pte_inuse(pte_t *ptep)	{ return mem_map[MAP_NR(ptep)] > 1; }
+extern inline int pte_inuse(pte_t *ptep)	{ return mem_map[MAP_NR(ptep)] != 1; }
 extern inline void pte_clear(pte_t *ptep)	{ pte_val(*ptep) = 0; }
 extern inline void pte_reuse(pte_t * ptep)
 {
@@ -169,7 +171,7 @@
 extern inline int pmd_none(pmd_t pmd)		{ return !pmd_val(pmd); }
 extern inline int pmd_bad(pmd_t pmd)		{ return (pmd_val(pmd) & ~_PFN_MASK) != _PAGE_TABLE || pmd_page(pmd) > high_memory; }
 extern inline int pmd_present(pmd_t pmd)	{ return pmd_val(pmd) & _PAGE_VALID; }
-extern inline int pmd_inuse(pmd_t *pmdp)	{ return mem_map[MAP_NR(pmdp)] > 1; }
+extern inline int pmd_inuse(pmd_t *pmdp)	{ return mem_map[MAP_NR(pmdp)] != 1; }
 extern inline void pmd_clear(pmd_t * pmdp)	{ pmd_val(*pmdp) = 0; }
 extern inline void pmd_reuse(pmd_t * pmdp)
 {
@@ -180,7 +182,7 @@
 extern inline int pgd_none(pgd_t pgd)		{ return !pgd_val(pgd); }
 extern inline int pgd_bad(pgd_t pgd)		{ return (pgd_val(pgd) & ~_PFN_MASK) != _PAGE_TABLE || pgd_page(pgd) > high_memory; }
 extern inline int pgd_present(pgd_t pgd)	{ return pgd_val(pgd) & _PAGE_VALID; }
-extern inline int pgd_inuse(pgd_t *pgdp)	{ return mem_map[MAP_NR(pgdp)] > 1; }
+extern inline int pgd_inuse(pgd_t *pgdp)	{ return mem_map[MAP_NR(pgdp)] != 1; }
 extern inline void pgd_clear(pgd_t * pgdp)	{ pgd_val(*pgdp) = 0; }
 extern inline void pgd_reuse(pgd_t * pgdp)
 {
@@ -212,9 +214,10 @@
 extern inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= __ACCESS_BITS; return pte; }
 extern inline pte_t pte_mkcow(pte_t pte)	{ pte_val(pte) |= _PAGE_COW; return pte; }
 
-/* to set the page-dir */
+/* to set the page-dir. Note the self-mapping in the last entry */
 extern inline void SET_PAGE_DIR(struct task_struct * tsk, pgd_t * pgdir)
 {
+	pgd_val(pgdir[PTRS_PER_PGD]) = pte_val(mk_pte((unsigned long) pgdir, PAGE_KERNEL));
 	tsk->tss.ptbr = ((unsigned long) pgdir - PAGE_OFFSET) >> PAGE_SHIFT;
 	if (tsk == current)
 		invalidate();
@@ -222,23 +225,23 @@
 
 #define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address))
 
-/* to find an entry in a page-table-directory */
+/* to find an entry in a page-table-directory. */
 extern inline pgd_t * pgd_offset(struct task_struct * tsk, unsigned long address)
 {
 	return (pgd_t *) ((tsk->tss.ptbr << PAGE_SHIFT) + PAGE_OFFSET) +
-		((address >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1));
+		((address >> PGDIR_SHIFT) & (PTRS_PER_PAGE - 1));
 }
 
 /* Find an entry in the second-level page table.. */
 extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
 {
-	return (pmd_t *) pgd_page(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
+	return (pmd_t *) pgd_page(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PAGE - 1));
 }
 
 /* Find an entry in the third-level page table.. */
 extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
 {
-	return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+	return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PAGE - 1));
 }
 
 /*              
@@ -373,5 +376,14 @@
 }
 
 extern pgd_t swapper_pg_dir[1024];
+
+/*
+ * The alpha doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ */
+extern inline void update_mmu_cache(struct vm_area_struct * vma,
+	unsigned long address, pte_t pte)
+{
+}
 
 #endif /* _ALPHA_PGTABLE_H */
diff -u --recursive --new-file v1.1.94/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h
--- v1.1.94/linux/include/asm-alpha/processor.h	Wed Feb 15 10:36:39 1995
+++ linux/include/asm-alpha/processor.h	Fri Feb 24 16:41:01 1995
@@ -8,12 +8,9 @@
 #define __ASM_ALPHA_PROCESSOR_H
 
 /*
- * We have a 8GB user address space to start with: 33 bits of vm
- * can be handled with just 2 page table levels.
- *
- * Eventually, this should be bumped to 40 bits or so..
+ * We have a 41-bit user address space: 2TB user VM...
  */
-#define TASK_SIZE (0x200000000UL)
+#define TASK_SIZE (0x20000000000UL)
 
 /*
  * Bus types
@@ -39,6 +36,9 @@
 	unsigned long flags;
 	unsigned long res1, res2;
 };
+
+#define INIT_MMAP { &init_task, 0xfffffc0000300000,  0xfffffc0010000000, \
+	PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC }
 
 #define INIT_TSS  { \
 	0, 0, 0, \
diff -u --recursive --new-file v1.1.94/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h
--- v1.1.94/linux/include/asm-alpha/system.h	Fri Feb 17 11:20:16 1995
+++ linux/include/asm-alpha/system.h	Fri Feb 24 16:41:01 1995
@@ -81,7 +81,12 @@
 
 #define halt() __asm__ __volatile__(".long 0");
 
-#define switch_to(x)		panic("switch_to() not yet done")
+extern void alpha_switch_to(unsigned long pctxp);
+
+#define switch_to(p) do { \
+	current = p; \
+	alpha_switch_to((unsigned long) &(p)->tss - 0xfffffc0000000000); \
+} while (0)
 
 #ifndef mb
 #define mb() __asm__ __volatile__("mb": : :"memory")
diff -u --recursive --new-file v1.1.94/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- v1.1.94/linux/include/asm-alpha/unistd.h	Mon Jan  9 07:22:09 1995
+++ linux/include/asm-alpha/unistd.h	Thu Mar  2 09:04:40 1995
@@ -46,4 +46,96 @@
 	return (type) -1; \
 }
 
+#ifdef __KERNEL_SYSCALLS__
+
+extern unsigned long kernel_fork(void);
+static inline unsigned long fork(void)
+{
+	printk("[%d]fork()\n",current->pid);
+	return kernel_fork();
+}
+
+extern void sys_idle(void);
+static inline void idle(void)
+{
+	printk("[%d]idle()\n",current->pid);
+	sys_idle();
+	for(;;);
+}
+
+extern int sys_setup(void);
+static inline int setup(void)
+{
+	int retval;
+
+	printk("[%d]setup()\n",current->pid);
+	retval = sys_setup();
+	printk("[%d]setup() returned %d\n",current->pid, retval);
+}
+
+extern int sys_open(const char *, int, int);
+static inline int open(const char * name, int mode, int flags)
+{
+	int fd;
+	printk("[%d]open(%s,%d,%d)\n",current->pid, name, mode, flags);
+	fd = sys_open(name, mode, flags);
+	printk("[%d]open(%s,%d,%d)=%d\n",current->pid, name, mode, flags, fd);
+	return fd;
+}
+
+extern int sys_dup(int);
+static inline int dup(int fd)
+{
+	int newfd = sys_dup(fd);
+	printk("[%d]dup(%d)=%d\n",current->pid, fd, newfd);
+	return newfd;
+}
+
+static inline int close(int fd)
+{
+	printk("[%d]close(%d)\n",current->pid,fd);
+	return sys_close(fd);
+}
+
+extern int sys_exit(int);
+static inline int _exit(int value)
+{
+	printk("[%d]_exit(%d)\n", current->pid, value);
+	return sys_exit(value);
+}
+
+#define exit(x) _exit(x)
+
+extern int sys_write(int, const char *, int);
+static inline int write(int fd, const char * buf, int nr)
+{
+	return sys_write(fd, buf, nr);
+}
+
+extern int sys_read(int, char *, int);
+static inline int read(int fd, char * buf, int nr)
+{
+	int res = sys_read(fd, buf, nr);
+	printk("[%d]read(%d,%s,%d)=%d\n",current->pid, fd, buf, nr, res);
+	return res;
+}
+
+#define execve(x,y,z)	({ printk("[%d]execve(%s,%p,%p)\n",current->pid, x, y, z); -1; })
+#define waitpid(x,y,z)	sys_waitpid(x,y,z)
+#define setsid()	({ printk("[%d]setsid()\n",current->pid); -1; })
+#define sync()		({ printk("[%d]sync()\n",current->pid); -1; })
+
+extern int sys_waitpid(int, int *, int);
+static inline pid_t wait(int * wait_stat)
+{
+	long retval, i;
+	printk("[%d]wait(%p)\n", current->pid, wait_stat);
+	retval = waitpid(-1,wait_stat,0);
+	printk("[%d]wait(%p) returned %ld\n", current->pid, wait_stat, retval);
+	for (i = 0; i < 1000000000; i++);
+	return retval;
+}
+
+#endif
+
 #endif /* _ALPHA_UNISTD_H */
diff -u --recursive --new-file v1.1.94/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v1.1.94/linux/include/asm-i386/pgtable.h	Fri Feb 17 11:20:16 1995
+++ linux/include/asm-i386/pgtable.h	Thu Mar  2 09:04:40 1995
@@ -130,7 +130,7 @@
 
 extern inline int pte_none(pte_t pte)		{ return !pte_val(pte); }
 extern inline int pte_present(pte_t pte)	{ return pte_val(pte) & _PAGE_PRESENT; }
-extern inline int pte_inuse(pte_t *ptep)	{ return mem_map[MAP_NR(ptep)] > 1; }
+extern inline int pte_inuse(pte_t *ptep)	{ return mem_map[MAP_NR(ptep)] != 1; }
 extern inline void pte_clear(pte_t *ptep)	{ pte_val(*ptep) = 0; }
 extern inline void pte_reuse(pte_t * ptep)
 {
@@ -154,7 +154,7 @@
 extern inline int pgd_none(pgd_t pgd)		{ return 0; }
 extern inline int pgd_bad(pgd_t pgd)		{ return 0; }
 extern inline int pgd_present(pgd_t pgd)	{ return 1; }
-extern inline int pgd_inuse(pgd_t * pgdp)	{ return mem_map[MAP_NR(pgdp)] > 1; }
+extern inline int pgd_inuse(pgd_t * pgdp)	{ return mem_map[MAP_NR(pgdp)] != 1; }
 extern inline void pgd_clear(pgd_t * pgdp)	{ }
 extern inline void pgd_reuse(pgd_t * pgdp)
 {
@@ -345,5 +345,14 @@
 }
 
 extern pgd_t swapper_pg_dir[1024];
+
+/*
+ * The i386 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ */
+extern inline void update_mmu_cache(struct vm_area_struct * vma,
+	unsigned long address, pte_t pte)
+{
+}
 
 #endif /* _I386_PAGE_H */
diff -u --recursive --new-file v1.1.94/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v1.1.94/linux/include/asm-i386/processor.h	Wed Feb 15 10:36:40 1995
+++ linux/include/asm-i386/processor.h	Fri Feb 24 16:41:01 1995
@@ -112,6 +112,8 @@
 	unsigned long v86flags, v86mask, v86mode;
 };
 
+#define INIT_MMAP { &init_task, 0, 0x40000000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC }
+
 #define INIT_TSS  { \
 	0,0, \
 	sizeof(init_kernel_stack) + (long) &init_kernel_stack, \
diff -u --recursive --new-file v1.1.94/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- v1.1.94/linux/include/asm-i386/unistd.h	Tue Oct 11 09:17:04 1994
+++ linux/include/asm-i386/unistd.h	Fri Feb 24 16:46:58 1995
@@ -84,4 +84,40 @@
 return -1; \
 }
 
+#ifdef __KERNEL_SYSCALLS__
+
+/*
+ * we need this inline - forking from kernel space will result
+ * in NO COPY ON WRITE (!!!), until an execve is executed. This
+ * is no problem, but for the stack. This is handled by not letting
+ * main() use the stack at all after fork(). Thus, no function
+ * calls - which means inline code for fork too, as otherwise we
+ * would use the stack upon exit from 'fork()'.
+ *
+ * Actually only pause and fork are needed inline, so that there
+ * won't be any messing with the stack from main(), but we define
+ * some others too.
+ */
+#define __NR__exit __NR_exit
+static inline _syscall0(int,idle)
+static inline _syscall0(int,fork)
+static inline _syscall0(int,pause)
+static inline _syscall0(int,setup)
+static inline _syscall0(int,sync)
+static inline _syscall0(pid_t,setsid)
+static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+static inline _syscall1(int,dup,int,fd)
+static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
+static inline _syscall1(int,close,int,fd)
+static inline _syscall1(int,_exit,int,exitcode)
+static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
+
+static inline pid_t wait(int * wait_stat)
+{
+	return waitpid(-1,wait_stat,0);
+}
+
+#endif
+
 #endif /* _ASM_I386_UNISTD_H_ */
diff -u --recursive --new-file v1.1.94/linux/include/asm-sparc/asi.h linux/include/asm-sparc/asi.h
--- v1.1.94/linux/include/asm-sparc/asi.h	Mon Jan  9 07:22:10 1995
+++ linux/include/asm-sparc/asi.h	Sun Feb 26 20:46:20 1995
@@ -10,6 +10,11 @@
  * be similar under regular sun4's.
  */
 
+#include <linux/config.h>
+#ifdef CONFIG_SUN4M
+#include "asi4m.h"
+#else
+
 #define ASI_NULL1        0x0
 #define ASI_NULL2        0x1
 
@@ -34,4 +39,5 @@
 #define ASI_FLUSHCTX     0xe
 
 
+#endif /* CONFIG_SUN4M */
 #endif /* _SPARC_ASI_H */
diff -u --recursive --new-file v1.1.94/linux/include/asm-sparc/asi4m.h linux/include/asm-sparc/asi4m.h
--- v1.1.94/linux/include/asm-sparc/asi4m.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/asi4m.h	Sun Feb 26 20:46:20 1995
@@ -0,0 +1,29 @@
+#ifndef _SPARC_ASI4M_H
+#define _SPARC_ASI4M_H
+
+/* asi4m.h: Address Space Identifier values for sun4m
+ 
+   Copyright (C) 1995 Paul Hatchman (paul@sfe.com.au)
+*/
+
+#define ASI_PTE 0x0
+
+#define ASI_NULL1			0x0
+#define ASI_NULL2			0x1
+#define	ASI_CONTROL			0x4	/* hmm? */
+#define	ASI_USERTXT			0x8	/* user text */
+#define	ASI_KERNELTXT		0x9	/* kernel text */
+#define	ASI_USERDATA		0xA	/* user data */
+#define	ASI_KERNELDATA		0xB	/* kernel data */
+
+/* cache flushing */
+#define ASI_FLUSHPG			0x10 
+#define ASI_FLUSHSEG		0x11
+#define ASI_FLUSHRGN		0x12
+#define ASI_FLUSHCTX		0x13
+
+/* MMU REGS */
+#define SRMMU_CTL 0x000
+#define SRMMU_CTP 0x100		/* set/get context pointer */
+#define SRMMU_CTX 0x200 	/* get/set context */
+#endif _SPARC_ASI4M_H
diff -u --recursive --new-file v1.1.94/linux/include/asm-sparc/head.h linux/include/asm-sparc/head.h
--- v1.1.94/linux/include/asm-sparc/head.h	Mon Feb 20 21:34:56 1995
+++ linux/include/asm-sparc/head.h	Sun Feb 26 20:46:20 1995
@@ -12,6 +12,10 @@
 #define INT_ENABLE_REG_PHYSADR      0xf5000000
 #define INTS_ENAB   0x01
 
+#define BOOT_MSG_LEN    61
+#define BOOT_MSG2_LEN   50
+
+
 #define WRITE_PAUSE     nop; nop; nop;
 
 #define PAGE_SIZE       4096
diff -u --recursive --new-file v1.1.94/linux/include/asm-sparc/page.h linux/include/asm-sparc/page.h
--- v1.1.94/linux/include/asm-sparc/page.h	Sun Feb  5 19:31:55 1995
+++ linux/include/asm-sparc/page.h	Wed Mar  1 09:12:33 1995
@@ -20,6 +20,19 @@
 
 #ifdef __KERNEL__
 
+/* The following structure is used to hold the physical
+ * memory configuration of the machine.  This is filled
+ * in probe_memory() and is later used by mem_init() to
+ * set up mem_map[].  We statically allocate 14 of these
+ * structs, this is arbitrary.  The entry after the last
+ * valid one has num_bytes==0.
+ */
+
+struct sparc_phys_banks {
+  unsigned long base_addr;
+  unsigned long num_bytes;
+};
+
 #define CONFIG_STRICT_MM_TYPECHECKS
 
 #ifdef CONFIG_STRICT_MM_TYPECHECKS
@@ -105,17 +118,17 @@
 {
   register unsigned long entry;
 
-  __asm__ __volatile__("lduha [%1] 0x3, %0" : 
+  __asm__ __volatile__("lduba [%1] 0x3, %0" : 
 		       "=r" (entry) :
 		       "r" (addr));
 
-  return entry;
+  return (entry&0x7f);
 }
 
-extern __inline__ void put_segmap(unsigned long* addr, unsigned long entry)
+extern __inline__ void put_segmap(unsigned long addr, unsigned long entry)
 {
 
-  __asm__ __volatile__("stha %1, [%0] 0x3" : : "r" (addr), "r" (entry));
+  __asm__ __volatile__("stba %1, [%0] 0x3" : : "r" (addr), "r" (entry&0x7f));
 
   return;
 }
diff -u --recursive --new-file v1.1.94/linux/include/asm-sparc/pgtable.h linux/include/asm-sparc/pgtable.h
--- v1.1.94/linux/include/asm-sparc/pgtable.h	Mon Feb 20 21:34:56 1995
+++ linux/include/asm-sparc/pgtable.h	Wed Mar  1 09:12:33 1995
@@ -8,12 +8,12 @@
  */
 
 /* PMD_SHIFT determines the size of the area a second-level page table can map */
-#define PMD_SHIFT       22
+#define PMD_SHIFT       18
 #define PMD_SIZE        (1UL << PMD_SHIFT)
 #define PMD_MASK        (~(PMD_SIZE-1))
 
 /* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT       22
+#define PGDIR_SHIFT       18
 #define PGDIR_SIZE        (1UL << PGDIR_SHIFT)
 #define PGDIR_MASK        (~(PGDIR_SIZE-1))
 #define PGDIR_ALIGN(addr) (((addr)+PGDIR_SIZE-1)&PGDIR_MASK)
@@ -48,7 +48,8 @@
 #define _PAGE_VALID     0x80000000   /* valid page */
 #define _PAGE_WRITE     0x40000000   /* can be written to */
 #define _PAGE_PRIV      0x20000000   /* bit to signify privileged page */
-#define _PAGE_REF       0x02000000   /* Page had been accessed/referenced */
+#define _PAGE_NOCACHE   0x10000000   /* non-cacheable page */
+#define _PAGE_REF       0x02000000   /* Page has been accessed/referenced */
 #define _PAGE_DIRTY     0x01000000   /* Page has been modified, is dirty */
 #define _PAGE_COW       0x00800000   /* COW page, hardware ignores this bit (untested) */
 
@@ -71,7 +72,8 @@
 #define PAGE_SHARED     __pgprot(_PAGE_VALID | _PAGE_WRITE | _PAGE_REF)
 #define PAGE_COPY       __pgprot(_PAGE_VALID | _PAGE_REF | _PAGE_COW)
 #define PAGE_READONLY   __pgprot(_PAGE_VALID | _PAGE_REF)
-#define PAGE_KERNEL     __pgprot(_PAGE_VALID | _PAGE_PRIV)
+#define PAGE_KERNEL     __pgprot(_PAGE_VALID | _PAGE_WRITE | _PAGE_NOCACHE | _PAGE_REF | _PAGE_PRIV)
+#define PAGE_INVALID    __pgprot(_PAGE_PRIV)
 
 #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | _PAGE_REF | (x))
 
diff -u --recursive --new-file v1.1.94/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h
--- v1.1.94/linux/include/asm-sparc/processor.h	Wed Feb 15 10:36:40 1995
+++ linux/include/asm-sparc/processor.h	Wed Mar  1 09:12:33 1995
@@ -66,6 +66,9 @@
 	unsigned long float_regs[64]; /* V8 and below have 32, V9 has 64 */
 };
 
+#define INIT_MMAP { &init_task, 0x0, 0x40000000, \
+		      PAGE_SHARED , VM_READ | VM_WRITE | VM_EXEC }
+
 #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, \
diff -u --recursive --new-file v1.1.94/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h
--- v1.1.94/linux/include/asm-sparc/system.h	Wed Feb 22 16:53:06 1995
+++ linux/include/asm-sparc/system.h	Sun Feb 26 20:46:20 1995
@@ -110,12 +110,12 @@
 	unsigned long dummy;
 
 	__asm__ __volatile__(
-		"ld [%1],%2\n\t"
-		"st %0, [%1]\n\t"
+		"ld %1,%2   ! xchg_u32() is here\n\t"
+		"st %0, %1\n\t"
 		"or %%g0, %2, %0"
-		: "=r" (val), "=r" (m), "=r" (dummy)
+		: "=r" (val), "=m" (*m), "=r" (dummy)
 		: "0" (val));
-	return (void *)val;
+	return (void *) val;
 }
 
 
diff -u --recursive --new-file v1.1.94/linux/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h
--- v1.1.94/linux/include/asm-sparc/unistd.h	Mon Jan 16 14:18:25 1995
+++ linux/include/asm-sparc/unistd.h	Wed Mar  1 09:12:33 1995
@@ -124,4 +124,40 @@
 return -1; \
 }
 
+#ifdef __KERNEL_SYSCALLS__
+
+/*
+ * we need this inline - forking from kernel space will result
+ * in NO COPY ON WRITE (!!!), until an execve is executed. This
+ * is no problem, but for the stack. This is handled by not letting
+ * main() use the stack at all after fork(). Thus, no function
+ * calls - which means inline code for fork too, as otherwise we
+ * would use the stack upon exit from 'fork()'.
+ *
+ * Actually only pause and fork are needed inline, so that there
+ * won't be any messing with the stack from main(), but we define
+ * some others too.
+ */
+#define __NR__exit __NR_exit
+static inline _syscall0(int,idle)
+static inline _syscall0(int,fork)
+static inline _syscall0(int,pause)
+static inline _syscall0(int,setup)
+static inline _syscall0(int,sync)
+static inline _syscall0(pid_t,setsid)
+static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+static inline _syscall1(int,dup,int,fd)
+static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
+static inline _syscall1(int,close,int,fd)
+static inline _syscall1(int,_exit,int,exitcode)
+static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
+
+static inline pid_t wait(int * wait_stat)
+{
+	return waitpid(-1,wait_stat,0);
+}
+
+#endif
+
 #endif /* _SPARC_UNISTD_H */
diff -u --recursive --new-file v1.1.94/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h
--- v1.1.94/linux/include/linux/ext2_fs.h	Mon Jan  9 07:22:10 1995
+++ linux/include/linux/ext2_fs.h	Sun Feb 26 18:52:02 1995
@@ -97,7 +97,7 @@
 # define EXT2_BLOCK_SIZE(s)		(EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
 #endif
 #define EXT2_ACLE_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
-#define	EXT2_ADDR_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (unsigned long))
+#define	EXT2_ADDR_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (__u32))
 #ifdef __KERNEL__
 # define EXT2_BLOCK_SIZE_BITS(s)	((s)->u.ext2_sb.s_es->s_log_block_size + 10)
 #else
@@ -124,20 +124,20 @@
  */
 struct ext2_acl_header	/* Header of Access Control Lists */
 {
-	unsigned long aclh_size;
-	unsigned long aclh_file_count;
-	unsigned long aclh_acle_count;
-	unsigned long aclh_first_acle;
+	__u32	aclh_size;
+	__u32	aclh_file_count;
+	__u32	aclh_acle_count;
+	__u32	aclh_first_acle;
 };
 
 struct ext2_acl_entry	/* Access Control List Entry */
 {
-	unsigned long  acle_size;
-	unsigned short acle_perms;	/* Access permissions */
-	unsigned short acle_type;	/* Type of entry */
-	unsigned short acle_tag;	/* User or group identity */
-	unsigned short acle_pad1;
-	unsigned long  acle_next;	/* Pointer on next entry for the */
+	__u32	acle_size;
+	__u16	acle_perms;	/* Access permissions */
+	__u16	acle_type;	/* Type of entry */
+	__u16	acle_tag;	/* User or group identity */
+	__u16	acle_pad1;
+	__u32	acle_next;	/* Pointer on next entry for the */
 					/* same inode or on next free entry */
 };
 
@@ -146,23 +146,23 @@
  */
 struct ext2_old_group_desc
 {
-	unsigned long  bg_block_bitmap;		/* Blocks bitmap block */
-	unsigned long  bg_inode_bitmap;		/* Inodes bitmap block */
-	unsigned long  bg_inode_table;		/* Inodes table block */
-	unsigned short bg_free_blocks_count;	/* Free blocks count */
-	unsigned short bg_free_inodes_count;	/* Free inodes count */
+	__u32	bg_block_bitmap;		/* Blocks bitmap block */
+	__u32	bg_inode_bitmap;		/* Inodes bitmap block */
+	__u32	bg_inode_table;		/* Inodes table block */
+	__u16	bg_free_blocks_count;	/* Free blocks count */
+	__u16	bg_free_inodes_count;	/* Free inodes count */
 };
 
 struct ext2_group_desc
 {
-	unsigned long  bg_block_bitmap;		/* Blocks bitmap block */
-	unsigned long  bg_inode_bitmap;		/* Inodes bitmap block */
-	unsigned long  bg_inode_table;		/* Inodes table block */
-	unsigned short bg_free_blocks_count;	/* Free blocks count */
-	unsigned short bg_free_inodes_count;	/* Free inodes count */
-	unsigned short bg_used_dirs_count;	/* Directories count */
-	unsigned short bg_pad;
-	unsigned long  bg_reserved[3];
+	__u32	bg_block_bitmap;		/* Blocks bitmap block */
+	__u32	bg_inode_bitmap;		/* Inodes bitmap block */
+	__u32	bg_inode_table;		/* Inodes table block */
+	__u16	bg_free_blocks_count;	/* Free blocks count */
+	__u16	bg_free_inodes_count;	/* Free inodes count */
+	__u16	bg_used_dirs_count;	/* Directories count */
+	__u16	bg_pad;
+	__u32	bg_reserved[3];
 };
 
 /*
@@ -210,53 +210,53 @@
  * Structure of an inode on the disk
  */
 struct ext2_inode {
-	unsigned short i_mode;		/* File mode */
-	unsigned short i_uid;		/* Owner Uid */
-	unsigned long  i_size;		/* Size in bytes */
-	unsigned long  i_atime;		/* Access time */
-	unsigned long  i_ctime;		/* Creation time */
-	unsigned long  i_mtime;		/* Modification time */
-	unsigned long  i_dtime;		/* Deletion Time */
-	unsigned short i_gid;		/* Group Id */
-	unsigned short i_links_count;	/* Links count */
-	unsigned long  i_blocks;	/* Blocks count */
-	unsigned long  i_flags;		/* File flags */
+	__u16 i_mode;		/* File mode */
+	__u16 i_uid;		/* Owner Uid */
+	__u32  i_size;		/* Size in bytes */
+	__u32  i_atime;		/* Access time */
+	__u32  i_ctime;		/* Creation time */
+	__u32  i_mtime;		/* Modification time */
+	__u32  i_dtime;		/* Deletion Time */
+	__u16 i_gid;		/* Group Id */
+	__u16 i_links_count;	/* Links count */
+	__u32  i_blocks;	/* Blocks count */
+	__u32  i_flags;		/* File flags */
 	union {
 		struct {
-			unsigned long  l_i_reserved1;
+			__u32  l_i_reserved1;
 		} linux1;
 		struct {
-			unsigned long  h_i_translator;
+			__u32  h_i_translator;
 		} hurd1;
 		struct {
-			unsigned long  m_i_reserved1;
+			__u32  m_i_reserved1;
 		} masix1;
 	} osd1;				/* OS dependent 1 */
-	unsigned long  i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
-	unsigned long  i_version;	/* File version (for NFS) */
-	unsigned long  i_file_acl;	/* File ACL */
-	unsigned long  i_dir_acl;	/* Directory ACL */
-	unsigned long  i_faddr;		/* Fragment address */
+	__u32	i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
+	__u32	i_version;	/* File version (for NFS) */
+	__u32	i_file_acl;	/* File ACL */
+	__u32	i_dir_acl;	/* Directory ACL */
+	__u32	i_faddr;		/* Fragment address */
 	union {
 		struct {
-			unsigned char  l_i_frag;	/* Fragment number */
-			unsigned char  l_i_fsize;	/* Fragment size */
-			unsigned short i_pad1;
-			unsigned long  l_i_reserved2[2];
+			__u8	l_i_frag;	/* Fragment number */
+			__u8	l_i_fsize;	/* Fragment size */
+			__u16	i_pad1;
+			__u32	l_i_reserved2[2];
 		} linux2;
 		struct {
-			unsigned char  h_i_frag;	/* Fragment number */
-			unsigned char  h_i_fsize;	/* Fragment size */
-			unsigned short h_i_mode_high;
-			unsigned short h_i_uid_high;
-			unsigned short h_i_gid_high;
-			unsigned long  h_i_author;
+			__u8	h_i_frag;	/* Fragment number */
+			__u8	h_i_fsize;	/* Fragment size */
+			__u16	h_i_mode_high;
+			__u16	h_i_uid_high;
+			__u16	h_i_gid_high;
+			__u32	h_i_author;
 		} hurd2;
 		struct {
-			unsigned char  m_i_frag;	/* Fragment number */
-			unsigned char  m_i_fsize;	/* Fragment size */
-			unsigned short m_pad1;
-			unsigned long  m_i_reserved2[2];
+			__u8	m_i_frag;	/* Fragment number */
+			__u8	m_i_fsize;	/* Fragment size */
+			__u16	m_pad1;
+			__u32	m_i_reserved2[2];
 		} masix2;
 	} osd2;				/* OS dependent 2 */
 };
@@ -326,32 +326,32 @@
  * Structure of the super block
  */
 struct ext2_super_block {
-	unsigned long  s_inodes_count;	/* Inodes count */
-	unsigned long  s_blocks_count;	/* Blocks count */
-	unsigned long  s_r_blocks_count;/* Reserved blocks count */
-	unsigned long  s_free_blocks_count;/* Free blocks count */
-	unsigned long  s_free_inodes_count;/* Free inodes count */
-	unsigned long  s_first_data_block;/* First Data Block */
-	unsigned long  s_log_block_size;/* Block size */
-	long           s_log_frag_size;	/* Fragment size */
-	unsigned long  s_blocks_per_group;/* # Blocks per group */
-	unsigned long  s_frags_per_group;/* # Fragments per group */
-	unsigned long  s_inodes_per_group;/* # Inodes per group */
-	unsigned long  s_mtime;		/* Mount time */
-	unsigned long  s_wtime;		/* Write time */
-	unsigned short s_mnt_count;	/* Mount count */
-	short          s_max_mnt_count;	/* Maximal mount count */
-	unsigned short s_magic;		/* Magic signature */
-	unsigned short s_state;		/* File system state */
-	unsigned short s_errors;	/* Behaviour when detecting errors */
-	unsigned short s_pad;
-	unsigned long  s_lastcheck;	/* time of last check */
-	unsigned long  s_checkinterval;	/* max. time between checks */
-	unsigned long  s_creator_os;	/* OS */
-	unsigned long  s_rev_level;	/* Revision level */
-	unsigned short s_def_resuid;	/* Default uid for reserved blocks */
-	unsigned short s_def_resgid;	/* Default gid for reserved blocks */
-	unsigned long  s_reserved[235];	/* Padding to the end of the block */
+	__u32	s_inodes_count;		/* Inodes count */
+	__u32	s_blocks_count;		/* Blocks count */
+	__u32	s_r_blocks_count;	/* Reserved blocks count */
+	__u32	s_free_blocks_count;	/* Free blocks count */
+	__u32	s_free_inodes_count;	/* Free inodes count */
+	__u32	s_first_data_block;	/* First Data Block */
+	__u32	s_log_block_size;	/* Block size */
+	__s32	s_log_frag_size;	/* Fragment size */
+	__u32	s_blocks_per_group;	/* # Blocks per group */
+	__u32	s_frags_per_group;	/* # Fragments per group */
+	__u32	s_inodes_per_group;	/* # Inodes per group */
+	__u32	s_mtime;		/* Mount time */
+	__u32	s_wtime;		/* Write time */
+	__u16	s_mnt_count;		/* Mount count */
+	__s16	s_max_mnt_count;	/* Maximal mount count */
+	__u16	s_magic;		/* Magic signature */
+	__u16	s_state;		/* File system state */
+	__u16	s_errors;		/* Behaviour when detecting errors */
+	__u16	s_pad;
+	__u32	s_lastcheck;		/* time of last check */
+	__u32	s_checkinterval;	/* max. time between checks */
+	__u32	s_creator_os;		/* OS */
+	__u32	s_rev_level;		/* Revision level */
+	__u16	s_def_resuid;		/* Default uid for reserved blocks */
+	__u16	s_def_resgid;		/* Default gid for reserved blocks */
+	__u32	s_reserved[235];	/* Padding to the end of the block */
 };
 
 #define EXT2_OS_LINUX		0
@@ -369,10 +369,10 @@
 #define EXT2_NAME_LEN 255
 
 struct ext2_dir_entry {
-	unsigned long  inode;			/* Inode number */
-	unsigned short rec_len;			/* Directory entry length */
-	unsigned short name_len;		/* Name length */
-	char           name[EXT2_NAME_LEN];	/* File name */
+	__u32	inode;			/* Inode number */
+	__u16	rec_len;		/* Directory entry length */
+	__u16	name_len;		/* Name length */
+	char	name[EXT2_NAME_LEN];	/* File name */
 };
 
 /*
@@ -409,7 +409,7 @@
 
 /* balloc.c */
 extern int ext2_new_block (struct super_block *, unsigned long,
-			   unsigned long *, unsigned long *);
+			   __u32 *, __u32 *);
 extern void ext2_free_blocks (struct super_block *, unsigned long,
 			      unsigned long);
 extern unsigned long ext2_count_free_blocks (struct super_block *);
diff -u --recursive --new-file v1.1.94/linux/include/linux/ext2_fs_i.h linux/include/linux/ext2_fs_i.h
--- v1.1.94/linux/include/linux/ext2_fs_i.h	Mon Aug 22 21:16:03 1994
+++ linux/include/linux/ext2_fs_i.h	Sun Feb 26 18:52:02 1995
@@ -19,21 +19,21 @@
  * second extended file system inode data in memory
  */
 struct ext2_inode_info {
-	unsigned long  i_data[15];
-	unsigned long  i_flags;
-	unsigned long  i_faddr;
-	unsigned char  i_frag_no;
-	unsigned char  i_frag_size;
-	unsigned short i_osync;
-	unsigned long  i_file_acl;
-	unsigned long  i_dir_acl;
-	unsigned long  i_dtime;
-	unsigned long  i_version;
-	unsigned long  i_block_group;
-	unsigned long  i_next_alloc_block;
-	unsigned long  i_next_alloc_goal;
-	unsigned long  i_prealloc_block;
-	unsigned long  i_prealloc_count;
+	__u32	i_data[15];
+	__u32	i_flags;
+	__u32	i_faddr;
+	__u8	i_frag_no;
+	__u8	i_frag_size;
+	__u16	i_osync;
+	__u32	i_file_acl;
+	__u32	i_dir_acl;
+	__u32	i_dtime;
+	__u32	i_version;
+	__u32	i_block_group;
+	__u32	i_next_alloc_block;
+	__u32	i_next_alloc_goal;
+	__u32	i_prealloc_block;
+	__u32	i_prealloc_count;
 };
 
 #endif	/* _LINUX_EXT2_FS_I */
diff -u --recursive --new-file v1.1.94/linux/include/linux/fs.h linux/include/linux/fs.h
--- v1.1.94/linux/include/linux/fs.h	Wed Feb 22 16:53:06 1995
+++ linux/include/linux/fs.h	Thu Feb 23 13:32:05 1995
@@ -266,10 +266,10 @@
 };
 
 struct file_lock {
-	struct file_lock *fl_next;	/* singly linked list for this inode (or the free list) */
+	struct file_lock *fl_next;	/* singly linked list for this inode  */
 	struct file_lock *fl_nextlink;	/* doubly linked list of all locks */
-	struct file_lock *fl_prevlink;	/* used to simplify garbage collecting */
-	struct task_struct *fl_owner;	/* NULL if on free list, for sanity checks */
+	struct file_lock *fl_prevlink;	/* used to simplify lock removal */
+	struct task_struct *fl_owner;
 	struct wait_queue *fl_wait;
 	char fl_type;
 	char fl_whence;
diff -u --recursive --new-file v1.1.94/linux/include/linux/in.h linux/include/linux/in.h
--- v1.1.94/linux/include/linux/in.h	Sun Feb  5 19:31:55 1995
+++ linux/include/linux/in.h	Thu Feb 23 13:32:05 1995
@@ -81,7 +81,7 @@
 #define	IN_CLASSB_HOST		(0xffffffff & ~IN_CLASSB_NET)
 #define	IN_CLASSB_MAX		65536
 
-#define	IN_CLASSC(a)		((((long int) (a)) & 0xc0000000) == 0xc0000000)
+#define	IN_CLASSC(a)		((((long int) (a)) & 0xe0000000) == 0xc0000000)
 #define	IN_CLASSC_NET		0xffffff00
 #define	IN_CLASSC_NSHIFT	8
 #define	IN_CLASSC_HOST		(0xffffffff & ~IN_CLASSC_NET)
diff -u --recursive --new-file v1.1.94/linux/include/linux/ip_fw.h linux/include/linux/ip_fw.h
--- v1.1.94/linux/include/linux/ip_fw.h	Sun Feb  5 19:31:55 1995
+++ linux/include/linux/ip_fw.h	Thu Feb 23 13:26:22 1995
@@ -7,6 +7,12 @@
  *
  *	Ported from BSD to Linux,
  *		Alan Cox 22/Nov/1994.
+ *	Merged and included the FreeBSD-Current changes at Ugen's request
+ *	(but hey its a lot cleaner now). Ugen would prefer in some ways
+ *	we waited for his final product but since Linux 1.2.0 is about to
+ *	appear its not practical - Read: It works, its not clean but please
+ *	don't consider it to be his standard of finished work.
+ *		Alan.
  *
  *	All the real work was done by .....
  */
@@ -38,43 +44,46 @@
 
 struct ip_fw 
 {
-	struct ip_fw *next;			/* Next firewall on chain */
-	struct in_addr src, dst;		/* Source and destination IP addr */
-	struct in_addr src_mask, dst_mask;	/* Mask for src and dest IP addr */
-	unsigned short flags;			/* Flags word */
-	unsigned short n_src_p, n_dst_p;        /* # of src ports and # of dst ports */
+	struct ip_fw  *fw_next;			/* Next firewall on chain */
+	struct in_addr fw_src, fw_dst;		/* Source and destination IP addr */
+	struct in_addr fw_smsk, fw_dmsk;	/* Mask for src and dest IP addr */
+	struct in_addr fw_via;			/* IP address of interface "via" */
+	unsigned short fw_flg;			/* Flags word */
+	unsigned short fw_nsp, fw_ndp;          /* N'of src ports and # of dst ports */
 						/* in ports array (dst ports follow */
     						/* src ports; max of 10 ports in all; */
     						/* count of 0 means match all ports) */
 #define IP_FW_MAX_PORTS	10      		/* A reasonable maximum */
-	unsigned short ports[IP_FW_MAX_PORTS];  /* Array of port numbers to match */
-	unsigned long p_cnt,b_cnt;		/* Packet and byte counters */
+	unsigned short fw_pts[IP_FW_MAX_PORTS]; /* Array of port numbers to match */
+	unsigned long  fw_pcnt,fw_bcnt;		/* Packet and byte counters */
 };
 
 /*
  *	Values for "flags" field .
  */
 
-#define IP_FW_F_ALL	0x00	/* This is a universal packet firewall*/
-#define IP_FW_F_TCP	0x01	/* This is a TCP packet firewall      */
-#define IP_FW_F_UDP	0x02	/* This is a UDP packet firewall      */
-#define IP_FW_F_ICMP	0x03	/* This is a ICMP packet firewall     */
-#define IP_FW_F_KIND	0x03	/* Mask to isolate firewall kind      */
-#define IP_FW_F_ACCEPT	0x04	/* This is an accept firewall (as     *
+#define IP_FW_F_ALL	0x000	/* This is a universal packet firewall*/
+#define IP_FW_F_TCP	0x001	/* This is a TCP packet firewall      */
+#define IP_FW_F_UDP	0x002	/* This is a UDP packet firewall      */
+#define IP_FW_F_ICMP	0x003	/* This is a ICMP packet firewall     */
+#define IP_FW_F_KIND	0x003	/* Mask to isolate firewall kind      */
+#define IP_FW_F_ACCEPT	0x004	/* This is an accept firewall (as     *
 				 *         opposed to a deny firewall)*
 				 *                                    */
-#define IP_FW_F_SRNG	0x08	/* The first two src ports are a min  *
+#define IP_FW_F_SRNG	0x008	/* The first two src ports are a min  *
 				 * and max range (stored in host byte *
 				 * order).                            *
 				 *                                    */
-#define IP_FW_F_DRNG	0x10	/* The first two dst ports are a min  *
+#define IP_FW_F_DRNG	0x010	/* The first two dst ports are a min  *
 				 * and max range (stored in host byte *
 				 * order).                            *
 				 * (ports[0] <= port <= ports[1])     *
 				 *                                    */
-#define IP_FW_F_PRN	0x20	/* In verbose mode print this firewall*/
-#define IP_FW_F_BIDIR	0x40	/* For accounting-count two way       */
-#define IP_FW_F_MASK	0x7F	/* All possible flag bits mask        */
+#define IP_FW_F_PRN	0x020	/* In verbose mode print this firewall*/
+#define IP_FW_F_BIDIR	0x040	/* For accounting-count two way       */
+#define IP_FW_F_TCPSYN	0x080	/* For tcp packets-check SYN only     */
+#define IP_FW_F_ICMPRPL 0x100	/* Send back icmp unreachable packet  */
+#define IP_FW_F_MASK	0x1FF	/* All possible flag bits mask        */
 
 /*    
  *	New IP firewall options for [gs]etsockopt at the RAW IP level.
@@ -116,14 +125,14 @@
 extern struct ip_fw *ip_fw_fwd_chain;
 extern int ip_fw_blk_policy;
 extern int ip_fw_fwd_policy;
-extern int ip_fw_chk(struct iphdr *, struct ip_fw *, int);
 extern int ip_fw_ctl(int, void *, int);
 #endif
 #ifdef CONFIG_IP_ACCT
 extern struct ip_fw *ip_acct_chain;
-extern void ip_acct_cnt(struct iphdr *, struct ip_fw *);
+extern int ip_acct_cnt(struct iphdr *, struct device *, struct ip_fw *);
 extern int ip_acct_ctl(int, void *, int);
 #endif
+extern int ip_fw_chk(struct iphdr *, struct device *rif,struct ip_fw *, int);
 #endif /* KERNEL */
 
 #endif /* _IP_FW_H */
diff -u --recursive --new-file v1.1.94/linux/include/linux/keyboard.h linux/include/linux/keyboard.h
--- v1.1.94/linux/include/linux/keyboard.h	Sun Jan  1 19:49:19 1995
+++ linux/include/linux/keyboard.h	Fri Feb 24 21:38:27 1995
@@ -320,6 +320,7 @@
 #define K_DECRCONSOLE	K(KT_SPEC,16)
 #define K_INCRCONSOLE	K(KT_SPEC,17)
 #define K_SPAWNCONSOLE	K(KT_SPEC,18)
+#define K_BARENUMLOCK	K(KT_SPEC,19)
 
 #define K_ALLOCATED	K(KT_SPEC,126) /* dynamically allocated keymap */
 #define K_NOSUCHMAP	K(KT_SPEC,127) /* returned by KDGKBENT */
diff -u --recursive --new-file v1.1.94/linux/include/linux/major.h linux/include/linux/major.h
--- v1.1.94/linux/include/linux/major.h	Fri Feb 17 11:20:16 1995
+++ linux/include/linux/major.h	Thu Feb 23 13:31:40 1995
@@ -36,8 +36,8 @@
  * 16 - sockets
  * 17 - af_unix
  * 18 - af_inet
- * 19 -                                               UNUSED
- * 20 -                                               UNUSED
+ * 19 - cyclades /dev/ttyC*
+ * 20 - cyclades /dev/cub*
  * 21 - scsi generic
  * 22 -                        (at2disk)
  * 23 -                        mitsumi cdrom
@@ -69,7 +69,8 @@
 #define SOCKET_MAJOR	16
 #define AF_UNIX_MAJOR	17
 #define AF_INET_MAJOR	18
-/* unused: 19, 20 */
+#define CYCLADES_MAJOR  19
+#define CYCLADESAUX_MAJOR 20
 #define SCSI_GENERIC_MAJOR 21
 #define IDE1_MAJOR	22
 #define MITSUMI_CDROM_MAJOR 23
diff -u --recursive --new-file v1.1.94/linux/include/linux/mm.h linux/include/linux/mm.h
--- v1.1.94/linux/include/linux/mm.h	Fri Feb 17 11:20:16 1995
+++ linux/include/linux/mm.h	Thu Mar  2 09:04:40 1995
@@ -179,6 +179,7 @@
 extern int remap_page_range(unsigned long from, unsigned long to, unsigned long size, pgprot_t prot);
 extern int zeromap_page_range(unsigned long from, unsigned long size, pgprot_t prot);
 
+extern void handle_mm_fault(struct vm_area_struct *vma, unsigned long address, int write_access);
 extern void do_wp_page(struct vm_area_struct * vma, unsigned long address, int write_access);
 extern void do_no_page(struct vm_area_struct * vma, unsigned long address, int write_access);
 
@@ -204,7 +205,7 @@
 extern void rw_swap_page(int rw, unsigned long nr, char * buf);
 
 /* mmap.c */
-extern int do_mmap(struct file * file, unsigned long addr, unsigned long len,
+extern unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags, unsigned long off);
 extern struct vm_area_struct * find_vma (struct task_struct *, unsigned long);
 extern struct vm_area_struct * find_vma_intersection (struct task_struct *, unsigned long, unsigned long);
diff -u --recursive --new-file v1.1.94/linux/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h
--- v1.1.94/linux/include/linux/msdos_fs.h	Tue Dec 27 08:37:13 1994
+++ linux/include/linux/msdos_fs.h	Sun Feb 26 18:52:02 1995
@@ -62,29 +62,29 @@
 
 
 struct msdos_boot_sector {
-	char ignored[3];	    /* Boot strap short or near jump */
-	char system_id[8];	    /* Name - can be used to special case
-				       partition manager volumes */
-	unsigned char sector_size[2];/* bytes per logical sector */
-	unsigned char cluster_size; /* sectors/cluster */
-	unsigned short reserved;    /* reserved sectors */
-	unsigned char fats;	    /* number of FATs */
-	unsigned char dir_entries[2];/* root directory entries */
-	unsigned char sectors[2];   /* number of sectors */
-	unsigned char media;	    /* media code (unused) */
-	unsigned short fat_length;  /* sectors/FAT */
-	unsigned short secs_track;  /* sectors per track */
-	unsigned short heads;	    /* number of heads */
-	unsigned long hidden;	    /* hidden sectors (unused) */
-	unsigned long total_sect;   /* number of sectors (if sectors == 0) */
+	__s8	ignored[3];	/* Boot strap short or near jump */
+	__s8	system_id[8];	/* Name - can be used to special case
+				   partition manager volumes */
+	__u8	sector_size[2];	/* bytes per logical sector */
+	__u8	cluster_size;	/* sectors/cluster */
+	__u16	reserved;	/* reserved sectors */
+	__u8	fats;		/* number of FATs */
+	__u8	dir_entries[2];	/* root directory entries */
+	__u8	sectors[2];	/* number of sectors */
+	__u8	media;		/* media code (unused) */
+	__u16	fat_length;	/* sectors/FAT */
+	__u16	secs_track;	/* sectors per track */
+	__u16	heads;		/* number of heads */
+	__u32	hidden;		/* hidden sectors (unused) */
+	__u32	total_sect;	/* number of sectors (if sectors == 0) */
 };
 
 struct msdos_dir_entry {
-	char name[8],ext[3]; /* name and extension */
-	unsigned char attr;  /* attribute bits */
-	char unused[10];
-	unsigned short time,date,start; /* time, date and first cluster */
-	unsigned long size;  /* file size (in bytes) */
+	__s8	name[8],ext[3];	/* name and extension */
+	__u8	attr;		/* attribute bits */
+	__u8	unused[10];
+	__u16	time,date,start;/* time, date and first cluster */
+	__u32	size;		/* file size (in bytes) */
 };
 
 struct fat_cache {
@@ -119,9 +119,8 @@
 extern void lock_fat(struct super_block *sb);
 extern void unlock_fat(struct super_block *sb);
 extern int msdos_add_cluster(struct inode *inode);
-extern int date_dos2unix(unsigned short time,unsigned short date);
-extern void date_unix2dos(int unix_date,unsigned short *time,
-    unsigned short *date);
+extern int date_dos2unix(__u16 time, __u16 date);
+extern void date_unix2dos(int unix_date,__u16 *time, __u16 *date);
 extern int msdos_get_entry(struct inode *dir,loff_t *pos,struct buffer_head **bh,
     struct msdos_dir_entry **de);
 extern int msdos_scan(struct inode *dir,char *name,struct buffer_head **res_bh,
diff -u --recursive --new-file v1.1.94/linux/include/linux/net.h linux/include/linux/net.h
--- v1.1.94/linux/include/linux/net.h	Fri Jan 13 16:57:06 1995
+++ linux/include/linux/net.h	Thu Feb 23 13:26:54 1995
@@ -135,6 +135,7 @@
 extern int	sock_wake_async(struct socket *sock, int how);
 extern int	sock_register(int family, struct proto_ops *ops);
 extern int	sock_unregister(int family);
-
+extern struct socket *sock_alloc(void);
+extern void	sock_release(struct socket *sock);
 #endif /* __KERNEL__ */
 #endif	/* _LINUX_NET_H */
diff -u --recursive --new-file v1.1.94/linux/include/linux/pci.h linux/include/linux/pci.h
--- v1.1.94/linux/include/linux/pci.h	Thu Feb  9 10:18:53 1995
+++ linux/include/linux/pci.h	Fri Feb 24 21:38:37 1995
@@ -229,7 +229,8 @@
 #define PCI_DEVICE_ID_DEC_BRD		0x0001
 
 #define PCI_VENDOR_ID_MATROX		0x102B
-#define PCI_DEVICE_ID_MATROX_2plus	0x0518
+#define PCI_DEVICE_ID_MATROX_MGA_2	0x0518
+#define PCI_DEVICE_ID_MATROX_MGA_IMP	0x0d10
 
 #define PCI_VENDOR_ID_INTEL		0x8086
 #define PCI_DEVICE_ID_INTEL_82378	0x0484
@@ -255,7 +256,7 @@
 #define PCI_DEVICE_ID_CIRRUS_6729	0x1100
 
 #define PCI_VENDOR_ID_BUSLOGIC		0x104B
-#define PCI_DEVICE_ID_BUSLOGIC_946C	0x0140
+#define PCI_DEVICE_ID_BUSLOGIC_946C	0x1040
 
 #define PCI_VENDOR_ID_N9		0x105D
 #define PCI_DEVICE_ID_N9_I128		0x2309
@@ -270,7 +271,8 @@
 #define PCI_VENDOR_ID_TSENG		0x100c
 #define PCI_DEVICE_ID_TSENG_W32P_2	0x3202
 #define PCI_DEVICE_ID_TSENG_W32P_b	0x3205
-#define PCI_DEVICE_ID_TSENG_W32P_c	0x3207
+#define PCI_DEVICE_ID_TSENG_W32P_c	0x3206
+#define PCI_DEVICE_ID_TSENG_W32P_d	0x3207
 
 #define PCI_VENDOR_ID_CMD		0x1095
 #define PCI_DEVICE_ID_CMD_640		0x0640
@@ -280,6 +282,7 @@
 
 #define PCI_VENDOR_ID_AMD		0x1022
 #define PCI_DEVICE_ID_AMD_LANCE		0x2000
+#define PCI_DEVICE_ID_AMD_SCSI		0x2020
 
 #define PCI_VENDOR_ID_VLSI		0x1004
 #define PCI_DEVICE_ID_VLSI_82C593	0x0006
@@ -298,6 +301,7 @@
 #define PCI_DEVICE_ID_CONTAQ_82C599	0x0600
 
 #define PCI_VENDOR_ID_NS		0x100b
+#define PCI_DEVICE_ID_NS_87410		0xd001
 
 #define PCI_VENDOR_ID_VIA		0x1106
 #define PCI_DEVICE_ID_VIA_82C505	0x0505
@@ -319,6 +323,8 @@
 #define PCI_VENDOR_ID_EF		0x111a
 #define PCI_DEVICE_ID_EF_ATM		0x0000
 
+#define PCI_VENDOR_ID_HER		0xedd8
+#define PCI_DEVICE_ID_HER_STING		0xa091
 
 struct pci_vendor_type {
 	unsigned short vendor_id;
@@ -326,7 +332,7 @@
 };
 
 
-#define PCI_VENDOR_NUM 33
+#define PCI_VENDOR_NUM 34
 #define PCI_VENDOR_TYPE { \
 	{PCI_VENDOR_ID_NCR,		"NCR"}, \
 	{PCI_VENDOR_ID_ADAPTEC,		"Adaptec"}, \
@@ -360,7 +366,8 @@
 	{PCI_VENDOR_ID_LEADTEK,		"Leadtek Research"}, \
 	{PCI_VENDOR_ID_IMS,		"IMS"}, \
 	{PCI_VENDOR_ID_ZEINET,		"ZeiNet"}, \
-	{PCI_VENDOR_ID_EF,		"Efficient Networks"} \
+	{PCI_VENDOR_ID_EF,		"Efficient Networks"}, \
+	{PCI_VENDOR_ID_HER,		"Hercules"} \
 }
 
 
@@ -379,7 +386,7 @@
 	char *device_name;
 };
 
-#define PCI_DEVICE_NUM 61
+#define PCI_DEVICE_NUM 66
 #define PCI_DEVICE_TYPE { \
 	{0xff,	PCI_VENDOR_ID_NCR,	PCI_DEVICE_ID_NCR_53C810,	"53c810"}, \
 	{0xff,	PCI_VENDOR_ID_NCR,	PCI_DEVICE_ID_NCR_53C815,	"53c815"}, \
@@ -403,7 +410,8 @@
 	{0xff,	PCI_VENDOR_ID_DEC,	PCI_DEVICE_ID_DEC_TULIP_FAST,	"DC21040"}, \
 	{0xff,	PCI_VENDOR_ID_DEC,	PCI_DEVICE_ID_DEC_FDDI,		"DEFPA"}, \
 	{0xff,	PCI_VENDOR_ID_DEC,	PCI_DEVICE_ID_DEC_BRD,		"DC21050"}, \
-	{0xff,	PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_2plus,	"MGA/2+"}, \
+	{0xff,	PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MGA_2,	"Atlas PX2085"}, \
+	{0xff,	PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MGA_IMP,	"MGA Impression"}, \
 	{0xff,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82378,	"82378IB"}, \
 	{0x00,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82424,	"82424ZX Saturn"}, \
 	{0xff,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	"82375EB"}, \
@@ -425,15 +433,18 @@
 	{0xff,	PCI_VENDOR_ID_TSENG,	PCI_DEVICE_ID_TSENG_W32P_2,	"ET4000W32P"}, \
 	{0xff,	PCI_VENDOR_ID_TSENG,	PCI_DEVICE_ID_TSENG_W32P_b,	"ET4000W32P rev B"}, \
 	{0xff,	PCI_VENDOR_ID_TSENG,	PCI_DEVICE_ID_TSENG_W32P_c,	"ET4000W32P rev C"}, \
+	{0xff,	PCI_VENDOR_ID_TSENG,	PCI_DEVICE_ID_TSENG_W32P_d,	"ET4000W32P rev D"}, \
 	{0xff,	PCI_VENDOR_ID_CMD,	PCI_DEVICE_ID_CMD_640,		"640A"}, \
 	{0xff,	PCI_VENDOR_ID_VISION,	PCI_DEVICE_ID_VISION_QD8500,	"QD-8500PCI"}, \
 	{0xff,	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_LANCE,	"79C970"}, \
+	{0xff,	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_SCSI,		"53C974"}, \
 	{0xff,	PCI_VENDOR_ID_VLSI,	PCI_DEVICE_ID_VLSI_82C593,	"82C593-FC1"}, \
 	{0xff,	PCI_VENDOR_ID_ADL,	PCI_DEVICE_ID_ADL_2301,		"2301"}, \
 	{0xff,	PCI_VENDOR_ID_SYMPHONY,	PCI_DEVICE_ID_SYMPHONY_101,	"82C101"}, \
 	{0xff,	PCI_VENDOR_ID_TRIDENT,	PCI_DEVICE_ID_TRIDENT_9420,	"TG 9420"}, \
 	{0xff,	PCI_VENDOR_ID_TRIDENT,	PCI_DEVICE_ID_TRIDENT_9440,	"TG 9440"}, \
 	{0xff,	PCI_VENDOR_ID_CONTAQ,	PCI_DEVICE_ID_CONTAQ_82C599,	"82C599"}, \
+	{0xff,	PCI_VENDOR_ID_NS,	PCI_DEVICE_ID_NS_87410,		"87410"}, \
 	{0xff,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C505,	"VT 82C505"}, \
 	{0xff,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_496,		"85C496"}, \
 	{0xff,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_501,		"85C501"}, \
@@ -441,7 +452,8 @@
 	{0xff,	PCI_VENDOR_ID_LEADTEK,	PCI_DEVICE_ID_LEADTEK_805,	"S3 805"}, \
 	{0xff,	PCI_VENDOR_ID_IMS,	PCI_DEVICE_ID_IMS_8849,		"8849"}, \
 	{0xff,	PCI_VENDOR_ID_ZEINET,	PCI_DEVICE_ID_ZEINET_1221,	"1221"}, \
-	{0xff,	PCI_VENDOR_ID_EF,	PCI_DEVICE_ID_EF_ATM,		"155P-MF1"} \
+	{0xff,	PCI_VENDOR_ID_EF,	PCI_DEVICE_ID_EF_ATM,		"155P-MF1"}, \
+	{0xff,	PCI_VENDOR_ID_HER,	PCI_DEVICE_ID_HER_STING,	"Stingray"} \
 }
 
 /* An item of this structure has the following meaning	*/
diff -u --recursive --new-file v1.1.94/linux/include/linux/sched.h linux/include/linux/sched.h
--- v1.1.94/linux/include/linux/sched.h	Wed Feb 22 16:53:06 1995
+++ linux/include/linux/sched.h	Fri Feb 24 16:41:01 1995
@@ -123,8 +123,6 @@
 	struct vm_area_struct * mmap_avl;
 };
 
-#define INIT_MMAP { &init_task, 0, 0x40000000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC }
-
 #define INIT_MM { \
 		0, \
 		0, 0, 0, \
diff -u --recursive --new-file v1.1.94/linux/include/linux/string.h linux/include/linux/string.h
--- v1.1.94/linux/include/linux/string.h	Mon Jan  9 11:24:24 1995
+++ linux/include/linux/string.h	Thu Mar  2 09:04:40 1995
@@ -21,6 +21,7 @@
 extern char * strtok(char *,const char *);
 extern char * strstr(const char *,const char *);
 extern size_t strlen(const char *);
+extern size_t strnlen(const char *,size_t);
 extern size_t strspn(const char *,const char *);
 extern int strcmp(const char *,const char *);
 extern int strncmp(const char *,const char *,size_t);
diff -u --recursive --new-file v1.1.94/linux/include/linux/tasks.h linux/include/linux/tasks.h
--- v1.1.94/linux/include/linux/tasks.h	Mon Jan 30 06:41:58 1995
+++ linux/include/linux/tasks.h	Mon Feb 27 11:16:24 1995
@@ -4,7 +4,7 @@
 /*
  * This is the maximum nr of tasks - change it if you need to
  */
-#define NR_TASKS	128
+#define NR_TASKS	512
 
 #define MAX_TASKS_PER_USER (NR_TASKS/2)
 #define MIN_TASKS_LEFT_FOR_ROOT 4
diff -u --recursive --new-file v1.1.94/linux/include/linux/tty.h linux/include/linux/tty.h
--- v1.1.94/linux/include/linux/tty.h	Wed Feb 22 16:53:06 1995
+++ linux/include/linux/tty.h	Sun Feb 26 16:45:26 1995
@@ -199,7 +199,7 @@
 	int pgrp;
 	int session;
 	dev_t	device;
-	int flags;
+	unsigned long flags;
 	int count;
 	struct winsize winsize;
 	unsigned char stopped:1, hw_stopped:1, packet:1;
@@ -231,7 +231,7 @@
 	int read_head;
 	int read_tail;
 	int read_cnt;
-	int read_flags[N_TTY_BUF_SIZE/32];
+	unsigned long read_flags[N_TTY_BUF_SIZE/(8*sizeof(unsigned long))];
 	int canon_data;
 	unsigned long canon_head;
 	unsigned int canon_column;
diff -u --recursive --new-file v1.1.94/linux/init/main.c linux/init/main.c
--- v1.1.94/linux/init/main.c	Fri Feb 17 11:20:17 1995
+++ linux/init/main.c	Fri Feb 24 16:41:01 1995
@@ -4,6 +4,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
+#define __KERNEL_SYSCALLS__
 #include <stdarg.h>
 
 #include <asm/system.h>
@@ -33,38 +34,6 @@
 extern char etext, end;
 extern char *linux_banner;
 
-/*
- * we need this inline - forking from kernel space will result
- * in NO COPY ON WRITE (!!!), until an execve is executed. This
- * is no problem, but for the stack. This is handled by not letting
- * main() use the stack at all after fork(). Thus, no function
- * calls - which means inline code for fork too, as otherwise we
- * would use the stack upon exit from 'fork()'.
- *
- * Actually only pause and fork are needed inline, so that there
- * won't be any messing with the stack from main(), but we define
- * some others too.
- */
-#define __NR__exit __NR_exit
-static inline _syscall0(int,idle)
-static inline _syscall0(int,fork)
-static inline _syscall0(int,pause)
-static inline _syscall0(int,setup)
-static inline _syscall0(int,sync)
-static inline _syscall0(pid_t,setsid)
-static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
-static inline _syscall1(int,dup,int,fd)
-static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
-static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
-static inline _syscall1(int,close,int,fd)
-static inline _syscall1(int,_exit,int,exitcode)
-static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
-
-static inline pid_t wait(int * wait_stat)
-{
-	return waitpid(-1,wait_stat,0);
-}
-
 static char printbuf[1024];
 
 extern int console_loglevel;
@@ -202,16 +171,16 @@
 	{ "ncr5380=", generic_NCR5380_setup },
 #endif
 #ifdef CONFIG_SCSI_AHA152X
-        { "aha152x=", aha152x_setup},
+	{ "aha152x=", aha152x_setup},
 #endif
 #ifdef CONFIG_SCSI_AHA1542
-        { "aha1542=", aha1542_setup},
+	{ "aha1542=", aha1542_setup},
 #endif
 #ifdef CONFIG_SCSI_AHA274X
-        { "aha274x=", aha274x_setup},
+	{ "aha274x=", aha274x_setup},
 #endif
 #ifdef CONFIG_SCSI_BUSLOGIC
-        { "buslogic=", buslogic_setup},
+	{ "buslogic=", buslogic_setup},
 #endif
 #ifdef CONFIG_BLK_DEV_XD
 	{ "xd=", xd_setup },
@@ -386,7 +355,7 @@
 	init_modules();
 #ifdef CONFIG_PROFILE
 	prof_buffer = (unsigned long *) memory_start;
-        /* only text is profiled */
+	/* only text is profiled */
 	prof_len = (unsigned long) &etext;
 	prof_len >>= CONFIG_PROFILE_SHIFT;
 	memory_start += prof_len * sizeof(unsigned long);
diff -u --recursive --new-file v1.1.94/linux/ipc/shm.c linux/ipc/shm.c
--- v1.1.94/linux/ipc/shm.c	Wed Feb 22 16:53:06 1995
+++ linux/ipc/shm.c	Sat Feb 25 15:42:57 1995
@@ -421,7 +421,6 @@
 	pmd_t *page_middle;
 	pte_t *page_table;
 	unsigned long tmp, shm_sgn;
-	int error;
 
 	/* clear old mappings */
 	do_munmap(shmd->vm_start, shmd->vm_end - shmd->vm_start);
@@ -437,10 +436,10 @@
 		page_dir = pgd_offset(shmd->vm_task,tmp);
 		page_middle = pmd_alloc(page_dir,tmp);
 		if (!page_middle)
-			break;
+			return -ENOMEM;
 		page_table = pte_alloc(page_middle,tmp);
 		if (!page_table)
-			break;
+			return -ENOMEM;
 		pte_val(*page_table) = shm_sgn;
 	}
 	invalidate();
diff -u --recursive --new-file v1.1.94/linux/kernel/fork.c linux/kernel/fork.c
--- v1.1.94/linux/kernel/fork.c	Wed Feb 22 16:53:06 1995
+++ linux/kernel/fork.c	Wed Mar  1 13:31:54 1995
@@ -137,7 +137,6 @@
 static int copy_mm(unsigned long clone_flags, struct task_struct * p)
 {
 	if (clone_flags & COPYVM) {
-		p->mm->swappable = 1;
 		p->mm->min_flt = p->mm->maj_flt = 0;
 		p->mm->cmin_flt = p->mm->cmaj_flt = 0;
 		if (copy_page_tables(p))
@@ -193,7 +192,6 @@
 	p->pid = last_pid;
 	p->p_pptr = p->p_opptr = current;
 	p->p_cptr = NULL;
-	SET_LINKS(p);
 	p->signal = 0;
 	p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
 	p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
@@ -202,7 +200,9 @@
 	p->utime = p->stime = 0;
 	p->cutime = p->cstime = 0;
 	p->start_time = jiffies;
+	p->mm->swappable = 0;	/* don't try to swap it out before it's set up */
 	task[nr] = p;
+	SET_LINKS(p);
 
 	/* copy all the process information */
 	copy_thread(nr, clone_flags, usp, p, regs);
@@ -213,6 +213,7 @@
 	copy_fs(clone_flags, p);
 
 	/* ok, now we should be set up.. */
+	p->mm->swappable = 1;
 	p->exit_signal = clone_flags & CSIGNAL;
 	p->counter = current->counter >> 1;
 	p->state = TASK_RUNNING;	/* do this last, just in case */
diff -u --recursive --new-file v1.1.94/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.1.94/linux/kernel/ksyms.c	Fri Feb 17 11:20:17 1995
+++ linux/kernel/ksyms.c	Thu Feb 23 13:52:40 1995
@@ -39,6 +39,7 @@
 #include <linux/netdevice.h>
 #include <linux/ip.h>
 #include "../net/inet/protocol.h"
+#include "../net/inet/arp.h"
 #endif
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
@@ -299,6 +300,7 @@
 	X(dev_queue_xmit),
 	X(dev_base),
 	X(dev_close),
+	X(arp_find),
 	X(n_tty_ioctl),
 	X(tty_register_ldisc),
 	X(kill_fasync),
diff -u --recursive --new-file v1.1.94/linux/kernel/sys.c linux/kernel/sys.c
--- v1.1.94/linux/kernel/sys.c	Wed Feb 22 16:53:06 1995
+++ linux/kernel/sys.c	Wed Mar  1 13:31:54 1995
@@ -172,8 +172,12 @@
 {
 	if (C_A_D)
 		hard_reset_now();
-	else
+	else {
+		int i;
 		send_sig(SIGINT,task[1],1);
+		for (i = 2; i < NR_TASKS; i++)
+			send_sig(SIGHUP,task[i],1);
+	}
 }
 	
 
diff -u --recursive --new-file v1.1.94/linux/lib/string.c linux/lib/string.c
--- v1.1.94/linux/lib/string.c	Sun Jan 22 23:04:00 1995
+++ linux/lib/string.c	Thu Mar  2 09:04:40 1995
@@ -104,6 +104,15 @@
 	return sc - s;
 }
 
+size_t strnlen(const char * s, size_t count)
+{
+	const char *sc;
+
+	for (sc = s; *sc != '\0' && count--; ++sc)
+		/* nothing */;
+	return sc - s;
+}
+
 size_t strspn(const char *s, const char *accept)
 {
 	const char *p;
diff -u --recursive --new-file v1.1.94/linux/lib/vsprintf.c linux/lib/vsprintf.c
--- v1.1.94/linux/lib/vsprintf.c	Mon Jan 30 08:53:06 1995
+++ linux/lib/vsprintf.c	Thu Mar  2 09:04:40 1995
@@ -217,11 +217,8 @@
 			s = va_arg(args, char *);
 			if (!s)
 				s = "<NULL>";
-			len = strlen(s);
-			if (precision < 0)
-				precision = len;
-			else if (len > precision)
-				len = precision;
+
+			len = strnlen(s, precision);
 
 			if (!(flags & LEFT))
 				while (len < field_width--)
diff -u --recursive --new-file v1.1.94/linux/mm/memory.c linux/mm/memory.c
--- v1.1.94/linux/mm/memory.c	Mon Feb 20 21:34:56 1995
+++ linux/mm/memory.c	Thu Mar  2 09:42:00 1995
@@ -246,7 +246,7 @@
 		pte = pte_wrprotect(pte);
 	if (delete_from_swap_cache(pte_page(pte)))
 		pte = pte_mkdirty(pte);
-	*new_pte = pte;
+	*new_pte = pte_mkold(pte);
 	*old_pte = pte;
 	mem_map[MAP_NR(pte_page(pte))]++;
 }
@@ -288,7 +288,7 @@
 	if (pgd_none(*old_pgd))
 		return 0;
 	if (pgd_bad(*old_pgd)) {
-		printk("copy_one_pgd: bad page table: probable memory corruption\n");
+		printk("copy_one_pgd: bad page table (%p: %08lx): probable memory corruption\n", old_pgd, pgd_val(*old_pgd));
 		pgd_clear(old_pgd);
 		return 0;
 	}
@@ -325,8 +325,8 @@
 	new_pgd = pgd_alloc();
 	if (!new_pgd)
 		return -ENOMEM;
-	old_pgd = pgd_offset(current, 0);
 	SET_PAGE_DIR(tsk, new_pgd);
+	old_pgd = pgd_offset(current, 0);
 	for (i = 0 ; i < PTRS_PER_PGD ; i++) {
 		int errno = copy_one_pgd(old_pgd, new_pgd);
 		if (errno) {
@@ -566,7 +566,7 @@
 static void put_page(pte_t * page_table, pte_t pte)
 {
 	if (!pte_none(*page_table)) {
-		printk("put_page: page already exists\n");
+		printk("put_page: page already exists %08lx\n", pte_val(*page_table));
 		free_page(pte_page(pte));
 		return;
 	}
@@ -590,11 +590,17 @@
 		printk("mem_map disagrees with %08lx at %08lx\n",page,address);
 	pgd = pgd_offset(tsk,address);
 	pmd = pmd_alloc(pgd, address);
-	if (!pmd)
+	if (!pmd) {
+		free_page(page);
+		oom(tsk);
 		return 0;
+	}
 	pte = pte_alloc(pmd, address);
-	if (!pte)
+	if (!pte) {
+		free_page(page);
+		oom(tsk);
 		return 0;
+	}
 	if (!pte_none(*pte)) {
 		printk("put_dirty_page: page already exists\n");
 		pte_clear(pte);
@@ -664,9 +670,9 @@
 			invalidate();
 			return;
 		}
+		*page_table = BAD_PAGE;
 		free_page(old_page);
 		oom(vma->vm_task);
-		*page_table = BAD_PAGE;
 		invalidate();
 		return;
 	}
@@ -809,6 +815,7 @@
 		return 0;
 	if (pgd_bad(*from_dir)) {
 		printk("try_to_share: bad page directory %08lx\n", pgd_val(*from_dir));
+		pgd_clear(from_dir);
 		return 0;
 	}
 	from_middle = pmd_offset(from_dir, from_address);
@@ -817,6 +824,7 @@
 		return 0;
 	if (pmd_bad(*from_middle)) {
 		printk("try_to_share: bad mid directory %08lx\n", pmd_val(*from_middle));
+		pmd_clear(from_middle);
 		return 0;
 	}
 	from_table = pte_offset(from_middle, from_address);
@@ -967,9 +975,15 @@
 
 	pgd = pgd_offset(tsk, address);
 	pmd = pmd_alloc(pgd, address);
-	if (!pmd)
+	if (!pmd) {
+		oom(tsk);
 		return NULL;
+	}
 	pte = pte_alloc(pmd, address);
+	if (!pte) {
+		oom(tsk);
+		return NULL;
+	}
 	return pte;
 }
 
@@ -1065,4 +1079,55 @@
 	} else if (mem_map[MAP_NR(page)] > 1 && !(vma->vm_flags & VM_SHARED))
 		entry = pte_wrprotect(entry);
 	put_page(page_table, entry);
+}
+
+/*
+ * The above separate functions for the no-page and wp-page
+ * cases will go away (they mostly do the same thing anyway),
+ * and we'll instead use only a general "handle_mm_fault()".
+ *
+ * These routines also need to handle stuff like marking pages dirty
+ * and/or accessed for architectures that don't do it in hardware (most
+ * RISC architectures).  The early dirtying is also good on the i386.
+ *
+ * There is also a hook called "update_mmu_cache()" that architectures
+ * with external mmu caches can use to update those (ie the Sparc or
+ * PowerPC hashed page tables that act as extended TLBs).
+ */
+static inline void handle_pte_fault(struct vm_area_struct * vma, unsigned long address,
+	int write_access, pte_t * pte)
+{
+	if (!pte_present(*pte)) {
+		do_no_page(vma, address, write_access);
+		return;
+	}
+	*pte = pte_mkyoung(*pte);
+	if (!write_access)
+		return;
+	if (pte_write(*pte)) {
+		*pte = pte_mkdirty(*pte);
+		return;
+	}
+	do_wp_page(vma, address, write_access);
+}
+
+void handle_mm_fault(struct vm_area_struct * vma, unsigned long address,
+	int write_access)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	pgd = pgd_offset(vma->vm_task, address);
+	pmd = pmd_alloc(pgd, address);
+	if (!pmd)
+		goto no_memory;
+	pte = pte_alloc(pmd, address);
+	if (!pte)
+		goto no_memory;
+	handle_pte_fault(vma, address, write_access, pte);
+	update_mmu_cache(vma, address, *pte);
+	return;
+no_memory:
+	oom(vma->vm_task);
 }
diff -u --recursive --new-file v1.1.94/linux/mm/mmap.c linux/mm/mmap.c
--- v1.1.94/linux/mm/mmap.c	Wed Feb  1 09:23:08 1995
+++ linux/mm/mmap.c	Thu Mar  2 09:04:40 1995
@@ -41,7 +41,7 @@
 	__S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111
 };
 
-int do_mmap(struct file * file, unsigned long addr, unsigned long len,
+unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags, unsigned long off)
 {
 	int error;
diff -u --recursive --new-file v1.1.94/linux/mm/swap.c linux/mm/swap.c
--- v1.1.94/linux/mm/swap.c	Wed Feb 22 16:53:06 1995
+++ linux/mm/swap.c	Wed Mar  1 13:32:36 1995
@@ -194,6 +194,8 @@
 		for (offset = p->lowest_bit; offset <= p->highest_bit ; offset++) {
 			if (p->swap_map[offset])
 				continue;
+			if (test_bit(offset, p->swap_lockmap))
+				continue;
 			p->swap_map[offset] = 1;
 			nr_swap_pages--;
 			if (offset == p->highest_bit)
@@ -257,8 +259,6 @@
 		printk("Trying to free swap from unused swap-device\n");
 		return;
 	}
-	while (set_bit(offset,p->swap_lockmap))
-		sleep_on(&lock_queue);
 	if (offset < p->lowest_bit)
 		p->lowest_bit = offset;
 	if (offset > p->highest_bit)
@@ -268,9 +268,6 @@
 	else
 		if (!--p->swap_map[offset])
 			nr_swap_pages++;
-	if (!clear_bit(offset,p->swap_lockmap))
-		printk("swap_free: lock already cleared\n");
-	wake_up(&lock_queue);
 }
 
 /*
@@ -311,7 +308,18 @@
   	return;
 }
 
-static inline int try_to_swap_out(struct vm_area_struct* vma, unsigned offset, pte_t * page_table)
+/*
+ * The swap-out functions return 1 of they successfully
+ * threw something out, and we got a free page. It returns
+ * zero if it couldn't do anything, and any other value
+ * indicates it decreased rss, but the page was shared.
+ *
+ * NOTE! If it sleeps, it *must* return 1 to make sure we
+ * don't continue with the swap-out. Otherwise we may be
+ * using a process that no longer actually exists (it might
+ * have died while we slept).
+ */
+static inline int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pte_t * page_table)
 {
 	pte_t pte;
 	unsigned long entry;
@@ -332,8 +340,9 @@
 	if (pte_dirty(pte)) {
 		if (mem_map[MAP_NR(page)] != 1)
 			return 0;
+		vma->vm_task->mm->rss--;
 		if (vma->vm_ops && vma->vm_ops->swapout)
-			vma->vm_ops->swapout(vma, offset, page_table);
+			vma->vm_ops->swapout(vma, address-vma->vm_start, page_table);
 		else {
 			if (!(entry = get_swap_page()))
 				return 0;
@@ -342,7 +351,7 @@
 			write_swap_page(entry, (char *) page);
 		}
 		free_page(page);
-		return 1 + mem_map[MAP_NR(page)];
+		return 1;	/* we slept: the process may not exist any more */
 	}
         if ((entry = find_in_swap_cache(page)))  {
 		if (mem_map[MAP_NR(page)] != 1) {
@@ -350,15 +359,18 @@
 			printk("Aiee.. duplicated cached swap-cache entry\n");
 			return 0;
 		}
+		vma->vm_task->mm->rss--;
 		pte_val(*page_table) = entry;
 		invalidate();
 		free_page(page);
 		return 1;
 	} 
+	vma->vm_task->mm->rss--;
 	pte_clear(page_table);
 	invalidate();
+	entry = mem_map[MAP_NR(page)];
 	free_page(page);
-	return 1 + mem_map[MAP_NR(page)];
+	return entry;
 }
 
 /*
@@ -409,20 +421,11 @@
 		end = pmd_end;
 
 	do {
-		switch (try_to_swap_out(vma, address-vma->vm_start, pte)) {
-			case 0:
-				break;
-
-			case 1:
-				vma->vm_task->mm->rss--;
-				/* continue with the following page the next time */
-				vma->vm_task->mm->swap_address = address + PAGE_SIZE;
-				return 1;
-
-			default:
-				vma->vm_task->mm->rss--;
-				break;
-		}
+		int result;
+		vma->vm_task->mm->swap_address = address + PAGE_SIZE;
+		result = try_to_swap_out(vma, address, pte);
+		if (result)
+			return result;
 		address += PAGE_SIZE;
 		pte++;
 	} while (address < end);
@@ -450,8 +453,9 @@
 		end = pgd_end;
 	
 	do {
-		if (swap_out_pmd(vma, pmd, address, end))
-			return 1;
+		int result = swap_out_pmd(vma, pmd, address, end);
+		if (result)
+			return result;
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;
 	} while (address < end);
@@ -465,8 +469,9 @@
 
 	end = vma->vm_end;
 	while (start < end) {
-		if (swap_out_pgd(vma, pgdir, start, end))
-			return 1;
+		int result = swap_out_pgd(vma, pgdir, start, end);
+		if (result)
+			return result;
 		start = (start + PGDIR_SIZE) & PGDIR_MASK;
 		pgdir++;
 	}
@@ -494,13 +499,16 @@
 		address = vma->vm_start;
 
 	for (;;) {
-		if (swap_out_vma(vma, pgd_offset(p, address), address))
-			return 1;
+		int result = swap_out_vma(vma, pgd_offset(p, address), address);
+		if (result)
+			return result;
 		vma = vma->vm_next;
 		if (!vma)
-			return 0;
+			break;
 		address = vma->vm_start;
 	}
+	p->mm->swap_address = 0;
+	return 0;
 }
 
 static int swap_out(unsigned int priority)
@@ -510,7 +518,7 @@
 	struct task_struct *p;
 
 	counter = 2*NR_TASKS >> priority;
-	for(; counter >= 0; counter--, swap_task++) {
+	for(; counter >= 0; counter--) {
 		/*
 		 * Check that swap_task is suitable for swapping.  If not, look for
 		 * the next suitable process.
@@ -547,10 +555,17 @@
 			else
 				p->mm->swap_cnt = SWAP_RATIO / p->mm->dec_flt;
 		}
-		if (swap_out_process(p)) {
-			if ((--p->mm->swap_cnt) == 0)
-				swap_task++;
-			return 1;
+		if (!--p->mm->swap_cnt)
+			swap_task++;
+		switch (swap_out_process(p)) {
+			case 0:
+				if (p->mm->swap_cnt)
+					swap_task++;
+				break;
+			case 1:
+				return 1;
+			default:
+				break;
 		}
 	}
 	return 0;
@@ -790,8 +805,8 @@
 		for (tmp = free_area_list[order].next ; tmp != free_area_list + order ; tmp = tmp->next) {
 			nr ++;
 		}
-		total += nr * (4 << order);
-		printk("%lu*%ukB ", nr, 4 << order);
+		total += nr * ((PAGE_SIZE>>10) << order);
+		printk("%lu*%lukB ", nr, (PAGE_SIZE>>10) << order);
 	}
 	restore_flags(flags);
 	printk("= %lukB)\n", total);
diff -u --recursive --new-file v1.1.94/linux/net/inet/af_inet.c linux/net/inet/af_inet.c
--- v1.1.94/linux/net/inet/af_inet.c	Wed Feb 22 16:53:07 1995
+++ linux/net/inet/af_inet.c	Thu Feb 23 14:02:24 1995
@@ -28,6 +28,11 @@
  *		Niibe Yutaka	:	4.4BSD style write async I/O
  *		Alan Cox, 
  *		Tony Gale 	:	Fixed reuse semantics.
+ *		Alan Cox	:	bind() shouldn't abort existing but dead
+ *					sockets. Stops FTP netin:.. I hope.
+ *		Alan Cox	:	bind() works correctly for RAW sockets. Note
+ *					that FreeBSD at least is broken in this respect
+ *					so be careful with compatibility tests...
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -823,77 +828,76 @@
 {
 	struct sockaddr_in *addr=(struct sockaddr_in *)uaddr;
 	struct sock *sk=(struct sock *)sock->data, *sk2;
-	unsigned short snum;
+	unsigned short snum = 0 /* Stoopid compiler.. this IS ok */;
 	int chk_addr_ret;
 
 	/* check this error. */
 	if (sk->state != TCP_CLOSE)
 		return(-EIO);
-	if (sk->num != 0) 
-		return(-EINVAL);
-
 	if(addr_len<sizeof(struct sockaddr_in))
 		return -EINVAL;
+		
+	if(sock->type != SOCK_RAW)
+	{
+		if (sk->num != 0) 
+			return(-EINVAL);
 
-	snum = ntohs(addr->sin_port);
+		snum = ntohs(addr->sin_port);
 
-	/*
-	 * We can't just leave the socket bound wherever it is, it might
-	 * be bound to a privileged port. However, since there seems to
-	 * be a bug here, we will leave it if the port is not privileged.
-	 */
-	if (snum == 0) 
-	{
-		snum = get_new_socknum(sk->prot, 0);
+		/*
+		 * We can't just leave the socket bound wherever it is, it might
+		 * be bound to a privileged port. However, since there seems to
+		 * be a bug here, we will leave it if the port is not privileged.
+		 */
+		if (snum == 0) 
+		{
+			snum = get_new_socknum(sk->prot, 0);
+		}
+		if (snum < PROT_SOCK && !suser()) 
+			return(-EACCES);
 	}
-	if (snum < PROT_SOCK && !suser()) 
-		return(-EACCES);
-
+	
 	chk_addr_ret = ip_chk_addr(addr->sin_addr.s_addr);
 	if (addr->sin_addr.s_addr != 0 && chk_addr_ret != IS_MYADDR && chk_addr_ret != IS_MULTICAST)
 		return(-EADDRNOTAVAIL);	/* Source address MUST be ours! */
-  	
+	  	
 	if (chk_addr_ret || addr->sin_addr.s_addr == 0)
 		sk->saddr = addr->sin_addr.s_addr;
-
-	/* Make sure we are allowed to bind here. */
-	cli();
-outside_loop:
-	for(sk2 = sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)];
-					sk2 != NULL; sk2 = sk2->next) 
+	
+	if(sock->type != SOCK_RAW)
 	{
-/* should be below! */
-		if (sk2->num != snum) continue;
-#if 0
-		if (sk2->dead) 
-		{
-			destroy_sock(sk2);
-			goto outside_loop;
-		}
-#endif
-		if (!sk->reuse)
-		{
-			sti();
-			return(-EADDRINUSE);
-		}
-		
-		if (sk2->num != snum) 
-			continue;		/* more than one */
-		if (sk2->saddr != sk->saddr) 
-			continue;	/* socket per slot ! -FB */
-		if (!sk2->reuse || sk2->state==TCP_LISTEN) 
+		/* Make sure we are allowed to bind here. */
+		cli();
+		for(sk2 = sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)];
+					sk2 != NULL; sk2 = sk2->next) 
 		{
-			sti();
-			return(-EADDRINUSE);
+		/* should be below! */
+			if (sk2->num != snum) 
+				continue;
+			if (!sk->reuse)
+			{
+				sti();
+				return(-EADDRINUSE);
+			}
+			
+			if (sk2->num != snum) 
+				continue;		/* more than one */
+			if (sk2->saddr != sk->saddr) 
+				continue;	/* socket per slot ! -FB */
+			if (!sk2->reuse || sk2->state==TCP_LISTEN) 
+			{
+				sti();
+				return(-EADDRINUSE);
+			}
 		}
-	}
-	sti();
+		sti();
 
-	remove_sock(sk);
-	put_sock(snum, sk);
-	sk->dummy_th.source = ntohs(sk->num);
-	sk->daddr = 0;
-	sk->dummy_th.dest = 0;
+		remove_sock(sk);
+		put_sock(snum, sk);
+		sk->dummy_th.source = ntohs(sk->num);
+		sk->daddr = 0;
+		sk->dummy_th.dest = 0;
+	}
 	return(0);
 }
 
@@ -1002,7 +1006,7 @@
 
 
 /*
- *	FIXME: Get BSD behaviour
+ *	Accept a pending connection. The TCP layer now gives BSD semantics.
  */
 
 static int inet_accept(struct socket *sock, struct socket *newsock, int flags)
diff -u --recursive --new-file v1.1.94/linux/net/inet/arp.c linux/net/inet/arp.c
--- v1.1.94/linux/net/inet/arp.c	Fri Feb 17 11:20:17 1995
+++ linux/net/inet/arp.c	Thu Feb 23 13:26:37 1995
@@ -37,6 +37,7 @@
  *                                      re-arranged proxy handling.
  *		Alan Cox	:	Changed to use notifiers.
  *		Niibe Yutaka	:	Reply for this device or proxies only.
+ *		Alan Cox	:	Don't proxy across hardware types!
  */
 
 #include <linux/types.h>
@@ -680,7 +681,7 @@
 			     having to use a huge number of proxy arp entries
 			     and having to keep them uptodate.
 			     */
-			  if (proxy_entry->dev != dev &&
+			  if (proxy_entry->dev != dev && proxy_entry->htype == htype &&
 			      !((proxy_entry->ip^tip)&proxy_entry->mask))
 			    break;
 
diff -u --recursive --new-file v1.1.94/linux/net/inet/dev_mcast.c linux/net/inet/dev_mcast.c
--- v1.1.94/linux/net/inet/dev_mcast.c	Mon Jan  9 11:24:24 1995
+++ linux/net/inet/dev_mcast.c	Thu Feb 23 13:26:57 1995
@@ -8,6 +8,10 @@
  *	Stir fried together from the IP multicast and CAP patches above
  *		Alan Cox <Alan.Cox@linux.org>	
  *
+ *	Fixes:
+ *		Alan Cox	:	Update the device on a real delete
+ *					rather than any time but...
+ *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
  *	as published by the Free Software Foundation; either version
@@ -114,10 +118,10 @@
 			*dmi=(*dmi)->next;
 			dev->mc_count--;
 			kfree_s(tmp,sizeof(*tmp));
+			dev_mc_upload(dev);
 			return;
 		}
 	}
-	dev_mc_upload(dev);
 }
 
 /*
diff -u --recursive --new-file v1.1.94/linux/net/inet/ip.c linux/net/inet/ip.c
--- v1.1.94/linux/net/inet/ip.c	Fri Feb 17 11:20:17 1995
+++ linux/net/inet/ip.c	Fri Feb 24 21:40:16 1995
@@ -1262,14 +1262,18 @@
 	struct rtable *rt;	/* Route we use */
 	unsigned char *ptr;	/* Data pointer */
 	unsigned long raddr;	/* Router IP address */
-
+	
 	/* 
 	 *	See if we are allowed to forward this.
 	 */
 
 #ifdef CONFIG_IP_FIREWALL
-	if(!ip_fw_chk(skb->h.iph, ip_fw_fwd_chain, ip_fw_fwd_policy))
+	int err;
+	
+	if((err=ip_fw_chk(skb->h.iph, dev, ip_fw_fwd_chain, ip_fw_fwd_policy))!=1)
 	{
+		if(err==-1)
+			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
 		return;
 	}
 #endif
@@ -1425,7 +1429,7 @@
 			 *	Count mapping we shortcut
 			 */
 			 
-			ip_acct_cnt(iph,ip_acct_chain);
+			ip_acct_cnt(iph,dev,ip_acct_chain);
 #endif			
 			
 			/*
@@ -1462,6 +1466,9 @@
 				take up stack space. */
 	int brd=IS_MYADDR;
 	int is_frag=0;
+#ifdef CONFIG_IP_FIREWALL
+	int err;
+#endif	
 
 	ip_statistics.IpInReceives++;
 
@@ -1493,9 +1500,10 @@
 
 #ifdef	CONFIG_IP_FIREWALL
 	
-	if(!LOOPBACK(iph->daddr) && !ip_fw_chk(iph,ip_fw_blk_chain,
-			ip_fw_blk_policy))
+	if ((err=ip_fw_chk(iph,dev,ip_fw_blk_chain,ip_fw_blk_policy))!=1)
 	{
+		if(err==-1)
+			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
 		kfree_skb(skb, FREE_WRITE);
 		return 0;	
 	}
@@ -1609,7 +1617,7 @@
 	 */
 	 
 #ifdef CONFIG_IP_ACCT
-	ip_acct_cnt(iph,ip_acct_chain);
+	ip_acct_cnt(iph,dev, ip_acct_chain);
 #endif	
 
 	/*
@@ -1906,7 +1914,7 @@
 	 
 	ip_statistics.IpOutRequests++;
 #ifdef CONFIG_IP_ACCT
-	ip_acct_cnt(iph,ip_acct_chain);
+	ip_acct_cnt(iph,dev, ip_acct_chain);
 #endif	
 	
 #ifdef CONFIG_IP_MULTICAST	
diff -u --recursive --new-file v1.1.94/linux/net/inet/ip_fw.c linux/net/inet/ip_fw.c
--- v1.1.94/linux/net/inet/ip_fw.c	Wed Feb 15 10:36:41 1995
+++ linux/net/inet/ip_fw.c	Thu Feb 23 13:26:12 1995
@@ -4,9 +4,18 @@
  *	and the licenses thus do not conflict. While this port is subject
  *	to the GPL I also place my modifications under the original 
  *	license in recognition of the original copyright. 
+ *				-- Alan Cox.
  *
  *	Ported from BSD to Linux,
  *		Alan Cox 22/Nov/1994.
+ *	Zeroing /proc and other additions
+ *		Jos Vos 4/Feb/1995.
+ *	Merged and included the FreeBSD-Current changes at Ugen's request
+ *	(but hey its a lot cleaner now). Ugen would prefer in some ways
+ *	we waited for his final product but since Linux 1.2.0 is about to
+ *	appear its not practical - Read: It works, its not clean but please
+ *	don't consider it to be his standard of finished work.
+ *		Alan Cox 12/Feb/1995
  *
  *	All the real work was done by .....
  */
@@ -25,6 +34,7 @@
  * This software is provided ``AS IS'' without any warranties of any kind.
  */
 
+#include <linux/config.h>
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <linux/types.h>
@@ -39,6 +49,8 @@
 #include <linux/in.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/icmp.h>
+#include <linux/udp.h>
 #include "ip.h"
 #include "protocol.h"
 #include "route.h"
@@ -52,11 +64,34 @@
  *	Implement IP packet firewall
  */
 
+#ifdef CONFIG_IPFIREWALL_DEBUG 
+#define dprintf1(a)		printk(a)
+#define dprintf2(a1,a2)		printk(a1,a2)
+#define dprintf3(a1,a2,a3)	printk(a1,a2,a3)
+#define dprintf4(a1,a2,a3,a4)	printk(a1,a2,a3,a4)
+#else
+#define dprintf1(a)	
+#define dprintf2(a1,a2)
+#define dprintf3(a1,a2,a3)
+#define dprintf4(a1,a2,a3,a4)
+#endif
+
+#define print_ip(a)	 printf("%d.%d.%d.%d",(ntohl(a.s_addr)>>24)&0xFF,\
+					      (ntohl(a.s_addr)>>16)&0xFF,\
+					      (ntohl(a.s_addr)>>8)&0xFF,\
+					      (ntohl(a.s_addr))&0xFF);
+
+#ifdef IPFIREWALL_DEBUG
+#define dprint_ip(a)	print_ip(a)
+#else
+#define dprint_ip(a)	
+#endif
+
 #ifdef CONFIG_IP_FIREWALL
 struct ip_fw *ip_fw_fwd_chain;
 struct ip_fw *ip_fw_blk_chain;
-int ip_fw_blk_policy=1;
-int ip_fw_fwd_policy=1;
+int ip_fw_blk_policy=IP_FW_F_ACCEPT;
+int ip_fw_fwd_policy=IP_FW_F_ACCEPT;
 #endif
 #ifdef CONFIG_IP_ACCT
 struct ip_fw *ip_acct_chain;
@@ -67,16 +102,6 @@
 #define IP_INFO_ACCT	2
 
 
-extern inline void print_ip(unsigned long xaddr)
-{
-	unsigned long addr = ntohl(xaddr);
-	printk("%ld.%ld.%ld.%ld",(addr>>24) & 0xff,
-                         (addr>>16)&0xff,
-                         (addr>>8)&0xff,
-                         addr&0xFF);
-}                  
-
-
 /*
  *	Returns 1 if the port is matched by the vector, 0 otherwise
  */
@@ -104,336 +129,230 @@
 	return(0);
 }
 
+#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
+
 
 /*
- *	Returns 0 if packet should be dropped, 1 or more if it should be accepted
+ *	Returns 0 if packet should be dropped, 1 or more if it should be accepted.
+ *	Also does accounting so you can feed it the accounting chain.
  */
 
-#ifdef CONFIG_IP_FIREWALL
 
-int ip_fw_chk(struct iphdr *ip, struct ip_fw *chain, int policy)
+int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int policy)
 {
-	unsigned long src, dst;
-	char got_proto=0;
-	int frwl_proto, proto=0;
 	struct ip_fw *f;
-	unsigned short src_port=0, dst_port=0;
-	unsigned short *portptr=(unsigned short *)&(((u_int *)ip)[ip->ihl]);
-
-	if (!chain) 
-		return(policy);  /* If no chain, use your policy. */
+	struct tcphdr		*tcp=(struct tcphdr *)((unsigned long *)ip+ip->ihl);
+	struct udphdr		*udp=(struct udphdr *)((unsigned long *)ip+ip->ihl);
+	__u32			src, dst;
+	__u16			src_port=0, dst_port=0;
+	unsigned short		f_prt=0, prt;
+	char			notcpsyn=1;
+	unsigned short		f_flag;
 
+	/*
+	 *	If the chain is empty follow policy. The BSD one
+	 *	accepts anything giving you a time window while
+	 *	flushing and rebuilding the tables.
+	 */
+	 
 	src = ip->saddr;
 	dst = ip->daddr;
 
-#ifdef DEBUG_CONFIG_IP_FIREWALL
-	{
-		printk("packet ");
-		switch(ip->protocol) 
-		{
-			case IPPROTO_TCP:
-				printf("TCP ");
-				break;
-			case IPPROTO_UDP:
-				printf("UDP ");
-				break;
-			case IPPROTO_ICMP:
-				printf("ICMP:%d ",((char *)portptr)[0]&0xff);
-				break;
-			default:
-				printf("p=%d ",ip->protocol);
-				break;
-		}
-		print_ip(ip->saddr);
-		if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) 
-		{
-			printf(":%d ",ntohs(portptr[0]));
-		}
-		print_ip(ip->daddr);
-		if ( ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) 
-		{
-			printf(":%d ",ntohs(portptr[1]));
-		}
-		printf("\n");
-	}
-#endif
-
-	for (f=chain;f;f=f->next) 
-	{
-		if ((src&f->src_mask.s_addr)==f->src.s_addr
-			&&  (dst&f->dst_mask.s_addr)==f->dst.s_addr) 
-		{
-			frwl_proto=f->flags&IP_FW_F_KIND;
-			if (frwl_proto==IP_FW_F_ALL) 
-			{
-				/* Universal frwl - we've got a match! */
-
-#ifdef DEBUG_CONFIG_IP_FIREWALL
-				printf("universal frwl match\n");
-#endif
-				f->p_cnt++;
-				f->b_cnt+=ntohs(ip->tot_len);
-#ifdef CONFIG_IP_FIREWALL_VERBOSE
-				if (!(f->flags & IP_FW_F_ACCEPT))
-					goto bad_packet;
-				return 1;
-#else
-				return( f->flags & IP_FW_F_ACCEPT );
-#endif
-			}
-			else
-			{
-				/*
-				 *	Specific firewall - packet's protocol must match firewall's
-				 */
-				if (!got_proto) 
-				{
-					/*
-	 				 * We still had not determined the protocol
-					 * of this packet,now the time to do so.
-					 */
-					switch(ip->protocol) 
-					{
-						case IPPROTO_TCP:
-							/*
-							 * 	First two shorts in TCP are src/dst ports
-							 */
-							proto=IP_FW_F_TCP;
-							src_port=ntohs(portptr[0]);
-							dst_port=ntohs(portptr[1]);
-							break;
-						case IPPROTO_UDP:
-							/*
-							 *	First two shorts in UDP are src/dst ports
-			 				 */
-							proto = IP_FW_F_UDP;
-							src_port = ntohs(portptr[0]);
-							dst_port = ntohs(portptr[1]);
-							break;
-						case IPPROTO_ICMP:
-							proto=IP_FW_F_ICMP;
-							break;
-						default:
-							proto=IP_FW_F_ALL;
-#ifdef DEBUG_CONFIG_IP_FIREWALL
-							printf("non TCP/UDP packet\n");
-#endif
-					}
-					got_proto=1;
-				} 
-				/*
-				 * At this moment we surely know the protocol of this
-				 * packet and we'll check if it matches,then proceed further..
-				 */
-				if (proto==frwl_proto) 
-				{
-	
-					if (proto==IP_FW_F_ICMP || (port_match(&f->ports[0],f->n_src_p,src_port,
-						f->flags&IP_FW_F_SRNG) &&
-					        port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port,
-						f->flags&IP_FW_F_DRNG))) 
-					{
-					/* We've got a match! */
-					f->p_cnt++;
-					f->b_cnt+=ntohs(ip->tot_len);
-#ifdef CONFIG_IP_FIREWALL_VERBOSE
-						if (!(f->flags & IP_FW_F_ACCEPT))
-							goto bad_packet;
-						return 1;
-#else
-						return( f->flags & IP_FW_F_ACCEPT);
-#endif
-					} /* Ports match */
-				} /* Proto matches */
-			}  /* ALL/Specific */
-		} /* IP addr/mask matches */
-	} /* Loop */
-	
-	/*
-	 * If we get here then none of the firewalls matched.
-	 * So now we relay on policy defined by user-unmatched packet can
-	 * be ever accepted or rejected...
+	/* 
+	 *	This way we handle fragmented packets.
+	 *	we ignore all fragments but the first one
+	 *	so the whole packet can't be reassembled.
+	 *	This way we relay on the full info which
+	 *	stored only in first packet.
+	 *
+	 *	Note that this theoretically allows partial packet
+	 *	spoofing. Not very dangerous but paranoid people may
+	 *	wish to play with this. It also allows the so called
+	 *	"fragment bomb" denial of service attack on some types
+	 *	of system.
 	 */
 
-#ifdef CONFIG_IP_FIREWALL_VERBOSE
-	if (!(policy))
-		goto bad_packet;
-	return 1;
-#else
-	return(policy);
-#endif
-
-#ifdef CONFIG_IP_FIREWALL_VERBOSE
-bad_packet:
-	/*
-	 * VERY ugly piece of code which actually
-	 * makes kernel printf for denied packets...
-	 */
-	if (f->flags&IP_FW_F_PRN) 
-	{
-		printf("ip_fw_chk says no to ");
-		switch(ip->protocol) 
-		{
-			case IPPROTO_TCP:
-				printf("TCP ");
-				break;
-			case IPPROTO_UDP:
-				printf("UDP ");
-				break;
-			case IPPROTO_ICMP:
-				printf("ICMP:%d ",((char *)portptr)[0]&0xff);
-				break;
-			default:
-				printf("p=%d ",ip->protocol);
-				break;
-		}
-		print_ip(ip->saddr);
-		if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) 
-		{
-			printf(":%d ",ntohs(portptr[0]));
-		}
-		else
-		{
-			printf("\n");
-		}
-		print_ip(ip->daddr);
-		if ( ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP ) 
-		{
-			printf(":%d ",ntohs(portptr[1]));
-		}
-		printf("\n");
-	}
-	return(0);
-#endif
-}
-#endif /* CONFIG_IP_FIREWALL */
-
-
-
-
-#ifdef CONFIG_IP_ACCT
-void ip_acct_cnt(struct iphdr *ip,struct ip_fw *chain)
-{
-	unsigned long src, dst;
-	char got_proto=0,rev=0;
-	int frwl_proto, proto=0;
-	struct ip_fw *f;
-	unsigned short src_port=0, dst_port=0;
-	unsigned short *portptr=(unsigned short *)&(((u_int *)ip)[ip->ihl]);
-
-	if (!chain) 
-		return;     
+	if (ip->frag_off&IP_OFFSET)
+		return(1);
 
 	src = ip->saddr;
 	dst = ip->daddr;
 
-	for (f=chain;f;f=f->next) 
-	{
-		if ((src&f->src_mask.s_addr)==f->src.s_addr
-			&&  (dst&f->dst_mask.s_addr)==f->dst.s_addr) 
-		{
-			rev=0;
-			goto addr_match;
-		}
-	 	if  ((f->flags&IP_FW_F_BIDIR) &&
-		    ((src&f->src_mask.s_addr)==f->dst.s_addr
-		&&  (dst&f->dst_mask.s_addr)==f->src.s_addr)) 
-		{ 
-			rev=1;
-			goto addr_match;
-		}
-		continue;
-addr_match:
-		frwl_proto=f->flags&IP_FW_F_KIND;
-		if (frwl_proto==IP_FW_F_ALL) 
+	/*
+	 *	If we got interface from which packet came
+	 *	we can use the address directly. This is unlike
+	 *	4.4BSD derived systems that have an address chain
+	 *	per device. We have a device per address with dummy
+	 *	devices instead.
+	 */
+	 
+	dprintf1("Packet ");
+	switch(ip->protocol) 
+	{
+		case IPPROTO_TCP:
+			dprintf1("TCP ");
+			src_port=ntohs(tcp->source);
+			dst_port=ntohs(tcp->dest);
+			if(tcp->syn)
+				notcpsyn=0; /* We *DO* have SYN, value FALSE */
+			prt=IP_FW_F_TCP;
+			break;
+		case IPPROTO_UDP:
+			dprintf1("UDP ");
+			src_port=ntohs(udp->source);
+			dst_port=ntohs(udp->dest);
+			prt=IP_FW_F_UDP;
+			break;
+		case IPPROTO_ICMP:
+			dprintf2("ICMP:%d ",((char *)portptr)[0]&0xff);
+			prt=IP_FW_F_ICMP;
+			break;
+		default:
+			dprintf2("p=%d ",ip->protocol);
+			prt=IP_FW_F_ALL;
+			break;
+	}
+	dprint_ip(ip->saddr);
+	
+	if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) 
+		dprintf2(":%d ", src_port);
+	dprint_ip(ip->daddr);
+	if ( ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) 
+		dprintf2(":%d ",dst_port);
+	dprintf1("\n");
+
+	for (f=chain;f;f=f->fw_next) 
+	{
+		/*
+		 *	This is a bit simpler as we don't have to walk
+		 *	an interface chain as you do in BSD - same logic
+		 *	however.
+		 */
+		if ((src&f->fw_smsk.s_addr)==f->fw_src.s_addr
+		&&  (dst&f->fw_dmsk.s_addr)==f->fw_dst.s_addr) 
 		{
-			/*	Universal frwl - we've got a match! */
-     			f->p_cnt++;	/*	Rise packet count */
-
 			/*
-			 *	Rise byte count, convert from host to network byte order.
-		     	 */
-		     	 
-			f->b_cnt+=ntohs(ip->tot_len);
+			 *	Look for a VIA match 
+			 */
+			if(f->fw_via.s_addr && rif)
+			{
+				if(rif->pa_addr!=f->fw_via.s_addr)
+					continue;	/* Mismatch */
+			}
+			/*
+			 *	Drop through - this is a match
+			 */
 		}
 		else
+			continue;
+		
+		/*
+		 *	Ok the chain addresses match.
+		 */
+
+		f_prt=f->fw_flg&IP_FW_F_KIND;
+		if (f_prt!=IP_FW_F_ALL) 
 		{
 			/*
-			 *	Specific firewall - packet's protocol must match firewall's
+			 * This is actually buggy as if you set SYN flag 
+			 * on UDP or ICMP firewall it will never work,but 
+			 * actually it is a concern of software which sets
+			 * firewall entries.
 			 */
 			 
-			if (!got_proto) 
-			{
-				/*
- 				 *	We still had not determined the protocol
-				 *	of this packet,now the time to do so.
-				 */
-				switch(ip->protocol) 
-				{
-				    	case IPPROTO_TCP:
-						/*
-						 *	First two shorts in TCP are src/dst ports
-						 */
-						proto=IP_FW_F_TCP;
-						src_port=ntohs(portptr[0]);
-						dst_port=ntohs(portptr[1]);
-						break;
-	    				case IPPROTO_UDP:
-						/*
-						 * First two shorts in UDP are src/dst ports
-						 */
-						proto = IP_FW_F_UDP;
-						src_port = ntohs(portptr[0]);
-						dst_port = ntohs(portptr[1]);
-						break;
-	    				case IPPROTO_ICMP:
-						proto=IP_FW_F_ICMP;
-						break;
-					default:
-						proto=IP_FW_F_ALL;
-				}
-				got_proto=1;
-			} 
+			 if((f->fw_flg&IP_FW_F_TCPSYN) && notcpsyn)
+			 	continue;
 			/*
-			 * At this moment we surely know the protocol of this
-			 * packet and we'll check if it matches,then proceed further..
+			 *	Specific firewall - packet's protocol
+			 *	must match firewall's.
 			 */
-			if (proto==frwl_proto) 
+
+			if(prt!=f_prt)
+				continue;
+				
+			if(!(prt==IP_FW_F_ICMP ||(
+				port_match(&f->fw_pts[0], f->fw_nsp, src_port,
+					f->fw_flg&IP_FW_F_SRNG) &&
+				port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port,
+					f->fw_flg&IP_FW_F_SRNG))))
 			{
+				continue;
+			}
+		}
+#ifdef CONFIG_IP_FIREWALL_VERBOSE
+		/*
+		 * VERY ugly piece of code which actually
+		 * makes kernel printf for denied packets...
+		 */
+
+		if (f->fw_flg & IP_FW_F_PRN)
+		{
+			if(f->fw_flg&IP_FW_F_ACCEPT)
+				printk("Accept ");
+			else
+				printk("Deny ");
+			switch(ip->protocol)
+			{
+				case IPPROTO_TCP:
+					printk("TCP ");
+					break;
+				case IPPROTO_UDP:
+					printk("UDP ");
+				case IPPROTO_ICMP:
+					printk("ICMP ");
+					break;
+				default:
+					printk("p=%d ",ip->protocol);
+					break;
+			}
+			print_ip(ip->saddr);
+			if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
+				printk(":%d", src_port);
+			printk(" ");
+			print_ip(ip->daddr);
+			if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
+				printk(":%d",dst_port);
+			printk("\n");
+		}
+#endif		
+		if(f->fw_flg&IP_FW_F_ACCEPT)
+		{
+			f->fw_bcnt+=ntohs(ip->tot_len);
+			f->fw_pcnt++;
+			return 1;
+		}
+		break;
+	} /* Loop */
+	
+	/*
+	 * If we get here then none of the firewalls matched or one matched
+	 * but was a no. So now we rely on policy defined in the rejecting
+	 * entry or if none was found in the policy variable
+	 */
+
+	if(f!=NULL)	/* A deny match */
+		f_flag=f->fw_flg;
+	else
+		f_flag=policy;
+	if(f_flag&IP_FW_F_ACCEPT)
+		return 1;
+	if(f_flag&IP_FW_F_ICMPRPL)
+		return -1;
+	return 0;
+}
+
+
 
-				if ((proto==IP_FW_F_ICMP ||
-					(port_match(&f->ports[0],f->n_src_p,src_port,
-					f->flags&IP_FW_F_SRNG) &&
-					port_match(&f->ports[f->n_src_p],f->n_dst_p,dst_port,
-					f->flags&IP_FW_F_DRNG)))
-					|| ((rev)   
-						&& (port_match(&f->ports[0],f->n_src_p,dst_port,
-                        	                f->flags&IP_FW_F_SRNG)
-						&& port_match(&f->ports[f->n_src_p],f->n_dst_p,src_port,
-	                       	                f->flags&IP_FW_F_DRNG))))
-				{
-					f->p_cnt++;                   /* Rise packet count */
-					/*
-					 * Rise byte count, convert from host to network byte order.
-					 */
-					f->b_cnt+=ntohs(ip->tot_len);
-				} /* Ports match */
-			} /* Proto matches */
-		}  /* ALL/Specific */
-	} /* IP addr/mask matches */
-} /* End of whole function */
-#endif /* CONFIG_IP_ACCT */
 
-#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
 
 static void zero_fw_chain(struct ip_fw *chainptr)
 {
 	struct ip_fw *ctmp=chainptr;
 	while(ctmp) 
 	{
-		ctmp->p_cnt=0l;
-		ctmp->b_cnt=0l;
-		ctmp=ctmp->next;
+		ctmp->fw_pcnt=0L;
+		ctmp->fw_bcnt=0L;
+		ctmp=ctmp->fw_next;
 	}
 }
 
@@ -446,7 +365,7 @@
 	{
 		struct ip_fw *ftmp;
 		ftmp = *chainptr;
-		*chainptr = ftmp->next;
+		*chainptr = ftmp->fw_next;
 		kfree_s(ftmp,sizeof(*ftmp));
 	}
 	restore_flags(flags);
@@ -475,15 +394,15 @@
 #ifdef DEBUG_CONFIG_IP_FIREWALL
 		printf("ip_fw_ctl:  malloc said no\n");
 #endif
-		return( ENOSPC );
+		return( ENOMEM );
 	}
 
 	memcpy(ftmp, frwl, sizeof( struct ip_fw ) );
 	
-	ftmp->p_cnt=0L;
-	ftmp->b_cnt=0L;
+	ftmp->fw_pcnt=0L;
+	ftmp->fw_bcnt=0L;
 
-	ftmp->next = NULL;
+	ftmp->fw_next = NULL;
 
 	cli();
 	
@@ -494,11 +413,11 @@
 	else
 	{
 		chtmp_prev=NULL;
-		for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->next) 
+		for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->fw_next) 
 		{
 			addb4=0;
-			newkind=ftmp->flags & IP_FW_F_KIND;
-			oldkind=chtmp->flags & IP_FW_F_KIND;
+			newkind=ftmp->fw_flg & IP_FW_F_KIND;
+			oldkind=chtmp->fw_flg & IP_FW_F_KIND;
 	
 			if (newkind!=IP_FW_F_ALL 
 				&&  oldkind!=IP_FW_F_ALL
@@ -513,15 +432,15 @@
 			 *	Sorry,but i had to do this....
 			 */
 
-			n_sa=ntohl(ftmp->src.s_addr);
-			n_da=ntohl(ftmp->dst.s_addr);
-			n_sm=ntohl(ftmp->src_mask.s_addr);
-			n_dm=ntohl(ftmp->dst_mask.s_addr);
-
-			o_sa=ntohl(chtmp->src.s_addr);
-			o_da=ntohl(chtmp->dst.s_addr);
-			o_sm=ntohl(chtmp->src_mask.s_addr);
-			o_dm=ntohl(chtmp->dst_mask.s_addr);
+			n_sa=ntohl(ftmp->fw_src.s_addr);
+			n_da=ntohl(ftmp->fw_dst.s_addr);
+			n_sm=ntohl(ftmp->fw_smsk.s_addr);
+			n_dm=ntohl(ftmp->fw_dmsk.s_addr);
+
+			o_sa=ntohl(chtmp->fw_src.s_addr);
+			o_da=ntohl(chtmp->fw_dst.s_addr);
+			o_sm=ntohl(chtmp->fw_smsk.s_addr);
+			o_dm=ntohl(chtmp->fw_dmsk.s_addr);
 
 			m_src_mask = o_sm & n_sm;
 			m_dst_mask = o_dm & n_dm;
@@ -563,23 +482,24 @@
 					 *	of ports.
 					 */
 
-					if (ftmp->flags & IP_FW_F_SRNG) 
-						n_sr=ftmp->ports[1]-ftmp->ports[0];
+					if (ftmp->fw_flg & IP_FW_F_SRNG) 
+						n_sr=ftmp->fw_pts[1]-ftmp->fw_pts[0];
 					else 
-						n_sr=(ftmp->n_src_p)?ftmp->n_src_p : 0xFFFF;
+						n_sr=(ftmp->fw_nsp)?
+							ftmp->fw_nsp : 0xFFFF;
 						
-					if (chtmp->flags & IP_FW_F_SRNG) 
-						o_sr=chtmp->ports[1]-chtmp->ports[0];
+					if (chtmp->fw_flg & IP_FW_F_SRNG) 
+						o_sr=chtmp->fw_pts[1]-chtmp->fw_pts[0];
 					else 
-						o_sr=(chtmp->n_src_p)?chtmp->n_src_p : 0xFFFF;
+						o_sr=(chtmp->fw_nsp)?chtmp->fw_nsp : 0xFFFF;
 
 					if (n_sr<o_sr)
 						addb4++;
 					if (n_sr>o_sr)
 						addb4--;
 					
-					n_n=ftmp->n_src_p;
-					n_o=chtmp->n_src_p;
+					n_n=ftmp->fw_nsp;
+					n_o=chtmp->fw_nsp;
 	
 					/*
 					 * Actually this cannot happen as the frwl control
@@ -591,15 +511,15 @@
 						(n_o>(IP_FW_MAX_PORTS-2)))
 						goto skip_check;
 
-					if (ftmp->flags & IP_FW_F_DRNG) 
-					       n_dr=ftmp->ports[n_n+1]-ftmp->ports[n_n];
+					if (ftmp->fw_flg & IP_FW_F_DRNG) 
+					       n_dr=ftmp->fw_pts[n_n+1]-ftmp->fw_pts[n_n];
 					else 
-					       n_dr=(ftmp->n_dst_p)? ftmp->n_dst_p : 0xFFFF;
+					       n_dr=(ftmp->fw_ndp)? ftmp->fw_ndp : 0xFFFF;
 
-					if (chtmp->flags & IP_FW_F_DRNG) 
-						o_dr=chtmp->ports[n_o+1]-chtmp->ports[n_o];
+					if (chtmp->fw_flg & IP_FW_F_DRNG) 
+						o_dr=chtmp->fw_pts[n_o+1]-chtmp->fw_pts[n_o];
 					else 
-						o_dr=(chtmp->n_dst_p)? chtmp->n_dst_p : 0xFFFF;
+						o_dr=(chtmp->fw_ndp)? chtmp->fw_ndp : 0xFFFF;
 					if (n_dr<o_dr)
 						addb4++;
 					if (n_dr>o_dr)
@@ -611,13 +531,13 @@
 			{
 				if (chtmp_prev) 
 				{
-					chtmp_prev->next=ftmp; 
-					ftmp->next=chtmp;
+					chtmp_prev->fw_next=ftmp; 
+					ftmp->fw_next=chtmp;
 				} 
 				else 
 				{
 					*chainptr=ftmp;
-					ftmp->next=chtmp;
+					ftmp->fw_next=chtmp;
 				}
 				restore_flags(flags);
 				return 0;
@@ -627,7 +547,7 @@
 	}
 	
 	if (chtmp_prev)
-		chtmp_prev->next=ftmp;
+		chtmp_prev->fw_next=ftmp;
 	else
         	*chainptr=ftmp;
 	restore_flags(flags);
@@ -649,7 +569,7 @@
 	if ( ftmp == NULL ) 
 	{
 #ifdef DEBUG_CONFIG_IP_FIREWALL
-		printf("ip_fw_ctl:  chain is empty\n");
+		printk("ip_fw_ctl:  chain is empty\n");
 #endif
 		restore_flags(flags);
 		return( EINVAL );
@@ -661,21 +581,22 @@
 	while( ftmp != NULL )
 	{
 		matches=1;
-		if ((memcmp(&ftmp->src,&frwl->src,sizeof(struct in_addr))) 
-     			|| (memcmp(&ftmp->src_mask,&frwl->src_mask,sizeof(struct in_addr)))
-     			|| (memcmp(&ftmp->dst,&frwl->dst,sizeof(struct in_addr)))
-     			|| (memcmp(&ftmp->dst_mask,&frwl->dst_mask,sizeof(struct in_addr)))
-     			|| (ftmp->flags!=frwl->flags))
+	     if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr 
+		     ||  ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr
+		     ||  ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr
+		     ||  ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr
+		     ||  ftmp->fw_via.s_addr!=frwl->fw_via.s_addr
+		     ||  ftmp->fw_flg!=frwl->fw_flg)
         		matches=0;
 
-		tport1=ftmp->n_src_p+ftmp->n_dst_p;
-		tport2=frwl->n_src_p+frwl->n_dst_p;
+		tport1=ftmp->fw_nsp+ftmp->fw_ndp;
+		tport2=frwl->fw_nsp+frwl->fw_ndp;
 		if (tport1!=tport2)
 		        matches=0;
 		else if (tport1!=0)
 		{
 			for (tmpnum=0;tmpnum < tport1 && tmpnum < IP_FW_MAX_PORTS;tmpnum++)
-        		if (ftmp->ports[tmpnum]!=frwl->ports[tmpnum])
+        		if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum])
         			matches=0;
 		}
 		if(matches)
@@ -683,13 +604,13 @@
 			was_found=1;
 			if (ltmp)
 			{
-				ltmp->next=ftmp->next;
+				ltmp->fw_next=ftmp->fw_next;
 				kfree_s(ftmp,sizeof(*ftmp));
-				ftmp=ltmp->next;
+				ftmp=ltmp->fw_next;
         		}
       			else
       			{
-      				*chainptr=ftmp->next; 
+      				*chainptr=ftmp->fw_next; 
 	 			kfree_s(ftmp,sizeof(*ftmp));
 				ftmp=*chainptr;
 			}       
@@ -697,7 +618,7 @@
 		else
 		{
 			ltmp = ftmp;
-			ftmp = ftmp->next;
+			ftmp = ftmp->fw_next;
 		 }
 	}
 	restore_flags(flags);
@@ -715,44 +636,44 @@
 	if ( len != sizeof(struct ip_fw) )
 	{
 #ifdef DEBUG_CONFIG_IP_FIREWALL
-		printf("ip_fw_ctl: len=%d, want %d\n",m->m_len,
+		printk("ip_fw_ctl: len=%d, want %d\n",m->m_len,
 					sizeof(struct ip_fw));
 #endif
 		return(NULL);
 	}
 
-	if ( (frwl->flags & ~IP_FW_F_MASK) != 0 )
+	if ( (frwl->fw_flg & ~IP_FW_F_MASK) != 0 )
 	{
 #ifdef DEBUG_CONFIG_IP_FIREWALL
-		printf("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
-			frwl->flags);
+		printk("ip_fw_ctl: undefined flag bits set (flags=%x)\n",
+			frwl->fw_flg);
 #endif
 		return(NULL);
 	}
 
-	if ( (frwl->flags & IP_FW_F_SRNG) && frwl->n_src_p < 2 ) 
+	if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 ) 
 	{
 #ifdef DEBUG_CONFIG_IP_FIREWALL
-		printf("ip_fw_ctl: src range set but n_src_p=%d\n",
-			frwl->n_src_p);
+		printk("ip_fw_ctl: src range set but n_src_p=%d\n",
+			frwl->fw_nsp);
 #endif
 		return(NULL);
 	}
 
-	if ( (frwl->flags & IP_FW_F_DRNG) && frwl->n_dst_p < 2 ) 
+	if ( (frwl->fw_flg & IP_FW_F_DRNG) && frwl->fw_ndp < 2 ) 
 	{
 #ifdef DEBUG_CONFIG_IP_FIREWALL
-		printf("ip_fw_ctl: dst range set but n_dst_p=%d\n",
-			frwl->n_dst_p);
+		printk("ip_fw_ctl: dst range set but n_dst_p=%d\n",
+			frwl->fw_ndp);
 #endif
 		return(NULL);
 	}
 
-	if ( frwl->n_src_p + frwl->n_dst_p > IP_FW_MAX_PORTS ) 
+	if ( frwl->fw_nsp + frwl->fw_ndp > IP_FW_MAX_PORTS ) 
 	{
 #ifdef DEBUG_CONFIG_IP_FIREWALL
-		printf("ip_fw_ctl: too many ports (%d+%d)\n",
-			frwl->n_src_p,frwl->n_dst_p);
+		printk("ip_fw_ctl: too many ports (%d+%d)\n",
+			frwl->fw_nsp,frwl->fw_ndp);
 #endif
 		return(NULL);
 	}
@@ -764,6 +685,12 @@
 
 
 #ifdef CONFIG_IP_ACCT
+
+int ip_acct_cnt(struct iphdr *iph, struct device *dev, struct ip_fw *f)
+{
+	return ip_fw_chk(iph, dev, f, 0);
+}
+
 int ip_acct_ctl(int stage, void *m, int len)
 {
 	if ( stage == IP_ACCT_FLUSH )
@@ -839,8 +766,6 @@
 	{
 		int *tmp_policy_ptr;
 		tmp_policy_ptr=(int *)m;
-		if ((*tmp_policy_ptr)!=1 && (*tmp_policy_ptr)!=0)
-			return (EINVAL);
 		if ( stage == IP_FW_POLICY_BLK )
 			ip_fw_blk_policy=*tmp_policy_ptr;
 		else
@@ -872,7 +797,7 @@
 			return(EINVAL);
 		}
 
-		if ( ip_fw_chk(ip,
+		if ( ip_fw_chk(ip, NULL,
 			stage == IP_FW_CHK_BLK ?
 	                ip_fw_blk_chain : ip_fw_fwd_chain,
 			stage == IP_FW_CHK_BLK ?
@@ -912,7 +837,7 @@
 	 		 *	Should be panic but... (Why are BSD people panic obsessed ??)
 			 */
 #ifdef DEBUG_CONFIG_IP_FIREWALL
-				printf("ip_fw_ctl:  unknown request %d\n",stage);
+				printk("ip_fw_ctl:  unknown request %d\n",stage);
 #endif
 				return(EINVAL);
 		}
@@ -968,16 +893,16 @@
 	
 	while(i!=NULL)
 	{
-		len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %X ",
-			ntohl(i->src.s_addr),ntohl(i->src_mask.s_addr),
-			ntohl(i->dst.s_addr),ntohl(i->dst_mask.s_addr),
-			i->flags);
+		len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %08lX %X ",
+			ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr),
+			ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr),
+			ntohl(i->fw_via.s_addr),i->fw_flg);
 		len+=sprintf(buffer+len,"%u %u %lu %lu ",
-			i->n_src_p,i->n_dst_p, i->p_cnt,i->b_cnt);
+			i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt);
 		len+=sprintf(buffer+len,"%u %u %u %u %u %u %u %u %u %u\n",
-			i->ports[0],i->ports[1],i->ports[2],i->ports[3],	
-			i->ports[4],i->ports[5],i->ports[6],i->ports[7],	
-			i->ports[8],i->ports[9]);	
+			i->fw_pts[0],i->fw_pts[1],i->fw_pts[2],i->fw_pts[3],	
+			i->fw_pts[4],i->fw_pts[5],i->fw_pts[6],i->fw_pts[7],	
+			i->fw_pts[8],i->fw_pts[9]);	
 		pos=begin+len;
 		if(pos<offset)
 		{
@@ -987,12 +912,12 @@
 		else if(reset)
 		{
 			/* This needs to be done at this specific place! */
-			i->p_cnt=0L;
-			i->b_cnt=0L;
+			i->fw_pcnt=0L;
+			i->fw_bcnt=0L;
 		}
 		if(pos>offset+length)
 			break;
-		i=i->next;
+		i=i->fw_next;
 	}
 	restore_flags(flags);
 	*start=buffer+(offset-begin);
@@ -1005,23 +930,38 @@
 
 #ifdef CONFIG_IP_ACCT
 
-int ip_acct_procinfo(char *buffer, char **start, off_t offset, int length, int reset)
+int ip_acct_procinfo(char *buffer, char **start, off_t offset, int length)
 {
-	return ip_chain_procinfo(IP_INFO_ACCT,buffer,start,offset,length,reset);
+	return ip_chain_procinfo(IP_INFO_ACCT, buffer,start,offset,length,0);
+}
+
+int ip_acct0_procinfo(char *buffer, char **start, off_t offset, int length)
+{
+	return ip_chain_procinfo(IP_INFO_ACCT, buffer,start,offset,length,1);
 }
 
 #endif
 
 #ifdef CONFIG_IP_FIREWALL
 
-int ip_fw_blk_procinfo(char *buffer, char **start, off_t offset, int length, int reset)
+int ip_fw_blk_procinfo(char *buffer, char **start, off_t offset, int length)
+{
+	return ip_chain_procinfo(IP_INFO_BLK, buffer,start,offset,length,0);
+}
+
+int ip_fw_blk0_procinfo(char *buffer, char **start, off_t offset, int length)
+{
+	return ip_chain_procinfo(IP_INFO_BLK, buffer,start,offset,length,1);
+}
+
+int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset, int length)
 {
-	return ip_chain_procinfo(IP_INFO_BLK,buffer,start,offset,length,reset);
+	return ip_chain_procinfo(IP_INFO_FWD, buffer,start,offset,length,0);
 }
 
-int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset, int length, int reset)
+int ip_fw_fwd0_procinfo(char *buffer, char **start, off_t offset, int length)
 {
-	return ip_chain_procinfo(IP_INFO_FWD,buffer,start,offset,length,reset);
+	return ip_chain_procinfo(IP_INFO_FWD, buffer,start,offset,length,1);
 }
 
 #endif
diff -u --recursive --new-file v1.1.94/linux/net/inet/ipx.c linux/net/inet/ipx.c
--- v1.1.94/linux/net/inet/ipx.c	Wed Feb 15 10:36:41 1995
+++ linux/net/inet/ipx.c	Thu Feb 23 13:31:40 1995
@@ -1276,8 +1276,6 @@
 			switch(optname)
 			{
 				case IPX_TYPE:
-					if(!suser())
-						return(-EPERM);
 					sk->ipx_type=opt;
 					return 0;
 				default:
@@ -1681,9 +1679,6 @@
 			return -EINVAL;
 		if(usipx->sipx_family != AF_IPX)
 			return -EINVAL;
-
-		if(htons(usipx->sipx_port)<IPX_MIN_EPHEMERAL_SOCKET && !suser())
-			return -EPERM;
 	} else {
 		if(sk->state!=TCP_ESTABLISHED)
 			return -ENOTCONN;
diff -u --recursive --new-file v1.1.94/linux/net/socket.c linux/net/socket.c
--- v1.1.94/linux/net/socket.c	Sun Feb  5 19:31:56 1995
+++ linux/net/socket.c	Thu Feb 23 13:26:45 1995
@@ -1,7 +1,7 @@
 /*
  * NET		An implementation of the SOCKET network access protocol.
  *
- * Version:	@(#)socket.c	1.0.5	05/25/93
+ * Version:	@(#)socket.c	1.1.93	18/02/95
  *
  * Authors:	Orest Zborowski, <obz@Kodak.COM>
  *		Ross Biro, <bir7@leland.Stanford.Edu>
@@ -29,6 +29,9 @@
  *					allowed to allocate.
  *		Linus		:	Argh. removed all the socket allocation
  *					altogether: it's in the inode now.
+ *		Alan Cox	:	Made sock_alloc()/sock_release() public
+ *					for NetROM and future kernel nfsd type
+ *					stuff.
  *
  *
  *		This program is free software; you can redistribute it and/or
@@ -225,7 +228,8 @@
 /*
  *	Allocate a socket.
  */
-static struct socket *sock_alloc(void)
+
+struct socket *sock_alloc(void)
 {
 	struct inode * inode;
 	struct socket * sock;
@@ -265,8 +269,7 @@
 	sock_wake_async(peer, 1);
 }
 
-
-static void sock_release(struct socket *sock)
+void sock_release(struct socket *sock)
 {
 	int oldstate;
 	struct socket *peersock, *nextsock;
