diff -u --recursive --new-file v2.1.2/linux/CREDITS linux/CREDITS
--- v2.1.2/linux/CREDITS	Wed Oct  9 08:55:16 1996
+++ linux/CREDITS	Thu Oct 10 11:36:39 1996
@@ -285,6 +285,7 @@
 N: Ray Dassen
 E: jdassen@wi.LeidenUniv.nl
 W: http://www.wi.leidenuniv.nl/~jdassen/
+P: 1024/672D05C1 DD 60 32 60 F7 90 64 80  E7 6F D4 E4 F8 C9 4A 58
 D: Debian GNU/Linux: www.debian.org maintainer, FAQ co-maintainer,
 D: packages testing, nit-picking & fixing. Enjoying BugFree (TM) kernels.
 S: Zuidsingel 10A
diff -u --recursive --new-file v2.1.2/linux/Makefile linux/Makefile
--- v2.1.2/linux/Makefile	Wed Oct  9 08:55:16 1996
+++ linux/Makefile	Wed Oct  9 08:54:36 1996
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 2
+SUBLEVEL = 3
 
 ARCH = i386
 
diff -u --recursive --new-file v2.1.2/linux/arch/alpha/kernel/ksyms.c linux/arch/alpha/kernel/ksyms.c
--- v2.1.2/linux/arch/alpha/kernel/ksyms.c	Sun Aug  4 13:37:59 1996
+++ linux/arch/alpha/kernel/ksyms.c	Thu Oct 10 16:19:17 1996
@@ -54,10 +54,12 @@
 	X(__remlu),
 	X(__divqu),
 	X(__remqu),
-	X(insl),
+	X(insb),
 	X(insw),
-	X(outsl),
+	X(insl),
+	X(outsb),
 	X(outsw),
+	X(outsl),
 	X(strcat),
 	X(strcmp),
 	X(strcpy),
diff -u --recursive --new-file v2.1.2/linux/arch/alpha/kernel/lca.c linux/arch/alpha/kernel/lca.c
--- v2.1.2/linux/arch/alpha/kernel/lca.c	Wed Oct  9 08:55:16 1996
+++ linux/arch/alpha/kernel/lca.c	Thu Oct 10 08:54:43 1996
@@ -429,7 +429,7 @@
 	switch (el.c->size) {
 	      case sizeof(struct el_lca_mcheck_short):
 		printk(KERN_CRIT
-		       "  Reason: %s (short frame%s, dc_stat=%lx):\pn",
+		       "  Reason: %s (short frame%s, dc_stat=%lx):\n",
 		       reason, el.c->retry ? ", retryable" : "", el.s->dc_stat);
 		if (el.s->esr & ESR_EAV) {
 		    mem_error(el.s->esr, el.s->ear);
diff -u --recursive --new-file v2.1.2/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.1.2/linux/arch/alpha/kernel/osf_sys.c	Sun Aug 18 10:42:02 1996
+++ linux/arch/alpha/kernel/osf_sys.c	Thu Oct 10 08:48:47 1996
@@ -18,7 +18,6 @@
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/malloc.h>
-#include <linux/ldt.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/utsname.h>
diff -u --recursive --new-file v2.1.2/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.1.2/linux/arch/alpha/kernel/process.c	Mon Sep  9 13:06:24 1996
+++ linux/arch/alpha/kernel/process.c	Wed Oct  9 07:58:02 1996
@@ -17,7 +17,6 @@
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/malloc.h>
-#include <linux/ldt.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/utsname.h>
diff -u --recursive --new-file v2.1.2/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v2.1.2/linux/arch/alpha/kernel/setup.c	Sun Aug 18 10:37:57 1996
+++ linux/arch/alpha/kernel/setup.c	Thu Oct 10 08:48:54 1996
@@ -16,7 +16,6 @@
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/malloc.h>
-#include <linux/ldt.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
diff -u --recursive --new-file v2.1.2/linux/arch/i386/kernel/ksyms.c linux/arch/i386/kernel/ksyms.c
--- v2.1.2/linux/arch/i386/kernel/ksyms.c	Sat Oct  5 16:58:34 1996
+++ linux/arch/i386/kernel/ksyms.c	Thu Oct 10 17:23:20 1996
@@ -4,6 +4,7 @@
 #include <linux/elfcore.h>
 
 #include <asm/semaphore.h>
+#include <asm/processor.h>
 #include <asm/io.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
@@ -12,6 +13,8 @@
 static struct symbol_table arch_symbol_table = {
 #include <linux/symtab_begin.h>
 	/* platform dependent support */
+	X(EISA_bus),
+	X(wp_works_ok),
 	X(dump_thread),
 	X(dump_fpu),
 	X(ioremap),
diff -u --recursive --new-file v2.1.2/linux/arch/i386/math-emu/errors.c linux/arch/i386/math-emu/errors.c
--- v2.1.2/linux/arch/i386/math-emu/errors.c	Mon May  6 16:31:17 1996
+++ linux/arch/i386/math-emu/errors.c	Thu Oct 10 16:01:11 1996
@@ -292,7 +292,7 @@
 	      0x242  in div_Xsig.S
  */
 
-void exception(int n)
+void FPU_exception(int n)
 {
   int i, int_type;
 
@@ -482,7 +482,7 @@
     }
   else
     {
-      exception(flags);
+      EXCEPTION(flags);
       return 1;
     }
 }
@@ -494,7 +494,7 @@
   if ( control_word & CW_Precision )
     partial_status |= (SW_Precision | SW_C1);   /* The masked response */
   else
-    exception(EX_Precision | SW_C1);
+    EXCEPTION(EX_Precision | SW_C1);
 
 }
 
@@ -508,7 +508,7 @@
       partial_status |= SW_Precision;
     }
   else
-    exception(EX_Precision);
+    EXCEPTION(EX_Precision);
 }
 
 
@@ -521,7 +521,7 @@
     }
   else
     {
-      exception(EX_Denormal);
+      EXCEPTION(EX_Denormal);
       return 1;
     }
 }
diff -u --recursive --new-file v2.1.2/linux/arch/i386/math-emu/exception.h linux/arch/i386/math-emu/exception.h
--- v2.1.2/linux/arch/i386/math-emu/exception.h	Thu Jun 29 18:25:27 1995
+++ linux/arch/i386/math-emu/exception.h	Thu Oct 10 16:01:12 1996
@@ -43,9 +43,9 @@
 
 #ifdef DEBUG
 #define	EXCEPTION(x)	{ printk("exception in %s at line %d\n", \
-	__FILE__, __LINE__); exception(x); }
+	__FILE__, __LINE__); FPU_exception(x); }
 #else
-#define	EXCEPTION(x)	exception(x)
+#define	EXCEPTION(x)	FPU_exception(x)
 #endif
 
 #endif __ASSEMBLY__
diff -u --recursive --new-file v2.1.2/linux/arch/i386/math-emu/fpu_asm.h linux/arch/i386/math-emu/fpu_asm.h
--- v2.1.2/linux/arch/i386/math-emu/fpu_asm.h	Thu Oct  5 15:30:43 1995
+++ linux/arch/i386/math-emu/fpu_asm.h	Thu Oct 10 16:01:12 1996
@@ -12,7 +12,7 @@
 
 #include <linux/linkage.h>
 
-#define	EXCEPTION	SYMBOL_NAME(exception)
+#define	EXCEPTION	SYMBOL_NAME(FPU_exception)
 
 
 #define PARAM1	8(%ebp)
diff -u --recursive --new-file v2.1.2/linux/arch/i386/math-emu/fpu_proto.h linux/arch/i386/math-emu/fpu_proto.h
--- v2.1.2/linux/arch/i386/math-emu/fpu_proto.h	Mon Aug  1 08:19:13 1994
+++ linux/arch/i386/math-emu/fpu_proto.h	Thu Oct 10 16:01:12 1996
@@ -7,7 +7,7 @@
 extern void stack_underflow_i(int i);
 extern void stack_underflow_pop(int i);
 extern int set_precision_flag(int flags);
-asmlinkage void exception(int n);
+asmlinkage void FPU_exception(int n);
 asmlinkage int real_2op_NaN(FPU_REG const *a, FPU_REG const *b, FPU_REG *dest);
 asmlinkage int arith_invalid(FPU_REG *dest);
 asmlinkage int divide_by_zero(int sign, FPU_REG *dest);
diff -u --recursive --new-file v2.1.2/linux/arch/i386/math-emu/reg_norm.S linux/arch/i386/math-emu/reg_norm.S
--- v2.1.2/linux/arch/i386/math-emu/reg_norm.S	Thu Oct  5 15:30:43 1995
+++ linux/arch/i386/math-emu/reg_norm.S	Thu Oct 10 16:01:12 1996
@@ -30,7 +30,7 @@
 	je	L_ok
 
 	pushl	$0x220
-	call	SYMBOL_NAME(exception)
+	call	SYMBOL_NAME(FPU_exception)
 	addl	$4,%esp
 
 L_ok:
@@ -107,7 +107,7 @@
 	je	L_ok_nuo
 
 	pushl	$0x221
-	call	SYMBOL_NAME(exception)
+	call	SYMBOL_NAME(FPU_exception)
 	addl	$4,%esp
 
 L_ok_nuo:
diff -u --recursive --new-file v2.1.2/linux/arch/i386/math-emu/reg_round.S linux/arch/i386/math-emu/reg_round.S
--- v2.1.2/linux/arch/i386/math-emu/reg_round.S	Thu Oct  5 15:30:43 1995
+++ linux/arch/i386/math-emu/reg_round.S	Thu Oct 10 16:01:12 1996
@@ -596,7 +596,7 @@
 	/* There must be a masked underflow */
 	push	%eax
 	pushl	EX_Underflow
-	call	SYMBOL_NAME(exception)
+	call	SYMBOL_NAME(FPU_exception)
 	popl	%eax
 	popl	%eax
 	jmp	xL_Normalised
@@ -613,7 +613,7 @@
 
 	push	%eax
 	pushl	EX_Underflow
-	call	SYMBOL_NAME(exception)
+	call	SYMBOL_NAME(FPU_exception)
 	popl	%eax
 	popl	%eax
 
diff -u --recursive --new-file v2.1.2/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
--- v2.1.2/linux/arch/i386/mm/fault.c	Wed Oct  9 08:55:17 1996
+++ linux/arch/i386/mm/fault.c	Thu Oct 10 17:09:51 1996
@@ -22,6 +22,57 @@
 extern void die_if_kernel(const char *,struct pt_regs *,long);
 
 /*
+ * Ugly, ugly, but the goto's result in better assembly..
+ */
+int __verify_write(const void * addr, unsigned long size)
+{
+	struct vm_area_struct * vma;
+	unsigned long start = (unsigned long) addr;
+
+	if (!size)
+		return 0;
+
+	vma = find_vma(current->mm, start);
+	if (!vma)
+		goto bad_area;
+	if (vma->vm_start > start)
+		goto check_stack;
+
+good_area:
+	if (!(vma->vm_flags & VM_WRITE))
+		goto bad_area;
+	size--;
+	size += start & ~PAGE_MASK;
+	size >>= PAGE_SHIFT;
+	start &= PAGE_MASK;
+
+	for (;;) {
+		do_wp_page(current, vma, start, 1);
+		if (!size)
+			break;
+		size--;
+		start += PAGE_SIZE;
+		if (start < vma->vm_end)
+			continue;
+		vma = vma->vm_next;
+		if (!vma || vma->vm_start != start)
+			goto bad_area;
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;;
+	}
+	return 0;
+
+check_stack:
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+	if (expand_stack(vma, start) == 0)
+		goto good_area;
+
+bad_area:
+	return -EFAULT;
+}
+
+/*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
  * routines.
diff -u --recursive --new-file v2.1.2/linux/drivers/block/md.c linux/drivers/block/md.c
--- v2.1.2/linux/drivers/block/md.c	Sun Jun 30 00:04:00 1996
+++ linux/drivers/block/md.c	Wed Oct  9 20:11:11 1996
@@ -439,6 +439,10 @@
 #include <linux/symtab_end.h>
 };
 
+static struct proc_dir_entry proc_md = {
+	PROC_MD, 6, "mdstat",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
 
 static void md_geninit (struct gendisk *gdisk)
 {
@@ -455,12 +459,7 @@
   blksize_size[MAJOR_NR] = md_blocksizes;
   register_symtab (&md_symbol_table);
 
-  proc_register(&proc_root,
-		&(struct proc_dir_entry)
-	      {
-		PROC_MD, 6, "mdstat",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	      });
+  proc_register(&proc_root, &proc_md);
 }
 
 
diff -u --recursive --new-file v2.1.2/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.1.2/linux/drivers/char/misc.c	Thu Aug 22 18:45:56 1996
+++ linux/drivers/char/misc.c	Wed Oct  9 20:11:11 1996
@@ -184,16 +184,18 @@
 #include <linux/symtab_end.h>
 };
 
+static struct proc_dir_entry proc_misc = {
+	0, 4, "misc",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, NULL /* ops -- default to array */,
+	&proc_misc_read /* get_info */,
+};
+
 int misc_init(void)
 {
 #ifndef MODULE
 #ifdef CONFIG_PROC_FS
-	proc_register_dynamic(&proc_root, &(struct proc_dir_entry) {
-		0, 4, "misc",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, NULL /* ops -- default to array */,
-		&proc_misc_read /* get_info */,
-	});	
+	proc_register_dynamic(&proc_root, &proc_misc);	
 #endif /* PROC_FS */
 #ifdef CONFIG_BUSMOUSE
 	bus_mouse_init();
diff -u --recursive --new-file v2.1.2/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c
--- v2.1.2/linux/drivers/char/tpqic02.c	Mon Sep 30 10:38:10 1996
+++ linux/drivers/char/tpqic02.c	Thu Oct 10 08:14:23 1996
@@ -471,12 +471,12 @@
 } /* ifc_init */
 
 
-static void report_exception(unsigned n)
+static void report_qic_exception(unsigned n)
 {
-	if (n >= NR_OF_EXC) { tpqputs(TPQD_ALWAYS, "Oops -- report_exception"); n = 0; }
+	if (n >= NR_OF_EXC) { tpqputs(TPQD_ALWAYS, "Oops -- report_qic_exception"); n = 0; }
 	if (TPQDBG(SENSE_TEXT) || n==0)
 		printk(TPQIC02_NAME ": sense: %s\n", exception_list[n].msg);
-} /* report_exception */
+} /* report_qic_exception */
 
 
 /* Try to map the drive-exception bits `s' to a predefined "exception number",
@@ -484,7 +484,7 @@
  * exception table (`exception_list[]').
  * It is assumed that s!=0.
  */
-static int decode_exception_nr(unsigned s)
+static int decode_qic_exception_nr(unsigned s)
 {
 	int i;
 
@@ -492,9 +492,9 @@
 		if ((s & exception_list[i].mask)==exception_list[i].code)
 			return i;
 	}
-	printk(TPQIC02_NAME ": decode_exception_nr: exception(%x) not recognized\n", s);
+	printk(TPQIC02_NAME ": decode_qic_exception_nr: exception(%x) not recognized\n", s);
 	return 0;
-} /* decode_exception_nr */
+} /* decode_qic_exception_nr */
 
 
 #ifdef OBSOLETE
@@ -576,7 +576,7 @@
 /* Perform appropriate action for certain exceptions.
  * should return a value to indicate stop/continue (in case of bad blocks)
  */
-static void handle_exception(int exnr, int exbits)
+static void handle_qic_exception(int exnr, int exbits)
 {
 	if (exnr==EXC_NCART) {
 		/* Cartridge was changed. Redo sense().
@@ -600,7 +600,7 @@
 		doing_read = NO;
 	} else if (exnr==EXC_FM)
 		doing_read = NO;
-} /* handle_exception */
+} /* handle_qic_exception */
 
 
 static inline int is_exception(void)
@@ -1035,9 +1035,9 @@
 
 	if (err & (TP_ST0|TP_ST1)) {
 		/* My Wangtek occasionally reports `status' 1212 which should be ignored. */
-		exnr = decode_exception_nr(err);
-		handle_exception(exnr, err);		/* update driver state wrt drive status */
-		report_exception(exnr);
+		exnr = decode_qic_exception_nr(err);
+		handle_qic_exception(exnr, err);		/* update driver state wrt drive status */
+		report_qic_exception(exnr);
 	}
 	err &= ~ignore;		/* mask unwanted errors -- not the correct way, use exception nrs?? */
 	if (((err & TP_ST0) && (err & REPORT_ERR0)) ||
diff -u --recursive --new-file v2.1.2/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.1.2/linux/drivers/net/Config.in	Mon May 20 08:08:36 1996
+++ linux/drivers/net/Config.in	Wed Oct  9 09:57:20 1996
@@ -82,10 +82,8 @@
       tristate 'ICL EtherTeam 16i/32 support' CONFIG_ETH16I
     fi
     tristate 'NE2000/NE1000 support' CONFIG_NE2000
-    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      tristate 'NI5210 support' CONFIG_NI52
-      bool 'NI6510 support' CONFIG_NI65
-    fi
+    tristate 'NI5210 support' CONFIG_NI52
+    tristate 'NI6510 support' CONFIG_NI65
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       bool 'SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005
     fi
diff -u --recursive --new-file v2.1.2/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.1.2/linux/drivers/net/Makefile	Mon May  6 12:44:31 1996
+++ linux/drivers/net/Makefile	Wed Oct  9 09:57:20 1996
@@ -360,6 +360,10 @@
 
 ifeq ($(CONFIG_NI65),y)
 L_OBJS += ni65.o
+else
+  ifeq ($(CONFIG_NI65),m)
+  M_OBJS += ni65.o
+  endif
 endif
 
 ifeq ($(CONFIG_ELPLUS),y)
diff -u --recursive --new-file v2.1.2/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.1.2/linux/drivers/net/Space.c	Mon Jun  3 12:42:41 1996
+++ linux/drivers/net/Space.c	Wed Oct  9 09:57:20 1996
@@ -195,6 +195,9 @@
 #ifdef CONFIG_NI52
 	&& ni52_probe(dev)
 #endif
+#ifdef CONFIG_NI65
+        && ni65_probe(dev)
+#endif
 #ifdef CONFIG_ATARILANCE	/* Lance-based Atari ethernet boards */
 	&& atarilance_probe(dev)
 #endif
diff -u --recursive --new-file v2.1.2/linux/drivers/net/ni52.c linux/drivers/net/ni52.c
--- v2.1.2/linux/drivers/net/ni52.c	Fri Apr 12 09:49:38 1996
+++ linux/drivers/net/ni52.c	Wed Oct  9 09:57:20 1996
@@ -4,13 +4,15 @@
  * This is an extension to the Linux operating system, and is covered by the
  * same Gnu Public License that covers that work.
  * 
- * Alphacode 0.80 (96/02/19) for Linux 1.3.66 (or later)
+ * Alphacode 0.82 (96/09/29) for Linux 2.0.0 (or later)
  * Copyrights (c) 1994,1995,1996 by M.Hipp (Michael.Hipp@student.uni-tuebingen.de)
  *    [feel free to mail ....]
  *
  * when using as module: (no autoprobing!)
- *   compile with: gcc -D__KERNEL__ -DMODULE -O2 -c ni52.c
- *   run with e.g: insmod ni52.o io=0x360 irq=9 memstart=0xd0000 memend=0xd4000
+ *   compile with:
+ *       gcc -O2 -fomit-frame-pointer -m486 -D__KERNEL__ -DMODULE -c ni52.c
+ *   run with e.g:
+ *       insmod ni52.o io=0x360 irq=9 memstart=0xd0000 memend=0xd4000
  *
  * CAN YOU PLEASE REPORT ME YOUR PERFORMANCE EXPERIENCES !!.
  * 
@@ -62,6 +64,7 @@
  */
 
 /*
+ * 29.Sept.96: virt_to_bus changes for new memory scheme 
  * 19.Feb.96: more Mcast changes, module support (MH)
  *
  * 18.Nov.95: Mcast changes (AC).
@@ -129,8 +132,8 @@
 #define ni_enaint()   {outb(0,dev->base_addr+NI52_INTENA);}
 
 #define make32(ptr16) (p->memtop + (short) (ptr16) )
-#define make24(ptr32) ((char *) (ptr32) - p->base)
-#define make16(ptr32) ((unsigned short) ((unsigned long) (ptr32) - (unsigned long) p->memtop ))
+#define make24(ptr32) ( ((char *) (ptr32)) - p->base)
+#define make16(ptr32) ((unsigned short) ((unsigned long)(ptr32) - (unsigned long) p->memtop ))
 
 /******************* how to calculate the buffers *****************************
 
@@ -285,8 +288,8 @@
   char *iscp_addrs[2];
   int i;
 
-  p->base = (unsigned long) where + size - 0x01000000;
-  p->memtop = where + size;
+  p->base = (unsigned long) bus_to_virt((unsigned long)where) + size - 0x01000000;
+  p->memtop = bus_to_virt((unsigned long)where) + size;
   p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
   memset((char *)p->scp,0, sizeof(struct scp_struct));
   for(i=0;i<sizeof(struct scp_struct);i++) /* memory was writeable? */
@@ -296,7 +299,7 @@
   if(p->scp->sysbus != SYSBUSVAL)
     return 0;
   
-  iscp_addrs[0] = where;
+  iscp_addrs[0] = bus_to_virt((unsigned long)where);
   iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct);
 
   for(i=0;i<2;i++)
@@ -328,7 +331,7 @@
   DELAY(1);
 
   p->scp  = (struct scp_struct *)  (p->base + SCP_DEFAULT_ADDRESS);
-  p->scb  = (struct scb_struct *)  (dev->mem_start);
+  p->scb  = (struct scb_struct *)  bus_to_virt(dev->mem_start);
   p->iscp = (struct iscp_struct *) ((char *)p->scp - sizeof(struct iscp_struct));
 
   memset((char *) p->iscp,0,sizeof(struct iscp_struct));
@@ -479,8 +482,8 @@
                                   /* warning: we don't free it on errors */
   memset((char *) dev->priv,0,sizeof(struct priv));
   
-  ((struct priv *) (dev->priv))->memtop = (char *) dev->mem_start + size;
-  ((struct priv *) (dev->priv))->base =  dev->mem_start + size - 0x01000000;
+  ((struct priv *) (dev->priv))->memtop = bus_to_virt(dev->mem_start) + size;
+  ((struct priv *) (dev->priv))->base =  (unsigned long) bus_to_virt(dev->mem_start) + size - 0x01000000;
   alloc586(dev);
 
   /* set number of receive-buffs according to memsize */
diff -u --recursive --new-file v2.1.2/linux/drivers/net/ni65.c linux/drivers/net/ni65.c
--- v2.1.2/linux/drivers/net/ni65.c	Fri Apr 12 09:49:38 1996
+++ linux/drivers/net/ni65.c	Wed Oct  9 09:57:20 1996
@@ -1,8 +1,15 @@
 /*
- * ni6510 (am7990 'lance' chip) driver for Linux-net-3 by MH
- * Alphacode v0.51 (96/02/20) for 1.3.66 (or later)
+ * ni6510 (am7990 'lance' chip) driver for Linux-net-3
+ * BETAcode v0.71 (96/09/29) for 2.0.0 (or later)
+ * copyrights (c) 1994,1995,1996 by M.Hipp
+ * 
+ * This driver can handle the old ni6510 board and the newer ni6510 
+ * EtherBlaster. (probably it also works with every full NE2100 
+ * compatible card)
  *
- * copyright (c) 1994,1995,1996 by M.Hipp
+ * To compile as module, type:
+ *     gcc -O2 -fomit-frame-pointer -m486 -D__KERNEL__ -DMODULE -c ni65.c
+ * driver probes: io: 0x360,0x300,0x320,0x340 / dma: 3,5,6,7
  *
  * This is an extension to the Linux operating system, and is covered by the
  * same Gnu Public License that covers the Linux-kernel.
@@ -16,27 +23,41 @@
  *   and from the original drivers by D.Becker
  *
  * known problems:
- *   on some PCI boards (including my own) the card/board/ISA-bridge has
- *   problems with bus master DMA. This results in lotsa overruns.
- *   It may help to '#define RCV_PARANOIA_CHECK'
- *   or just play with your BIOS options to optimize ISA-DMA access.
+ *   - on some PCI boards (including my own) the card/board/ISA-bridge has
+ *     problems with bus master DMA. This results in lotsa overruns.
+ *     It may help to '#define RCV_PARANOIA_CHECK' or try to #undef
+ *     the XMT and RCV_VIA_SKB option .. this reduces driver performance.
+ *     Or just play with your BIOS options to optimize ISA-DMA access.
+ *     Maybe you also wanna play with the LOW_PERFORAMCE and MID_PERFORMANCE
+ *     defines -> please report me your experience then
+ *   - Harald reported for ASUS SP3G mainboards, that you should use
+ *     the 'optimal settings' from the user's manual on page 3-12!
  *
  * credits:
  *   thanx to Jason Sullivan for sending me a ni6510 card!
+ *   lot of debug runs with ASUS SP3G Boards (Intel Saturn) by Harald Koenig
  *
- * simple performance test:
- *   8.1 seconds for getting a 8MB file via FTP -> near 1MB/s
+ * simple performance test: (486DX-33/Ni6510-EB receives from 486DX4-100/Ni6510-EB)
+ *    average: FTP -> 8384421 bytes received in 8.5 seconds
+ *           (no RCV_VIA_SKB,no XMT_VIA_SKB,PARANOIA_CHECK,4 XMIT BUFS, 8 RCV_BUFFS)
+ *    peak: FTP -> 8384421 bytes received in 7.5 seconds 
+ *           (RCV_VIA_SKB,XMT_VIA_SKB,no PARANOIA_CHECK,1(!) XMIT BUF, 16 RCV BUFFS)
  */
 
 /*
- * 96.Feb.19: fixed a few bugs .. cleanups .. tested for 1.3.66
+ * 96.Sept.29: virt_to_bus stuff added for new memory modell
+ * 96.April.29: Added Harald Koenig's Patches (MH)
+ * 96.April.13: enhanced error handling .. more tests (MH)
+ * 96.April.5/6: a lot of performance tests. Got it stable now (hopefully) (MH)
+ * 96.April.1: (no joke ;) .. added EtherBlaster and Module support (MH)
+ * 96.Feb.19: fixed a few bugs .. cleanups .. tested for 1.3.66 (MH)
  *            hopefully no more 16MB limit
  *
  * 95.Nov.18: multicast tweaked (AC).
  *
  * 94.Aug.22: changes in xmit_intr (ack more than one xmitted-packet), ni65_send_packet (p->lock) (MH)
  *
- * 94,July.16: fixed bugs in recv_skb and skb-alloc stuff  (MH)
+ * 94.July.16: fixed bugs in recv_skb and skb-alloc stuff  (MH)
  */
 
 #include <linux/kernel.h>
@@ -56,75 +77,121 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
+#include <linux/version.h>
+#include <linux/module.h>
+
 #include "ni65.h"
 
 /*
- * the current setting allows max. performance
+ * the current setting allows an acceptable performance
  * for 'RCV_PARANOIA_CHECK' read the 'known problems' part in 
  * the header of this file
+ * 'invert' the defines for max. performance. This may cause DMA problems
+ * on some boards (e.g on my ASUS SP3G)
  */
-#define RCV_VIA_SKB
-#undef RCV_PARANOIA_CHECK
-#define XMT_VIA_SKB
+#undef XMT_VIA_SKB
+#undef RCV_VIA_SKB
+#define RCV_PARANOIA_CHECK
+
+#define MID_PERFORMANCE
+
+#if   defined( LOW_PERFORMANCE )
+ static int isa0=7,isa1=7,csr80=0x0c10;
+#elif defined( MID_PERFORMANCE )
+ static int isa0=5,isa1=5,csr80=0x2810;
+#else	/* high performance */
+ static int isa0=4,isa1=4,csr80=0x0017;
+#endif
 
 /*
- * a few card specific defines
+ * a few card/vendor specific defines
  */
-#define NI65_TOTAL_SIZE    16
-#define NI65_ADDR0 0x02
-#define NI65_ADDR1 0x07
-#define NI65_ADDR2 0x01
-#define NI65_ID0   0x00
-#define NI65_ID1   0x55
+#define NI65_ID0    0x00
+#define NI65_ID1    0x55
+#define NI65_EB_ID0 0x52
+#define NI65_EB_ID1 0x44
+#define NE2100_ID0  0x57
+#define NE2100_ID1  0x57
 
-#define PORT dev->base_addr
+#define PORT p->cmdr_addr
 
 /*
  * buffer configuration
  */
+#if 1
+#define RMDNUM 16
+#define RMDNUMMASK 0x80000000 
+#else
 #define RMDNUM 8
 #define RMDNUMMASK 0x60000000 /* log2(RMDNUM)<<29 */
+#endif
+
+#if 0
+#define TMDNUM 1
+#define TMDNUMMASK 0x00000000
+#else
 #define TMDNUM 4
 #define TMDNUMMASK 0x40000000 /* log2(TMDNUM)<<29 */
+#endif
 
-#define R_BUF_SIZE 1536
-#define T_BUF_SIZE 1536
+/* slightly oversized */
+#define R_BUF_SIZE 1544
+#define T_BUF_SIZE 1544
 
 /*
  * lance register defines
  */
 #define L_DATAREG 0x00
 #define L_ADDRREG 0x02
-
 #define L_RESET   0x04
 #define L_CONFIG  0x05
-#define L_EBASE   0x08
+#define L_BUSIF   0x06
 
 /* 
- * to access the am7990-regs, you have to write
+ * to access the lance/am7990-regs, you have to write
  * reg-number into L_ADDRREG, then you can access it using L_DATAREG
  */
-#define CSR0 0x00
-#define CSR1 0x01
-#define CSR2 0x02
-#define CSR3 0x03
+#define CSR0  0x00
+#define CSR1  0x01
+#define CSR2  0x02
+#define CSR3  0x03
+
+#define INIT_RING_BEFORE_START	0x1
+#define FULL_RESET_ON_ERROR	0x2
 
+#if 0
 #define writereg(val,reg) {outw(reg,PORT+L_ADDRREG);inw(PORT+L_ADDRREG); \
                            outw(val,PORT+L_DATAREG);inw(PORT+L_DATAREG);}
 #define readreg(reg) (outw(reg,PORT+L_ADDRREG),inw(PORT+L_ADDRREG),\
                        inw(PORT+L_DATAREG))
+#if 0
 #define writedatareg(val) {outw(val,PORT+L_DATAREG);inw(PORT+L_DATAREG);}
+#else
+#define writedatareg(val) {  writereg(val,CSR0); }
+#endif
+#else
+#define writereg(val,reg) {outw(reg,PORT+L_ADDRREG);outw(val,PORT+L_DATAREG);}
+#define readreg(reg) (outw(reg,PORT+L_ADDRREG),inw(PORT+L_DATAREG))
+#define writedatareg(val) { writereg(val,CSR0); }
+#endif
 
-static int  ni65_probe1(struct device **dev,int);
-static void ni65_interrupt(int irq, void * dev_id, struct pt_regs *regs);
-static void ni65_recv_intr(struct device *dev,int);
-static void ni65_xmit_intr(struct device *dev,int);
-static int  ni65_open(struct device *dev);
-static int  ni65_am7990_reinit(struct device *dev);
-static int  ni65_send_packet(struct sk_buff *skb, struct device *dev);
-static int  ni65_close(struct device *dev);
-static struct enet_statistics *ni65_get_stats(struct device *);
-static void set_multicast_list(struct device *dev);
+static unsigned char ni_vendor[] = { 0x02,0x07,0x01 };
+
+static struct card {
+	unsigned char id0,id1;
+	short id_offset;
+	short total_size;
+	short cmd_offset;
+	short addr_offset;
+	unsigned char *vendor_id;
+	char *cardname;
+	unsigned char config;
+} cards[] = {
+	{ NI65_ID0,NI65_ID1,0x0e,0x10,0x0,0x8,ni_vendor,"ni6510", 0x1 } ,
+	{ NI65_EB_ID0,NI65_EB_ID1,0x0e,0x18,0x10,0x0,ni_vendor,"ni6510 EtherBlaster", 0x2 } ,
+	{ NE2100_ID0,NE2100_ID1,0x0e,0x18,0x10,0x0,NULL,"generic NE2100", 0x0 }
+};
+#define NUM_CARDS 3
 
 struct priv 
 {
@@ -142,132 +209,267 @@
   struct sk_buff *tmd_skb[TMDNUM];
 #endif
   void *tmdbounce[TMDNUM];
+  int tmdbouncenum;
   int lock,xmit_queued;
   struct enet_statistics stats;
+  void *self;
+  int cmdr_addr;
+  int cardno;
+  int features;
 }; 
 
+static int  ni65_probe1(struct device *dev,int);
+static void ni65_interrupt(int irq, void * dev_id, struct pt_regs *regs);
+static void ni65_recv_intr(struct device *dev,int);
+static void ni65_xmit_intr(struct device *dev,int);
+static int  ni65_open(struct device *dev);
+static int  ni65_lance_reinit(struct device *dev);
+static void ni65_init_lance(struct priv *p,unsigned char*,int,int);
+static int  ni65_send_packet(struct sk_buff *skb, struct device *dev);
+static int  ni65_close(struct device *dev);
+static int  ni65_alloc_buffer(struct device *dev);
+static void ni65_free_buffer(struct priv *p);
+static struct enet_statistics *ni65_get_stats(struct device *);
+static void set_multicast_list(struct device *dev);
+
 static int irqtab[] = { 9,12,15,5 }; /* irq config-translate */
-static int dmatab[] = { 0,3,5,6 };   /* dma config-translate */
-static int debuglevel = 0;
+static int dmatab[] = { 0,3,5,6,7 }; /* dma config-translate and autodetect */
+
+static int debuglevel = 1;
 
 /*
- * open (most done by init) 
+ * set 'performance' registers .. we must STOP lance for that
+ */
+static void ni65_set_performance(struct priv *p)
+{
+  writereg(CSR0_STOP | CSR0_CLRALL,CSR0); /* STOP */
+
+  if( !(cards[p->cardno].config & 0x02) )
+    return;
+ 
+  outw(80,PORT+L_ADDRREG);
+  if(inw(PORT+L_ADDRREG) != 80)
+    return;
+ 
+  writereg( (csr80 & 0x3fff) ,80); /* FIFO watermarks */
+  outw(0,PORT+L_ADDRREG);
+  outw((short)isa0,PORT+L_BUSIF); /* write ISA 0: DMA_R : isa0 * 50ns */
+  outw(1,PORT+L_ADDRREG);
+  outw((short)isa1,PORT+L_BUSIF); /* write ISA 1: DMA_W : isa1 * 50ns  */
+
+  outw(CSR0,PORT+L_ADDRREG);	/* switch back to CSR0 */
+}
+
+/*
+ * open interface (up)
  */
 static int ni65_open(struct device *dev)
 {
-  if(ni65_am7990_reinit(dev))
+  struct priv *p = (struct priv *) dev->priv;
+  int irqval = request_irq(dev->irq, &ni65_interrupt,0,
+                        cards[p->cardno].cardname,NULL);
+  if (irqval) {
+    printk ("%s: unable to get IRQ %d (irqval=%d).\n", 
+              dev->name,dev->irq, irqval);
+    return -EAGAIN;
+  }
+  irq2dev_map[dev->irq] = dev;
+
+  if(ni65_lance_reinit(dev))
   {
     dev->tbusy     = 0;
     dev->interrupt = 0;
     dev->start     = 1;
+    MOD_INC_USE_COUNT;
     return 0;
   }
   else
   {
+    irq2dev_map[dev->irq] = NULL;
+    free_irq(dev->irq,NULL);
     dev->start = 0;
     return -EAGAIN;
   }
 }
 
+/*
+ * close interface (down)
+ */
 static int ni65_close(struct device *dev)
 {
-  outw(0,PORT+L_RESET); /* that's the hard way */
+  struct priv *p = (struct priv *) dev->priv;
+
+  outw(inw(PORT+L_RESET),PORT+L_RESET); /* that's the hard way */
+
+#ifdef XMT_VIA_SKB
+  {
+    int i;
+    for(i=0;i<TMDNUM;i++)
+    {
+      if(p->tmd_skb[i]) {
+        dev_kfree_skb(p->tmd_skb[i],FREE_WRITE);
+        p->tmd_skb[i] = NULL;
+      }
+    }
+  }
+#endif
+  irq2dev_map[dev->irq] = NULL;
+  free_irq(dev->irq,NULL);
   dev->tbusy = 1;
   dev->start = 0;
+  MOD_DEC_USE_COUNT;
   return 0; 
 }
 
 /* 
  * Probe The Card (not the lance-chip) 
- * and set hardaddress
  */ 
+#ifdef MODULE
+static
+#endif
 int ni65_probe(struct device *dev)
 {
   int *port;
-  static int ports[] = {0x300,0x320,0x340,0x360, 0};
+  static int ports[] = {0x360,0x300,0x320,0x340, 0};
 
-  if(dev) {
-    int base_addr = dev->base_addr;
-    if (base_addr > 0x1ff)          /* Check a single specified location. */
-       return ni65_probe1(&dev, base_addr);
-    else if (base_addr > 0)         /* Don't probe at all. */
-       return -ENXIO;
-    dev->base_addr = base_addr;
-  }
+  if (dev->base_addr > 0x1ff)          /* Check a single specified location. */
+     return ni65_probe1(dev, dev->base_addr);
+  else if (dev->base_addr > 0)         /* Don't probe at all. */
+     return -ENXIO;
 
   for (port = ports; *port; port++) 
   {
-    int ioaddr = *port;
-
-    if (check_region(ioaddr, NI65_TOTAL_SIZE))
-       continue;
-    if( !(inb(ioaddr+L_EBASE+6) == NI65_ID0) || 
-        !(inb(ioaddr+L_EBASE+7) == NI65_ID1) )
-       continue;
-    if (ni65_probe1(&dev, ioaddr) == 0)
+    if (ni65_probe1(dev, *port) == 0)
        return 0;
   }
 
   return -ENODEV;
 }
 
-int ni65_init(void)
-{
-        ni65_probe(NULL);
-        return 0;
-}
-
-static int ni65_probe1(struct device **dev1,int ioaddr)
+/*
+ * this is the real card probe .. 
+ */
+static int ni65_probe1(struct device *dev,int ioaddr)
 {
-  int i;
-  unsigned char *ptr;
+  int i,j;
   struct priv *p; 
-  struct device *dev = *dev1;
 
-  if(inb(ioaddr+L_EBASE+0) != NI65_ADDR0 || inb(ioaddr+L_EBASE+1) != NI65_ADDR1 
-      || inb(ioaddr+L_EBASE+2) != NI65_ADDR2)
-  {
-    printk("%s: wrong Hardaddress \n",dev ? dev->name : "ni6510" );
-    return -ENODEV;
-  }
-
-  if(!dev) {
-    dev = init_etherdev(0,0);
-    *dev1 = dev;
+  for(i=0;i<NUM_CARDS;i++) {
+    if(check_region(ioaddr, cards[i].total_size))
+      continue;
+    if(cards[i].id_offset >= 0) {
+      if(inb(ioaddr+cards[i].id_offset+0) != cards[i].id0 ||
+         inb(ioaddr+cards[i].id_offset+1) != cards[i].id1) {
+         continue;
+      }
+    }
+    if(cards[i].vendor_id) {
+      for(j=0;j<3;j++)
+        if(inb(ioaddr+cards[i].addr_offset+j) != cards[i].vendor_id[j])
+          continue;
+    }
+    break;
   }
-  dev->base_addr = ioaddr;
+  if(i == NUM_CARDS)
+    return -ENODEV;
 
-  for(i=0;i<6;i++)
-    dev->dev_addr[i] = inb(PORT+L_EBASE+i);
+  for(j=0;j<6;j++)
+    dev->dev_addr[j] = inb(ioaddr+cards[i].addr_offset+j);
 
-  if(dev->irq == 0) 
-    dev->irq = irqtab[(inw(PORT+L_CONFIG)>>2)&3];
-  if(dev->dma == 0)  
-    dev->dma = dmatab[inw(PORT+L_CONFIG)&3];
-
-  printk("%s: %s found at %#3lx, IRQ %d DMA %d.\n", dev->name,
-           "ni6510", dev->base_addr, dev->irq,dev->dma);
-
-  {        
-    int irqval = request_irq(dev->irq, &ni65_interrupt,0,"ni6510",NULL);
-    if (irqval) {
-      printk ("%s: unable to get IRQ %d (irqval=%d).\n", 
-                dev->name,dev->irq, irqval);
-      return -EAGAIN;
+  if( (j=ni65_alloc_buffer(dev)) < 0)
+    return j;
+  p = (struct priv *) dev->priv;
+  p->cmdr_addr = ioaddr + cards[i].cmd_offset;
+  p->cardno = i;
+
+  printk("%s: %s found at %#3x, ", dev->name, cards[p->cardno].cardname , ioaddr);
+
+  outw(inw(PORT+L_RESET),PORT+L_RESET); /* first: reset the card */
+  if( (j=readreg(CSR0)) != 0x4) {
+     printk(KERN_ERR "can't RESET card: %04x\n",j);
+     ni65_free_buffer(p);
+     return -EAGAIN;
+  }
+
+  outw(88,PORT+L_ADDRREG);
+  if(inw(PORT+L_ADDRREG) == 88) {
+    unsigned long v;
+    v = inw(PORT+L_DATAREG);
+    v <<= 16;
+    outw(89,PORT+L_ADDRREG);
+    v |= inw(PORT+L_DATAREG);
+    printk("Version %#08lx, ",v);
+    p->features = INIT_RING_BEFORE_START;
+  }
+  else {
+    printk("ancient LANCE, ");
+    p->features = 0x0;
+  }
+
+  if(test_bit(0,&cards[i].config)) {
+    dev->irq = irqtab[(inw(ioaddr+L_CONFIG)>>2)&3];
+    dev->dma = dmatab[inw(ioaddr+L_CONFIG)&3];
+    printk("IRQ %d (from card), DMA %d (from card).\n",dev->irq,dev->dma);
+  }
+  else {
+    if(dev->dma == 0) {
+		/* 'stuck test' from lance.c */
+      int dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) | (inb(DMA2_STAT_REG) & 0xf0);
+      for(i=1;i<5;i++) {
+        int dma = dmatab[i];
+        if(test_bit(dma,&dma_channels) || request_dma(dma,"ni6510"))
+          continue;
+        disable_dma(dma);
+        set_dma_mode(dma,DMA_MODE_CASCADE);
+        enable_dma(dma);
+        ni65_init_lance(p,dev->dev_addr,0,0); /* trigger memory access */
+        disable_dma(dma);
+        free_dma(dma);
+        if(readreg(CSR0) & CSR0_IDON)
+          break;
+      }
+      if(i == 5) {
+        printk("Can't detect DMA channel!\n");
+        ni65_free_buffer(p);
+        return -EAGAIN;
+      }
+      dev->dma = dmatab[i];
+      printk("DMA %d (autodetected), ",dev->dma);
     }
-    if(request_dma(dev->dma, "ni6510") != 0)
+    else
+      printk("DMA %d (assigned), ",dev->dma);
+
+    if(dev->irq < 2)
     {
-      printk("%s: Can't request dma-channel %d\n",dev->name,(int) dev->dma);
-      free_irq(dev->irq,NULL);
-      return -EAGAIN;
+      ni65_init_lance(p,dev->dev_addr,0,0);
+      autoirq_setup(0);
+      writereg(CSR0_INIT|CSR0_INEA,CSR0); /* trigger interrupt */
+
+      if(!(dev->irq = autoirq_report(2)))
+      {
+        printk("Failed to detect IRQ line!\n");
+        ni65_free_buffer(p);
+        return -EAGAIN;
+      }
+      printk("IRQ %d (autodetected).\n",dev->irq);
     }
+    else
+      printk("IRQ %d (assigned).\n",dev->irq);
+  }
+
+  if(request_dma(dev->dma, cards[p->cardno].cardname ) != 0)
+  {
+    printk("%s: Can't request dma-channel %d\n",dev->name,(int) dev->dma);
+    ni65_free_buffer(p);
+    return -EAGAIN;
   }
-  irq2dev_map[dev->irq] = dev;
 
   /* 
-   * Grab the region so we can find another board if autoIRQ fails. 
+   * Grab the region so we can find another board. 
    */
-  request_region(ioaddr,NI65_TOTAL_SIZE,"ni6510");
+  request_region(ioaddr,cards[p->cardno].total_size,cards[p->cardno].cardname);
+
+  dev->base_addr = ioaddr;
 
   dev->open               = ni65_open;
   dev->stop               = ni65_close;
@@ -281,75 +483,240 @@
   dev->tbusy          = 0;
   dev->start          = 0;
 
+  return 0; /* everything is OK */
+}
+
+/*
+ * set lance register and trigger init 
+ */
+static void ni65_init_lance(struct priv *p,unsigned char *daddr,int filter,int mode) 
+{
+  int i;
+  u32 pib;
+
+  writereg(CSR0_CLRALL|CSR0_STOP,CSR0);
+
+  for(i=0;i<6;i++)
+    p->ib.eaddr[i] = daddr[i];
+
+  for(i=0;i<8;i++)
+    p->ib.filter[i] = filter;
+  p->ib.mode = mode;
+
+  p->ib.trp = (u32) virt_to_bus(p->tmdhead) | TMDNUMMASK;
+  p->ib.rrp = (u32) virt_to_bus(p->rmdhead) | RMDNUMMASK;
+  writereg(0,CSR3);  /* busmaster/no word-swap */
+  pib = (u32) virt_to_bus(&p->ib);
+  writereg(pib & 0xffff,CSR1);
+  writereg(pib >> 16,CSR2);
+
+  writereg(CSR0_INIT,CSR0); /* this changes L_ADDRREG to CSR0 */
+
+  for(i=0;i<32;i++)
+  {
+    udelay(4000);
+    if(inw(PORT+L_DATAREG) & (CSR0_IDON | CSR0_MERR) )
+      break; /* init ok ? */
+  }
+}
+
+/*
+ * allocate memory area and check the 16MB border
+ */
+static void *ni65_alloc_mem(struct device *dev,char *what,int size,int type)
+{
+  struct sk_buff *skb=NULL;
+  unsigned char *ptr;
+  void *ret;
+
+  if(type) {
+    ret = skb = alloc_skb(2+16+size,GFP_KERNEL|GFP_DMA);
+    if(!skb) {
+      printk("%s: unable to allocate %s memory.\n",dev->name,what);
+      return NULL;
+    }
+    skb->dev = dev;
+    skb_reserve(skb,2+16);
+    skb_put(skb,R_BUF_SIZE);   /* grab the whole space .. (not necessary) */
+    ptr = skb->data;
+  }
+  else {
+    ret = ptr = kmalloc(T_BUF_SIZE,GFP_KERNEL | GFP_DMA);
+    if(!ret) {
+      printk("%s: unable to allocate %s memory.\n",dev->name,what);
+      return NULL;
+    }
+  }
+  if( (u32) virt_to_bus(ptr+size) > 0x1000000) {
+    printk("%s: unable to allocate %s memory in lower 16MB!\n",dev->name,what);
+    if(type)
+      kfree_skb(skb,FREE_WRITE);
+    else
+      kfree(ptr);
+    return NULL;
+  }
+  return ret;
+}
+
+/*
+ * allocate all memory structures .. send/recv buffers etc ...
+ */
+static int ni65_alloc_buffer(struct device *dev)
+{
+  unsigned char *ptr;
+  struct priv *p;
+  int i;
+ 
   /* 
    * we need 8-aligned memory ..
    */
-  ptr = kmalloc(sizeof(struct priv)+8,GFP_KERNEL|GFP_DMA);
+  ptr = ni65_alloc_mem(dev,"BUFFER",sizeof(struct priv)+8,0);
   if(!ptr)
     return -ENOMEM;
-  ptr = (unsigned char *) (((unsigned long) ptr + 7) & ~0x7);
-  if( (unsigned long) ptr + sizeof(struct priv) > 0x1000000) {
-    printk("%s: Can't alloc buffer in lower 16MB!\n",dev->name);
-    return -EAGAIN;
-  }
-  p = dev->priv = (struct priv *) ptr;
+
+  p = dev->priv = (struct priv *) (((unsigned long) ptr + 7) & ~0x7);
   memset((char *) dev->priv,0,sizeof(struct priv));
+  p->self = ptr;
 
   for(i=0;i<TMDNUM;i++)
   {
-    if( (ptr = kmalloc(T_BUF_SIZE,GFP_KERNEL | GFP_DMA )) == NULL) {
-      printk("%s: Can't alloc Xmit-Mem.\n",dev->name);
+#ifdef XMT_VIA_SKB
+    p->tmd_skb[i] = NULL;
+#endif
+    p->tmdbounce[i] = ni65_alloc_mem(dev,"XMIT",T_BUF_SIZE,0);
+    if(!p->tmdbounce[i]) {
+      ni65_free_buffer(p);
+      return -ENOMEM;
+    }
+  }
+
+  for(i=0;i<RMDNUM;i++)
+  {
+#ifdef RCV_VIA_SKB
+    p->recv_skb[i] = ni65_alloc_mem(dev,"RECV",R_BUF_SIZE,1);
+    if(!p->recv_skb[i]) {
+      ni65_free_buffer(p);
       return -ENOMEM;
     }
-    if( (unsigned long) (ptr+T_BUF_SIZE) > 0x1000000) {
-      printk("%s: Can't alloc Xmit-Mem in lower 16MB!\n",dev->name);
-      return -EAGAIN;
+#else
+    p->recvbounce[i] = ni65_alloc_mem(dev,"RECV",R_BUF_SIZE,0);
+    if(!p->recvbounce[i]) {
+      ni65_free_buffer(p);
+      return -ENOMEM;
     }
-    p->tmdbounce[i] = ptr;
+#endif
+  }
+
+  return 0; /* everything is OK */
+}
+
+/*
+ * free buffers and private struct 
+ */
+static void ni65_free_buffer(struct priv *p)
+{
+  int i;
+
+  if(!p)
+    return;
+
+  for(i=0;i<TMDNUM;i++) {
+    if(p->tmdbounce[i])
+      kfree(p->tmdbounce[i]);
 #ifdef XMT_VIA_SKB
-    p->tmd_skb[i] = NULL;
+    if(p->tmd_skb[i])
+      dev_kfree_skb(p->tmd_skb[i],FREE_WRITE);
 #endif
   }
 
+  for(i=0;i<RMDNUM;i++)
+  {
 #ifdef RCV_VIA_SKB
-   for(i=0;i<RMDNUM;i++)
-   {
-     struct sk_buff *skb;
-     if( !(skb = dev_alloc_skb(R_BUF_SIZE+2)) ) {
-       printk("%s: unable to alloc recv-mem\n",dev->name);
-       return -ENOMEM;
-     }
-     skb->dev = dev;
-     skb_reserve(skb,2);
-     skb_put(skb,R_BUF_SIZE);	/* grab the whole space .. (not necessary) */
-     if( (unsigned long) (skb->data + R_BUF_SIZE) > 0x1000000 ) {
-       printk("%s: unable to alloc receive-memory in lower 16MB!\n",dev->name);
-       return -EAGAIN;
-     }
-     p->recv_skb[i] = skb;
-   }
+    if(p->recv_skb[i])
+      dev_kfree_skb(p->recv_skb[i],FREE_WRITE);
 #else
-   for(i=0;i<RMDNUM;i++)
-   {
-     if( !(p->recvbounce[i] = kmalloc(R_BUF_SIZE,GFP_KERNEL | GFP_DMA )) ) {
-       printk("%s: unable to alloc recv-mem\n",dev->name);
-       return -ENOMEM;
-     }
-     if( (unsigned long) p->recvbounce[i] + R_BUF_SIZE > 0x1000000 ) {
-       printk("%s: unable to alloc receive-memory in lower 16MB!\n",dev->name);
-       return -EAGAIN;
-     }
-   }
+    if(p->recvbounce[i])
+      kfree(p->recvbounce[i]);
+#endif
+  }
+  if(p->self)
+    kfree(p->self);
+}
+
+
+/*
+ * stop and (re)start lance .. e.g after an error
+ */
+static void ni65_stop_start(struct device *dev,struct priv *p)
+{
+  int csr0 = CSR0_INEA;
+
+  writedatareg(CSR0_STOP);
+
+  if(debuglevel > 1)
+    printk("ni65_stop_start\n");
+
+  if(p->features & INIT_RING_BEFORE_START) {
+    int i;
+#ifdef XMT_VIA_SKB
+    struct sk_buff *skb_save[TMDNUM];
 #endif
+    unsigned long buffer[TMDNUM];
+    short blen[TMDNUM];
 
-  return 0; /* we've found everything */
+    if(p->xmit_queued) {
+      while(1) {
+        if((p->tmdhead[p->tmdlast].u.s.status & XMIT_OWN))
+          break;
+        p->tmdlast = (p->tmdlast + 1) & (TMDNUM-1);
+        if(p->tmdlast == p->tmdnum)
+          break;
+      }
+    }
+    
+    for(i=0;i<TMDNUM;i++) {
+      struct tmd *tmdp = p->tmdhead + i;
+#ifdef XMT_VIA_SKB
+      skb_save[i] = p->tmd_skb[i];
+#endif
+      buffer[i] = (u32) bus_to_virt(tmdp->u.buffer);
+      blen[i] = tmdp->blen;
+      tmdp->u.s.status = 0x0;
+    }
+
+    for(i=0;i<RMDNUM;i++) {
+      struct rmd *rmdp = p->rmdhead + i;
+      rmdp->u.s.status = RCV_OWN;
+    }
+    p->tmdnum = p->xmit_queued = 0;
+    writedatareg(CSR0_STRT | csr0);
+
+    for(i=0;i<TMDNUM;i++) {
+      int num = (i + p->tmdlast) & (TMDNUM-1);
+      p->tmdhead[i].u.buffer = (u32) virt_to_bus((char *)buffer[num]); /* status is part of buffer field */
+      p->tmdhead[i].blen = blen[num];
+      if(p->tmdhead[i].u.s.status & XMIT_OWN) {
+         p->tmdnum = (p->tmdnum + 1) & (TMDNUM-1);
+         p->xmit_queued = 1;
+	 writedatareg(CSR0_TDMD | CSR0_INEA | csr0);
+      }
+#ifdef XMT_VIA_SKB
+      p->tmd_skb[i] = skb_save[num];
+#endif
+    }
+    p->rmdnum = p->tmdlast = 0;
+    if(!p->lock)
+      dev->tbusy = (p->tmdnum || !p->xmit_queued) ? 0 : 1;
+    dev->trans_start = jiffies;
+  } 
+  else
+    writedatareg(CSR0_STRT | csr0);
 }
 
 /* 
  * init lance (write init-values .. init-buffers) (open-helper)
  */
-
-static int ni65_am7990_reinit(struct device *dev)
+static int ni65_lance_reinit(struct device *dev)
 {
    int i;
    struct priv *p = (struct priv *) dev->priv;
@@ -361,17 +728,16 @@
    set_dma_mode(dev->dma,DMA_MODE_CASCADE);
    enable_dma(dev->dma); 
 
-   outw(0,PORT+L_RESET); /* first: reset the card */
-   if(inw(PORT+L_DATAREG) != 0x4)
+   outw(inw(PORT+L_RESET),PORT+L_RESET); /* first: reset the card */
+   if( (i=readreg(CSR0) ) != 0x4)
    {
-     printk(KERN_ERR "%s: can't RESET ni6510 card: %04x\n",dev->name,(int) inw(PORT+L_DATAREG));
+     printk(KERN_ERR "%s: can't RESET %s card: %04x\n",dev->name,
+              cards[p->cardno].cardname,(int) i);
      disable_dma(dev->dma);
-     free_dma(dev->dma);
-     free_irq(dev->irq, NULL);
      return 0;
    }
 
-   p->tmdnum = 0; p->tmdlast = 0;
+   p->rmdnum = p->tmdnum = p->tmdlast = p->tmdbouncenum = 0;
    for(i=0;i<TMDNUM;i++)
    {
      struct tmd *tmdp = p->tmdhead + i;
@@ -386,66 +752,40 @@
      tmdp->blen = tmdp->status2 = 0;
    }
 
-   p->rmdnum = 0;
    for(i=0;i<RMDNUM;i++)
    {
      struct rmd *rmdp = p->rmdhead + i;
 #ifdef RCV_VIA_SKB
-     rmdp->u.buffer = (unsigned long) p->recv_skb[i]->data;
+     rmdp->u.buffer = (u32) virt_to_bus(p->recv_skb[i]->data);
 #else
-     rmdp->u.buffer = (unsigned long) p->recvbounce[i];
+     rmdp->u.buffer = (u32) virt_to_bus(p->recvbounce[i]);
 #endif
      rmdp->blen = -(R_BUF_SIZE-8);
      rmdp->mlen = 0;
      rmdp->u.s.status = RCV_OWN;
    }
    
-   for(i=0;i<6;i++)
-     p->ib.eaddr[i] = dev->dev_addr[i];
-
-   for(i=0;i<8;i++)
-     p->ib.filter[i] = 0x0;
-   p->ib.mode = 0x0;
-
-   if(dev->flags & IFF_PROMISC) {
-     p->ib.mode = M_PROM;
-   }
-   else if(dev->mc_count || dev->flags & IFF_ALLMULTI) {
-     for(i=0;i<8;i++)
-       p->ib.filter[i] = 0xff;
-   }
-
-   p->ib.trp = (unsigned long) p->tmdhead | TMDNUMMASK;
-   p->ib.rrp = (unsigned long) p->rmdhead | RMDNUMMASK;
-
-   writereg(0,CSR3);  /* busmaster/no word-swap */
-   writereg((unsigned short) (((unsigned long) &(p->ib)) & 0xffff),CSR1);
-   writereg((unsigned short) (((unsigned long) &(p->ib))>>16),CSR2);
-
-   writereg(CSR0_INIT,CSR0); /* this changes L_ADDRREG to CSR0 */
+   if(dev->flags & IFF_PROMISC)
+     ni65_init_lance(p,dev->dev_addr,0x00,M_PROM);
+   else if(dev->mc_count || dev->flags & IFF_ALLMULTI)
+     ni65_init_lance(p,dev->dev_addr,0xff,0x0);
+   else 
+     ni65_init_lance(p,dev->dev_addr,0x00,0x00);
 
   /*
+   * ni65_set_lance_mem() sets L_ADDRREG to CSR0
    * NOW, WE WILL NEVER CHANGE THE L_ADDRREG, CSR0 IS ALWAYS SELECTED 
    */
 
-    for(i=0;i<32;i++)
-    {
-      __delay((loops_per_sec>>8)); /* wait a while */
-      if(inw(PORT+L_DATAREG) & CSR0_IDON) 
-        break; /* init ok ? */
-    }
-    if(i == 32) 
-    {
-      printk(KERN_ERR "%s: can't init am7990/lance, status: %04x\n",dev->name,(int) inw(PORT+L_DATAREG));
-      disable_dma(dev->dma);
-      free_dma(dev->dma);
-      free_irq(dev->irq, NULL);
-      return 0; /* false */
-    } 
-
-    writedatareg(CSR0_CLRALL | CSR0_INEA | CSR0_STRT); /* start lance , enable interrupts */
-
-    return 1; /* OK */
+   if(inw(PORT+L_DATAREG) & CSR0_IDON)  {
+     ni65_set_performance(p);
+           /* init OK: start lance , enable interrupts */
+     writedatareg(CSR0_CLRALL | CSR0_INEA | CSR0_STRT);
+     return 1; /* ->OK */
+   }
+   printk(KERN_ERR "%s: can't init lance, status: %04x\n",dev->name,(int) inw(PORT+L_DATAREG));
+   disable_dma(dev->dma);
+   return 0; /* ->Error */
 }
  
 /* 
@@ -455,6 +795,7 @@
 {
   int csr0;
   struct device *dev = (struct device *) irq2dev_map[irq];
+  struct priv *p;
   int bcnt = 32;
 
   if (dev == NULL) {
@@ -462,62 +803,104 @@
     return;
   }
 
-  dev->interrupt = 1;
+  if(set_bit(0,(int *) &dev->interrupt)) {
+    printk("ni65: oops .. interrupt while proceeding interrupt\n");
+    return;
+  }
+  p = (struct priv *) dev->priv;
 
   while(--bcnt) {
-
     csr0 = inw(PORT+L_DATAREG);
-    writedatareg(csr0 & CSR0_CLRALL); /* ack interrupts, disable int. */
+
+#if 0
+    writedatareg( (csr0 & CSR0_CLRALL) ); /* ack interrupts, disable int. */
+#else
+    writedatareg( (csr0 & CSR0_CLRALL) | CSR0_INEA ); /* ack interrupts, interrupts enabled */
+#endif
 
     if(!(csr0 & (CSR0_ERR | CSR0_RINT | CSR0_TINT)))
       break;
 
+    if(csr0 & CSR0_RINT) /* RECV-int? */
+      ni65_recv_intr(dev,csr0);
+    if(csr0 & CSR0_TINT) /* XMIT-int? */
+      ni65_xmit_intr(dev,csr0);
+
     if(csr0 & CSR0_ERR)
     {
       struct priv *p = (struct priv *) dev->priv;
-
+      if(debuglevel > 1)
+        printk("%s: general error: %04x.\n",dev->name,csr0);
       if(csr0 & CSR0_BABL)
         p->stats.tx_errors++;
-      if(csr0 & CSR0_MISS)
+      if(csr0 & CSR0_MISS) {
+        int i;
+        for(i=0;i<RMDNUM;i++)
+          printk("%02x ",p->rmdhead[i].u.s.status);
+        printk("\n");
         p->stats.rx_errors++;
+      }
       if(csr0 & CSR0_MERR) {
-        writedatareg(CSR0_STOP);
-        writedatareg(CSR0_STRT);
+        if(debuglevel > 1)
+          printk("%s: Ooops .. memory error: %04x.\n",dev->name,csr0);
+        ni65_stop_start(dev,p);
       }
     }
-    if(csr0 & CSR0_RINT) /* RECV-int? */
-      ni65_recv_intr(dev,csr0);
-    if(csr0 & CSR0_TINT) /* XMIT-int? */
-      ni65_xmit_intr(dev,csr0);
   }
 
 #ifdef RCV_PARANOIA_CHECK
 {
+ int j;
+ for(j=0;j<RMDNUM;j++)
+ {
   struct priv *p = (struct priv *) dev->priv;
-  int i,f=0;
-  for(i=0;i<RMDNUM;i++) {
-     struct rmd *rmdp = p->rmdhead + ((p->rmdnum - i - 1) & (RMDNUM-1));
-     if(! (rmdp->u.s.status & RCV_OWN) )
-        f = 1;
-     else if(f)
+  int i,k,num1,num2;
+  for(i=RMDNUM-1;i>0;i--) {
+     num2 = (p->rmdnum + i) & (RMDNUM-1);
+     if(!(p->rmdhead[num2].u.s.status & RCV_OWN))
         break;
   }
 
-  if(i < RMDNUM) {
-    p->rmdnum = (p->rmdnum + 8 - i) & (RMDNUM - 1);
-    printk(KERN_ERR "%s: Ooops, receive ring corrupted\n",dev->name);
+  if(i) {
+    for(k=0;k<RMDNUM;k++) {
+      num1 = (p->rmdnum + k) & (RMDNUM-1);
+      if(!(p->rmdhead[num1].u.s.status & RCV_OWN))
+        break;
+    }
+    if(!k)
+      break;
+
+    if(debuglevel > 0)
+    {
+      char buf[256],*buf1;
+      int k;
+      buf1 = buf;
+      for(k=0;k<RMDNUM;k++) {
+        sprintf(buf1,"%02x ",(p->rmdhead[k].u.s.status)); /* & RCV_OWN) ); */
+        buf1 += 3;
+      }
+      *buf1 = 0;
+      printk(KERN_ERR "%s: Ooops, receive ring corrupted %2d %2d | %s\n",dev->name,p->rmdnum,i,buf);
+    }
 
+    p->rmdnum = num1;
     ni65_recv_intr(dev,csr0);
+    if((p->rmdhead[num2].u.s.status & RCV_OWN))
+      break;	/* ok, we are 'in sync' again */
   }
+  else
+    break;
+ }
 }
 #endif
 
-  if(csr0 & (CSR0_RXON | CSR0_TXON) != (CSR0_RXON | CSR0_TXON) ) {
-    writedatareg(CSR0_STOP);
-    writedatareg(CSR0_STRT | CSR0_INEA);
+  if( (csr0 & (CSR0_RXON | CSR0_TXON)) != (CSR0_RXON | CSR0_TXON) ) {
+    printk("%s: RX or TX was offline -> restart\n",dev->name);
+    ni65_stop_start(dev,p);
   }
   else
     writedatareg(CSR0_INEA);
+
   dev->interrupt = 0;
 
   return;
@@ -539,13 +922,6 @@
     if(tmdstat & XMIT_OWN)
       break;
 
-#ifdef XMT_VIA_SKB
-    if(p->tmd_skb[p->tmdlast]) {
-       dev_kfree_skb(p->tmd_skb[p->tmdlast],FREE_WRITE);
-       p->tmd_skb[p->tmdlast] = NULL;
-    }
-#endif
-
     if(tmdstat & XMIT_ERR)
     {
 #if 0
@@ -558,20 +934,34 @@
       if(tmdp->status2 & XMIT_LCAR)
         p->stats.tx_carrier_errors++;
       if(tmdp->status2 & (XMIT_BUFF | XMIT_UFLO )) {
+		/* this stops the xmitter */
         p->stats.tx_fifo_errors++;
-        writedatareg(CSR0_STOP);
-        writedatareg(CSR0_STRT);
-        if(debuglevel > 1)
+        if(debuglevel > 0)
           printk(KERN_ERR "%s: Xmit FIFO/BUFF error\n",dev->name);
+        if(p->features & INIT_RING_BEFORE_START) {
+          tmdp->u.s.status = XMIT_OWN | XMIT_START | XMIT_END;	/* test: resend this frame */
+          ni65_stop_start(dev,p);
+          break;	/* no more Xmit processing .. */
+        }
+        else
+         ni65_stop_start(dev,p);
       }
       if(debuglevel > 2)
         printk(KERN_ERR "%s: xmit-error: %04x %02x-%04x\n",dev->name,csr0,(int) tmdstat,(int) tmdp->status2);
-      p->stats.tx_errors++;
+      if(!(csr0 & CSR0_BABL)) /* don't count errors twice */
+        p->stats.tx_errors++;
       tmdp->status2 = 0;
     }
     else
       p->stats.tx_packets++;
 
+#ifdef XMT_VIA_SKB
+    if(p->tmd_skb[p->tmdlast]) {
+       dev_kfree_skb(p->tmd_skb[p->tmdlast],FREE_WRITE);
+       p->tmd_skb[p->tmdlast] = NULL;
+    }
+#endif
+
     p->tmdlast = (p->tmdlast + 1) & (TMDNUM-1);
     if(p->tmdlast == p->tmdnum)
       p->xmit_queued = 0;
@@ -583,16 +973,17 @@
 /*
  * We have received a packet
  */
-
 static void ni65_recv_intr(struct device *dev,int csr0)
 {
   struct rmd *rmdp; 
   int rmdstat,len;
+  int cnt=0;
   struct priv *p = (struct priv *) dev->priv;
 
   rmdp = p->rmdhead + p->rmdnum;
   while(!( (rmdstat = rmdp->u.s.status) & RCV_OWN))
   {
+    cnt++;
     if( (rmdstat & (RCV_START | RCV_END | RCV_ERR)) != (RCV_START | RCV_END) ) /* error or oversized? */ 
     {
       if(!(rmdstat & RCV_ERR)) {
@@ -603,27 +994,27 @@
         }
       }
       else {
-        printk(KERN_ERR "%s: receive-error: %04x, lance-status: %04x/%04x\n",
-                dev->name,(int) rmdstat,csr0,(int) inw(PORT+L_DATAREG) );
+        if(debuglevel > 2)
+          printk(KERN_ERR "%s: receive-error: %04x, lance-status: %04x/%04x\n",
+                  dev->name,(int) rmdstat,csr0,(int) inw(PORT+L_DATAREG) );
         if(rmdstat & RCV_FRAM)
           p->stats.rx_frame_errors++;
         if(rmdstat & RCV_OFLO)
           p->stats.rx_over_errors++;
-        if(rmdstat & (RCV_OFLO | RCV_BUF_ERR) ) { 
-          writedatareg(CSR0_STOP);
-          writedatareg(CSR0_STRT);
-          if(debuglevel > 1)
-            printk(KERN_ERR "%s: Rcv FIFO/BUFF error.\n",dev->name);
-        }
-        if(rmdstat & RCV_CRC)  p->stats.rx_crc_errors++;
+        if(rmdstat & RCV_CRC) 
+          p->stats.rx_crc_errors++;
+        if(rmdstat & RCV_BUF_ERR)
+          p->stats.rx_fifo_errors++;
       }
-      rmdp->u.s.status = RCV_OWN; /* change owner */
-      p->stats.rx_errors++;
+      if(!(csr0 & CSR0_MISS)) /* don't count errors twice */
+        p->stats.rx_errors++;
     }
     else if( (len = (rmdp->mlen & 0x0fff) - 4) >= 60)
     {
 #ifdef RCV_VIA_SKB
-      struct sk_buff *skb = dev_alloc_skb(R_BUF_SIZE+2);
+      struct sk_buff *skb = alloc_skb(R_BUF_SIZE+2+16,GFP_ATOMIC);
+      if (skb)
+        skb_reserve(skb,16);
 #else
       struct sk_buff *skb = dev_alloc_skb(len+2);
 #endif
@@ -640,7 +1031,7 @@
           struct sk_buff *skb1 = p->recv_skb[p->rmdnum];
           skb_put(skb,R_BUF_SIZE);
           p->recv_skb[p->rmdnum] = skb;
-          rmdp->u.buffer = (unsigned long) skb->data;
+          rmdp->u.buffer = (u32) virt_to_bus(skb->data);
           skb = skb1;
           skb_trim(skb,len);
         }
@@ -648,23 +1039,23 @@
         skb_put(skb,len);
         eth_copy_and_sum(skb, (unsigned char *) p->recvbounce[p->rmdnum],len,0);
 #endif
-        rmdp->u.s.status = RCV_OWN;
         p->stats.rx_packets++;
         skb->protocol=eth_type_trans(skb,dev);
         netif_rx(skb);
       }
       else
       {
-        rmdp->u.s.status = RCV_OWN;
         printk(KERN_ERR "%s: can't alloc new sk_buff\n",dev->name);
         p->stats.rx_dropped++;
       }
     }
     else {
-      rmdp->u.s.status = RCV_OWN;
       printk(KERN_INFO "%s: received runt packet\n",dev->name);
       p->stats.rx_errors++;
     }
+    rmdp->blen = -(R_BUF_SIZE-8);
+    rmdp->mlen = 0;
+    rmdp->u.s.status = RCV_OWN; /* change owner */
     p->rmdnum = (p->rmdnum + 1) & (RMDNUM-1);
     rmdp = p->rmdhead + p->rmdnum;
   }
@@ -680,11 +1071,17 @@
   if(dev->tbusy)
   {
     int tickssofar = jiffies - dev->trans_start;
-    if (tickssofar < 5)
+    if (tickssofar < 50)
       return 1;
 
     printk(KERN_ERR "%s: xmitter timed out, try to restart!\n",dev->name);
-    ni65_am7990_reinit(dev);
+{
+  int i;
+  for(i=0;i<TMDNUM;i++)
+    printk("%02x ",p->tmdhead[i].u.s.status);
+  printk("\n");
+}
+    ni65_lance_reinit(dev);
     dev->tbusy=0;
     dev->trans_start = jiffies;
   }
@@ -708,28 +1105,37 @@
 
   {
     short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-    struct tmd *tmdp = p->tmdhead + p->tmdnum;
+    struct tmd *tmdp;
     long flags;
 
 #ifdef XMT_VIA_SKB
     if( (unsigned long) (skb->data + skb->len) > 0x1000000) {
 #endif
-      tmdp->u.buffer = (unsigned long ) p->tmdbounce[p->tmdnum]; 
-      memcpy((char *) tmdp->u.buffer,(char *)skb->data,
+
+      memcpy((char *) p->tmdbounce[p->tmdbouncenum] ,(char *)skb->data,
                (skb->len > T_BUF_SIZE) ? T_BUF_SIZE : skb->len);
       dev_kfree_skb (skb, FREE_WRITE);
+
+      save_flags(flags);
+      cli();
+
+      tmdp = p->tmdhead + p->tmdnum;
+      tmdp->u.buffer = (u32) virt_to_bus(p->tmdbounce[p->tmdbouncenum]);
+      p->tmdbouncenum = (p->tmdbouncenum + 1) & (TMDNUM - 1);
+
 #ifdef XMT_VIA_SKB
     }
     else {
-      tmdp->u.buffer = (unsigned long) skb->data;
+      save_flags(flags);
+      cli();
+ 
+      tmdp = p->tmdhead + p->tmdnum;
+      tmdp->u.buffer = (u32) virt_to_bus(skb->data);
       p->tmd_skb[p->tmdnum] = skb;
     }
 #endif
     tmdp->blen = -len;
 
-    save_flags(flags);
-    cli();
-
     tmdp->u.s.status = XMIT_OWN | XMIT_START | XMIT_END;
     writedatareg(CSR0_TDMD | CSR0_INEA); /* enable xmit & interrupt */
 
@@ -748,17 +1154,75 @@
 
 static struct enet_statistics *ni65_get_stats(struct device *dev)
 {
+
+#if 0
+ int i;
+ struct priv *p = (struct priv *) dev->priv;
+ for(i=0;i<RMDNUM;i++) {
+   struct rmd *rmdp = p->rmdhead + ((p->rmdnum + i) & (RMDNUM-1));
+   printk("%02x ",rmdp->u.s.status);
+ }
+ printk("\n");
+#endif
+
   return &((struct priv *) dev->priv)->stats;
 }
 
 static void set_multicast_list(struct device *dev)
 {
-	if(!ni65_am7990_reinit(dev))
+	if(!ni65_lance_reinit(dev))
 		printk(KERN_ERR "%s: Can't switch card into MC mode!\n",dev->name);
 	dev->tbusy = 0;
 }
 
+#ifdef MODULE
+static struct device dev_ni65 = {
+  "        ",  /* "ni6510": device name inserted by net_init.c */
+  0, 0, 0, 0,
+  0x360, 9,   /* I/O address, IRQ */
+  0, 0, 0, NULL, ni65_probe };
+
+/* set: io,irq,dma or set it when calling insmod */
+static int irq=0;
+static int io=0;
+static int dma=0;
+
+int init_module(void)
+{
+#if 0
+  if(io <= 0x0 || irq < 2) {
+    printk("ni65: Autoprobing not allowed for modules.\n");
+    printk("ni65: Set symbols 'io' 'irq' and 'dma'\n");
+    return -ENODEV;
+  }
+#endif
+  dev_ni65.irq = irq;
+  dev_ni65.dma = dma;
+  dev_ni65.base_addr = io;
+  if (register_netdev(&dev_ni65) != 0)
+    return -EIO;
+  return 0;
+}
+
+void cleanup_module(void)
+{
+  struct priv *p;
+  p = (struct priv *) dev_ni65.priv;
+  if(!p) {
+    printk("Ooops .. no privat struct\n");
+    return;
+  }
+  disable_dma(dev_ni65.dma);
+  free_dma(dev_ni65.dma);
+  release_region(dev_ni65.base_addr,cards[p->cardno].total_size);
+  ni65_free_buffer(p);
+  dev_ni65.priv = NULL;
+  unregister_netdev(&dev_ni65);
+}
+#endif /* MODULE */
+
 /*
  * END of ni65.c 
  */
+
 
diff -u --recursive --new-file v2.1.2/linux/drivers/net/ni65.h linux/drivers/net/ni65.h
--- v2.1.2/linux/drivers/net/ni65.h	Wed Oct  9 08:55:20 1996
+++ linux/drivers/net/ni65.h	Wed Oct  9 09:57:20 1996
@@ -92,23 +92,23 @@
   unsigned char eaddr[6];
   unsigned char filter[8];
   /* bit 29-31: number of rmd's (power of 2) */
-  unsigned long rrp;   /* receive ring pointer (align 8) */
+  u32 rrp;   /* receive ring pointer (align 8) */
   /* bit 29-31: number of tmd's (power of 2) */
-  unsigned long trp;   /* transmit ring pointer (align 8) */
+  u32 trp;   /* transmit ring pointer (align 8) */
 };
 
 struct rmd /* Receive Message Descriptor */
 { 
   union
   {
-    volatile unsigned long buffer;
+    volatile u32 buffer;
     struct 
     {
       volatile unsigned char dummy[3];
       volatile unsigned char status; 
     } s;
   } u;
-  short blen;
+  volatile short blen;
   volatile unsigned short mlen;
 };
 
@@ -116,14 +116,14 @@
 {
   union 
   {
-    volatile unsigned long buffer;
+    volatile u32 buffer;
     struct 
     {
       volatile unsigned char dummy[3];
       volatile unsigned char status;
     } s;
   } u;
-  unsigned short blen;
+  volatile unsigned short blen;
   volatile unsigned short status2;
 };
 
diff -u --recursive --new-file v2.1.2/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.1.2/linux/drivers/net/ppp.c	Wed Jul 17 07:17:30 1996
+++ linux/drivers/net/ppp.c	Tue Oct  8 21:21:23 1996
@@ -3081,6 +3081,14 @@
 	len   = skb->len;
 	data  = skb_data(skb);
 /*
+ * Bug trap for null data. Release the skb and bail out.
+ */
+	if(data == NULL) {
+		printk("ppp_dev_xmit: data=NULL before ppp_dev_xmit_ip.\n");
+		dev_kfree_skb (skb, FREE_WRITE);
+		return 0;
+	}
+/*
  * Look at the protocol in the skb to determine the difference between
  * an IP frame and an IPX frame.
  */
diff -u --recursive --new-file v2.1.2/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- v2.1.2/linux/drivers/net/tulip.c	Wed Apr 17 09:31:21 1996
+++ linux/drivers/net/tulip.c	Tue Oct  8 21:21:46 1996
@@ -1096,7 +1096,7 @@
 		/* Log any net taps. */
 		printk("%s: Promiscuous mode enabled.\n", dev->name);
 	}
-	else if (dev->mc_count > 15 || (dev->flags&IFF_ALLMULTI)) 
+	else if (dev->mc_count > 14 || (dev->flags&IFF_ALLMULTI)) 
 	{
 		/* Too many to filter perfectly -- accept all multicasts. */
 		tio_write(csr6 | TCMOD_ALLMCAST, CSR6);
@@ -1109,7 +1109,7 @@
 		unsigned short *eaddrs;
 		int i;
 
-		/* We have <= 15 addresses that we can use the wonderful
+		/* We have < 15 addresses that we can use the wonderful
 		   16 address perfect filtering of the Tulip.  Note that only
 		   the low shortword of setup_frame[] is valid. */
 		tio_write(csr6 | 0x0000, CSR6);
@@ -1122,11 +1122,15 @@
 		}
 		/* Fill the rest of the table with our physical address. */
 		eaddrs = (unsigned short *)dev->dev_addr;
+		/* Always accept broadcast packets */
+		*setup_frm++ = 0xffff;
+		*setup_frm++ = 0xffff;
+		*setup_frm++ = 0xffff;
 		do {
 			*setup_frm++ = eaddrs[0];
 			*setup_frm++ = eaddrs[1];
 			*setup_frm++ = eaddrs[2];
-		} while (++i < 16);
+		} while (++i < 15);
 
 		/* Now add this frame to the Tx list. */
 	}
diff -u --recursive --new-file v2.1.2/linux/fs/buffer.c linux/fs/buffer.c
--- v2.1.2/linux/fs/buffer.c	Wed Sep 25 12:15:57 1996
+++ linux/fs/buffer.c	Wed Oct  9 11:30:47 1996
@@ -156,77 +156,66 @@
 static int sync_buffers(kdev_t dev, int wait)
 {
 	int i, retry, pass = 0, err = 0;
-	int nlist, ncount;
 	struct buffer_head * bh, *next;
 
 	/* One pass for no-wait, three for wait:
 	   0) write out all dirty, unlocked buffers;
 	   1) write out all dirty buffers, waiting if locked;
 	   2) wait for completion by waiting for all buffers to unlock. */
- repeat:
-	retry = 0;
- repeat2:
-	ncount = 0;
+	do {
+		retry = 0;
+repeat:
 	/* We search all lists as a failsafe mechanism, not because we expect
 	   there to be dirty buffers on any of the other lists. */
-	for(nlist = 0; nlist < NR_LIST; nlist++)
-	 {
-	 repeat1:
-		 bh = lru_list[nlist];
-		 if(!bh) continue;
-		 for (i = nr_buffers_type[nlist]*2 ; i-- > 0 ; bh = next) {
-			 if(bh->b_list != nlist) goto repeat1;
-			 next = bh->b_next_free;
-			 if(!lru_list[nlist]) break;
-			 if (dev && bh->b_dev != dev)
-				  continue;
-			 if (buffer_locked(bh))
-			  {
-				  /* Buffer is locked; skip it unless wait is
-				     requested AND pass > 0. */
-				  if (!wait || !pass) {
-					  retry = 1;
-					  continue;
-				  }
-				  wait_on_buffer (bh);
-				  goto repeat2;
-			  }
-			 /* If an unlocked buffer is not uptodate, there has
-			     been an IO error. Skip it. */
-			 if (wait && buffer_req(bh) && !buffer_locked(bh) &&
-			     !buffer_dirty(bh) && !buffer_uptodate(bh)) {
-				  err = 1;
-				  continue;
-			  }
-			 /* Don't write clean buffers.  Don't write ANY buffers
-			    on the third pass. */
-			 if (!buffer_dirty(bh) || pass>=2)
-				  continue;
-			 /* don't bother about locked buffers */
-			 if (buffer_locked(bh))
-				 continue;
-			 bh->b_count++;
-			 bh->b_flushtime = 0;
-			 ll_rw_block(WRITE, 1, &bh);
-
-			 if(nlist != BUF_DIRTY) { 
-				 printk("[%d %s %ld] ", nlist,
-					kdevname(bh->b_dev), bh->b_blocknr);
-				 ncount++;
-			 }
-			 bh->b_count--;
-			 retry = 1;
-		 }
-	 }
-	if (ncount)
-	  printk("sys_sync: %d dirty buffers not on dirty list\n", ncount);
+		bh = lru_list[BUF_DIRTY];
+		if (!bh)
+			break;
+		for (i = nr_buffers_type[BUF_DIRTY]*2 ; i-- > 0 ; bh = next) {
+			if (bh->b_list != BUF_DIRTY)
+				goto repeat;
+			next = bh->b_next_free;
+			if (!lru_list[BUF_DIRTY])
+				break;
+			if (dev && bh->b_dev != dev)
+				continue;
+			if (buffer_locked(bh)) {
+				/* Buffer is locked; skip it unless wait is
+				   requested AND pass > 0. */
+				if (!wait || !pass) {
+					retry = 1;
+					continue;
+				}
+				wait_on_buffer (bh);
+				goto repeat;
+			}
+			/* If an unlocked buffer is not uptodate, there has
+			    been an IO error. Skip it. */
+			if (wait && buffer_req(bh) && !buffer_locked(bh) &&
+			    !buffer_dirty(bh) && !buffer_uptodate(bh)) {
+				err = 1;
+				continue;
+			}
+			/* Don't write clean buffers.  Don't write ANY buffers
+			   on the third pass. */
+			if (!buffer_dirty(bh) || pass >= 2)
+				continue;
+			/* don't bother about locked buffers */
+			if (buffer_locked(bh))
+				continue;
+			bh->b_count++;
+			next->b_count++;
+			bh->b_flushtime = 0;
+			ll_rw_block(WRITE, 1, &bh);
+			bh->b_count--;
+			next->b_count--;
+			retry = 1;
+		}
 	
 	/* If we are waiting for the sync to succeed, and if any dirty
 	   blocks were written, then repeat; on the second pass, only
 	   wait for buffers being written (do not pass to write any
 	   more buffers on the second pass). */
-	if (wait && retry && ++pass<=2)
-		 goto repeat;
+	} while (wait && retry && ++pass<=2);
 	return err;
 }
 
diff -u --recursive --new-file v2.1.2/linux/fs/namei.c linux/fs/namei.c
--- v2.1.2/linux/fs/namei.c	Fri Sep 20 13:17:18 1996
+++ linux/fs/namei.c	Wed Oct  9 10:43:24 1996
@@ -21,68 +21,66 @@
 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
 
 /*
- * How long a filename can we get from user space?
- *  -EFAULT if invalid area
- *  0 if ok (ENAMETOOLONG before EFAULT)
- *  >0 EFAULT after xx bytes
- */
-static inline int get_max_filename(unsigned long address)
-{
-	struct vm_area_struct * vma;
-
-	if (get_fs() == KERNEL_DS)
-		return 0;
-	vma = find_vma(current->mm, address);
-	if (!vma || vma->vm_start > address || !(vma->vm_flags & VM_READ))
-		return -EFAULT;
-	address = vma->vm_end - address;
-	if (address > PAGE_SIZE)
-		return 0;
-	if (vma->vm_next && vma->vm_next->vm_start == vma->vm_end &&
-	   (vma->vm_next->vm_flags & VM_READ))
-		return 0;
-	return address;
-}
-
-/*
  * In order to reduce some races, while at the same time doing additional
  * checking and hopefully speeding things up, we copy filenames to the
  * kernel data space before using them..
  *
  * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
  */
-int getname(const char * filename, char **result)
+static inline int do_getname(const char * filename, char *buf)
 {
-	int i, error;
-	unsigned long page;
-	char * tmp, c;
+	int error, maxlen = PAGE_SIZE;
+	int c;
 
-	i = get_max_filename((unsigned long) filename);
-	if (i < 0)
-		return i;
-	error = -EFAULT;
-	if (!i) {
-		error = -ENAMETOOLONG;
-		i = PAGE_SIZE;
+	error = -ENAMETOOLONG;
+	if (get_fs() != KERNEL_DS) {
+		error = -EFAULT;
+		if (TASK_SIZE <= (unsigned long) filename)
+			return error;
+		maxlen = TASK_SIZE - (unsigned long) filename;
+		if (maxlen >= PAGE_SIZE) {
+			maxlen = PAGE_SIZE;
+			error = -ENAMETOOLONG;
+		}
 	}
-	c = get_user(filename++);
+
+	c = (unsigned char) get_user(filename++);
 	if (!c)
 		return -ENOENT;
-	if(!(page = __get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	*result = tmp = (char *) page;
-	while (--i) {
-		*(tmp++) = c;
+
+	while (--maxlen) {
+		*(buf++) = c;
 		c = get_user(filename++);
 		if (!c) {
-			*tmp = '\0';
+			*buf = '\0';
 			return 0;
 		}
 	}
-	free_page(page);
 	return error;
 }
 
+int getname(const char *filename, char **result)
+{
+	int error;
+	unsigned long page = __get_free_page(GFP_KERNEL);
+
+	error = -ENOMEM;
+	if (page) {
+		error = -EFAULT;
+		if (!exception()) {
+			int retval = do_getname(filename, (char *) page);
+			end_exception();
+			if (!retval) {
+				*result = (char *) page;
+				return 0;
+			}
+			error = retval;
+		}
+		free_page(page);
+	}
+	return error;
+}
+		
 void putname(char * name)
 {
 	free_page((unsigned long) name);
diff -u --recursive --new-file v2.1.2/linux/fs/proc/base.c linux/fs/proc/base.c
--- v2.1.2/linux/fs/proc/base.c	Wed Feb 21 11:26:09 1996
+++ linux/fs/proc/base.c	Wed Oct  9 20:10:26 1996
@@ -80,72 +80,83 @@
 	NULL, &proc_root, NULL
 };
 
+static struct proc_dir_entry proc_pid_status = {
+	PROC_PID_STATUS, 6, "status",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_array_inode_operations,
+	NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_mem = {
+	PROC_PID_MEM, 3, "mem",
+	S_IFREG | S_IRUSR | S_IWUSR, 1, 0, 0,
+	0, &proc_mem_inode_operations,
+	NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_cwd = {
+	PROC_PID_CWD, 3, "cwd",
+	S_IFLNK | S_IRWXU, 1, 0, 0,
+	0, &proc_link_inode_operations,
+	NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_root = {
+	PROC_PID_ROOT, 4, "root",
+	S_IFLNK | S_IRWXU, 1, 0, 0,
+	0, &proc_link_inode_operations,
+	NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_exe = {
+	PROC_PID_EXE, 3, "exe",
+	S_IFLNK | S_IRWXU, 1, 0, 0,
+	0, &proc_link_inode_operations,
+	NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_fd = {
+	PROC_PID_FD, 2, "fd",
+	S_IFDIR | S_IRUSR | S_IXUSR, 1, 0, 0,
+	0, &proc_fd_inode_operations,
+	NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_environ = {
+	PROC_PID_ENVIRON, 7, "environ",
+	S_IFREG | S_IRUSR, 1, 0, 0,
+	0, &proc_array_inode_operations,
+	NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_cmdline = {
+	PROC_PID_CMDLINE, 7, "cmdline",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_array_inode_operations,
+	NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_stat = {
+	PROC_PID_STAT, 4, "stat",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_array_inode_operations,
+	NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_statm = {
+	PROC_PID_STATM, 5, "statm",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_array_inode_operations,
+	NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_maps = {
+	PROC_PID_MAPS, 4, "maps",
+	S_IFIFO | S_IRUGO, 1, 0, 0,
+	0, &proc_arraylong_inode_operations,
+	NULL, proc_pid_fill_inode,
+};
 void proc_base_init(void)
 {
-	proc_register(&proc_pid, &(struct proc_dir_entry) {
-		PROC_PID_STATUS, 6, "status",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_array_inode_operations,
-		NULL, proc_pid_fill_inode,
-	});
-	proc_register(&proc_pid, &(struct proc_dir_entry) {
-		PROC_PID_MEM, 3, "mem",
-		S_IFREG | S_IRUSR | S_IWUSR, 1, 0, 0,
-		0, &proc_mem_inode_operations,
-		NULL, proc_pid_fill_inode,
-	});
-	proc_register(&proc_pid, &(struct proc_dir_entry) {
-		PROC_PID_CWD, 3, "cwd",
-		S_IFLNK | S_IRWXU, 1, 0, 0,
-		0, &proc_link_inode_operations,
-		NULL, proc_pid_fill_inode,
-	});
-	proc_register(&proc_pid, &(struct proc_dir_entry) {
-		PROC_PID_ROOT, 4, "root",
-		S_IFLNK | S_IRWXU, 1, 0, 0,
-		0, &proc_link_inode_operations,
-		NULL, proc_pid_fill_inode,
-	});
-	proc_register(&proc_pid, &(struct proc_dir_entry) {
-		PROC_PID_EXE, 3, "exe",
-		S_IFLNK | S_IRWXU, 1, 0, 0,
-		0, &proc_link_inode_operations,
-		NULL, proc_pid_fill_inode,
-	});
-	proc_register(&proc_pid, &(struct proc_dir_entry) {
-		PROC_PID_FD, 2, "fd",
-		S_IFDIR | S_IRUSR | S_IXUSR, 1, 0, 0,
-		0, &proc_fd_inode_operations,
-		NULL, proc_pid_fill_inode,
-	});
-	proc_register(&proc_pid, &(struct proc_dir_entry) {
-		PROC_PID_ENVIRON, 7, "environ",
-		S_IFREG | S_IRUSR, 1, 0, 0,
-		0, &proc_array_inode_operations,
-		NULL, proc_pid_fill_inode,
-	});
-	proc_register(&proc_pid, &(struct proc_dir_entry) {
-		PROC_PID_CMDLINE, 7, "cmdline",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_array_inode_operations,
-		NULL, proc_pid_fill_inode,
-	});
-	proc_register(&proc_pid, &(struct proc_dir_entry) {
-		PROC_PID_STAT, 4, "stat",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_array_inode_operations,
-		NULL, proc_pid_fill_inode,
-	});
-	proc_register(&proc_pid, &(struct proc_dir_entry) {
-		PROC_PID_STATM, 5, "statm",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_array_inode_operations,
-		NULL, proc_pid_fill_inode,
-	});
-	proc_register(&proc_pid, &(struct proc_dir_entry) {
-		PROC_PID_MAPS, 4, "maps",
-		S_IFIFO | S_IRUGO, 1, 0, 0,
-		0, &proc_arraylong_inode_operations,
-		NULL, proc_pid_fill_inode,
-	});
+	proc_register(&proc_pid, &proc_pid_status);
+	proc_register(&proc_pid, &proc_pid_mem);
+	proc_register(&proc_pid, &proc_pid_cwd);
+	proc_register(&proc_pid, &proc_pid_root);
+	proc_register(&proc_pid, &proc_pid_exe);
+	proc_register(&proc_pid, &proc_pid_fd);
+	proc_register(&proc_pid, &proc_pid_environ);
+	proc_register(&proc_pid, &proc_pid_cmdline);
+	proc_register(&proc_pid, &proc_pid_stat);
+	proc_register(&proc_pid, &proc_pid_statm);
+	proc_register(&proc_pid, &proc_pid_maps);
 };
diff -u --recursive --new-file v2.1.2/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.1.2/linux/fs/proc/root.c	Tue Apr 30 13:09:45 1996
+++ linux/fs/proc/root.c	Wed Oct  9 20:10:26 1996
@@ -250,6 +250,114 @@
 	NULL			/* permission */
 };
 
+static struct proc_dir_entry proc_root_loadavg = {
+	PROC_LOADAVG, 7, "loadavg",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_uptime = {
+	PROC_UPTIME, 6, "uptime",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_meminfo = {
+	PROC_MEMINFO, 7, "meminfo",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_kmsg = {
+	PROC_KMSG, 4, "kmsg",
+	S_IFREG | S_IRUSR, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_version = {
+	PROC_VERSION, 7, "version",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#ifdef CONFIG_PCI
+static struct proc_dir_entry proc_root_pci = {
+	PROC_PCI, 3, "pci",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#endif
+static struct proc_dir_entry proc_root_cpuinfo = {
+	PROC_CPUINFO, 7, "cpuinfo",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_self = {
+	PROC_SELF, 4, "self",
+	S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
+	64, &proc_self_inode_operations,
+};
+#ifdef CONFIG_DEBUG_MALLOC
+static struct proc_dir_entry proc_root_malloc = {
+	PROC_MALLOC, 6, "malloc",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#endif
+static struct proc_dir_entry proc_root_kcore = {
+	PROC_KCORE, 5, "kcore",
+	S_IFREG | S_IRUSR, 1, 0, 0,
+};
+#ifdef CONFIG_MODULES
+static struct proc_dir_entry proc_root_modules = {
+	PROC_MODULES, 7, "modules",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_ksyms = {
+	PROC_KSYMS, 5, "ksyms",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#endif
+static struct proc_dir_entry proc_root_stat = {
+	PROC_STAT, 4, "stat",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_devices = {
+	PROC_DEVICES, 7, "devices",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_interrupts = {
+	PROC_INTERRUPTS, 10,"interrupts",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#ifdef __SMP_PROF__
+static struct proc_dir_entry proc_root_smp = {
+	PROC_SMP_PROF, 3,"smp",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#endif
+static struct proc_dir_entry proc_root_filesystems = {
+	PROC_FILESYSTEMS, 11,"filesystems",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_dma = {
+	PROC_DMA, 3, "dma",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_ioports = {
+	PROC_IOPORTS, 7, "ioports",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_cmdline = {
+	PROC_CMDLINE, 7, "cmdline",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#ifdef CONFIG_RTC
+static struct proc_dir_entry proc_root_rtc = {
+	PROC_RTC, 3, "rtc",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#endif
+static struct proc_dir_entry proc_root_locks = {
+	PROC_LOCKS, 5, "locks",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_mounts = {
+	PROC_MTAB, 6, "mounts",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_profile = {
+	PROC_PROFILE, 7, "profile",
+	S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+};
+
 void proc_root_init(void)
 {
 	static int done = 0;
@@ -258,119 +366,48 @@
 		return;
 	done = 1;
 	proc_base_init();
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_LOADAVG, 7, "loadavg",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_UPTIME, 6, "uptime",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_MEMINFO, 7, "meminfo",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_KMSG, 4, "kmsg",
-		S_IFREG | S_IRUSR, 1, 0, 0,
-	});
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_VERSION, 7, "version",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
+	proc_register(&proc_root, &proc_root_loadavg);
+	proc_register(&proc_root, &proc_root_uptime);
+	proc_register(&proc_root, &proc_root_meminfo);
+	proc_register(&proc_root, &proc_root_kmsg);
+	proc_register(&proc_root, &proc_root_version);
 #ifdef CONFIG_PCI
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_PCI, 3, "pci",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-#endif
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_CPUINFO, 7, "cpuinfo",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_SELF, 4, "self",
-		S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
-		64, &proc_self_inode_operations,
-	});
+	proc_register(&proc_root, &proc_root_pci);
+#endif
+	proc_register(&proc_root, &proc_root_cpuinfo);
+	proc_register(&proc_root, &proc_root_self);
 	proc_register(&proc_root, &proc_net);
 	proc_register(&proc_root, &proc_scsi);
 	proc_register(&proc_root, &proc_sys_root);
 
 #ifdef CONFIG_DEBUG_MALLOC
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_MALLOC, 6, "malloc",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-#endif
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_KCORE, 5, "kcore",
-		S_IFREG | S_IRUSR, 1, 0, 0,
-	});
+	proc_register(&proc_root, &proc_root_malloc);
+#endif
+	proc_register(&proc_root, &proc_root_kcore);
 
 #ifdef CONFIG_MODULES
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_MODULES, 7, "modules",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_KSYMS, 5, "ksyms",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-#endif
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_STAT, 4, "stat",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_DEVICES, 7, "devices",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_INTERRUPTS, 10,"interrupts",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
+	proc_register(&proc_root, &proc_root_modules);
+	proc_register(&proc_root, &proc_root_ksyms);
+#endif
+	proc_register(&proc_root, &proc_root_stat);
+	proc_register(&proc_root, &proc_root_devices);
+	proc_register(&proc_root, &proc_root_interrupts);
 #ifdef __SMP_PROF__
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_SMP_PROF, 3,"smp",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
+	proc_register(&proc_root, &proc_root_smp);
 #endif 
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_FILESYSTEMS, 11,"filesystems",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_DMA, 3, "dma",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_IOPORTS, 7, "ioports",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_CMDLINE, 7, "cmdline",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
+	proc_register(&proc_root, &proc_root_filesystems);
+	proc_register(&proc_root, &proc_root_dma);
+	proc_register(&proc_root, &proc_root_ioports);
+	proc_register(&proc_root, &proc_root_cmdline);
 #ifdef CONFIG_RTC
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_RTC, 3, "rtc",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
-#endif
-	proc_register(&proc_root, &(struct proc_dir_entry) {
-		PROC_LOCKS, 5, "locks",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-	});
+	proc_register(&proc_root, &proc_root_rtc);
+#endif
+	proc_register(&proc_root, &proc_root_locks);
 
-	proc_register( &proc_root, &(struct proc_dir_entry)
-	   { PROC_MTAB, 6, "mounts", S_IFREG | S_IRUGO, 1, 0, 0, } );
+	proc_register(&proc_root, &proc_root_mounts);
 		   
 	if (prof_shift) {
-		proc_register(&proc_root, &(struct proc_dir_entry) {
-			PROC_PROFILE, 7, "profile",
-			S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
-		});
+		proc_register(&proc_root, &proc_root_profile);
 	}
 }
 
diff -u --recursive --new-file v2.1.2/linux/include/asm-alpha/jensen.h linux/include/asm-alpha/jensen.h
--- v2.1.2/linux/include/asm-alpha/jensen.h	Tue Nov  7 09:18:36 1995
+++ linux/include/asm-alpha/jensen.h	Wed Oct  9 09:54:05 1996
@@ -95,6 +95,8 @@
 		set_hae(addr);
 }
 
+#ifdef __KERNEL__
+
 /*
  * IO functions
  *
@@ -258,6 +260,8 @@
 
 #define outb(x, port) \
 (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
+
+#endif /* __KERNEL__ */
 
 /*
  * The Alpha Jensen hardware for some rather strange reason puts
diff -u --recursive --new-file v2.1.2/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h
--- v2.1.2/linux/include/asm-alpha/processor.h	Wed Oct  9 08:55:22 1996
+++ linux/include/asm-alpha/processor.h	Thu Oct 10 17:07:16 1996
@@ -21,12 +21,6 @@
 #define MCA_bus__is_a_macro /* for versions in ksyms.c */
 
 /*
- * The alpha has no problems with write protection
- */
-#define wp_works_ok 1
-#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
-
-/*
  * The VM exception save area. We need to save
  *	return address (r26)
  *	PC (r30)
diff -u --recursive --new-file v2.1.2/linux/include/asm-alpha/segment.h linux/include/asm-alpha/segment.h
--- v2.1.2/linux/include/asm-alpha/segment.h	Mon Sep 23 17:44:17 1996
+++ linux/include/asm-alpha/segment.h	Thu Oct 10 17:14:32 1996
@@ -51,4 +51,7 @@
 	return 0;
 }
 
+/* Hardware write protection */
+#define verify_write(type, addr, size) 0
+
 #endif /* _ASM_SEGMENT_H */
diff -u --recursive --new-file v2.1.2/linux/include/asm-i386/io.h linux/include/asm-i386/io.h
--- v2.1.2/linux/include/asm-i386/io.h	Wed Oct  9 08:55:22 1996
+++ linux/include/asm-i386/io.h	Wed Oct  9 09:31:45 1996
@@ -37,58 +37,6 @@
 #define SLOW_DOWN_IO __SLOW_DOWN_IO
 #endif
 
-#include <asm/page.h>
-
-#define __io_virt(x)		((void *)(PAGE_OFFSET | (unsigned long)(x)))
-#define __io_phys(x)		((unsigned long)(x) & ~PAGE_OFFSET)
-/*
- * Change virtual addresses to physical addresses and vv.
- * These are pretty trivial
- */
-extern inline unsigned long virt_to_phys(volatile void * address)
-{
-	return __io_phys(address);
-}
-
-extern inline void * phys_to_virt(unsigned long address)
-{
-	return __io_virt(address);
-}
-
-extern void * ioremap(unsigned long offset, unsigned long size);
-extern void iounmap(void *addr);
-
-/*
- * IO bus memory addresses are also 1:1 with the physical address
- */
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-
-/*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the x86 architecture, we just read/write the
- * memory location directly.
- */
-
-#define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
-#define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
-#define readl(addr) (*(volatile unsigned int *) __io_virt(addr))
-
-#define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
-#define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
-#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
-
-#define memset_io(a,b,c)	memset(__io_virt(a),(b),(c))
-#define memcpy_fromio(a,b,c)	memcpy((a),__io_virt(b),(c))
-#define memcpy_toio(a,b,c)	memcpy(__io_virt(a),(b),(c))
-
-/*
- * Again, i386 does not require mem IO specific function.
- */
-
-#define eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),__io_virt(b),(c),(d))
-
 /*
  * Talk about misusing macros..
  */
@@ -216,6 +164,60 @@
 	__inlc_p(port) : \
 	__inl_p(port))
 
+#ifdef __KERNEL__
+
+#include <asm/page.h>
+
+#define __io_virt(x)		((void *)(PAGE_OFFSET | (unsigned long)(x)))
+#define __io_phys(x)		((unsigned long)(x) & ~PAGE_OFFSET)
+/*
+ * Change virtual addresses to physical addresses and vv.
+ * These are pretty trivial
+ */
+extern inline unsigned long virt_to_phys(volatile void * address)
+{
+	return __io_phys(address);
+}
+
+extern inline void * phys_to_virt(unsigned long address)
+{
+	return __io_virt(address);
+}
+
+extern void * ioremap(unsigned long offset, unsigned long size);
+extern void iounmap(void *addr);
+
+/*
+ * IO bus memory addresses are also 1:1 with the physical address
+ */
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the x86 architecture, we just read/write the
+ * memory location directly.
+ */
+
+#define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
+#define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
+#define readl(addr) (*(volatile unsigned int *) __io_virt(addr))
+
+#define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
+#define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
+#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
+
+#define memset_io(a,b,c)	memset(__io_virt(a),(b),(c))
+#define memcpy_fromio(a,b,c)	memcpy((a),__io_virt(b),(c))
+#define memcpy_toio(a,b,c)	memcpy(__io_virt(a),(b),(c))
+
+/*
+ * Again, i386 does not require mem IO specific function.
+ */
+
+#define eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),__io_virt(b),(c),(d))
+
 static inline int check_signature(unsigned long io_addr,
 	const unsigned char *signature, int length)
 {
@@ -231,5 +233,7 @@
 out:
 	return retval;
 }
+
+#endif /* __KERNEL__ */
 
 #endif
diff -u --recursive --new-file v2.1.2/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v2.1.2/linux/include/asm-i386/processor.h	Wed Oct  9 08:55:22 1996
+++ linux/include/asm-i386/processor.h	Thu Oct 10 17:08:35 1996
@@ -33,7 +33,6 @@
  */
 extern int EISA_bus;
 #define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
 
 /*
  * User space process size: 3GB. This is hardcoded into a few places,
diff -u --recursive --new-file v2.1.2/linux/include/asm-i386/segment.h linux/include/asm-i386/segment.h
--- v2.1.2/linux/include/asm-i386/segment.h	Sat Oct  5 16:58:36 1996
+++ linux/include/asm-i386/segment.h	Thu Oct 10 17:13:14 1996
@@ -48,6 +48,23 @@
 #define set_fs(x)	(current->tss.segment = (x))
 #define get_ds()	(KERNEL_DS)
 
+extern int __verify_write(const void *addr, unsigned long size);
+
+#if CPU > 386
+
+#define verify_write(type,addr,size) 0
+
+#else
+
+/*
+ * The intel i386 CPU needs to check writability by hand, as the
+ * CPU does not honour the write protect bit in supervisor mode
+ */
+#define verify_write(type,addr,size) \
+(((type) && !wp_works_ok)?__verify_write((addr),(size)):0)
+
+#endif
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_SEGMENT_H */
diff -u --recursive --new-file v2.1.2/linux/include/asm-i386/user.h linux/include/asm-i386/user.h
--- v2.1.2/linux/include/asm-i386/user.h	Wed Oct  9 08:55:23 1996
+++ linux/include/asm-i386/user.h	Thu Oct 10 11:35:12 1996
@@ -43,7 +43,7 @@
 
 /*
  * This is the old layout of "struct pt_regs", and
- * is still the layout used by user more (the new
+ * is still the layout used by user mode (the new
  * pt_regs doesn't have all registers as the kernel
  * doesn't use the extra segment registers)
  */
diff -u --recursive --new-file v2.1.2/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.1.2/linux/include/linux/mm.h	Wed Oct  9 08:55:23 1996
+++ linux/include/linux/mm.h	Thu Oct 10 17:15:49 1996
@@ -19,11 +19,6 @@
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
 
-extern int __verify_write(const void *, unsigned long);
-
-#define verify_write(type,addr,size) \
-(((type) && !wp_works_ok)?__verify_write((addr),(size)):0)
-
 extern inline int verify_area(int type, const void * addr, unsigned long size)
 {
 	int retval = 0;
diff -u --recursive --new-file v2.1.2/linux/include/net/sock.h linux/include/net/sock.h
--- v2.1.2/linux/include/net/sock.h	Mon Sep 30 11:21:33 1996
+++ linux/include/net/sock.h	Thu Oct 10 17:17:56 1996
@@ -167,6 +167,7 @@
 	unsigned short		rcv_ack_cnt;		/* count of same ack */
 	__u32			window_seq;
 	__u32			fin_seq;
+	__u32			syn_seq;
 	__u32			urg_seq;
 	__u32			urg_data;
 	int			users;			/* user count */
diff -u --recursive --new-file v2.1.2/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.1.2/linux/kernel/ksyms.c	Wed Oct  9 08:55:24 1996
+++ linux/kernel/ksyms.c	Thu Oct 10 17:08:09 1996
@@ -92,18 +92,6 @@
 #endif
 	X(get_options),
 
-	/* system info variables */
-	/* These check that they aren't defines (0/1) */
-#ifndef EISA_bus__is_a_macro
-	X(EISA_bus),
-#endif
-#ifndef MCA_bus__is_a_macro
-	X(MCA_bus),
-#endif
-#ifndef wp_works_ok__is_a_macro
-	X(wp_works_ok),
-#endif
-
 #ifdef CONFIG_PCI
 	/* PCI BIOS support */
 	X(pcibios_present),
diff -u --recursive --new-file v2.1.2/linux/mm/memory.c linux/mm/memory.c
--- v2.1.2/linux/mm/memory.c	Wed Oct  9 08:55:24 1996
+++ linux/mm/memory.c	Thu Oct 10 17:09:51 1996
@@ -676,57 +676,6 @@
 }
 
 /*
- * Ugly, ugly, but the goto's result in better assembly..
- */
-int __verify_write(const void * addr, unsigned long size)
-{
-	struct vm_area_struct * vma;
-	unsigned long start = (unsigned long) addr;
-
-	if (!size)
-		return 0;
-
-	vma = find_vma(current->mm, start);
-	if (!vma)
-		goto bad_area;
-	if (vma->vm_start > start)
-		goto check_stack;
-
-good_area:
-	if (!(vma->vm_flags & VM_WRITE))
-		goto bad_area;
-	size--;
-	size += start & ~PAGE_MASK;
-	size >>= PAGE_SHIFT;
-	start &= PAGE_MASK;
-
-	for (;;) {
-		do_wp_page(current, vma, start, 1);
-		if (!size)
-			break;
-		size--;
-		start += PAGE_SIZE;
-		if (start < vma->vm_end)
-			continue;
-		vma = vma->vm_next;
-		if (!vma || vma->vm_start != start)
-			goto bad_area;
-		if (!(vma->vm_flags & VM_WRITE))
-			goto bad_area;;
-	}
-	return 0;
-
-check_stack:
-	if (!(vma->vm_flags & VM_GROWSDOWN))
-		goto bad_area;
-	if (expand_stack(vma, start) == 0)
-		goto good_area;
-
-bad_area:
-	return -EFAULT;
-}
-
-/*
  * This function zeroes out partial mmap'ed pages at truncation time..
  */
 static void partial_clear(struct vm_area_struct *vma, unsigned long address)
diff -u --recursive --new-file v2.1.2/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v2.1.2/linux/net/appletalk/ddp.c	Fri May 31 13:46:27 1996
+++ linux/net/appletalk/ddp.c	Wed Oct  9 20:10:26 1996
@@ -2006,6 +2006,26 @@
 
 static char ddp_snap_id[]={0x08,0x00,0x07,0x80,0x9B};
 
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_appletalk = {
+	PROC_NET_ATALK, 9, "appletalk",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	atalk_get_info
+};
+static struct proc_dir_entry proc_atalk_route = {
+	PROC_NET_AT_ROUTE, 11,"atalk_route",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	atalk_rt_get_info
+};
+static struct proc_dir_entry proc_atalk_iface = {
+	PROC_NET_ATIF, 11,"atalk_iface",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	atalk_if_get_info
+};
+#endif
 
 /* Called by proto.c on kernel start up */
 
@@ -2025,24 +2045,9 @@
 	aarp_proto_init();
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_ATALK, 9, "appletalk",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		atalk_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_AT_ROUTE, 11,"atalk_route",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		atalk_rt_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_ATIF, 11,"atalk_iface",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		atalk_if_get_info
-	});
+	proc_net_register(&proc_appletalk);
+	proc_net_register(&proc_atalk_route);
+	proc_net_register(&proc_atalk_iface);
 #endif	
 
 	printk(KERN_INFO "Appletalk 0.17 for Linux NET3.035\n");
diff -u --recursive --new-file v2.1.2/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.1.2/linux/net/ax25/af_ax25.c	Wed Aug  7 08:41:57 1996
+++ linux/net/ax25/af_ax25.c	Wed Oct  9 20:11:11 1996
@@ -2365,6 +2365,35 @@
 	0
 };
 
+#ifdef CONFIG_PROC_FS			  
+static struct proc_dir_entry proc_ax25_route = {
+	PROC_NET_AX25_ROUTE, 10, "ax25_route",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ax25_rt_get_info
+};
+static struct proc_dir_entry proc_ax25 = {
+	PROC_NET_AX25, 4, "ax25",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ax25_get_info
+};
+static struct proc_dir_entry proc_ax25_calls = {
+	PROC_NET_AX25_CALLS, 10, "ax25_calls",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ax25_cs_get_info
+};
+#endif
+#ifdef CONFIG_BPQETHER
+static struct proc_dir_entry proc_ax25_bpqether = {
+	PROC_NET_AX25_BPQETHER, 13, "ax25_bpqether",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ax25_bpq_get_info
+};
+#endif
+
 void ax25_proto_init(struct net_proto *pro)
 {
 	sock_register(ax25_proto_ops.family, &ax25_proto_ops);
@@ -2376,35 +2405,15 @@
 #endif
 	register_netdevice_notifier(&ax25_dev_notifier);
 #ifdef CONFIG_PROC_FS			  
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_AX25_ROUTE, 10, "ax25_route",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ax25_rt_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_AX25, 4, "ax25",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ax25_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_AX25_CALLS, 10, "ax25_calls",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ax25_cs_get_info
-	});
+	proc_net_register(&proc_ax25_route);
+	proc_net_register(&proc_ax25);
+	proc_net_register(&proc_ax25_calls);
 #endif	
 
 	printk(KERN_INFO "G4KLX/GW4PTS AX.25 for Linux. Version 0.32 for Linux NET3.035 (Linux 2.0)\n");
 
 #ifdef CONFIG_BPQETHER
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_AX25_BPQETHER, 13, "ax25_bpqether",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ax25_bpq_get_info
-	});
+	proc_net_register(&proc_ax25_bpqether);
 
 	printk(KERN_INFO "G8BPQ Encapsulation of AX.25 frames enabled\n");
 #endif
diff -u --recursive --new-file v2.1.2/linux/net/core/dev.c linux/net/core/dev.c
--- v2.1.2/linux/net/core/dev.c	Thu Aug  1 15:43:04 1996
+++ linux/net/core/dev.c	Wed Oct  9 20:11:11 1996
@@ -1369,6 +1369,15 @@
 extern void sdla_setup(void);
 extern void dlci_setup(void);
 
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_dev = {
+	PROC_NET_DEV, 3, "dev",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	dev_get_info
+};
+#endif
+
 int net_dev_init(void)
 {
 	struct device *dev, **dp;
@@ -1395,9 +1404,6 @@
 #if defined(CONFIG_LANCE)
 	lance_init();
 #endif
-#if defined(CONFIG_NI65)
-	ni65_init();
-#endif
 #if defined(CONFIG_PI)
 	pi_init();
 #endif	
@@ -1449,12 +1455,7 @@
 	}
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_DEV, 3, "dev",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		dev_get_info
-	});
+	proc_net_register(&proc_net_dev);
 #endif
 
 	/*	
diff -u --recursive --new-file v2.1.2/linux/net/core/net_alias.c linux/net/core/net_alias.c
--- v2.1.2/linux/net/core/net_alias.c	Sat Aug 31 19:39:10 1996
+++ linux/net/core/net_alias.c	Wed Oct  9 20:11:11 1996
@@ -1278,6 +1278,22 @@
   0
 };
 
+#ifndef ALIAS_USER_LAND_DEBUG
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_alias_types = {
+	PROC_NET_ALIAS_TYPES, 11, "alias_types",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	net_alias_types_getinfo
+};
+static struct proc_dir_entry proc_net_aliases = {
+	PROC_NET_ALIASES, 7, "aliases",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	net_alias_getinfo
+};
+#endif
+#endif
 
 /*
  * net_alias initialisation
@@ -1299,18 +1315,8 @@
   
 #ifndef ALIAS_USER_LAND_DEBUG
 #ifdef CONFIG_PROC_FS
-  proc_net_register(&(struct proc_dir_entry) {
-    PROC_NET_ALIAS_TYPES, 11, "alias_types",
-    S_IFREG | S_IRUGO, 1, 0, 0,
-    0, &proc_net_inode_operations,
-    net_alias_types_getinfo
-  });
-  proc_net_register(&(struct proc_dir_entry) {
-    PROC_NET_ALIASES, 7, "aliases",
-    S_IFREG | S_IRUGO, 1, 0, 0,
-    0, &proc_net_inode_operations,
-    net_alias_getinfo
-  });
+  proc_net_register(&proc_net_alias_types);
+  proc_net_register(&proc_net_aliases);
 #endif
 #endif
   
diff -u --recursive --new-file v2.1.2/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.1.2/linux/net/ipv4/af_inet.c	Sun Aug  4 12:56:25 1996
+++ linux/net/ipv4/af_inet.c	Wed Oct  9 20:11:11 1996
@@ -1593,6 +1593,59 @@
 
 extern unsigned long seq_offset;
 
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_INET_RARP
+static struct proc_dir_entry proc_net_rarp = {
+	PROC_NET_RARP, 4, "rarp",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	rarp_get_info
+};
+#endif		/* RARP */
+static struct proc_dir_entry proc_net_raw = {
+	PROC_NET_RAW, 3, "raw",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	raw_get_info
+};
+static struct proc_dir_entry proc_net_snmp = {
+	PROC_NET_SNMP, 4, "snmp",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	snmp_get_info
+};
+static struct proc_dir_entry proc_net_sockstat = {
+	PROC_NET_SOCKSTAT, 8, "sockstat",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	afinet_get_info
+};
+static struct proc_dir_entry proc_net_tcp = {
+	PROC_NET_TCP, 3, "tcp",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	tcp_get_info
+};
+static struct proc_dir_entry proc_net_udp = {
+	PROC_NET_UDP, 3, "udp",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	udp_get_info
+};
+static struct proc_dir_entry proc_net_route = {
+	PROC_NET_ROUTE, 5, "route",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	rt_get_info
+};
+static struct proc_dir_entry proc_net_rtcache = {
+	PROC_NET_RTCACHE, 8, "rt_cache",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	rt_cache_get_info
+};
+#endif		/* CONFIG_PROC_FS */
+
 /*
  *	Called by socket.c on kernel startup.  
  */
@@ -1683,55 +1736,15 @@
 #ifdef CONFIG_PROC_FS
 
 #ifdef CONFIG_INET_RARP
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_RARP, 4, "rarp",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		rarp_get_info
-	});
+	proc_net_register(&proc_net_rarp);
 #endif		/* RARP */
 
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_RAW, 3, "raw",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		raw_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_SNMP, 4, "snmp",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		snmp_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_SOCKSTAT, 8, "sockstat",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		afinet_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_TCP, 3, "tcp",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		tcp_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_UDP, 3, "udp",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		udp_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_ROUTE, 5, "route",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		rt_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_RTCACHE, 8, "rt_cache",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		rt_cache_get_info
-	});
+	proc_net_register(&proc_net_raw);
+	proc_net_register(&proc_net_snmp);
+	proc_net_register(&proc_net_sockstat);
+	proc_net_register(&proc_net_tcp);
+	proc_net_register(&proc_net_udp);
+	proc_net_register(&proc_net_route);
+	proc_net_register(&proc_net_rtcache);
 #endif		/* CONFIG_PROC_FS */
 }
diff -u --recursive --new-file v2.1.2/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.1.2/linux/net/ipv4/arp.c	Sat Oct  5 16:58:36 1996
+++ linux/net/ipv4/arp.c	Wed Oct  9 20:11:11 1996
@@ -2389,6 +2389,15 @@
 	0
 };
 
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_arp = {
+	PROC_NET_ARP, 3, "arp",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	arp_get_info
+};
+#endif
+
 void arp_init (void)
 {
 	/* Register the packet type */
@@ -2400,12 +2409,7 @@
 	register_netdevice_notifier(&arp_dev_notifier);
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_ARP, 3, "arp",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		arp_get_info
-	});
+	proc_net_register(&proc_net_arp);
 #endif
 
 #ifdef CONFIG_ARPD
diff -u --recursive --new-file v2.1.2/linux/net/ipv4/ip_forward.c linux/net/ipv4/ip_forward.c
--- v2.1.2/linux/net/ipv4/ip_forward.c	Wed Aug  7 13:59:29 1996
+++ linux/net/ipv4/ip_forward.c	Thu Oct 10 16:04:10 1996
@@ -264,8 +264,12 @@
 		if (iph->protocol == IPPROTO_ICMP)
 		{
 			if ((fw_res = ip_fw_masq_icmp(&skb, dev2)) < 0)
+			{
+				if (rt)
+					ip_rt_put(rt);
 				/* Problem - ie bad checksum */
 				return -1;
+			}
 
 			if (fw_res)
 				/* ICMP matched - skip firewall */
diff -u --recursive --new-file v2.1.2/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- v2.1.2/linux/net/ipv4/ip_fw.c	Wed Aug 21 08:33:37 1996
+++ linux/net/ipv4/ip_fw.c	Wed Oct  9 20:11:11 1996
@@ -1244,16 +1244,45 @@
 
 #endif
 
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_IP_ACCT
+static struct proc_dir_entry proc_net_ipacct = {
+	PROC_NET_IPACCT, 7, "ip_acct",
+	S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ip_acct_procinfo
+};
+#endif
+#endif
+
+#ifdef CONFIG_IP_FIREWALL
+#ifdef CONFIG_PROC_FS		
+static struct proc_dir_entry proc_net_ipfwin = {
+	PROC_NET_IPFWIN, 8, "ip_input",
+	S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ip_fw_in_procinfo
+};
+static struct proc_dir_entry proc_net_ipfwout = {
+	PROC_NET_IPFWOUT, 9, "ip_output",
+	S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ip_fw_out_procinfo
+};
+static struct proc_dir_entry proc_net_ipfwfwd = {
+	PROC_NET_IPFWFWD, 10, "ip_forward",
+	S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ip_fw_fwd_procinfo
+};
+#endif
+#endif
+
 void ip_fw_init(void)
 {
 #ifdef CONFIG_PROC_FS
 #ifdef CONFIG_IP_ACCT
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_IPACCT, 7, "ip_acct",
-		S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ip_acct_procinfo
-	});
+	proc_net_register(&proc_net_ipacct);
 #endif
 #endif
 #ifdef CONFIG_IP_FIREWALL
@@ -1262,24 +1291,9 @@
 		panic("Unable to register IP firewall.\n");
 
 #ifdef CONFIG_PROC_FS		
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_IPFWIN, 8, "ip_input",
-		S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ip_fw_in_procinfo
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_IPFWOUT, 9, "ip_output",
-		S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ip_fw_out_procinfo
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_IPFWFWD, 10, "ip_forward",
-		S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ip_fw_fwd_procinfo
-	});
+	proc_net_register(&proc_net_ipfwin);
+	proc_net_register(&proc_net_ipfwout);
+	proc_net_register(&proc_net_ipfwfwd);
 #endif
 #endif
 #ifdef CONFIG_IP_MASQUERADE
diff -u --recursive --new-file v2.1.2/linux/net/ipv4/ip_masq.c linux/net/ipv4/ip_masq.c
--- v2.1.2/linux/net/ipv4/ip_masq.c	Thu Jun  6 16:23:49 1996
+++ linux/net/ipv4/ip_masq.c	Wed Oct  9 20:11:11 1996
@@ -994,6 +994,15 @@
 	return len;
 }
 
+#ifdef CONFIG_PROC_FS        
+static struct proc_dir_entry proc_net_ipmsqhst = {
+	PROC_NET_IPMSQHST, 13, "ip_masquerade",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ip_msqhst_procinfo
+};
+#endif	
+
 /*
  *	Initialize ip masquerading
  */
@@ -1001,12 +1010,7 @@
 {
         register_symtab (&ip_masq_syms);
 #ifdef CONFIG_PROC_FS        
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_IPMSQHST, 13, "ip_masquerade",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ip_msqhst_procinfo
-	});
+	proc_net_register(&proc_net_ipmsqhst);
 #endif	
         ip_masq_app_init();
 
diff -u --recursive --new-file v2.1.2/linux/net/ipv4/ip_masq_app.c linux/net/ipv4/ip_masq_app.c
--- v2.1.2/linux/net/ipv4/ip_masq_app.c	Fri Jun 28 18:49:55 1996
+++ linux/net/ipv4/ip_masq_app.c	Wed Oct  9 20:11:11 1996
@@ -473,6 +473,15 @@
 }
 
 
+#ifdef CONFIG_PROC_FS        
+static struct proc_dir_entry proc_net_ip_masq_app = {
+	PROC_NET_IP_MASQ_APP, 11, "ip_masq_app",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ip_masq_app_getinfo
+};
+#endif        
+
 /*
  *	Initialization routine
  */
@@ -482,12 +491,7 @@
         
         register_symtab (&ip_masq_app_syms);
 #ifdef CONFIG_PROC_FS        
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_IP_MASQ_APP, 11, "ip_masq_app",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ip_masq_app_getinfo
- 	});
+	proc_net_register(&proc_net_ip_masq_app);
 #endif        
         return 0;
 }
diff -u --recursive --new-file v2.1.2/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- v2.1.2/linux/net/ipv4/ip_output.c	Tue Jul  9 14:28:32 1996
+++ linux/net/ipv4/ip_output.c	Wed Oct  9 20:11:11 1996
@@ -1086,6 +1086,17 @@
 	0
 };
 
+#ifdef CONFIG_IP_MULTICAST
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_igmp = {
+	PROC_NET_IGMP, 4, "igmp",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ip_mc_procinfo
+};
+#endif	
+#endif
+
 /*
  *	IP registers the packet type and then calls the subprotocol initialisers
  */
@@ -1105,12 +1116,7 @@
 
 #ifdef CONFIG_IP_MULTICAST
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_IGMP, 4, "igmp",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ip_mc_procinfo
-	});
+	proc_net_register(&proc_net_igmp);
 #endif	
 #endif
 }
diff -u --recursive --new-file v2.1.2/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v2.1.2/linux/net/ipv4/ipmr.c	Fri Jul 19 08:24:05 1996
+++ linux/net/ipv4/ipmr.c	Wed Oct  9 20:11:11 1996
@@ -913,6 +913,21 @@
   	return len;
 }
 
+#ifdef CONFIG_PROC_FS	
+static struct proc_dir_entry proc_net_ipmr_vif = {
+	PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ipmr_vif_info
+};
+static struct proc_dir_entry proc_net_ipmr_mfc = {
+	PROC_NET_IPMR_MFC, 11 ,"ip_mr_cache",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	ipmr_mfc_info
+};
+#endif	
+
 /*
  *	Setup for IP multicast routing
  */
@@ -922,17 +937,7 @@
 	printk(KERN_INFO "Linux IP multicast router 0.06.\n");
 	register_netdevice_notifier(&ip_mr_notifier);
 #ifdef CONFIG_PROC_FS	
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ipmr_vif_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_IPMR_MFC, 11 ,"ip_mr_cache",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		ipmr_mfc_info
-	});
+	proc_net_register(&proc_net_ipmr_vif);
+	proc_net_register(&proc_net_ipmr_mfc);
 #endif	
 }
diff -u --recursive --new-file v2.1.2/linux/net/ipv4/rarp.c linux/net/ipv4/rarp.c
--- v2.1.2/linux/net/ipv4/rarp.c	Thu Aug  1 15:43:04 1996
+++ linux/net/ipv4/rarp.c	Wed Oct  9 20:11:11 1996
@@ -544,15 +544,17 @@
 	return len;
 }
 
+struct proc_dir_entry proc_net_rarp = {
+	PROC_NET_RARP, 4, "rarp",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	rarp_get_info
+};
+
 void
 rarp_init(void)
 {
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_RARP, 4, "rarp",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		rarp_get_info
-	});
+	proc_net_register(&proc_net_rarp);
 	rarp_ioctl_hook = rarp_ioctl;
 }
 
diff -u --recursive --new-file v2.1.2/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.1.2/linux/net/ipv4/tcp.c	Wed Oct  9 08:55:24 1996
+++ linux/net/ipv4/tcp.c	Thu Oct 10 08:51:22 1996
@@ -873,6 +873,8 @@
 		sk->socket->flags &= ~SO_NOSPACE;
 		add_wait_queue(sk->sleep, &wait);
 		for (;;) {
+			if (current->signal & ~current->blocked)
+				break;
 			current->state = TASK_INTERRUPTIBLE;
 			if (tcp_memory_free(sk))
 				break;
@@ -930,6 +932,7 @@
 	skb->tail += copy;
 	skb->len += copy;
 	skb->csum = csum_partial(skb->tail - tcp_size, tcp_size, 0);
+	sk->write_seq += copy;
 	if (!sk->packets_out)
 		send = tcp_send_skb;
 	send(sk, skb);
@@ -1064,7 +1067,6 @@
 					from += retval;
 					copied += retval;
 					len -= retval;
-					sk->write_seq += retval;
 					continue;
 				}
 				tcp_send_skb(sk, skb);
diff -u --recursive --new-file v2.1.2/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.1.2/linux/net/ipv4/tcp_input.c	Wed Oct  9 08:55:24 1996
+++ linux/net/ipv4/tcp_input.c	Thu Oct 10 16:19:56 1996
@@ -470,6 +470,7 @@
 	newsk->delay_acks = 1;
 	newsk->copied_seq = skb->seq+1;
 	newsk->fin_seq = skb->seq;
+	newsk->syn_seq = skb->seq;
 	newsk->state = TCP_SYN_RECV;
 	newsk->timeout = 0;
 	newsk->ip_xmit_timeout = 0;
@@ -1587,6 +1588,9 @@
  *	moved inline now as tcp_urg is only called from one
  *	place. We handle URGent data wrong. We have to - as
  *	BSD still doesn't use the correction from RFC961.
+ *
+ *	For 1003.1g we should support a new option TCP_STDURG to permit
+ *	either form.
  */
  
 static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
@@ -1613,6 +1617,15 @@
 			kill_pg(-sk->proc, SIGURG, 1);
 		}
 	}
+	/*
+	 *	We may be adding urgent data when the last byte read was
+	 *	urgent. To do this requires some care. We cannot just ignore
+	 *	sk->copied_seq since we would read the last urgent byte again
+	 *	as data, nor can we alter copied_seq until this data arrives
+	 *	or we break the sematics of SIOCATMARK (and thus sockatmark())
+	 */
+	if (sk->urg_seq == sk->copied_seq)
+		sk->copied_seq++;	/* Move the copied sequence on correctly */
 	sk->urg_data = URG_NOTYET;
 	sk->urg_seq = ptr;
 }
@@ -1735,7 +1748,6 @@
 {
 	struct tcphdr *th;
 	struct sock *sk;
-	int syn_ok=0;
 	__u32 seq;
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
 	int r;
@@ -1959,7 +1971,6 @@
 				 *	Ok.. it's good. Set up sequence numbers and
 				 *	move to established.
 				 */
-				syn_ok=1;	/* Don't reset this connection for the syn */
 				sk->acked_seq = skb->seq+1;
 				sk->lastwin_seq = skb->seq+1;
 				sk->fin_seq = skb->seq;
@@ -2074,10 +2085,21 @@
 		return tcp_reset(sk,skb);
 	
 	/*
-	 *	!syn_ok is effectively the state test in RFC793.
+	 *	Check for a SYN, and ensure it matches the SYN we were
+	 *	first sent. We have to handle the rather unusual (but valid)
+	 *	sequence that KA9Q derived products may generate of
+	 *
+	 *	SYN
+	 *				SYN|ACK Data
+	 *	ACK	(lost)
+	 *				SYN|ACK Data + More Data
+	 *	.. we must ACK not RST...
+	 *
+	 *	We keep syn_seq as the sequence space occupied by the 
+	 *	original syn. 
 	 */
 	 
-	if(th->syn && !syn_ok)
+	if(th->syn && skb->seq!=sk->syn_seq)
 	{
 		tcp_send_reset(daddr,saddr,th, &tcp_prot, opt, dev, skb->ip_hdr->tos, 255);
 		return tcp_reset(sk,skb);	
diff -u --recursive --new-file v2.1.2/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v2.1.2/linux/net/netrom/af_netrom.c	Wed Aug  7 08:41:57 1996
+++ linux/net/netrom/af_netrom.c	Wed Oct  9 20:11:11 1996
@@ -1401,6 +1401,27 @@
 	0
 };
 
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_nr = {
+	PROC_NET_NR, 2, "nr",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations, 
+	nr_get_info
+};
+static struct proc_dir_entry proc_net_nr_neigh = {
+	PROC_NET_NR_NEIGH, 8, "nr_neigh",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations, 
+	nr_neigh_get_info
+};
+static struct proc_dir_entry proc_net_nr_nodes = {
+	PROC_NET_NR_NODES, 8, "nr_nodes",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations, 
+	nr_nodes_get_info
+};
+#endif	
+
 void nr_proto_init(struct net_proto *pro)
 {
 	sock_register(nr_proto_ops.family, &nr_proto_ops);
@@ -1418,24 +1439,9 @@
 	nr_default.paclen     = NR_DEFAULT_PACLEN;
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_NR, 2, "nr",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations, 
-		nr_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_NR_NEIGH, 8, "nr_neigh",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations, 
-		nr_neigh_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_NR_NODES, 8, "nr_nodes",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations, 
-		nr_nodes_get_info
-	});
+	proc_net_register(&proc_net_nr);
+	proc_net_register(&proc_net_nr_neigh);
+	proc_net_register(&proc_net_nr_nodes);
 #endif	
 }
 
diff -u --recursive --new-file v2.1.2/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.1.2/linux/net/unix/af_unix.c	Wed Oct  9 08:55:24 1996
+++ linux/net/unix/af_unix.c	Wed Oct  9 20:10:26 1996
@@ -1294,18 +1294,21 @@
 	unix_recvmsg
 };
 
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_unix = {
+	PROC_NET_UNIX,  4, "unix",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	unix_get_info
+};
+#endif
 
 void unix_proto_init(struct net_proto *pro)
 {
 	printk(KERN_INFO "NET3: Unix domain sockets 0.12 for Linux NET3.035.\n");
 	sock_register(unix_proto_ops.family, &unix_proto_ops);
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_UNIX,  4, "unix",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations,
-		unix_get_info
-	});
+	proc_net_register(&proc_net_unix);
 #endif
 }
 /*
