diff -u --recursive --new-file v1.3.9/linux/CREDITS linux/CREDITS
--- v1.3.9/linux/CREDITS	Tue Jul 11 10:02:47 1995
+++ linux/CREDITS	Thu Jul 13 13:05:10 1995
@@ -172,13 +172,20 @@
 S: Australia
 
 N: Alan Cox
-E: A.Cox@swansea.ac.uk
-E: iiitac@pyr.swan.ac.uk
+E: iialan@iifeak.swan.ac.uk
+E: alan@cymru.net (use for commercial traffic)
 E: gw4pts@gw4pts.ampr.org
 E: GW4PTS@GB7SWN (packet radio)
-D: NET2Debugged author
+S: c/o I^2IT Limited
+S: The Innovation Centre
+S: University Of Wales
+S: Swansea, SA2 8PP
+S: Wales, UK
+D: NET2Debugged/NET3 author
 D: Network layer debugging
-D: AX.25 & IPX alpha releases
+D: Initial AX.25 & IPX releases
+D: Original Linux netatalk patches.
+D: Current 3c501 hacker. >>More 3c501 info/tricks wanted<<.
 
 N: Laurence Culhane
 E: loz@holmes.demon.co.uk
diff -u --recursive --new-file v1.3.9/linux/Makefile linux/Makefile
--- v1.3.9/linux/Makefile	Tue Jul 11 10:02:47 1995
+++ linux/Makefile	Thu Jul 13 08:25:55 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 9
+SUBLEVEL = 10
 
 ARCH = i386
 
@@ -283,3 +283,5 @@
 dummy:
 
 endif
+
+include Rules.make
diff -u --recursive --new-file v1.3.9/linux/Rules.make linux/Rules.make
--- v1.3.9/linux/Rules.make	Tue Jul 11 10:02:47 1995
+++ linux/Rules.make	Wed Jul 12 07:08:18 1995
@@ -6,7 +6,7 @@
 # Common rules
 #
 .c.s:
-	$(CC) $(CFLAGS) -S $<
+	$(CC) $(CFLAGS) -S $< -o $@
 
 #
 # A rule to do nothing
diff -u --recursive --new-file v1.3.9/linux/arch/alpha/boot/bootloader.lds linux/arch/alpha/boot/bootloader.lds
--- v1.3.9/linux/arch/alpha/boot/bootloader.lds	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/boot/bootloader.lds	Wed Jul 12 06:41:58 1995
@@ -0,0 +1,49 @@
+OUTPUT_FORMAT("ecoff-littlealpha")
+ENTRY(__start)
+SECTIONS
+{
+  .text 0x20000000: {
+     _ftext = . ;
+     __istart = . ;
+     eprol  =  .;
+    *(.text)
+     __fstart = . ;
+     _etext  =  .;
+  }
+  .rdata : {
+    *(.rdata)
+  }
+  .pdata : {
+     _fpdata = .;
+    *(.pdata)
+  }
+  .data : {
+     _fdata = .;
+    *(.data)
+    CONSTRUCTORS
+  }
+  .xdata : {
+    *(.xdata)
+  }
+   _gp = ALIGN (16) + 0x8000;
+  .lit8 : {
+    *(.lit8)
+  }
+  .lita : {
+    *(.lita)
+  }
+  .sdata : {
+    *(.sdata)
+  }
+   _EDATA  =  .;
+   _FBSS = .;
+  .sbss : {
+    *(.sbss)
+    *(.scommon)
+  }
+  .bss : {
+    *(.bss)
+    *(COMMON)
+  }
+   _end = .;
+}
diff -u --recursive --new-file v1.3.9/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile
--- v1.3.9/linux/arch/alpha/kernel/Makefile	Tue Jul 11 10:02:47 1995
+++ linux/arch/alpha/kernel/Makefile	Wed Jul 12 06:29:19 1995
@@ -17,7 +17,7 @@
 	$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
 
 OBJS  = entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
-	lca.o bios32.o
+	lca.o bios32.o ptrace.o
 
 all: kernel.o head.o
 
diff -u --recursive --new-file v1.3.9/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v1.3.9/linux/arch/alpha/kernel/entry.S	Tue Jul 11 10:02:47 1995
+++ linux/arch/alpha/kernel/entry.S	Thu Jul 13 13:02:25 1995
@@ -105,6 +105,9 @@
 
 .text
 .set noat
+#ifdef __linux__
+  .set singlegp
+#endif
 
 .align 3
 .globl	entInt
@@ -191,9 +194,11 @@
 	stq $16,24($30)
 	stq $17,32($30)
 	stq $18,40($30)
+	bis $31,2,$0	/* Register v0: syscall nr for fork() */
 	SAVE_ALL
 	lda $27,sys_fork
 	jsr $26,($27),sys_fork
+	stq $0,0($30)	
 	br ret_from_sys_call
 .end	kernel_fork
 
@@ -240,7 +245,7 @@
 	stt $f28,288($30)
 	stt $f29,296($30)
 	stt $f30,304($30)
-	ret $31,($0),1
+	ret $31,($1),1
 .end do_switch_stack
 
 .align 3
@@ -286,7 +291,7 @@
 	ldt $f29,296($30)
 	ldt $f30,304($30)
 	lda $30,SWITCH_STACK_SIZE($30)
-	ret $31,($0),1
+	ret $31,($1),1
 .end undo_switch_stack
 
 .align 3
@@ -363,14 +368,11 @@
 .globl	sys_fork
 .ent	sys_fork
 sys_fork:
-	br $0,do_switch_stack
+	br $1,do_switch_stack
 	bis $30,$30,$16
 	lda $27,alpha_fork
 	jsr $26,($27),alpha_fork
-	br $0,undo_switch_stack
-	ldq $0,0($30)
-	bis $31,2,$19	/* Make sure that the stored user register v0 has */
-	stq $19,0($30)	/* the syscall # for fork */
+	br $1,undo_switch_stack
 	ret $31,($26),1
 .end	sys_fork
 
@@ -378,9 +380,9 @@
 .globl  alpha_switch_to
 .ent    alpha_switch_to
 alpha_switch_to:
-	br $0,do_switch_stack
+	br $1,do_switch_stack
 	call_pal PAL_swpctx
-	br $0,undo_switch_stack
+	br $1,undo_switch_stack
 	ret $31,($26),1
 .end alpha_switch_to
 
@@ -450,7 +452,7 @@
 .align 3
 signal_return:
 	bis	$30,$30,$17
-	br	$0,do_switch_stack
+	br	$1,do_switch_stack
 	bis	$30,$30,$18
 	lda	$27,do_signal
 	jsr	$26,($27),do_signal
@@ -480,7 +482,7 @@
 	bis	$30,$30,$18
 	lda	$27,do_sigreturn
 	jsr	$26,($27),do_sigreturn
-	br	$0,undo_switch_stack
+	br	$1,undo_switch_stack
 	br	$31,ret_from_sys_call
 .end sys_sigreturn
 
@@ -488,7 +490,7 @@
 .ent sys_sigsuspend
 sys_sigsuspend:
 	bis	$30,$30,$17
-	br	$0,do_switch_stack
+	br	$1,do_switch_stack
 	bis	$30,$30,$18
 	lda	$27,do_sigsuspend
 	jsr	$26,($27),do_sigsuspend
@@ -504,7 +506,7 @@
 	.quad sys_unlink, do_entSys, sys_chdir, sys_fchdir, sys_mknod
 	.quad sys_chmod, sys_chown, sys_brk, do_entSys, sys_lseek
 	.quad sys_getxpid, osf_mount, osf_umount, sys_setuid, sys_getxuid
-	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+	.quad do_entSys, sys_ptrace, do_entSys, do_entSys, do_entSys
 	.quad do_entSys, do_entSys, do_entSys, sys_access, do_entSys
 	.quad do_entSys, sys_sync, sys_kill, do_entSys, sys_setpgid
 	.quad do_entSys, sys_dup, sys_pipe, do_entSys, do_entSys
diff -u --recursive --new-file v1.3.9/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v1.3.9/linux/arch/alpha/kernel/process.c	Thu Jun  1 13:22:06 1995
+++ linux/arch/alpha/kernel/process.c	Thu Jul 13 13:02:25 1995
@@ -123,7 +123,6 @@
 	childregs->r0 = 0;
 	childregs->r19 = 0;
 	childregs->r20 = 1;	/* OSF/1 has some strange fork() semantics.. */
-	regs->r0 = p->pid;
 	regs->r20 = 0;
 	stack = ((struct switch_stack *) regs) - 1;
 	childstack = ((struct switch_stack *) childregs) - 1;
diff -u --recursive --new-file v1.3.9/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c
--- v1.3.9/linux/arch/alpha/kernel/ptrace.c	Tue Jul 11 10:02:47 1995
+++ linux/arch/alpha/kernel/ptrace.c	Wed Jul 12 06:29:19 1995
@@ -16,6 +16,25 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
+#undef DEBUG
+
+#ifdef DEBUG
+
+  enum {
+      DBG_MEM = (1<<0),
+      DBG_BPT = (1<<1)
+  };
+
+  int debug_mask = DBG_BPT;
+
+# define DBG(fac,args)	{if ((fac) & debug_mask) printk args;}
+
+#else
+# define DBG(fac,args)
+#endif
+
+#define BREAKINST	0x00000080	/* call_pal bpt */
+
 /* This was determined via brute force. */
 #define MAGICNUM 496
 
@@ -24,18 +43,6 @@
  * in exit.c or in signal.c.
  */
 
-/* determines which flags the user has access to. */
-/* 1 = access 0 = no access */
-#define FLAG_MASK 0x00044dd5
-
-/* set's the trap flag. */
-#define TRAP_FLAG 0x100
-
-/*
- * this is the number to subtract from the top of the stack. To find
- * the local frame.
- */
-
 /* A mapping between register number and its offset on the kernel stack.
  * You also need to add MAGICNUM to get past the kernel stack frame
  * to the actual saved user info.
@@ -43,6 +50,12 @@
  * 320 is the size of the switch_stack area.
  */
 
+enum {
+	REG_R0 =  0,
+	REG_F0 = 32,
+	REG_PC = 64
+};
+
 static int map_reg_to_offset[] = {
    320+0,320+8,320+16,320+24,320+32,320+40,320+48,320+56,320+64, /* 0-8 */
    0,8,16,24,32,40,48, /* 9-15 */
@@ -58,17 +71,12 @@
    320+168
 };
 
-static int offset_of_register(int reg_num) {
-   if(reg_num<0 || reg_num>64) {
-      return -1;
-   }
-   return map_reg_to_offset[reg_num];
-}
-
-static void unset_singlestep(struct task_struct *child) {
-}
-
-static void set_singlestep(struct task_struct *child) {
+static int offset_of_register(int reg_num)
+{
+	if (reg_num < 0 || reg_num > 64) {
+		return -1;
+	}
+	return map_reg_to_offset[reg_num];
 }
 
 /* change a pid into a task struct. */
@@ -130,9 +138,7 @@
 	pte_t * pgtable;
 	unsigned long page;
 
-#ifdef DEBUG
-	printk("Getting long at 0x%lx\n",addr);
-#endif
+	DBG(DBG_MEM, ("Getting long at 0x%lx\n", addr));
 repeat:
 	pgdir = pgd_offset(vma->vm_task, addr);
 	if (pgd_none(*pgdir)) {
@@ -177,7 +183,7 @@
  * even if a debugger scribbles breakpoints into it.  -M.U-
  */
 static void put_long(struct vm_area_struct * vma, unsigned long addr,
-	unsigned long data)
+		     unsigned long data)
 {
 	pgd_t *pgdir;
 	pmd_t *pgmiddle;
@@ -250,13 +256,11 @@
  * within the task area. It then calls get_long() to read a long.
  */
 static int read_long(struct task_struct * tsk, unsigned long addr,
-	unsigned long * result)
+		     unsigned long * result)
 {
 	struct vm_area_struct * vma = find_extend_vma(tsk, addr);
 
-#ifdef DEBUG
-	printk("in read_long\n");
-#endif
+	DBG(DBG_MEM, ("in read_long\n"));
 	if (!vma) {
 	        printk("Unable to find vma for addr 0x%lx\n",addr);
 		return -EIO;
@@ -306,9 +310,7 @@
 	} else {
 	        long l =get_long(vma, addr);
 
-#ifdef DEBUG
-		printk("value is 0x%lx\n",l);
-#endif
+		DBG(DBG_MEM, ("value is 0x%lx\n",l));
 		*result = l;
 	}
 	return 0;
@@ -391,33 +393,160 @@
 	return 0;
 }
 
-/* Uh, this does ugly stuff. It stores the specified value in the a3
+/*
+ * Read a 32bit int from address space TSK.
+ */
+static int read_int(struct task_struct * tsk, unsigned long addr, unsigned int *data)
+{
+	unsigned long l, align;
+	int res;
+
+	align = addr & 0x7;
+	addr &= ~0x7;
+
+	res = read_long(tsk, addr, &l);
+	if (res < 0)
+	  return res;
+
+	if (align == 0) {
+		*data = l;
+	} else {
+		*data = l >> 32;
+	}
+	return 0;
+}
+
+/*
+ * Write a 32bit word to address space TSK.
+ *
+ * For simplicity, do a read-modify-write of the 64bit word that
+ * contains the 32bit word that we are about to write.
+ */
+static int write_int(struct task_struct * tsk, unsigned long addr, unsigned int data)
+{
+	unsigned long l, align;
+	int res;
+
+	align = addr & 0x7;
+	addr &= ~0x7;
+
+	res = read_long(tsk, addr, &l);
+	if (res < 0)
+	  return res;
+
+	if (align == 0) {
+		l = (l & 0xffffffff00000000UL) | ((unsigned long) data <<  0);
+	} else {
+		l = (l & 0x00000000ffffffffUL) | ((unsigned long) data << 32);
+	}
+	return write_long(tsk, addr, l);
+}
+
+/*
+ * Uh, this does ugly stuff. It stores the specified value in the a3
  * register. entry.S will swap a3 and the returned value from
  * sys_ptrace() before returning to the user.
  */
 
-static inline void set_success(struct pt_regs *regs,long resval) {
-   regs->r19=resval;
+static inline void set_success(struct pt_regs *regs,long resval)
+{
+	regs->r19 = resval;
 }
 
-/* This doesn't do diddly, actually--if the value returned from 
+/*
+ * This doesn't do diddly, actually--if the value returned from 
  * sys_ptrace() is != 0, it sets things up properly.
  */
 
-static inline void set_failure(struct pt_regs *regs,long errcode) {
-   regs->r19=0;
+static inline void set_failure(struct pt_regs *regs, long errcode)
+{
+	regs->r19 = 0;
+}
+
+/*
+ * Set breakpoint.
+ */
+static int set_bpt(struct task_struct *child)
+{
+	int displ, i, res, reg_b, off, nsaved = 0;
+	u32 insn, op_code;
+	unsigned long pc;
+
+	pc  = get_stack_long(child, map_reg_to_offset[REG_PC]);
+	res = read_int(child, pc, &insn);
+	if (res < 0)
+	  return res;
+
+	op_code = insn >> 26;
+	if (op_code >= 0x30) {
+		/*
+		 * It's a branch: instead of trying to figure out
+		 * whether the branch will be taken or not, we'll put
+		 * a breakpoint at either location.  This is simpler,
+		 * more reliable, and probably not a whole lot slower
+		 * than the alternative approach of emulating the
+		 * branch (emulation can be tricky for fp branches).
+		 */
+		displ = ((s32)(insn << 11)) >> 9;
+		child->debugreg[nsaved++] = pc + 4;
+		if (displ)			/* guard against unoptimized code */
+		  child->debugreg[nsaved++] = pc + 4 + displ;
+		DBG(DBG_BPT, ("execing branch\n"));
+	} else if (op_code == 0x1a) {
+		reg_b = (insn >> 16) & 0x1f;
+		off = offset_of_register(reg_b);
+		if (off >= 0) {
+			child->debugreg[nsaved++] = get_stack_long(child, off);
+		} else {
+			/* $31 (aka zero) doesn't have a stack-slot */
+			if (reg_b == 31) {
+				child->debugreg[nsaved++] = 0;
+			} else {
+				return -EIO;
+			}
+		}
+		DBG(DBG_BPT, ("execing jump\n"));
+	} else {
+		child->debugreg[nsaved++] = pc + 4;
+		DBG(DBG_BPT, ("execing normal insn\n"));
+	}
+
+	/* install breakpoints: */
+	for (i = 0; i < nsaved; ++i) {
+		res = read_int(child, child->debugreg[i], &insn);
+		if (res < 0)
+		  return res;
+		child->debugreg[i + 2] = insn;
+		DBG(DBG_BPT, ("    -> next_pc=%lx\n", child->debugreg[i]));
+		res = write_int(child, child->debugreg[i], BREAKINST);
+		if (res < 0)
+		  return res;
+	}
+	child->debugreg[4] = nsaved;
+	return 0;
+}
+
+int ptrace_cancel_bpt(struct task_struct *child)
+{
+	int i, nsaved = child->debugreg[4];
+
+	child->debugreg[4] = 0;
+	for (i = 0; i < nsaved; ++i) {
+		write_int(child, child->debugreg[i], child->debugreg[i + 2]);
+	}
+	return nsaved;
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4, int a5, struct pt_regs regs)
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4, int a5,
+			   struct pt_regs regs)
 {
 	struct task_struct *child;
 	struct user * dummy;
+	int res;
 
 	dummy = NULL;
 
-#ifdef DEBUG
-	printk("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",request,pid,addr,data);
-#endif
+	DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",request,pid,addr,data));
 	set_success(&regs,0);
 	if (request == PTRACE_TRACEME) {
 		/* are we already being traced? */
@@ -465,25 +594,19 @@
 	   return 0;
 	}
 	if (!(child->flags & PF_PTRACED)) {
-#ifdef DEBUG
-	   printk("child not traced\n");
-#endif
-	   set_failure(&regs,-ESRCH);
-	   return -ESRCH;
+	    DBG(DBG_MEM, ("child not traced\n"));
+	    set_failure(&regs,-ESRCH);
+	    return -ESRCH;
 	}
 	if (child->state != TASK_STOPPED) {
-#ifdef DEBUG
-	   printk("child process not stopped\n");
-#endif
+	   DBG(DBG_MEM, ("child process not stopped\n"));
 	   if (request != PTRACE_KILL) {
 	      set_failure(&regs,-ESRCH);
 	      return -ESRCH;
 	   }
 	}
 	if (child->p_pptr != current) {
-#ifdef DEBUG
-	   printk("child not parent of this process\n");
-#endif
+	   DBG(DBG_MEM, ("child not parent of this process\n"));
 	   set_failure(&regs,-ESRCH);
 	   return -ESRCH;
 	}
@@ -495,9 +618,7 @@
 			unsigned long tmp;
 			int res;
 
-#ifdef DEBUG
-			printk("doing request at addr 0x%lx\n",addr);
-#endif
+			DBG(DBG_MEM, ("doing request at addr 0x%lx\n",addr));
 			res = read_long(child, addr, &tmp);
 			if (res < 0) {
 			   set_failure(&regs,res);
@@ -520,16 +641,16 @@
 			   tmp=child->tss.usp;
 			}
 			else {
+#ifdef DEBUG
 			   int reg=addr;
+#endif
 			   addr = offset_of_register(addr);
-			   if(addr < 0) {
-			      set_failure(&regs,-EIO);
+			   if (addr < 0) {
+			      set_failure(&regs, -EIO);
 			      return -EIO;
 			   }
 			   tmp = get_stack_long(child, addr);
-#ifdef DEBUG
-			   printk("%d = reg 0x%lx=tmp\n",reg,tmp);
-#endif
+			   DBG(DBG_MEM, ("%d = reg 0x%lx=tmp\n",reg,tmp));
 			}
 			set_success(&regs,tmp);
 			return 0;
@@ -573,12 +694,12 @@
 				child->flags &= ~PF_TRACESYS;
 			child->exit_code = data;
 			child->state = TASK_RUNNING;
-			unset_singlestep(child);
+			ptrace_cancel_bpt(child);
 			set_success(&regs,data);
 			return 0;
 		}
 
-/*
+ /*
  * make the child exit.  Best I can do is send it a sigkill. 
  * perhaps it should be put in the status that it wants to 
  * exit.
@@ -586,7 +707,7 @@
 		case PTRACE_KILL: {
 			child->state = TASK_RUNNING;
 			child->exit_code = SIGKILL;
-			unset_singlestep(child);
+			ptrace_cancel_bpt(child);
 			return 0;
 		}
 
@@ -595,8 +716,11 @@
 			   set_failure(&regs,-EIO);
 			   return -EIO;
 			}
+			res = set_bpt(child);
+			if (res < 0) {
+				return res;
+			}
 			child->flags &= ~PF_TRACESYS;
-			set_singlestep(child);
 			child->state = TASK_RUNNING;
 			child->exit_code = data;
 			/* give it a chance to run. */
@@ -615,7 +739,7 @@
 			child->p_pptr = child->p_opptr;
 			SET_LINKS(child);
 			/* make sure the single step bit is not set. */
-			unset_singlestep(child);
+			ptrace_cancel_bpt(child);
 			return 0;
 		}
 
diff -u --recursive --new-file v1.3.9/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v1.3.9/linux/arch/alpha/kernel/traps.c	Fri Jun 16 22:02:54 1995
+++ linux/arch/alpha/kernel/traps.c	Wed Jul 12 06:44:40 1995
@@ -19,10 +19,10 @@
 	unsigned long sp;
 	unsigned int * pc;
 
+	if (regs->ps & 8)
+		return;
 	printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
 	sp = (unsigned long) (regs+1);
-	if (regs->ps & 8)
-		sp = rdusp();
 	printk("pc = %lx ps = %04lx\n", regs->pc, regs->ps);
 	printk("rp = %lx sp = %lx\n", regs->r26, sp);
 	printk("r0=%lx r1=%lx r2=%lx r3=%lx\n",
@@ -36,8 +36,6 @@
 		regs->r24, regs->r25, regs->r26, regs->r27);
 	printk("r28=%lx r29=%lx r30=%lx\n",
 		regs->r28, regs->gp, sp);
-	if (regs->ps & 8)
-		return;
 	printk("Code:");
 	pc = (unsigned int *) regs->pc;
 	for (i = -3; i < 6; i++)
@@ -61,8 +59,29 @@
 	unsigned long a3, unsigned long a4, unsigned long a5,
 	struct pt_regs regs)
 {
+	extern int ptrace_cancel_bpt (struct task_struct *who);
+
 	die_if_kernel("Instruction fault", &regs, type);
-	send_sig(SIGILL, current, 1);
+	switch (type) {
+	      case 0: /* breakpoint */
+		if (ptrace_cancel_bpt(current)) {
+			regs.pc -= 4;	/* make pc point to former bpt */
+		}
+		if (current->flags & PF_PTRACED)
+		  current->blocked &= ~(1 << (SIGTRAP - 1));
+		send_sig(SIGTRAP, current, 1);
+		break;
+
+	      case 1: /* bugcheck */
+	      case 2: /* gentrap */
+	      case 3: /* FEN fault */
+	      case 4: /* opDEC */
+		send_sig(SIGILL, current, 1);
+		break;
+
+	      default:
+		panic("do_entIF: unexpected instruction-fault type");
+	}
 }
 
 /*
@@ -131,7 +150,8 @@
 asmlinkage long do_entSys(unsigned long a0, unsigned long a1, unsigned long a2,
 	unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs regs)
 {
-	printk("<sc %ld(%lx,%lx,%lx)>", regs.r0, a0, a1, a2);
+	if (regs.r0 != 112)
+	  printk("<sc %ld(%lx,%lx,%lx)>", regs.r0, a0, a1, a2);
 	return -1;
 }
 
diff -u --recursive --new-file v1.3.9/linux/arch/alpha/vmlinux.lds linux/arch/alpha/vmlinux.lds
--- v1.3.9/linux/arch/alpha/vmlinux.lds	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/vmlinux.lds	Wed Jul 12 06:41:58 1995
@@ -0,0 +1,49 @@
+OUTPUT_FORMAT("ecoff-littlealpha")
+ENTRY(__start)
+SECTIONS
+{
+  .text 0xfffffc0000310000: {
+     _ftext = . ;
+     __istart = . ;
+     eprol  =  .;
+    *(.text)
+     __fstart = . ;
+     _etext  =  .;
+  }
+  .rdata : {
+    *(.rdata)
+  }
+  .pdata : {
+     _fpdata = .;
+    *(.pdata)
+  }
+  .data : {
+     _fdata = .;
+    *(.data)
+    CONSTRUCTORS
+  }
+  .xdata : {
+    *(.xdata)
+  }
+   _gp = ALIGN (16) + 0x8000;
+  .lit8 : {
+    *(.lit8)
+  }
+  .lita : {
+    *(.lita)
+  }
+  .sdata : {
+    *(.sdata)
+  }
+   _EDATA  =  .;
+   _FBSS = .;
+  .sbss : {
+    *(.sbss)
+    *(.scommon)
+  }
+  .bss : {
+    *(.bss)
+    *(COMMON)
+  }
+   _end = .;
+}
diff -u --recursive --new-file v1.3.9/linux/arch/i386/config.in linux/arch/i386/config.in
--- v1.3.9/linux/arch/i386/config.in	Tue Jul 11 10:02:47 1995
+++ linux/arch/i386/config.in	Wed Jul 12 18:24:18 1995
@@ -60,6 +60,7 @@
 bool 'IP: Assume subnets are local' CONFIG_INET_SNARL y
 bool 'IP: Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF n
 bool 'IP: Drop source routed frames' CONFIG_IP_NOSR y
+bool 'IP: Allow large windows (not recommend if <16Mb of memory)' CONFIG_SKB_LARGE y
 fi
 bool 'The IPX protocol' CONFIG_IPX n
 bool 'Appletalk DDP' CONFIG_ATALK n
diff -u --recursive --new-file v1.3.9/linux/drivers/block/cdu31a.c linux/drivers/block/cdu31a.c
--- v1.3.9/linux/drivers/block/cdu31a.c	Wed Apr  5 13:07:22 1995
+++ linux/drivers/block/cdu31a.c	Wed Jul 12 07:07:32 1995
@@ -185,7 +185,7 @@
 
 #define DEBUG 0
 
-#define CDU31A_READAHEAD 64  /* 64 sector, 32kB, 16 reads read-ahead */
+#define CDU31A_READAHEAD 128  /* 128 sector, 64kB, 32 reads read-ahead */
 #define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10
 
 /* Define the following if you have data corruption problems. */
@@ -380,6 +380,8 @@
 static inline void
 sony_sleep(void)
 {
+   unsigned long flags;
+
    if (irq_used <= 0)
    {
       current->state = TASK_INTERRUPTIBLE;
@@ -388,10 +390,11 @@
    }
    else /* Interrupt driven */
    {
+      save_flags(flags);
       cli();
       enable_interrupts();
       interruptible_sleep_on(&cdu31a_irq_wait);
-      sti();
+      restore_flags(flags);
    }
 }
 
@@ -516,6 +519,18 @@
    unsigned char params[3];
 
 
+   params[0] = SONY_SD_AUTO_SPIN_DOWN_TIME;
+   params[1] = 0x00; /* Never spin down the drive. */
+   do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
+                  params,
+                  2,
+                  res_reg,
+                  &res_size);
+   if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))
+   {
+      printk("  Unable to set spin-down time: 0x%2.2x\n", res_reg[1]);
+   }
+
    params[0] = SONY_SD_MECH_CONTROL;
    params[1] = 0x03; /* Set auto spin up and auto eject */
    if (is_double_speed)
@@ -753,8 +768,10 @@
    unsigned int retry_count;
    int num_retries;
    int recursive_call;
+   unsigned long flags;
 
 
+   save_flags(flags);
    cli();
    if (current != has_cd_task) /* Allow recursive calls to this routine */
    {
@@ -777,7 +794,7 @@
    {
       recursive_call = 1;
    }
-   sti();
+   restore_flags(flags);
 
    num_retries = 0;
 retry_cd_operation:
@@ -1356,24 +1373,31 @@
    unsigned char res_reg[12];
    unsigned int res_size;
    int num_retries;
+   unsigned long flags;
 
 
    /* 
     * Make sure no one else is using the driver; wait for them
     * to finish if it is so.
     */
+   save_flags(flags);
    cli();
    while (sony_inuse)
    {
       interruptible_sleep_on(&sony_wait);
       if (current->signal & ~current->blocked)
       {
+         restore_flags(flags);
+         if (CURRENT && (CURRENT->dev > 0))
+         {
+            end_request(0);
+         }
          return;
       }
    }
    sony_inuse = 1;
    has_cd_task = current;
-   sti();
+   restore_flags(flags);
 
    /* Get drive status before doing anything. */
    while (handle_sony_cd_attention())
@@ -1507,6 +1531,7 @@
             }
             if (start_request(block / 4, CDU31A_READAHEAD / 4, 0))
             {
+               printk("CDU31a: start request failed\n");
                end_request(0);
                goto cdu31a_request_startover;
             }
@@ -1991,11 +2016,13 @@
    unsigned char res_reg[12];
    unsigned int res_size;
    unsigned int cframe;
+   unsigned long flags;
 
    /* 
     * Make sure no one else is using the driver; wait for them
     * to finish if it is so.
     */
+   save_flags(flags);
    cli();
    while (sony_inuse)
    {
@@ -2007,7 +2034,7 @@
    }
    sony_inuse = 1;
    has_cd_task = current;
-   sti();
+   restore_flags(flags);
 
    if (!sony_spun_up)
    {
@@ -2167,8 +2194,20 @@
 /*
  * The big ugly ioctl handler.
  */
-static int
-scd_ioctl(struct inode *inode,
+ 
+static int do_sony_cd_cmd_chk(char *name, unsigned char cmd, unsigned char *params, unsigned int num_params,
+		unsigned char *result_buffer, unsigned int *result_size)
+{      
+      do_sony_cd_cmd(cmd, params, num_params, result_buffer, result_size);
+      if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20))
+      {
+         printk("Sony CDROM error 0x%2.2x (CDROM%s)\n", result_buffer[1], name);
+         return -EIO;
+      }
+      return 0;
+}
+ 
+static int scd_ioctl(struct inode *inode,
           struct file  *file,
           unsigned int  cmd,
           unsigned long arg)
@@ -2187,12 +2226,7 @@
    switch (cmd)
    {
    case CDROMSTART:     /* Spin up the drive */
-      do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
-      if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))
-      {
-         printk("Sony CDROM error 0x%2.2x (CDROMSTART)\n", res_reg[1]);
-         return -EIO;
-      }
+      return do_sony_cd_cmd_chk("START",SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
       return 0;
       break;
       
@@ -2204,25 +2238,11 @@
        * already not spinning.
        */
       sony_audio_status = CDROM_AUDIO_NO_STATUS;
-      do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
-      if (   ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))
-          && (res_reg[1] != SONY_NOT_SPIN_ERR))
-      {
-         printk("Sony CDROM error 0x%2.2x (CDROMSTOP)\n", res_reg[1]);
-         return -EIO;
-      }
-      
-      return 0;
-      break;
+      return do_sony_cd_cmd_chk("STOP",SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
 
    case CDROMPAUSE:     /* Pause the drive */
-      do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size);
-      if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))
-      {
-         printk("Sony CDROM error 0x%2.2x (CDROMPAUSE)\n", res_reg[1]);
-         return -EIO;
-      }
-
+      if(do_sony_cd_cmd_chk("PAUSE", SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size))
+      	return -EIO;
       /* Get the current position and save it for resuming */
       if (read_subcode() < 0)
       {
@@ -2251,18 +2271,15 @@
       params[5] = final_pos_msf[1];
       params[6] = final_pos_msf[2];
       params[0] = 0x03;
-      do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size);
-      if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))
-      {
-         printk("Sony CDROM error 0x%2.2x (CDROMRESUME)\n", res_reg[1]);
-         return -EIO;
-      }
+      if(do_sony_cd_cmd_chk("RESUME",SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size)<0)
+      	return -EIO;
       sony_audio_status = CDROM_AUDIO_PLAY;
       return 0;
-      break;
 
    case CDROMPLAYMSF:   /* Play starting at the given MSF address. */
-      verify_area(VERIFY_READ, (char *) arg, 6);
+      i=verify_area(VERIFY_READ, (char *) arg, 6);
+      if(i)
+      	return i;
       do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
       memcpy_fromfs(&(params[1]), (void *) arg, 6);
       
@@ -2272,12 +2289,8 @@
          params[i] = int_to_bcd(params[i]);
       }
       params[0] = 0x03;
-      do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size);
-      if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))
-      {
-         printk("Sony CDROM error 0x%2.2x (CDROMPLAYMSF)\n", res_reg[1]);
-         return -EIO;
-      }
+      if(do_sony_cd_cmd_chk("PLAYMSF",SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size)<0)
+      	return -EIO;
       
       /* Save the final position for pauses and resumes */
       final_pos_msf[0] = params[4];
@@ -2285,7 +2298,6 @@
       final_pos_msf[2] = params[6];
       sony_audio_status = CDROM_AUDIO_PLAY;
       return 0;
-      break;
 
    case CDROMREADTOCHDR:        /* Read the table of contents header */
       {
@@ -2299,13 +2311,14 @@
          }
          
          hdr = (struct cdrom_tochdr *) arg;
-         verify_area(VERIFY_WRITE, hdr, sizeof(*hdr));
+         i=verify_area(VERIFY_WRITE, hdr, sizeof(*hdr));
+         if(i<0)
+         	return i;
          loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
          loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
          memcpy_tofs(hdr, &loc_hdr, sizeof(*hdr));
       }
       return 0;
-      break;
 
    case CDROMREADTOCENTRY:      /* Read a given table of contents entry */
       {
@@ -2321,8 +2334,12 @@
          }
          
          entry = (struct cdrom_tocentry *) arg;
-         verify_area(VERIFY_READ, entry, sizeof(*entry));
-         verify_area(VERIFY_WRITE, entry, sizeof(*entry));
+         i=verify_area(VERIFY_READ, entry, sizeof(*entry));
+         if(i<0)
+         	return i;
+         i=verify_area(VERIFY_WRITE, entry, sizeof(*entry));
+         if(i<0)
+         	return i;
          
          memcpy_fromfs(&loc_entry, entry, sizeof(loc_entry));
          
@@ -2373,7 +2390,9 @@
             return -EIO;
          }
          
-         verify_area(VERIFY_READ, (char *) arg, sizeof(ti));
+         i=verify_area(VERIFY_READ, (char *) arg, sizeof(ti));
+         if(i<0)
+         	return i;
          
          memcpy_fromfs(&ti, (char *) arg, sizeof(ti));
          if (   (ti.cdti_trk0 < sony_toc->first_track_num)
@@ -2416,6 +2435,7 @@
          do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
          
          do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size);
+         
          if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))
          {
             printk("Params: %x %x %x %x %x %x %x\n", params[0], params[1],
@@ -2439,34 +2459,22 @@
       {
          struct cdrom_volctrl volctrl;
          
-         verify_area(VERIFY_READ, (char *) arg, sizeof(volctrl));
+         i=verify_area(VERIFY_READ, (char *) arg, sizeof(volctrl));
+         if(i<0)
+         	return i;
          
          memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
          params[0] = SONY_SD_AUDIO_VOLUME;
          params[1] = volctrl.channel0;
          params[2] = volctrl.channel1;
-         do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, params, 3, res_reg, &res_size);
-         if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))
-         {
-            printk("Sony CDROM error 0x%2.2x (CDROMVOLCTRL)\n", res_reg[1]);
-            return -EIO;
-         }
+         return do_sony_cd_cmd_chk("VOLCTRL",SONY_SET_DRIVE_PARAM_CMD, params, 3, res_reg, &res_size);
       }
-      return 0;
-
    case CDROMEJECT:     /* Eject the drive */
       do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size);
       do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
 
       sony_audio_status = CDROM_AUDIO_INVALID;
-      do_sony_cd_cmd(SONY_EJECT_CMD, NULL, 0, res_reg, &res_size);
-      if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))
-      {
-         printk("Sony CDROM error 0x%2.2x (CDROMEJECT)\n", res_reg[1]);
-         return -EIO;
-      }
-      return 0;
-      break;
+      return do_sony_cd_cmd_chk("EJECT",SONY_EJECT_CMD, NULL, 0, res_reg, &res_size);
      
     case CDROMREADAUDIO:      /* Read 2352 byte audio tracks and 2340 byte
 				 raw data tracks. */
@@ -2480,10 +2488,14 @@
             return -EIO;
          }
          
-         verify_area(VERIFY_READ, (char *) arg, sizeof(ra));
+         i=verify_area(VERIFY_READ, (char *) arg, sizeof(ra));
+         if(i<0)
+         	return i;
          memcpy_fromfs(&ra, (char *) arg, sizeof(ra));
 
-         verify_area(VERIFY_WRITE, ra.buf, CD_FRAMESIZE_RAW * ra.nframes);
+         i=verify_area(VERIFY_WRITE, ra.buf, CD_FRAMESIZE_RAW * ra.nframes);
+         if(i<0)
+         	return i;
 
          if (ra.addr_format == CDROM_LBA)
          {
diff -u --recursive --new-file v1.3.9/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v1.3.9/linux/drivers/block/genhd.c	Tue Jul 11 10:02:49 1995
+++ linux/drivers/block/genhd.c	Wed Jul 12 06:29:19 1995
@@ -114,7 +114,9 @@
 	struct buffer_head *bh;
 	struct partition *p;
 	int mask = (1 << hd->minor_shift) - 1;
+#ifdef CONFIG_BLK_DEV_IDE
 	extern void ide_xlate_1024(dev_t);
+#endif
 
 read_mbr:
 	if (!(bh = bread(dev,0,1024))) {
@@ -149,7 +151,9 @@
 		first_sector                    += p->end_sector;
 		hd->part[MINOR(dev)].start_sect += p->end_sector;
 		hd->part[MINOR(dev)].nr_sects   -= p->end_sector;
+#ifdef CONFIG_BLK_DEV_IDE
 		ide_xlate_1024(dev);	/* harmless if not an IDE drive */
+#endif
 		bh->b_dirt = 0;		/* prevent re-use of this block */
 		bh->b_uptodate = 0;
 		bh->b_req = 0;
@@ -162,7 +166,9 @@
 	 */
 	if (p->sys_ind == DM6_AUXPARTITION) {
 		printk(" [DM6]");
+#ifdef CONFIG_BLK_DEV_IDE
 		ide_xlate_1024(dev);	/* harmless if not an IDE drive */
+#endif
 	}
 
 	current_minor += 4;  /* first "extra" minor (for extended partitions) */
diff -u --recursive --new-file v1.3.9/linux/drivers/char/selection.c linux/drivers/char/selection.c
--- v1.3.9/linux/drivers/char/selection.c	Tue Jun 27 14:11:34 1995
+++ linux/drivers/char/selection.c	Wed Jul 12 06:41:58 1995
@@ -15,6 +15,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
+#include <linux/types.h>
 
 #include <asm/segment.h>
 
@@ -69,7 +70,7 @@
  * User settable table: what characters are to be considered alphabetic?
  * 256 bits
  */
-static unsigned long inwordLut[8]={
+static u32 inwordLut[8]={
   0x00000000, /* control chars     */
   0x03FF0000, /* digits            */
   0x87FFFFFE, /* uppercase and '_' */
@@ -90,7 +91,7 @@
 	int i = verify_area(VERIFY_READ, (char *) arg, 36);
 	if (i)
 		return i;
-	memcpy_fromfs(inwordLut, (unsigned long *)(arg+4), 32);
+	memcpy_fromfs(inwordLut, (u32 *)(arg+4), 32);
 	return 0;
 }
 
diff -u --recursive --new-file v1.3.9/linux/drivers/char/tty_ioctl.c linux/drivers/char/tty_ioctl.c
--- v1.3.9/linux/drivers/char/tty_ioctl.c	Tue Jun 27 14:11:35 1995
+++ linux/drivers/char/tty_ioctl.c	Thu Jul 13 09:53:52 1995
@@ -94,48 +94,13 @@
 			old->c_cc[i] : termios->c_cc[i];
 }
 
-static int set_termios(struct tty_struct * tty, unsigned long arg, int opt)
+static void change_termios(struct tty_struct * tty, struct termios * new_termios)
 {
-	struct termio tmp_termio;
-	struct termios tmp_termios;
+	int canon_change;
 	struct termios old_termios = *tty->termios;
-	int retval, canon_change;
-
-	retval = tty_check_change(tty);
-	if (retval)
-		return retval;
-
-	if (opt & TERMIOS_TERMIO) {
-		retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termio));
-		if (retval)
-			return retval;
-		tmp_termios = *tty->termios;
-		memcpy_fromfs(&tmp_termio, (struct termio *) arg,
-			      sizeof (struct termio));
-
-#define SET_LOW_BITS(x,y)	((x) = (0xffff0000 & (x)) | (y))
-		SET_LOW_BITS(tmp_termios.c_iflag, tmp_termio.c_iflag);
-		SET_LOW_BITS(tmp_termios.c_oflag, tmp_termio.c_oflag);
-		SET_LOW_BITS(tmp_termios.c_cflag, tmp_termio.c_cflag);
-		SET_LOW_BITS(tmp_termios.c_lflag, tmp_termio.c_lflag);
-		memcpy(&tmp_termios.c_cc, &tmp_termio.c_cc, NCC);
-#undef SET_LOW_BITS
-	} else {
-		retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termios));
-		if (retval)
-			return retval;
-		memcpy_fromfs(&tmp_termios, (struct termios *) arg,
-			      sizeof (struct termios));
-	}
-
-	if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
-
-	if (opt & TERMIOS_WAIT)
-		tty_wait_until_sent(tty, 0);
 
 	cli();
-	*tty->termios = tmp_termios;
+	*tty->termios = *new_termios;
 	unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
 	canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
 	if (canon_change) {
@@ -173,7 +138,41 @@
 
 	if (tty->ldisc.set_termios)
 		(*tty->ldisc.set_termios)(tty, &old_termios);
-		
+}
+
+static int set_termios(struct tty_struct * tty, unsigned long arg, int opt)
+{
+	struct termios tmp_termios;
+	int retval;
+
+	retval = tty_check_change(tty);
+	if (retval)
+		return retval;
+
+	if (opt & TERMIOS_TERMIO) {
+		struct termio tmp_termio;
+		retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termio));
+		if (retval)
+			return retval;
+		tmp_termios = *tty->termios;
+		memcpy_fromfs(&tmp_termio, (struct termio *) arg,
+			      sizeof (struct termio));
+		trans_from_termio(&tmp_termio, &tmp_termios);
+	} else {
+		retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termios));
+		if (retval)
+			return retval;
+		memcpy_fromfs(&tmp_termios, (struct termios *) arg,
+			      sizeof (struct termios));
+	}
+
+	if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+
+	if (opt & TERMIOS_WAIT)
+		tty_wait_until_sent(tty, 0);
+
+	change_termios(tty, &tmp_termios);
 	return 0;
 }
 
@@ -185,13 +184,7 @@
 	i = verify_area(VERIFY_WRITE, termio, sizeof (struct termio));
 	if (i)
 		return i;
-	tmp_termio.c_iflag = tty->termios->c_iflag;
-	tmp_termio.c_oflag = tty->termios->c_oflag;
-	tmp_termio.c_cflag = tty->termios->c_cflag;
-	tmp_termio.c_lflag = tty->termios->c_lflag;
-	tmp_termio.c_line = tty->termios->c_line;
-	for(i=0 ; i < NCC ; i++)
-		tmp_termio.c_cc[i] = tty->termios->c_cc[i];
+	trans_to_termio(tty->termios, &tmp_termio);
 	memcpy_tofs(termio, &tmp_termio, sizeof (struct termio));
 	return 0;
 }
@@ -215,6 +208,169 @@
 	return nr;
 }
 
+#ifdef TIOCGETP
+/*
+ * These are depracated, but there is limited support..
+ *
+ * The "sg_flags" translation is a joke..
+ */
+static int get_sgflags(struct tty_struct * tty)
+{
+	int flags = 0;
+
+	if (!(tty->termios->c_lflag & ICANON))
+		if (tty->termios->c_lflag & ISIG)
+			flags |= 0x02;		/* cbreak */
+		else
+			flags |= 0x20;		/* raw */
+	if (tty->termios->c_lflag & ECHO)
+		flags |= 0x08;			/* echo */
+	if (tty->termios->c_oflag & OPOST)
+		if (tty->termios->c_oflag & ONLCR)
+			flags |= 0x10;		/* crmod */
+	return flags;
+}
+
+static int get_sgttyb(struct tty_struct * tty, struct sgttyb * sgttyb)
+{
+	int retval;
+	struct sgttyb tmp;
+
+	retval = verify_area(VERIFY_WRITE, sgttyb, sizeof(struct sgttyb));
+	if (retval)
+		return retval;
+	tmp.sg_ispeed = 0;
+	tmp.sg_ospeed = 0;
+	tmp.sg_erase = tty->termios->c_cc[VERASE];
+	tmp.sg_kill = tty->termios->c_cc[VKILL];
+	tmp.sg_flags = get_sgflags(tty);
+	memcpy_tofs(sgttyb, &tmp, sizeof(tmp));
+	return 0;
+}
+
+static void set_sgflags(struct termios * termios, int flags)
+{
+	termios->c_iflag = ICRNL | IXON;
+	termios->c_oflag = 0;
+	termios->c_lflag = ISIG | ICANON;
+	if (flags & 0x02) {	/* cbreak */
+		termios->c_iflag = 0;
+		termios->c_lflag &= ~ICANON;
+	}
+	if (flags & 0x08) {		/* echo */
+		termios->c_lflag |= ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
+	}
+	if (flags & 0x10) {		/* crmod */
+		termios->c_oflag |= OPOST | ONLCR;
+	}
+	if (flags & 0x20) {	/* raw */
+		termios->c_iflag = 0;
+		termios->c_lflag &= ~(ISIG | ICANON);
+	}
+	if (!(termios->c_lflag & ICANON)) {
+		termios->c_cc[VMIN] = 1;
+		termios->c_cc[VTIME] = 0;
+	}
+}
+
+static int set_sgttyb(struct tty_struct * tty, struct sgttyb * sgttyb)
+{
+	int retval;
+	struct sgttyb tmp;
+	struct termios termios;
+
+	retval = verify_area(VERIFY_READ, sgttyb, sizeof(struct sgttyb));
+	if (retval)
+		return retval;
+	retval = tty_check_change(tty);
+	if (retval)
+		return retval;
+	termios =  *tty->termios;
+	memcpy_fromfs(&tmp, sgttyb, sizeof(tmp));
+	termios.c_cc[VERASE] = tmp.sg_erase;
+	termios.c_cc[VKILL] = tmp.sg_kill;
+	set_sgflags(&termios, tmp.sg_flags);
+	change_termios(tty, &termios);
+	return 0;
+}
+#endif
+
+#ifdef TIOCGETC
+static int get_tchars(struct tty_struct * tty, struct tchars * tchars)
+{
+	int retval;
+	struct tchars tmp;
+
+	retval = verify_area(VERIFY_WRITE, tchars, sizeof(struct tchars));
+	if (retval)
+		return retval;
+	tmp.t_intrc = tty->termios->c_cc[VINTR];
+	tmp.t_quitc = tty->termios->c_cc[VQUIT];
+	tmp.t_startc = tty->termios->c_cc[VSTART];
+	tmp.t_stopc = tty->termios->c_cc[VSTOP];
+	tmp.t_eofc = tty->termios->c_cc[VEOF];
+	tmp.t_brkc = tty->termios->c_cc[VEOL2];	/* what is brkc anyway? */
+	memcpy_tofs(tchars, &tmp, sizeof(tmp));
+	return 0;
+}
+
+static int set_tchars(struct tty_struct * tty, struct tchars * tchars)
+{
+	int retval;
+	struct tchars tmp;
+
+	retval = verify_area(VERIFY_READ, tchars, sizeof(struct tchars));
+	if (retval)
+		return retval;
+	memcpy_fromfs(&tmp, tchars, sizeof(tmp));
+	tty->termios->c_cc[VINTR] = tmp.t_intrc;
+	tty->termios->c_cc[VQUIT] = tmp.t_quitc;
+	tty->termios->c_cc[VSTART] = tmp.t_startc;
+	tty->termios->c_cc[VSTOP] = tmp.t_stopc;
+	tty->termios->c_cc[VEOF] = tmp.t_eofc;
+	tty->termios->c_cc[VEOL2] = tmp.t_brkc;	/* what is brkc anyway? */
+	return 0;
+}
+#endif
+
+#ifdef TIOCGLTC
+static int get_ltchars(struct tty_struct * tty, struct ltchars * ltchars)
+{
+	int retval;
+	struct ltchars tmp;
+
+	retval = verify_area(VERIFY_WRITE, ltchars, sizeof(struct ltchars));
+	if (retval)
+		return retval;
+	tmp.t_suspc = tty->termios->c_cc[VSUSP];
+	tmp.t_dsuspc = tty->termios->c_cc[VSUSP];	/* what is dsuspc anyway? */
+	tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
+	tmp.t_flushc = tty->termios->c_cc[VEOL2];	/* what is flushc anyway? */
+	tmp.t_werasc = tty->termios->c_cc[VWERASE];
+	tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
+	memcpy_tofs(ltchars, &tmp, sizeof(tmp));
+	return 0;
+}
+
+static int set_ltchars(struct tty_struct * tty, struct ltchars * ltchars)
+{
+	int retval;
+	struct ltchars tmp;
+
+	retval = verify_area(VERIFY_READ, ltchars, sizeof(struct ltchars));
+	if (retval)
+		return retval;
+	memcpy_fromfs(&tmp, ltchars, sizeof(tmp));
+	tty->termios->c_cc[VSUSP] = tmp.t_suspc;
+	tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;	/* what is dsuspc anyway? */
+	tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
+	tty->termios->c_cc[VEOL2] = tmp.t_flushc;	/* what is flushc anyway? */
+	tty->termios->c_cc[VWERASE] = tmp.t_werasc;
+	tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
+	return 0;
+}
+#endif
+
 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
 		       unsigned int cmd, unsigned long arg)
 {
@@ -229,6 +385,25 @@
 		real_tty = tty;
 
 	switch (cmd) {
+#ifdef TIOCGETP
+		case TIOCGETP:
+			return get_sgttyb(real_tty, (struct sgttyb *) arg);
+		case TIOCSETP:
+		case TIOCSETN:
+			return set_sgttyb(real_tty, (struct sgttyb *) arg);
+#endif
+#ifdef TIOCGETC
+		case TIOCGETC:
+			return get_tchars(real_tty, (struct tchars *) arg);
+		case TIOCSETC:
+			return set_tchars(real_tty, (struct tchars *) arg);
+#endif
+#ifdef TIOCGLTC
+		case TIOCGLTC:
+			return get_ltchars(real_tty, (struct ltchars *) arg);
+		case TIOCSLTC:
+			return set_ltchars(real_tty, (struct ltchars *) arg);
+#endif
 		case TCGETS:
 			retval = verify_area(VERIFY_WRITE, (void *) arg,
 					     sizeof (struct termios));
diff -u --recursive --new-file v1.3.9/linux/drivers/net/README.arcnet linux/drivers/net/README.arcnet
--- v1.3.9/linux/drivers/net/README.arcnet	Fri Mar 24 17:20:02 1995
+++ linux/drivers/net/README.arcnet	Wed Jul 12 07:53:14 1995
@@ -1,13 +1,13 @@
 
----------------------------------------------------------------------------
+----------------------------------------------------------------------------
 NOTE:  See also README.arcnet-jumpers in this directory for jumper-setting
-information if you're like most of us and didn't happen to get a manual with
+information if you're like many of us and didn't happen to get a manual with
 your ARCnet card.
----------------------------------------------------------------------------
+----------------------------------------------------------------------------
 
 Since no one seems to listen to me otherwise, perhaps a poem will get your
 attention:
-			This is scary software
+			This is alpha software
 			If it works I DO CARE.
 			
 Hmm, I think I'm allowed to call that a poem, even though it's only two
@@ -30,63 +30,67 @@
 			
 These are the ARCnet drivers for Linux.
 
-This is the first non-ALPHA release, so please be careful, and send all
-possible success/failure reports to me.  If I don't know when/if/how it
-works, I won't be able to answer people's questions.  Do we want that?  Of
-course not.
+We're now back to more ALPHA releases after the 1.01 release which made it
+into Linux 1.2.2, so please be careful, and send all possible
+success/failure reports to me.  If I don't know when/if/how it works, I
+won't be able to answer people's questions.  Do we want that?  Of course
+not.
 
 Once again:  DO send me success reports!  I want to know if this is working!
 (You know, it might be argued that I'm pushing this point a little too much. 
-If you think so, why not flame me in a quick little email?  Please also
+If you think so, why not flame me in a quick little e-mail?  Please also
 include the type of card(s) you're using, software, size of network, and
 whether it's working or not.)
 
 My e-mail address is:
-	apenwarr@tourism.807-city.on.ca
+	apenwarr@foxnet.net
 
 
 Where do I discuss these drivers?
 ---------------------------------
 
-As of the 0.22 release, we have a mailing list specifically for discussion
-of the ARCnet drivers for Linux, and anything you might want to interface
-them with (ie. DOS).  I'll also post new versions of the Linux-ARCnet
-distribution to the list in tar-gzip-uuencode format.
+There is a mailing list specifically for discussion of the ARCnet drivers
+for Linux, and anything you might want to interface them with (ie. DOS). 
+I'll also post new versions of the Linux-ARCnet distribution to the list in
+tar-gzip-uuencode format.
 
-To subscribe to the list, send a message to listserv@tourism.807-city.on.ca
+To subscribe to the list, send a message to listserv@807-city.on.ca
 with the following line in the BODY (not the SUBJECT) of your message:
 	subscribe linux-arcnet YOUR REAL NAME
 Remember to remove your signature, or you'll get an error back.
 
 Send all bug (or success) reports to me or to the list.
 
-You're free to use the comp.os.linux.development newsgroup too, but I can't
-guarantee I'll see it there.  (Hopefully, if my news server stays sane, I
-will.)
+The people on linux-net@vger.rutgers.edu have also been known to be very
+helpful! :)
+
+
+Other Drivers and Info
+----------------------
 
 Also, SMC (one of the companies that makes ARCnet cards) has a WorldWideWeb
 site you might be interested in, which includes several drivers for various
 cards including ARCnet.  Try:
 	http://www.smc.com/
 	
+Performance Technologies makes various network software that supports
+ARCnet.
+	http://www.perftech.com/ or ftp to ftp.perftech.com.
+	
 Novell makes a networking stack for DOS which includes ARCnet drivers.  Try
 ftp'ing to ftp.novell.com.
 
 You can get the Crynwr packet driver collection (including arcether.com, the
-one you'll want for arcnet cards) from oak.oakland.edu:/pub/msdos/pktdrvr. 
+one you'll want for arcnet cards) from oak.oakland.edu:/simtel/msdos/pktdrvr.
 It won't work perfectly on a 386+ without patches, though, and also doesn't
-like several cards.  Mail me if you want a fixed version.
-
-
-Last warning:  This driver may be extremely dangerous, crash your computer,
-or kill your dog!  (although I'm pretty sure that I've worked that one
-out...)
+like several cards.  Mail me if you want a fixed version.  (Ahem:  I may or
+may not have a 100% fixed version by the time I get your mail!)
 
 
 Loadable Module Support
 -----------------------
 
-This is a new feature as of 0.42 ALPHA.
+This is a available starting with 0.42 ALPHA.
 
 Configure and rebuild Linux.  When asked, say NO to "arcnet support" if you
 want loadable module support.
@@ -124,28 +128,47 @@
 --------------------------------
 
 NFS: Should be fine linux->linux, just pretend you're using ethernet cards. 
-        oak.oakland.edu:/pub/msdos/nfs has some nice DOS clients.  I can't
-        get SOSS (dos-based server) to work, although someone has and can't
-        figure out why it won't work for me.
+        oak.oakland.edu:/simtel/msdos/nfs has some nice DOS clients.  There
+        is also a DOS-based NFS server called SOSS.  It doesn't multitask
+        quite the way Linux does (actually, it doesn't multitask AT ALL) but
+        you never know what you might need.
 
 DOS: If you're using the freeware arcether.com, you might want to install
         the source code patch.  It helps with PC/TCP, and also can get
-        arcether to load if it timed out too quickly.  Mail me if you need a
-        precompiled version of arcether.com. (ie. you if don't have a DOS
-        assembler)
+        arcether to load if it timed out too quickly during initialization. 
+        Mail me if you need a precompiled version of arcether.com. (ie. you
+        if don't have a DOS assembler)
 	
-Windows:  See DOS :)
+Windows:  See DOS :)  Trumpet Winsock works fine with either the Novell or
+	Arcether client, assuming you remember to load winpkt of course.
 
-OS2: May work okay.  Please e-mail me if you find a freeware TCP/IP stack
-        for OS/2.
-        
 LAN Manager and Windows for Workgroups: These programs use protocols that
-        are incompatible with ARCnet for Linux.  Rather than using the
-        internet-standard ARCnet protocol, they try to pretend the cards are
-        ethernet, and confuse everyone else on the network.
+        are incompatible with the internet standard.  They try to pretend
+        the cards are ethernet, and confuse everyone else on the network. 
+        However, v1.90 ALPHA and later of the Linux ARCnet driver support
+        this protocol via the 'arc0w' device.  After setting up arc0 as
+        usual, ifconfig and set up routes to your WfWg-protocol hosts
+        through arc0w.
         
-        An upcoming release of ARCnet for Linux may have workarounds for
-	this stupid behaviour.
+	Using the freeware Samba server and clients for Linux, you can now
+	interface quite nicely with TCP/IP-based WfWg or Lan Manager
+	networks.  In addition, the Linux host can be used as a router
+	between the standard and WfWg protocols, so hosts that could
+	previously never talk to each other should now be able to.
+
+        This feature is still in early testing, so please e-mail with any
+	comments/questions you might have.
+	
+OS2: Has not been tested.  The "correct" solution would be to buy either of
+	IBM's "TCP/IP for OS/2" or "Warp Connect" packages.  However,
+	ftp.microsoft.com also has a freeware Lan Manager for OS/2 client
+	which should use the same protocol as WfWg does.  This has not been
+	tested, however.  Please mail me with any results.
+        
+NetBSD/AmiTCP: These use an old version of the Internet standard ARCnet
+	protocol which is incompatible with the Linux driver at present. 
+	Work to support these is underway and should be available in a
+	standard release soon.
 
 
 It works: what now?
@@ -154,11 +177,12 @@
 Send mail describing your setup, preferably including driver version, kernel
 version, ARCnet card model, CPU type, number of systems on your network, and
 list of software in use to me at the following address:
-	apenwarr@tourism.807-city.on.ca
+	apenwarr@foxnet.net
 
-I do send (sometimes automated) replies to all messages I receive.  My mail
-host is quite weird, so if you don't get a reply within a reasonable time,
-please resend.
+I do send (sometimes automated) replies to all messages I receive.  My email
+can be weird (and also usually gets forwarded all over the place along the
+way to me), so if you don't get a reply within a reasonable time, please
+resend.
 
 
 It doesn't work: what now?
@@ -171,31 +195,36 @@
 If you want to try fixing it yourself (I highly recommend that you mail me
 about the problem first, since it might already have been solved) you may
 want to try some of the debug levels available.  For heavy testing on
-DEBUG_DURING or more, it would be a REALLY good idea to kill your klogd
-daemon first!  DEBUG_DURING displays 4-5 lines for each packet sent or
-received.  DEBUG_TX and RX actually DISPLAY each packet as it is sent or
+D_DURING or more, it would be a REALLY good idea to kill your klogd
+daemon first!  D_DURING displays 4-5 lines for each packet sent or
+received.  D_TX and RX actually DISPLAY each packet as it is sent or
 received, which is obviously quite big.
 
-You can run the arcdump shell script (available from me) as root to list the
-contents of the arcnet buffers at any time.  To make any sense at all out of
-this, you should grab the pertinent RFC's. (some are listed near the top of
-arcnet.c).  arcdump assumes your card is at 0xD0000.  If it isn't, edit the
-script.
+You can run the arcdump shell script (available from me or in the full
+ARCnet package if you got it) as root to list the contents of the arcnet
+buffers at any time.  To make any sense at all out of this, you should grab
+the pertinent RFC's. (some are listed near the top of arcnet.c).  arcdump
+assumes your card is at 0xD0000.  If it isn't, edit the script.
 
 Buffers #0 and 1 are used for receiving, and Buffers #2 and 3 are for
-sending.  Ping-pong buffers are implemented both ways, just to confuse you.
+sending.  Ping-pong buffers are implemented both ways.
 
-If your debug level is DEBUG_DURING or more, the buffers are cleared to a
-constant value of 0x42 every time the card is reset (which should only
-happen when you do an ifconfig up, or when Linux decides that the driver is
-broken).  This is to make it easier to figure out which bytes are being used
-by a packet.
+If your debug level includes D_DURING, the buffers are cleared to a constant
+value of 0x42 every time the card is reset (which should only happen when
+you do an ifconfig up, or when Linux decides that the driver is broken). 
+This is to make it easier to figure out which bytes are being used by a
+packet.
 
 You can change the debug level without recompiling the kernel by typing:
-	ifconfig arc0 down metric 1x
+	ifconfig arc0 down metric 1xxx
 	/etc/rc.d/rc.inet1
-where "x" is the debug level you want.  For example, "metric 14" would put
-you at debug level 4.  Debug level 3 is the default (D_EXTRA).
+where "xxx" is the debug level you want.  For example, "metric 1015" would put
+you at debug level 15.  Debug level 7 is currently the default.
+
+Note that the debug level is (as of v1.90 ALPHA) a binary combination of
+different debug flags; so debug level 7 is really 1+2+4 or
+D_NORMAL+D_INIT+D_EXTRA.  To reach D_DURING, you would add 8 to this,
+resulting in debug level 15.
 
 
 I want to send money: what now?
diff -u --recursive --new-file v1.3.9/linux/drivers/net/README.arcnet-jumpers linux/drivers/net/README.arcnet-jumpers
--- v1.3.9/linux/drivers/net/README.arcnet-jumpers	Wed Apr  5 12:59:50 1995
+++ linux/drivers/net/README.arcnet-jumpers	Wed Jul 12 07:53:14 1995
@@ -6,7 +6,7 @@
 
 Because so many people (myself included) seem to have obtained ARCnet cards
 without manuals, this will be a quick listing of all jumper settings I can
-find.  Please e-mail apenwarr@tourism.807-city.on.ca with any settings for
+find.  Please e-mail apenwarr@foxnet.net with any settings for
 your particular card.
 
 Even if your ARCnet model isn't listed, but has the same jumpers, please
@@ -15,7 +15,7 @@
 If your model isn't listed, and has different settings, PLEASE PLEASE tell
 me.  I had to figure mine out without the manual, and it WASN'T FUN!
 
-Cards Listed in this file:
+Cards Listed in this file (in this order, mostly):
 
 	Manufacturer	Model #		Bits
 	------------	-------		----
@@ -28,10 +28,14 @@
 	SMC		PC500Longboard	16
 	SMC		PC550Longboard	16
 	SMC		PC600		16
+	SMC?		LCS-8830-T	16?
 	Puredata	PDI507		16
 	CNet Tech	CN120-Series	8
 	CNet Tech	CN160-Series	16
 	No Name		--		8/16
+	No Name		Taiwan R.O.C(?)	8
+	Tiara		Tiara Lancard(?)
+	
 
 ** SMC = Standard Microsystems Corp.
 ** CNet Tech = CNet Technology, Inc.
@@ -46,7 +50,7 @@
   
   - And some unknowns (other info is welcome!):
      From: root@ultraworld.xs4all.nl (Timo Hilbrink)
-     To: apenwarr@tourism.807-city.on.ca (Avery Pennarun)
+     To: apenwarr@foxnet.net (Avery Pennarun)
      Date: Wed, 26 Oct 1994 02:10:32 +0000 (GMT)
      Reply-To: timoh@xs4all.nl
 
@@ -55,7 +59,7 @@
      About the jumpers: On my PC130 there is one more jumper, located near the
      cable-connector and it's for changing to star or bus topology; 
      closed: star - open: bus
-     On the PC500 are some more jumper-pins, one block labeled with RX,PDN,TXI
+     On the PC500 are some more jumper-pins, one block labled with RX,PDN,TXI
      and another with ALE,LA17,LA18,LA19 these are undocumented..
 
      [...more parts deleted...]
@@ -67,16 +71,17 @@
 ---------------
 
 All ARCnet cards should have a total of four different settings:
+
   - the I/O address:  this is the "port" your ARCnet card is on.  Probed
     values, as of v0.14, are only from 0x200 through 0x3F0. (If your card
     has additional ones, which is possible, please tell me.) This should not
-    be the same as any other device on your system.  Supposedly MS Windows
-    prefers values of 0x300 or more, eating net connections on my system
-    otherwise.
+    be the same as any other device on your system.  According to a doc I
+    got from Novell, MS Windows prefers values of 0x300 or more, eating
+    netconnections on my system otherwise.
 	- Avery's favourite: 0x300.
 
   - the IRQ:  on 8-bit cards, it might be 2 (9), 3, 4, 5, or 7.
-             on 16-bit cards, it might be 2 (9), 3, 4, 5, 7, or 9-15.  Make
+             on 16-bit cards, it might be 2 (9), 3, 4, 5, 7, or 10-15.  Make
     sure this is different from any other card on your system.  Note that
     IRQ2 is the same as IRQ9, as far as Linux is concerned.
 	- Avery's favourite: IRQ2.
@@ -108,12 +113,18 @@
 PC100, PC110, PC120, PC130 (8-bit cards)
 PC500, PC600 (16-bit cards)
 ---------------------------------
-  - mainly from Avery Pennarun <apenwarr@tourism.807-city.on.ca>
-  - values depicted are from Avery's setup.
+  - mainly from Avery Pennarun <apenwarr@foxnet.net>.  Values depicted are
+    from Avery's setup.
   - special thanks to Timo Hilbrink <timoh@xs4all.nl> for noting that PC120,
     130, 500, and 600 all have the same switches as Avery's PC100. 
     PC500/600 have several extra, undocumented pins though. (?)
   - PC110 settings were verified by Stephen A. Wood <saw@cebaf.gov>
+  - On the other hand, John Edward Bauer <jbauer@badlands.NoDak.edu> said
+    the PC110 settings are all wrong.  In his case, you need to switch all
+    the 1's with 0's.  If you're having problems, try that.
+  - Also, the JP- and S-numbers probably don't match your card exactly.  Try
+    to find jumpers/switches with the same number of settings - it's
+    probably more reliable.
   
 
      JP5		       [|]    :    :    :    :
@@ -184,6 +195,7 @@
 
 		DO NOT SET THIS TO 0 OR 255 (0xFF)!
 
+
 *****************************************************************************
 
 ** Standard Microsystems Corp (SMC) **
@@ -270,7 +282,7 @@
 
 The eight switches in group S2 are used to set the node ID.
 Each node attached to the network must have an unique node ID which
-must be different from 0.
+must be diffrent from 0.
 Switch 1 serves as the least significant bit (LSB).
 
 The node ID is the sum of the values of all switches set to "1"  
@@ -309,7 +321,7 @@
 ----------------------------
 
 The first three switches in switch group S1 are used to select one
-of eight possible I/O Base addresses using the following table
+of eight possible I/O Base addresses using the followig table
 
 
    Switch | Hex I/O
@@ -317,7 +329,7 @@
    -------|--------
    0 0 0  |  260
    0 0 1  |  290
-   0 1 0  |  2E0  (Manufacturer's default)
+   0 1 0  |  2E0  (Manufactor's default)
    0 1 1  |  2F0
    1 0 0  |  300
    1 0 1  |  350
@@ -352,7 +364,7 @@
    0 1 0  1 0 |  CD000  |  CE000
    0 1 0  1 1 |  CD800  |  CE000
               |         |
-   0 1 1  0 0 |  D0000  |  D2000  (Manufacturer's default)
+   0 1 1  0 0 |  D0000  |  D2000  (Manufactor's default)
    0 1 1  0 1 |  D0800  |  D2000
    0 1 1  1 0 |  D1000  |  D2000
    0 1 1  1 1 |  D1800  |  D2000
@@ -389,7 +401,7 @@
 Refer to the COM9026 Data Sheet for alternate configurations.
 
 To select a hardware interrupt level set one (only one!) of the jumpers
-IRQ2, IRQ3, IRQ4, IRQ5, IRQ7. The manufacturer's default is IRQ2.
+IRQ2, IRQ3, IRQ4, IRQ5, IRQ7. The Manufactor's default is IRQ2.
  
 
 Configuring the PC130E for Star or Bus Topology
@@ -412,7 +424,7 @@
  -------|-------------------   ---------|-------------------
   on    | normal activity      flash/on | data transfer
   blink | reconfiguration      off      | no data transfer;
-  off   | defective board or            | incorrect memory or
+  off   | defectiv board or             | incorect memory or
         | node ID is zero               | I/O address
 
 
@@ -506,7 +518,7 @@
 
 The eight switches in group SW3 are used to set the node ID. Each node
 attached to the network must have an unique node ID which must be 
-different from 0.
+diffrent from 0.
 Switch 1 serves as the least significant bit (LSB).
 
 The node ID is the sum of the values of all switches set to "1"  
@@ -546,7 +558,7 @@
 ----------------------------
 
 The first six switches in switch group SW1 are used to select one
-of 32 possible I/O Base addresses using the following table
+of 32 possible I/O Base addresses using the followig table
 
    Switch       | Hex I/O
    6 5  4 3 2 1 | Address
@@ -565,7 +577,7 @@
    0 1  1 0 1 1 |  2B0
    0 1  1 1 0 0 |  2C0
    0 1  1 1 0 1 |  2D0
-   0 1  1 1 1 0 |  2E0 (Manufacturer's default)
+   0 1  1 1 1 0 |  2E0 (Manufactor's default)
    0 1  1 1 1 1 |  2F0
    1 1  0 0 0 0 |  300
    1 1  0 0 0 1 |  310
@@ -634,12 +646,121 @@
  -------|-------------------   ---------|-------------------
   on    | normal activity      flash/on | data transfer
   blink | reconfiguration      off      | no data transfer;
-  off   | defective board or            | incorrect memory or
+  off   | defectiv board or             | incorect memory or
         | node ID is zero               | I/O address
 
 
 *****************************************************************************
 
+** Possibly SMC **
+LCS-8830-T (16-bit card)
+------------------------
+	- from Mathias Katzer <mkatzer@HRZ.Uni-Bielefeld.DE>
+	
+This is a LCS-8830-T made by SMC, I think ('SMC' only appears on one PLCC,
+nowhere else, not even on the few xeroxed sheets from the manual).
+
+SMC Arcnet Board Type LCS-8830-T
+
+   ------------------------------------
+  |                                    |
+  |              JP3 88  8 JP2         |
+  |       #####      | \               |
+  |       #####    ET1 ET2          ###|
+  |                              8  ###|
+  |  U3   SW 1                  JP0 ###|  Phone Jacks
+  |  --                             ###|
+  | |  |                               |
+  | |  |   SW2                         |
+  | |  |                               |
+  | |  |  #####                        |
+  |  --   #####                       ####  BNC Connector 
+  |                                   ####
+  |   888888 JP1                       |
+  |   234567                           |
+   --                           -------
+     |||||||||||||||||||||||||||
+      --------------------------
+
+
+SW1: DIP-Switches for Station Address
+SW2: DIP-Switches for Memory Base and I/O Base addresses
+
+JP0: If closed, internal termination on (default open)
+JP1: IRQ Jumpers
+JP2: Boot-ROM enabled if closed
+JP3: Jumpers for respsonse timeout
+ 
+U3: Boot-ROM Socket          
+
+
+ET1 ET2     Response Time     Idle Time    Reconfiguration Time
+
+               78                86               840
+ X            285               316              1680
+     X        563               624              1680
+ X   X       1130              1237              1680
+
+(X means closed jumper)
+
+(DIP-Switch downwards means "0")
+
+The station address is binary-coded with SW1.
+
+The I/O base address is coded with DIP-Switches 6,7 and 8 of SW2:
+
+Switches        Base
+678             Address
+000		260-26f
+100		290-29f
+010		2e0-2ef
+110		2f0-2ff
+001		300-30f
+101		350-35f
+011		380-38f
+111 		3e0-3ef
+
+
+DIP Switches 1-5 of SW2 encode the RAM and ROM Adress Range:
+
+Switches        Ram           Rom
+12345           Adress Range  Address Range
+00000		C:0000-C:07ff	C:2000-C:3fff
+10000		C:0800-C:0fff
+01000		C:1000-C:17ff
+11000		C:1800-C:1fff
+00100		C:4000-C:47ff	C:6000-C:7fff
+10100		C:4800-C:4fff
+01100		C:5000-C:57ff 
+11100		C:5800-C:5fff
+00010		C:C000-C:C7ff	C:E000-C:ffff
+10010		C:C800-C:Cfff
+01010		C:D000-C:D7ff
+11010		C:D800-C:Dfff
+00110		D:0000-D:07ff	D:2000-D:3fff
+10110		D:0800-D:0fff
+01110		D:1000-D:17ff
+11110		D:1800-D:1fff
+00001		D:4000-D:47ff	D:6000-D:7fff
+10001		D:4800-D:4fff
+01001		D:5000-D:57ff
+11001		D:5800-D:5fff
+00101		D:8000-D:87ff	D:A000-D:bfff
+10101		D:8800-D:8fff
+01101		D:9000-D:97ff
+11101		D:9800-D:9fff 
+00011		D:C000-D:c7ff	D:E000-D:ffff
+10011		D:C800-D:cfff
+01011		D:D000-D:d7ff
+11011		D:D800-D:dfff
+00111		E:0000-E:07ff	E:2000-E:3fff
+10111		E:0800-E:0fff
+01111		E:1000-E:17ff
+11111		E:1800-E:1fff
+
+
+*****************************************************************************
+
 ** PureData Corp **
 PDI507 (16-bit card)
 --------------------
@@ -690,7 +811,7 @@
 
 DIP Switches:
 
-	The dip switches accessible on the accessible end of the card while
+	The dipswitches accessible on the accessible end of the card while
         it is installed, is used to set the arcnet address.  There are 8
         switches.  Use an address from 1 to 254.
 
@@ -781,6 +902,7 @@
 ------------------------
   - from Juergen Seifert <seifert@htwm.de>
 
+
 CNET TECHNOLOGY INC. (CNet) ARCNET 120A SERIES
 ==============================================
 
@@ -856,7 +978,7 @@
 -------------------
 
 The eight switches in SW2 are used to set the node ID. Each node attached
-to the network must have an unique node ID which must be different from 0.
+to the network must have an unique node ID which must be diffrent from 0.
 Switch 1 (ID0) serves as the least significant bit (LSB).
 
 The node ID is the sum of the values of all switches set to "1"  
@@ -896,7 +1018,7 @@
 ----------------------------
 
 The last three switches in switch block SW1 are used to select one
-of eight possible I/O Base addresses using the following table
+of eight possible I/O Base addresses using the followig table
 
 
    Switch      | Hex I/O
@@ -904,7 +1026,7 @@
    ------------|--------
    ON  ON  ON  |  260
    OFF ON  ON  |  290
-   ON  OFF ON  |  2E0  (Manufacturer's default)
+   ON  OFF ON  |  2E0  (Manufactor's default)
    OFF OFF ON  |  2F0
    ON  ON  OFF |  300
    OFF ON  OFF |  350
@@ -926,7 +1048,7 @@
    ON  ON  ON  ON  ON  |  C0000  |  C2000
    ON  ON  OFF ON  ON  |  C4000  |  C6000
    ON  ON  ON  OFF ON  |  CC000  |  CE000
-   ON  ON  OFF OFF ON  |  D0000  |  D2000  (Manufacturer's default)
+   ON  ON  OFF OFF ON  |  D0000  |  D2000  (Manufactor's default)
    ON  ON  ON  ON  OFF |  D4000  |  D6000
    ON  ON  OFF ON  OFF |  D8000  |  DA000
    ON  ON  ON  OFF OFF |  DC000  |  DE000
@@ -937,7 +1059,7 @@
 Note: Since the switches 1 and 2 are always set to ON it may be possible
       that they can be used to add an offset of 2K, 4K or 6K to the base
       address, but this feature is not documented in the manual and I
-      haven't tested it yet.
+      haven't testet it yet.
 
 
 Setting the Interrupt Line
@@ -1066,7 +1188,7 @@
 -------------------
 
 The eight switches in SW2 are used to set the node ID. Each node attached
-to the network must have an unique node ID which must be different from 0.
+to the network must have an unique node ID which must be diffrent from 0.
 Switch 1 (ID0) serves as the least significant bit (LSB).
 
 The node ID is the sum of the values of all switches set to "1"  
@@ -1106,14 +1228,14 @@
 ----------------------------
 
 The first six switches in switch block SW1 are used to select the I/O Base
-address using the following table:
+address using the followig table:
 
              Switch        | Hex I/O
     1   2   3   4   5   6  | Address
    ------------------------|--------
    OFF ON  ON  OFF OFF ON  |  260
    OFF ON  OFF ON  ON  OFF |  290
-   OFF ON  OFF OFF OFF ON  |  2E0  (Manufacturer's default)
+   OFF ON  OFF OFF OFF ON  |  2E0  (Manufactor's default)
    OFF ON  OFF OFF OFF OFF |  2F0
    OFF OFF ON  ON  ON  ON  |  300
    OFF OFF ON  OFF ON  OFF |  350
@@ -1162,9 +1284,9 @@
     13    |   2 (=9) Default!
 
 Note:  - Do not use JP11=IRQ6, it may conflict with your Floppy Disk
-         Controller
+         Controler
        - Use JP3=IRQ14 only, if you don't have an IDE-, MFM-, or RLL-
-         Hard Disk, it may conflict with their controllers
+         Hard Disk, it may conflict with their controlers
 
 
 Setting the Timeout Parameters
@@ -1185,8 +1307,8 @@
 ===================
 
 I have named this ARCnet card "NONAME", since there is no name of any
-manufacturer on the Installation manual nor on the shipping box. The only
-hint to the existence of a manufacturer at all is written into copper,
+manufactor on the Installation manual nor on the shipping box. The only
+hint to the existence of a manufactor at all is written into cupper,
 it is "Made in Taiwan"
 
 This description has been written by Juergen Seifert <seifert@htwm.de>
@@ -1230,7 +1352,7 @@
 ROM     ROM Enable Select
 CN              RG62 Coax Connector
 STAR| BUS | T/P Three fields for placing a sign (colored circle)
-                indicating the topology of the card
+                indicating the topologie of the card
 
 Setting one of the switches to Off means "1", On means "0".
 
@@ -1240,7 +1362,7 @@
 
 The eight switches in group SW1 are used to set the node ID.
 Each node attached to the network must have an unique node ID which
-must be different from 0.
+must be diffrent from 0.
 Switch 8 serves as the least significant bit (LSB).
 
 The node ID is the sum of the values of all switches set to "1"  
@@ -1280,14 +1402,14 @@
 ----------------------------
 
 The first three switches in switch group SW2 are used to select one
-of eight possible I/O Base addresses using the following table
+of eight possible I/O Base addresses using the followig table
 
    Switch      | Hex I/O
     1   2   3  | Address
    ------------|--------
    ON  ON  ON  |  260
    ON  ON  OFF |  290
-   ON  OFF ON  |  2E0  (Manufacturer's default)
+   ON  OFF ON  |  2E0  (Manufactor's default)
    ON  OFF OFF |  2F0
    OFF ON  ON  |  300
    OFF ON  OFF |  350
@@ -1322,7 +1444,7 @@
    0 1 0  1 0 |  CD000  |  CE000
    0 1 0  1 1 |  CD800  |  CE000
               |         |
-   0 1 1  0 0 |  D0000  |  D2000  (Manufacturer's default)
+   0 1 1  0 0 |  D0000  |  D2000  (Manufactor's default)
    0 1 1  0 1 |  D0800  |  D2000
    0 1 1  1 0 |  D1000  |  D2000
    0 1 1  1 1 |  D1800  |  D2000
@@ -1355,14 +1477,14 @@
 -------------------------------------
 
 To select a hardware interrupt level set one (only one!) of the jumpers
-IRQ2, IRQ3, IRQ4, IRQ5 or IRQ7. The manufacturer's default is IRQ2.
+IRQ2, IRQ3, IRQ4, IRQ5 or IRQ7. The Manufactor's default is IRQ2.
  
 
 Setting the Timeouts
 --------------------
 
 The two jumpers labeled ET1 and ET2 are used to determine the timeout
-parameters (response and reconfiguration time). Every node in a network
+parameters (respons and reconfiguration time). Every node in a network
 must be set to the same timeout values.
 
    ET1 ET2 | Response Time (us) | Reconfiguration Time (ms)
@@ -1382,7 +1504,7 @@
 of a 16-Bit Coax / Twisted Pair Card. This description is incomplete,
 because there are missing two pages in the manual booklet. (The table
 of contents reports pages ... 2-9, 2-11, 2-12, 3-1, ... but inside
-the booklet there is a different way of counting ... 2-9, 2-10, A-1,
+the booklet there is a diffrent way of counting ... 2-9, 2-10, A-1,
 (empty page), 3-1, ..., 3-18, A-1 (again), A-2)
 Also the picture of the board layout is not as good as the picture of
 8-Bit card, because there isn't any letter like "SW1" written to the
@@ -1429,7 +1551,7 @@
 
 The eight switches in group SW2 are used to set the node ID.
 Each node attached to the network must have an unique node ID which
-must be different from 0.
+must be diffrent from 0.
 Switch 8 serves as the least significant bit (LSB).
 
 The node ID is the sum of the values of all switches set to "1"  
@@ -1469,14 +1591,14 @@
 ----------------------------
 
 The first three switches in switch group SW1 are used to select one
-of eight possible I/O Base addresses using the following table
+of eight possible I/O Base addresses using the followig table
 
    Switch      | Hex I/O
     3   2   1  | Address
    ------------|--------
    ON  ON  ON  |  260
    ON  ON  OFF |  290
-   ON  OFF ON  |  2E0  (Manufacturer's default)
+   ON  OFF ON  |  2E0  (Manufactor's default)
    ON  OFF OFF |  2F0
    OFF ON  ON  |  300
    OFF ON  OFF |  350
@@ -1511,7 +1633,7 @@
    0 1 0  1 0 |  CD000  |  CE000
    0 1 0  1 1 |  CD800  |  CE000
               |         |
-   0 1 1  0 0 |  D0000  |  D2000  (Manufacturer's default)
+   0 1 1  0 0 |  D0000  |  D2000  (Manufactor's default)
    0 1 1  0 1 |  D0800  |  D2000
    0 1 1  1 0 |  D1000  |  D2000
    0 1 1  1 1 |  D1800  |  D2000
@@ -1551,11 +1673,239 @@
 
 *****************************************************************************
 
+** No Name **
+8-bit cards ("Made in Taiwan R.O.C.")
+-----------
+ - from Vojtech Pavlik <vpav4328@diana.troja.mff.cuni.cz>
+
+I have named this ARCnet card "NONAME", since I got only the card with
+no manual at all and the only text identifying the manufacturer is 
+"MADE IN TAIWAN R.O.C" printed on the card.
+
+This description was written by Vojtech Pavlik 
+(vpav4328@diana.troja.mff.cuni.cz) using parts of the ARCNET-jumpers 
+README file from Linux kernel 1.2.2. 
+
+          ____________________________________________________________
+         |                 1 2 3 4 5 6 7 8                            |
+         | |o|o| JP1       o|o|o|o|o|o|o|o| ON                        |
+         |  +              o|o|o|o|o|o|o|o|                        ___|
+         |  _____________  o|o|o|o|o|o|o|o| OFF         _____     |   | ID7
+         | |             | SW1                         |     |    |   | ID6
+         | > RAM (2k)    |        ____________________ |  H  |    | S | ID5
+         | |_____________|       |                    ||  y  |    | W | ID4
+         |                       |                    ||  b  |    | 2 | ID3
+         |                       |                    ||  r  |    |   | ID2
+         |                       |                    ||  i  |    |   | ID1
+         |                       |       90C65        ||  d  |    |___| ID0
+         |      SW3              |                    ||     |        |      
+         | |o|o|o|o|o|o|o|o| ON  |                    ||  I  |        |
+         | |o|o|o|o|o|o|o|o|     |                    ||  C  |        |
+         | |o|o|o|o|o|o|o|o| OFF |____________________||     |   _____|
+         |  1 2 3 4 5 6 7 8                            |     |  |     |___
+         |  ______________                             |     |  | BNC |___|
+         | |              |                            |_____|  |_____|
+         | > EPROM SOCKET |                                           |
+         | |______________|                                           |
+         |                                              ______________|
+         |                                             |
+         |_____________________________________________|
+
+Legend:
+
+90C65       ARCNET Chip 
+SW1 1-5:    Base Memory Address Select
+    6-8:    Base I/O Address Select
+SW2 1-8:    Node ID Select (ID0-ID7)
+SW3 1-5:    IRQ Select   
+    6-7:    Extra Timeout
+    8  :    Rom Enable   
+JP1         Led connector
+BNC         Coax connector
+
+Although the jumpers SW1 and SW3 are marked SW, not JP, they are jumpers, not 
+switches.
+
+Setting the jumpers to ON means connecting the upper two pins, off the bottom 
+two - or - in case of IRQ setting, connecting none of them at all.
+
+Setting the Node ID
+-------------------
+
+The eight switches in SW2 are used to set the node ID. Each node attached
+to the network must have an unique node ID which must be diffrent from 0.
+Switch 1 (ID0) serves as the least significant bit (LSB).
+
+Setting one of the switches to Off means "1", On means "0".
+
+The node ID is the sum of the values of all switches set to "1"  
+These values are:
+
+   Switch | Label | Value
+   -------|-------|-------
+     1    | ID0   |   1
+     2    | ID1   |   2
+     3    | ID2   |   4
+     4    | ID3   |   8
+     5    | ID4   |  16
+     6    | ID5   |  32
+     7    | ID6   |  64
+     8    | ID7   | 128
+
+Some Examples:
+
+    Switch         | Hex     | Decimal 
+   8 7 6 5 4 3 2 1 | Node ID | Node ID
+   ----------------|---------|---------
+   0 0 0 0 0 0 0 0 |    not allowed
+   0 0 0 0 0 0 0 1 |    1    |    1 
+   0 0 0 0 0 0 1 0 |    2    |    2
+   0 0 0 0 0 0 1 1 |    3    |    3
+       . . .       |         |
+   0 1 0 1 0 1 0 1 |   55    |   85
+       . . .       |         |
+   1 0 1 0 1 0 1 0 |   AA    |  170
+       . . .       |         |  
+   1 1 1 1 1 1 0 1 |   FD    |  253
+   1 1 1 1 1 1 1 0 |   FE    |  254
+   1 1 1 1 1 1 1 1 |   FF    |  255
+
+
+Setting the I/O Base Address
+----------------------------
+
+The last three switches in switch block SW1 are used to select one
+of eight possible I/O Base addresses using the followig table
+
+
+   Switch      | Hex I/O
+    6   7   8  | Address
+   ------------|--------
+   ON  ON  ON  |  260
+   OFF ON  ON  |  290
+   ON  OFF ON  |  2E0  (Manufactor's default)
+   OFF OFF ON  |  2F0
+   ON  ON  OFF |  300
+   OFF ON  OFF |  350
+   ON  OFF OFF |  380
+   OFF OFF OFF |  3E0
+
+
+Setting the Base Memory (RAM) buffer Address
+--------------------------------------------
+
+The memory buffer (RAM) requires 2K. The base of this buffer can be 
+located in any of eight positions. The address of the Boot Prom is
+memory base + 0x2000.
+Jumpers 3-5 of jumper block SW1 select the Memory Base address.
+
+   Switch              | Hex RAM | Hex ROM
+    1   2   3   4   5  | Address | Address *)
+   --------------------|---------|-----------
+   ON  ON  ON  ON  ON  |  C0000  |  C2000
+   ON  ON  OFF ON  ON  |  C4000  |  C6000
+   ON  ON  ON  OFF ON  |  CC000  |  CE000
+   ON  ON  OFF OFF ON  |  D0000  |  D2000  (Manufactor's default)
+   ON  ON  ON  ON  OFF |  D4000  |  D6000
+   ON  ON  OFF ON  OFF |  D8000  |  DA000
+   ON  ON  ON  OFF OFF |  DC000  |  DE000
+   ON  ON  OFF OFF OFF |  E0000  |  E2000
+  
+*) To enable the Boot ROM set the jumper 8 of jumper block SW3 to position ON.
+
+The jumpers 1 and 2 probably add 0x0800, 0x1000 and 0x1800 to RAM addres.
+
+Setting the Interrupt Line
+--------------------------
+
+Jumpers 1-5 of the jumper block SW3 controll the IRQ level.
+
+    Jumper              |  IRQ
+    1   2   3   4   5   |
+   ----------------------------
+    ON  OFF OFF OFF OFF |  2
+    OFF ON  OFF OFF OFF |  3
+    OFF OFF ON  OFF OFF |  4
+    OFF OFF OFF ON  OFF |  5
+    OFF OFF OFF OFF ON  |  7
+
+
+Setting the Timeout Parameters
+------------------------------
+
+The jumpers 6-7 of the jumper block SW3 are used to determine the timeout 
+parameters. These two jumpers are normally left in the OFF position.
+
+
+*****************************************************************************
+** Tiara **
+(model unknown)
+-------------------------
+  - from Christoph Lameter <clameter@netcom.com>
+  
+
+Here is information about my card as far as I could figure it out:
+----------------------------------------------- tiara
+Tiara LanCard of Tiara Computer Systems.
+
++----------------------------------------------+
+!           ! Transmitter Unit !               !
+!           +------------------+             -------
+!          MEM                              Coax Connector
+!  ROM    7654321 <- I/O                     -------
+!  :  :   +--------+                           !
+!  :  :   ! 90C66LJ!                         +++
+!  :  :   !        !                         !D  Switch to set
+!  :  :   !        !                         !I  the Nodenumber
+!  :  :   +--------+                         !P
+!                                            !++
+!         234567 <- IRQ                      !
++------------!!!!!!!!!!!!!!!!!!!!!!!!--------+
+             !!!!!!!!!!!!!!!!!!!!!!!!
+
+0 = Jumper Installed
+1 = Open
+
+Top Jumper line Bit 7 = Rom Enable 654=Memory location 321=I/O
+
+Settings for Memory Location (Top Jumper Line)
+456     Address selected
+000	C0000
+001     C4000
+010     CC000
+011     D0000
+100     D4000
+101     D8000
+110     DC000     
+111     E0000
+
+Settings for I/O Address (Top Jumper Line)
+123     Port
+000	260
+001	290
+010	2E0
+011	2F0
+100	300
+101	350
+110	380
+111	3E0
+
+Settings for IRQ Selection (Lower Jumper Line)
+234567
+011111 IRQ 2
+101111 IRQ 3
+110111 IRQ 4
+111011 IRQ 5
+111110 IRQ 7
+
+*****************************************************************************
+
+
 Other Cards
 -----------
 
 I have no information on other models of ARCnet cards at the moment.  Please
 send any and all info to:
-	apenwarr@tourism.807-city.on.ca
+	apenwarr@foxnet.net
 
 Thanks.
diff -u --recursive --new-file v1.3.9/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
--- v1.3.9/linux/drivers/net/arcnet.c	Fri Jul  7 08:54:46 1995
+++ linux/drivers/net/arcnet.c	Wed Jul 12 07:59:38 1995
@@ -6,6 +6,8 @@
 	RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
 	
 	**********************
+	
+	The original copyright was as follows:
 
 	skeleton.c Written 1993 by Donald Becker.
 	Copyright 1993 United States Government as represented by the
@@ -14,102 +16,144 @@
         modified by SRC, incorporated herein by reference.
          
 	**********************
-
-	v1.02 (95/06/21)
-	  - A fix to make "exception" packets sent from Linux receivable
-	    on other systems.  (The protocol_id byte was sometimes being set
-	    incorrectly, and Linux wasn't checking it on receive so it
-	    didn't show up)
-	  - Updated my email address.  Please use apenwarr@foxnet.net
-	    from now on.
+	
+	v1.92 ALPHA (95/07/11)
+	  - Fixes to make things work with kernel 1.3.x.  Completely broke
+	    1.2.x support.  Oops?  1.2.x users keep using 1.91 ALPHA until I
+	    get out a version that supports both.
+
+	v1.91 ALPHA (95/07/02)
+	  - Oops.  Exception packets hit us again!  I remembered to test
+	    them in Windows-protocol mode, but due to the many various
+	    changes they broke in RFC1201 instead.  All fixed.
+	  - A long-standing bug with "exception" packets not setting
+	    protocol_id properly has been corrected.  This would have caused
+	    random problems talking to non-Linux servers.  I've also sent in
+	    a patch to fix this in the latest stable ARCnet (now 1.02).
+	  - ARC_P_IPX is an RFC1201 protocol too.  Thanks, Tomasz.
+	  - We're now "properly" (I think) handling the multiple 'tbusy' and
+	    'start' flags (one for each protocol device) better.
+	  - The driver should now start without a NULL-pointer dereference
+	    if you aren't connected to the network.
+	  
+	v1.90 ALPHA (95/06/18)
+	  - Removal of some outdated and messy config options (no one has
+	    ever complained about the defaults since they were introduced):
+	    DANGER_PROBE, EXTRA_DELAYS, IRQ_XMIT, CAREFUL_XMIT,
+	    STRICT_MEM_DETECT, LIMIT_MTU, USE_TIMER_HANDLER.  Also took out
+	    a few "#if 0" sections which are no longer useful.
+	  - Cleaned up debug levels - now instead of levels, there are
+	    individual flags.  Watch out when changing with ifconfig.
+	  - More cleanups and beautification.  Removed more dead code and
+	    made sure every function was commented.
+	  - Fixed the DETECT_RECONFIGS option so that it actually _won't_
+	    detect reconfigs.  Previously, the RECON irq would be disabled
+	    but the recon messages would still be logged on the next normal
+	    IRQ.
+	  - Initial support for "multiprotocol" ARCnet (this involved a LOT
+	    of reorganizing!).  Added an arc0w device, which allows us to
+	    talk to "Windows" ARCnet TCP/IP protocol.  To use it, ifconfig
+	    arc0 and arc0w (in that order).  For now, Windows-protocol
+	    hosts should have routes through arc0w - eventually I hope to
+	    make things more automatic.
+	v1.11 ALPHA (95/06/07)
+	  - Tomasz saves the day again with patches to fix operation if the
+	    new VERIFY_ACK option is disabled.
+	  - LOTS of little code cleanups/improvements by Tomasz.
+	  - Changed autoprobe, since the "never-changing command port"
+	    probe was causing problems for some people.  I also reset the
+	    card fewer times during the probe if DANGER_PROBE is defined,
+	    since DANGER_PROBE seems to be a more reliable method anyway.
+	  - It looks like the null-pointer problem was finally REALLY fixed
+	    by some change from Linux 1.2.8 to 1.2.9.  How handy!
+	v1.10 ALPHA (95/04/15)
+	  - Fixed (?) some null-pointer dereference bugs
+	  - Added better network error detection (from Tomasz) - in
+	    particular, we now notice when our network isn't connected,
+	    also known as a "network reconfiguration."
+	  - We now increment lp->stats.tx_dropped in several more places,
+	    on a suggestion from Tomasz.
+	  - Minor cleanups/spelling fixes.
+	  - We now monitor the TXACK bit in the status register: we don't do
+	    anything with it yet, just notice when a transmitted packet isn't
+	    acknowledged.
+	  - Minor fix with sequence numbers (sometimes they were being sent in
+	    the wrong order due to Linux's packet queuing).
 	v1.01 (95/03/24)
 	  - Fixed some IPX-related bugs. (Thanks to Tomasz Motylewski
             <motyl@tichy.ch.uj.edu.pl> for the patches to make arcnet work
             with dosemu!)
-	v1.0 (95/02/15)
+	v1.00 (95/02/15)
 	  - Initial non-alpha release.
 	
          
 	TO DO:
 	
          - Test in systems with NON-ARCnet network cards, just to see if
-           autoprobe kills anything.  With any luck, it won't.  (It's pretty
-           careful.)
-           	- Except some unfriendly NE2000's die. (as of 0.40-ALPHA)
-         - cards with shared memory that can be "turned off?"
+           autoprobe kills anything.  Currently, we do cause some NE2000's to
+           die.
+         - What about cards with shared memory that can be "turned off?"
          - NFS mount freezes after several megabytes to SOSS for DOS. 
- 	   unmount/remount works.  Is this arcnet-specific?  I don't know.
- 	 - Add support for the various stupid bugs ("I didn't read the RFC"
-           syndrome) in Windows for Workgroups and LanMan.
- */
- 
-/**************************************************************************/
-
-/* define this if you want to use the new but possibly dangerous ioprobe
- * If you get lockups right after status5, you probably need
- * to undefine this.  It should make more cards probe correctly,
- * I hope.
- */
-#define DANGER_PROBE
-
-/* define this if you want to use the "extra delays" which were removed
- * in 0.41 since they seemed needless.
- */
-#undef EXTRA_DELAYS
+ 	   unmount/remount fixes it.  Is this arcnet-specific?  I don't know.
+         - Add support for "old" (RFC1051) protocol arcnet, such as AmiTCP
+           and NetBSD.  Work in Tomasz' initial support for this.
+         - How about TCP/IP over netbios?
+         - Some newer ARCnets support promiscuous mode, supposedly. 
+           If someone sends me information, I'll try to implement it.
+         - Remove excess lock variables that are probably not necessary
+           anymore due to the changes in Linux 1.2.9.
+
+           
+	Sources:
+	 - Crynwr arcnet.com/arcether.com packet drivers.
+	 - arcnet.c v0.00 dated 1/1/94 and apparently by
+	 	Donald Becker - it didn't work :)
+	 - skeleton.c v0.05 dated 11/16/93 by Donald Becker
+	 	(from Linux Kernel 1.1.45)
+	 - The official ARCnet data sheets (!) thanks to Ken Cornetet
+		<kcornete@nyx10.cs.du.edu>
+	 - RFC's 1201 and 1051 (mostly 1201) - re: ARCnet IP packets
+	 - net/inet/eth.c (from kernel 1.1.50) for header-building info...
+	 - Alternate Linux ARCnet source by V.Shergin <vsher@sao.stavropol.su>
+	 - Textual information and more alternate source from Joachim Koenig
+	 	<jojo@repas.de>
+*/
 
-/* undefine this if you want to use the non-IRQ-driven transmitter. (possibly
- * safer, although it takes more CPU time and IRQ_XMIT seems fine right now)
- */
-#define IRQ_XMIT
+static char *version =
+ "arcnet.c:v1.92 ALPHA 95/07/11 Avery Pennarun <apenwarr@foxnet.net>\n";
  
-/* define this for "careful" transmitting.  Try with and without if you have
- * problems.  If you use IRQ_XMIT, do NOT define this.
- */
-#undef CAREFUL_XMIT
+/**************************************************************************/
 
-/* define this for an extra-careful memory detect.  This should work all
- * the time now, but you never know.
+/* Define this if you want to detect network reconfigurations.
+ * They may be a real nuisance on a larger ARCnet network: but if you are
+ * a network administrator you probably would like to count them. 
+ * Reconfigurations will be recorded in stats.tx_carrier_errors 
+ * (the last field of the /proc/net/dev file).
+ *
+ * The card sends the reconfiguration signal when it loses the connection
+ * to the rest of its network. It is a 'Hello, is anybody there?' cry.  This
+ * usually happens when a new computer on the network is powered on or when
+ * the cable is broken.
  */
-#define STRICT_MEM_DETECT
+#define DETECT_RECONFIGS
 
-/* define this to use the "old-style" limited MTU by default.  It basically
- * disables packet splitting.  ifconfig can still be used to reset the MTU.
+/* Define this if you want to make sure transmitted packets are "acknowledged"
+ * by the destination host, as long as they're not to the broadcast address.
  *
- * leave this disabled if possible, so it will use ethernet defaults,
- * which is our goal.
+ * That way, if one segment of a split packet doesn't get through, it can
+ * be resent immediately rather than confusing the other end.
+ *
+ * Disable this to return to 1.01-style behaviour, if you have problems.
  */
-#undef LIMIT_MTU
+#define VERIFY_ACK
 
-/* define this if you have a problem with the card getting "stuck" now and
- * then, which can only be fixed by a reboot or resetting the card manually
- * via ifconfig up/down.  ARCnet will set a timer function which is called
- * 8 times every second.
- *
- * This should no longer be necessary.  if you experience "stuck" ARCnet
- * drivers, please email apenwarr@foxnet.net or I will remove
- * this feature in a future release.
+/* Define this if you want to make it easier to use the "call trace" when
+ * a kernel NULL pointer assignment occurs.
  */
-#undef USE_TIMER_HANDLER
+#undef static
 
 /**************************************************************************/
  
-static char *version =
- "arcnet.c:v1.02 95/06/21 Avery Pennarun <apenwarr@foxnet.net>\n";
-
-/*
-  Sources:
-	Crynwr arcnet.com/arcether.com packet drivers.
-	arcnet.c v0.00 dated 1/1/94 and apparently by
-		Donald Becker - it didn't work :)
-	skeleton.c v0.05 dated 11/16/93 by Donald Becker
-		(from Linux Kernel 1.1.45)
-	...I sure wish I had the ARCnet data sheets right about now!
-	RFC's 1201 and 1051 (mostly 1201) - re: ARCnet IP packets
-	net/inet/eth.c (from kernel 1.1.50) for header-building info...
-	Alternate Linux ARCnet source by V.Shergin <vsher@sao.stavropol.su>
-	Textual information and more alternate source from Joachim Koenig
-		<jojo@repas.de>
-*/
 
 #include <linux/config.h>
 #ifdef MODULE
@@ -139,31 +183,31 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+
 #include <net/arp.h>
 
 
-/* debug levels:
- * D_OFF	production
- * D_NORMAL	verification
- * D_INIT	show init/detect messages
- * D_DURING	show messages during normal use (ie interrupts)
- * D_DATA   show packets data from skb's, not on Arcnet card
- * D_TX		show tx packets
- * D_RX		show tx+rx packets
- */
-#define D_OFF		0
-#define D_NORMAL	1
-#define	D_INIT		2
-#define D_EXTRA		3
-#define D_DURING	4
-#define D_DATA		6
-#define D_TX		8
-#define D_RX		9
+/* new debugging bitflags: each option can be enabled individually.
+ *
+ * these can be set while the driver is running by typing:
+ *	ifconfig arc0 down metric 1xxx HOSTNAME
+ *		where 1xx is 1000 + the debug level you want
+ *		and HOSTNAME is your hostname/ip address
+ * and then resetting your routes.
+ */
+#define D_NORMAL	1	/* D_NORMAL  startup announcement	*/
+#define	D_INIT		2	/* D_INIT    show init/probe messages	*/
+#define D_EXTRA		4	/* D_EXTRA   extra information		*/
+/* debug levels past this point give LOTS of output! */
+#define D_DURING	8	/* D_DURING  during normal use (irq's)	*/
+#define D_TX		16	/* D_TX	     show tx packets		*/
+#define D_RX		32	/* D_RX	     show rx packets		*/
+#define D_SKB		64	/* D_SKB     dump skb's			*/
 
 #ifndef NET_DEBUG
-#define NET_DEBUG 	D_INIT
+#define NET_DEBUG D_NORMAL|D_INIT|D_EXTRA
 #endif
-static unsigned int net_debug = NET_DEBUG;
+int arcnet_debug = NET_DEBUG;
 
 #ifndef HAVE_AUTOIRQ
 /* From auto_irq.c, in ioport.h for later versions. */
@@ -180,10 +224,20 @@
 #endif
 
 /* macro to simplify debug checking */
-#define BUGLVL(x) if (net_debug>=x)
+#define BUGLVL(x) if (arcnet_debug&(x))
+
+
+/* Some useful multiprotocol macros */
+#define TBUSY lp->adev->tbusy \
+		=lp->wdev->tbusy
+#define IF_TBUSY (lp->adev->tbusy \
+		|| lp->wdev->tbusy)
+#define START lp->adev->start \
+		=lp->wdev->start
+
 
 /* The number of low I/O ports used by the ethercard. */
-#define ETHERCARD_TOTAL_SIZE	16
+#define ARCNET_TOTAL_SIZE	16
 
 
 /* Handy defines for ARCnet specific stuff */
@@ -193,7 +247,8 @@
 #define COMMAND (ioaddr+1)	/* writable, returns random vals on read (?) */
 #define RESET  (ioaddr+8)		/* software reset writable */
 
-	/* time needed for various things (in clock ticks, 1/100 sec) */
+	/* Time needed for various things (in clock ticks, 1/100 sec) */
+	/* We mostly don't bother with these - watch out. */
 #define RESETtime 40		/* reset */
 #define XMITtime 10		/* send (?) */
 #define ACKtime 10		/* acknowledge (?) */
@@ -206,66 +261,73 @@
 	 * These numbers are compared with the length of the full packet,
 	 * including ClientData header.
 	 */
-#define MTU	(253+EXTRA_CLIENTDATA)  /* normal packet max size */
-#define MinTU	(257+EXTRA_CLIENTDATA)	/* extended packet min size */
-#define XMTU	(508+EXTRA_CLIENTDATA)  /* extended packet max size */
+#define MTU	253	/* normal packet max size */
+#define MinTU	257	/* extended packet min size */
+#define XMTU	508	/* extended packet max size */
 
 	/* status/interrupt mask bit fields */
-#define TXFREEflag	0x001            /* transmitter available */
-#define TXACKflag       0x002            /* transmitted msg. ackd */
-#define RECONflag       0x004            /* system reconfigured */
-#define TESTflag        0x008            /* test flag */
-#define RESETflag       0x010            /* power-on-reset */
-#define RES1flag        0x020            /* unused */
-#define RES2flag        0x040            /* unused */
-#define NORXflag        0x080            /* receiver inhibited */
+#define TXFREEflag	0x01            /* transmitter available */
+#define TXACKflag       0x02            /* transmitted msg. ackd */
+#define RECONflag       0x04            /* system reconfigured */
+#define TESTflag        0x08            /* test flag */
+#define RESETflag       0x10            /* power-on-reset */
+#define RES1flag        0x20            /* unused */
+#define RES2flag        0x40            /* unused */
+#define NORXflag        0x80            /* receiver inhibited */
+
+#ifdef DETECT_RECONFIGS
+	#define RECON_flag RECONflag
+#else
+	#define RECON_flag 0
+#endif
 
        /* in the command register, the following bits have these meanings:
         *                0-2     command
         *                3-4     page number (for enable rcv/xmt command)
         *                 7      receive broadcasts
         */
-#define NOTXcmd         0x001            /* disable transmitter */
-#define NORXcmd         0x002            /* disable receiver */
-#define TXcmd           0x003            /* enable transmitter */
-#define RXcmd           0x004            /* enable receiver */
-#define CONFIGcmd       0x005            /* define configuration */
-#define CFLAGScmd       0x006            /* clear flags */
-#define TESTcmd         0x007            /* load test flags */
+#define NOTXcmd         0x01            /* disable transmitter */
+#define NORXcmd         0x02            /* disable receiver */
+#define TXcmd           0x03            /* enable transmitter */
+#define RXcmd           0x04            /* enable receiver */
+#define CONFIGcmd       0x05            /* define configuration */
+#define CFLAGScmd       0x06            /* clear flags */
+#define TESTcmd         0x07            /* load test flags */
 
        /* flags for "clear flags" command */
-#define RESETclear      0x008            /* power-on-reset */
-#define CONFIGclear     0x010            /* system reconfigured */
+#define RESETclear      0x08            /* power-on-reset */
+#define CONFIGclear     0x10            /* system reconfigured */
 
       /* flags for "load test flags" command */
-#define TESTload        0x008            /* test flag (diagnostic) */
+#define TESTload        0x08            /* test flag (diagnostic) */
 
       /* byte deposited into first address of buffers on reset */
 #define TESTvalue       0321		 /* that's octal for 0xD1 :) */
 
       /* for "enable receiver" command */
-#define RXbcasts        0x080            /* receive broadcasts */
+#define RXbcasts        0x80            /* receive broadcasts */
 
       /* flags for "define configuration" command */
-#define NORMALconf      0x000            /* 1-249 byte packets */
-#define EXTconf         0x008            /* 250-504 byte packets */
+#define NORMALconf      0x00            /* 1-249 byte packets */
+#define EXTconf         0x08            /* 250-504 byte packets */
 
 	/* buffers (4 total) used for receive and xmit.
 	 */
 #define EnableReceiver()	outb(RXcmd|(recbuf<<3)|RXbcasts,COMMAND)
-/*#define TXbuf		2 (Obsoleted by ping-pong xmits) */
 
-	/* Protocol ID's */
+	/* RFC1201 Protocol ID's */
 #define ARC_P_IP	212		/* 0xD4 */
 #define ARC_P_ARP	213		/* 0xD5 */
 #define ARC_P_RARP	214		/* 0xD6 */
 #define ARC_P_IPX	250		/* 0xFA */
+
+	/* MS LanMan/WfWg protocol */
+#define ARC_P_MS_TCPIP	0xE8
+
+	/* Unsupported/indirectly supported protocols */
 #define ARC_P_LANSOFT	251		/* 0xFB */
 #define ARC_P_ATALK	0xDD
 
-	/* Length of time between "stuck" checks */
-#define TIMERval	(HZ/8)		/* about 1/8 second */
-
 	/* these structures define the format of an arcnet packet. */
 #define NORMAL		0
 #define EXTENDED	1
@@ -293,17 +355,16 @@
 	 */
 struct ClientData
 {
-	/* data that's NOT part of real packet */
-	u_char	daddr;		/* Destination address - stored here,
-				 *   but WE MUST GET RID OF IT BEFORE SENDING A
-				 *   PACKET!!
-				 */
-	u_char  saddr;		/* Source address - necessary for IPX protocol */
+	/* data that's NOT part of real packet - we MUST get rid of it before
+	 * actually sending!!
+	 */
+	u_char  saddr,		/* Source address - needed for IPX */
+		daddr;		/* Destination address */
 	
 	/* data that IS part of real packet */
-	u_char	protocol_id,	/* ARC_P_IP, ARC_P_ARP, or ARC_P_RARP */
+	u_char	protocol_id,	/* ARC_P_IP, ARC_P_ARP, etc */
 		split_flag;	/* for use with split packets */
-	u_short	sequence;	/* sequence number (?) */
+	u_short	sequence;	/* sequence number */
 };
 #define EXTRA_CLIENTDATA (sizeof(struct ClientData)-4)
 
@@ -329,6 +390,11 @@
 	      segnum,			/* segment being sent */
 	      numsegs,			/* number of segments */
 	      seglen;			/* length of segment */
+#ifdef VERIFY_ACK
+	short lastload_dest,		/* can last loaded packet be acked? */
+	      lasttrans_dest;		/* can last TX'd packet be acked? */
+#endif
+	
 };
 
 
@@ -344,9 +410,13 @@
 	      in_txhandler,	/* in TX_IRQ handler? */
 	      sending;		/* transmit in progress? */
 	short tx_left;		/* segments of split packet left to TX */
+	
 	struct timer_list timer; /* the timer interrupt struct */
 	struct Incoming incoming[256];	/* one from each address */
 	struct Outgoing outgoing; /* packet currently being sent */
+	
+	struct device *adev;	/* RFC1201 protocol device */
+	struct device *wdev;	/* Windows protocol device */
 };
 
 
@@ -356,40 +426,38 @@
 static int arcnet_memprobe(struct device *dev,u_char *addr);
 static int arcnet_ioprobe(struct device *dev, short ioaddr);
 #endif
+static int arcnetW_init(struct device *dev);
 
 static int arcnet_open(struct device *dev);
 static int arcnet_close(struct device *dev);
+static int arcnet_reset(struct device *dev);
 
-static int arcnet_send_packet(struct sk_buff *skb, struct device *dev);
-#ifdef CAREFUL_XMIT
- static void careful_xmit_wait(struct device *dev);
-#else
- #define careful_xmit_wait(dev)
-#endif
-static void arcnet_continue_tx(struct device *dev);
-static void arcnet_prepare_tx(struct device *dev,struct ClientData *hdr,
+static int arcnetA_send_packet(struct sk_buff *skb, struct device *dev);
+static void arcnetA_continue_tx(struct device *dev);
+static void arcnetA_prepare_tx(struct device *dev,struct ClientData *hdr,
 		short length,char *data);
-static void arcnet_go_tx(struct device *dev);
+static void arcnetA_go_tx(struct device *dev);
+
+static int arcnetW_send_packet(struct sk_buff *skb, struct device *dev);
 
 static void arcnet_interrupt(int irq,struct pt_regs *regs);
 static void arcnet_inthandler(struct device *dev);
-static void arcnet_rx(struct device *dev,int recbuf);
 
-#ifdef USE_TIMER_HANDLER
-static void arcnet_timer(unsigned long arg);
-#endif
+static void arcnet_rx(struct device *dev,int recbuf);
+static void arcnetA_rx(struct device *dev,struct ClientData *arcsoft,
+	int length,u_char saddr, u_char daddr);
+static void arcnetW_rx(struct device *dev,u_char *arcsoft,
+	int length,u_char saddr, u_char daddr);
 
 static struct enet_statistics *arcnet_get_stats(struct device *dev);
 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 
 	/* annoying functions for header/arp/etc building */
-int arc_header(struct sk_buff *skb,struct device *dev,unsigned short type,
+int arcnetA_header(struct sk_buff *skb,struct device *dev,unsigned short type,
 		void *daddr,void *saddr,unsigned len);
-int arc_rebuild_header(void *eth,struct device *dev,unsigned long raddr,
+int arcnetA_rebuild_header(void *eth,struct device *dev,unsigned long raddr,
 		struct sk_buff *skb);
-unsigned short arc_type_trans(struct sk_buff *skb,struct device *dev);
-
-static int arcnet_reset(struct device *dev);
+unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev);
 
 #ifdef MODULE
 int  init_module(void);
@@ -398,19 +466,17 @@
 
 #define tx_done(dev) 1
 
-/*
-#define JIFFER(time) for (delayval=jiffies+(time); delayval>jiffies;);
-*/
 #define JIFFER(time) for (delayval=0; delayval<(time*10); delayval++) \
 		udelay(1000);
+		
 
-#ifdef EXTRA_DELAYS
- #define XJIFFER(time) JIFFER(time)
-#else
- #define XJIFFER(time)
-#endif
+/****************************************************************************
+ *                                                                          *
+ * Probe and initialization                                                 *
+ *                                                                          *
+ ****************************************************************************/
+ 
 
-
 /* Check for a network adaptor of this type, and return '0' if one exists.
  *  If dev->base_addr == 0, probe all likely locations.
  *  If dev->base_addr == 1, always return failure.
@@ -450,14 +516,14 @@
 	int delayval;
 	struct arcnet_local *lp;
 
-	if (net_debug)
+	BUGLVL(D_NORMAL)
 	{
 		printk(version);
 		printk("arcnet: ***\n");
 		printk("arcnet: * Read linux/drivers/net/README.arcnet for important release notes!\n");
 		printk("arcnet: *\n");
-		printk("arcnet: * This version should be stable, but e-mail me if you have any\n");
-		printk("arcnet: * questions, comments, or bug reports!\n");
+		printk("arcnet: * This is an ALPHA version!  (Last stable release: v1.02)  E-mail me if\n");
+		printk("arcnet: * you have any questions, comments, or bug reports.\n");
 		printk("arcnet: ***\n");
 	}
 
@@ -473,7 +539,7 @@
 	else for (port = &ports[0]; *port; port++)
 	{
 		int ioaddr = *port;
-		if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE))
+		if (check_region(ioaddr, ARCNET_TOTAL_SIZE))
 		{
 			BUGLVL(D_INIT)
 				printk("arcnet: Skipping %Xh because of check_region...\n",
@@ -534,7 +600,7 @@
 	 }
 	 
 	/* Grab the region so we can find another board if autoIRQ fails. */
-	request_region(dev->base_addr, ETHERCARD_TOTAL_SIZE,"arcnet");
+	request_region(dev->base_addr, ARCNET_TOTAL_SIZE,"arcnet");
 	
 	printk("%s: ARCnet card found at %03lXh, IRQ %d, ShMem at %lXh.\n", 
 		dev->name, dev->base_addr, dev->irq, dev->mem_start);
@@ -544,27 +610,26 @@
 	memset(dev->priv, 0, sizeof(struct arcnet_local));
 	lp=(struct arcnet_local *)(dev->priv);
 
-	dev->open		= arcnet_open;
-	dev->stop		= arcnet_close;
-	dev->hard_start_xmit = arcnet_send_packet;
-	dev->get_stats	= arcnet_get_stats;
+	dev->open=arcnet_open;
+	dev->stop=arcnet_close;
+	dev->hard_start_xmit=arcnetA_send_packet;
+	dev->get_stats=arcnet_get_stats;
 #ifdef HAVE_MULTICAST
 	dev->set_multicast_list = &set_multicast_list;
 #endif
 
-	/* Fill in the fields of the device structure with ethernet-generic values. */
+	/* Fill in the fields of the device structure with ethernet-generic
+	 * values.
+	 */
 	ether_setup(dev);
-
-	/* And now fill particular ones with arcnet values :) */
 	
+	/* And now fill particular fields with arcnet values */
 	dev->type=ARPHRD_ARCNET;
 	dev->hard_header_len=sizeof(struct ClientData);
-	BUGLVL(D_EXTRA)
+	BUGLVL(D_DURING)
 		printk("arcnet: ClientData header size is %d.\narcnet: HardHeader size is %d.\n",
 			sizeof(struct ClientData),sizeof(struct HardHeader));
-#if LIMIT_MTU	/* the old way - normally, now use ethernet default */
-	dev->mtu=512-sizeof(struct HardHeader)+EXTRA_CLIENTDATA;
-#endif
+
 		/* since we strip EXTRA_CLIENTDATA bytes off before sending,
 		 * we let Linux add that many bytes to the packet data...
 		 */
@@ -585,8 +650,8 @@
 	lp->sequence=1;
 	lp->recbuf=0;
 
-	dev->hard_header        = arc_header;
-	dev->rebuild_header     = arc_rebuild_header;
+	dev->hard_header=arcnetA_header;
+	dev->rebuild_header=arcnetA_rebuild_header;
 
 	return 0;
 }
@@ -598,10 +663,10 @@
 	int delayval,airq;
 
 	BUGLVL(D_INIT)
+	{
 		printk("arcnet: probing address %Xh\n",ioaddr);
-
-	BUGLVL(D_INIT)
 		printk("arcnet:  status1=%Xh\n",inb(STATUS));
+	}
 
 		
 	/* very simple - all we have to do is reset the card, and if there's
@@ -621,6 +686,7 @@
 		return ENODEV;
 	}
 
+#if 0
 	/* we'll try to be reasonably sure it's an arcnet by making sure
 	 * the value of the COMMAND port changes automatically once in a
 	 * while.  I have no idea what those values ARE, but at least
@@ -641,13 +707,13 @@
 			return ENODEV;
 		}
 	}
+#endif
 
 	BUGLVL(D_INIT)
 		printk("arcnet:  status2=%Xh\n",inb(STATUS));
 
 	/* now we turn the reset bit off so we can IRQ next reset... */
 	outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND);
-	XJIFFER(ACKtime);
 	if (inb(STATUS) & RESETflag) /* reset flag STILL on */
 	{
 		BUGLVL(D_INIT)
@@ -659,32 +725,6 @@
 	/* set up automatic IRQ detection */
 	autoirq_setup(0);
 	
-	/* enable reset IRQ's (shouldn't be necessary, but worth a try) */
-	outb(RESETflag,INTMASK);
-
-	/* now reset it again to generate an IRQ */
-	inb(RESET);
-	JIFFER(RESETtime);
-
-	BUGLVL(D_INIT)
-		printk("arcnet:  status3=%Xh\n",inb(STATUS));
-
-	/* and turn the reset flag back off */
-	outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND);
-	XJIFFER(ACKtime);
-
-	BUGLVL(D_INIT)
-		printk("arcnet:  status4=%Xh\n",inb(STATUS));
-
-	/* enable reset IRQ's again */
-	outb(RESETflag,INTMASK);
-
-	/* now reset it again to generate an IRQ */
-	inb(RESET);
-	JIFFER(RESETtime);
-	
-	BUGLVL(D_INIT)
-		printk("arcnet:  status5=%Xh\n",inb(STATUS));
 
 	/* if we do this, we're sure to get an IRQ since the card has
 	 * just reset and the NORXflag is on until we tell it to start
@@ -693,18 +733,15 @@
 	 * However, this could, theoretically, cause a lockup.  Maybe I'm just
 	 * not very good at theory! :)
 	 */
-#ifdef DANGER_PROBE
 	outb(NORXflag,INTMASK);
 	JIFFER(RESETtime);
 	outb(0,INTMASK);
-#endif
 
 	/* and turn the reset flag back off */
 	outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND);
-	XJIFFER(ACKtime);
 
 	airq = autoirq_report(0);
-	if (net_debug>=D_INIT && airq)
+	BUGLVL(D_INIT) if (airq)
 		printk("arcnet:  autoirq is %d\n", airq);
 
 	/* if there was no autoirq AND the user hasn't set any defaults,
@@ -723,7 +760,6 @@
 	{
 		/* now we turn the reset bit off */
 		outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND);
-		XJIFFER(ACKtime);
 	}
 	
 	if (inb(STATUS) & RESETflag) /* reset flag STILL on */
@@ -744,7 +780,7 @@
 	}
 	else if (dev->irq == 2)
 	{
-		if (net_debug)
+		BUGLVL(D_NORMAL)
 			printk("arcnet: IRQ2 == IRQ9, don't worry.\n");
 		dev->irq = 9;
 	}
@@ -758,7 +794,7 @@
 
 /* A memory probe that is called after the card is reset.
  * It checks for the official TESTvalue in byte 0 and makes sure the buffer
- * has certain characteristics of an ARCnet...
+ * has certain characteristics of an ARCnet.
  */
 int arcnet_memprobe(struct device *dev,u_char *addr)
 {
@@ -767,7 +803,6 @@
 		
 	dev->mem_start=0;
 
-#ifdef STRICT_MEM_DETECT /* probably better. */
 	/* ARCnet memory byte 0 is TESTvalue */
 	if (addr[0]!=TESTvalue)
 	{
@@ -786,15 +821,6 @@
 				(unsigned long)addr,addr[0]);
 	 	return ENODEV;
 	}
-#else
-	if (addr[0]!=TESTvalue)
-	{
-		BUGLVL(D_INIT)
-			printk("arcnet:  probe failed.  addr=%lXh, addr[0]=%Xh (not %Xh)\n",
-				(unsigned long)addr,addr[0],TESTvalue);
-		return ENODEV;
-	}
-#endif
 
 	/* got it!  fill in dev */
 	dev->mem_start=(unsigned long)addr;
@@ -807,64 +833,136 @@
 
 #endif /* MODULE */
 
-
-/* Open/initialize the board.  This is called (in the current kernel)
-   sometime after booting when the 'ifconfig' program is run.
 
-   This routine should set everything up anew at each open, even
-   registers that "should" only need to be set once at boot, so that
-   there is non-reboot way to recover if something goes wrong.
-   */
+int arcnet_reset(struct device *dev)
+{
+	struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
+	short ioaddr=dev->base_addr;
+	int delayval,recbuf=lp->recbuf;
+	u_char *cardmem;
+	
+	outb(0,INTMASK);	/* no IRQ's, please! */
+	
+	BUGLVL(D_INIT)
+		printk("arcnet: Resetting %s (status=%Xh)\n",
+			dev->name,inb(STATUS));
+
+	inb(RESET);		/* Reset by reading this port */
+	JIFFER(RESETtime);
+
+	outb(CFLAGScmd|RESETclear, COMMAND); /* clear flags & end reset */
+	outb(CFLAGScmd|CONFIGclear,COMMAND);
+
+	/* after a reset, the first byte of shared mem is TESTvalue and the
+	 * second byte is our 8-bit ARCnet address.
+	 */
+	cardmem = (u_char *) dev->mem_start;
+	if (cardmem[0] != TESTvalue)
+	{
+		BUGLVL(D_INIT)
+			printk("arcnet: reset failed: TESTvalue not present.\n");
+		return 1;
+	}
+	lp->arcnum=cardmem[1];  /* save address for later use */
+	
+	/* clear out status variables */
+	recbuf=lp->recbuf=0;
+	lp->txbuf=2;
+
+	/* enable extended (512-byte) packets */
+	outb(CONFIGcmd|EXTconf,COMMAND);
+	
+	/* clean out all the memory to make debugging make more sense :) */
+	BUGLVL(D_DURING)
+		memset((void *)dev->mem_start,0x42,2048);
+	
+	/* and enable receive of our first packet to the first buffer */
+	EnableReceiver();
+
+	/* re-enable interrupts */
+	outb(NORXflag|RECON_flag,INTMASK);
+	
+	/* done!  return success. */
+	return 0;
+}
+
+static int arcnetW_init(struct device *dev)
+{
+	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+
+	ether_setup(lp->wdev);
+	dev->dev_addr[0]=0;
+	dev->dev_addr[5]=lp->arcnum;
+	dev->mtu=493;	/* MTU is small because of missing packet splitting */
+	lp->wdev->open=NULL;
+	lp->wdev->stop=NULL;
+	lp->wdev->hard_start_xmit=arcnetW_send_packet;
+
+	BUGLVL(D_EXTRA)
+		printk("%s: ARCnet \"Windows\" protocol initialized.\n",
+			lp->wdev->name);
+			
+	return 0;
+}
+
+
+/****************************************************************************
+ *                                                                          *
+ * Open and close the driver                                                *
+ *                                                                          *
+ ****************************************************************************/
+ 
+
+/* Open/initialize the board.  This is called sometime after booting when
+ * the 'ifconfig' program is run.
+ *
+ * This routine should set everything up anew at each open, even
+ * registers that "should" only need to be set once at boot, so that
+ * there is non-reboot way to recover if something goes wrong.
+ */
 static int
 arcnet_open(struct device *dev)
 {
 	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-/*	int ioaddr = dev->base_addr;*/
 
-	if (dev->metric>=10)
+	if (dev->metric>=1000)
 	{
-		net_debug=dev->metric-10;
+		arcnet_debug=dev->metric-1000;
+		printk("arcnet: debug level set to %d\n",arcnet_debug);
 		dev->metric=1;
 	}
 
-	if (net_debug) printk(version);
-
-#if 0	/* Yup, they're hardwired in arcnets */
-	/* This is used if the interrupt line can turned off (shared).
-	   See 3c503.c for an example of selecting the IRQ at config-time. */
-	if (request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet")) {
-		return -EAGAIN;
-	}
-#endif
+	BUGLVL(D_NORMAL) printk(version);
 
 	irq2dev_map[dev->irq] = dev;
 
-	/* Reset the hardware here. */
 	BUGLVL(D_EXTRA) printk("arcnet: arcnet_open: resetting card.\n");
 	
 	/* try to reset - twice if it fails the first time */
 	if (arcnet_reset(dev) && arcnet_reset(dev))
 		return -ENODEV;
 	
-/*	chipset_init(dev, 1);*/
-/*	outb(0x00, ioaddr);*/
-
-/*	lp->open_time = jiffies;*/
-
 	dev->tbusy=0;
 	dev->interrupt=0;
-	dev->start=1;
 	lp->intx=0;
 	lp->in_txhandler=0;
+	
+	/* The RFC1201 driver is the default - just store */
+	lp->adev=dev;
+	BUGLVL(D_EXTRA)
+		printk("%s:  ARCnet RFC1201 protocol initialized.\n",
+			lp->adev->name);
+	
+	/* Initialize the Windows protocol driver */
+	lp->wdev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
+	memcpy(lp->wdev,dev,sizeof(struct device));
+	lp->wdev->name=(char *)kmalloc(10,GFP_KERNEL);
+	sprintf(lp->wdev->name,"%sw",dev->name);
+	lp->wdev->init=arcnetW_init;
+	register_netdev(lp->wdev);
 
-#ifdef USE_TIMER_HANDLER
-	/* grab a timer handler to recover from any missed IRQ's */
-	init_timer(&lp->timer);
-	lp->timer.expires = TIMERval;         /* length of time */
-	lp->timer.data = (unsigned long)dev;  /* pointer to "dev" structure */
-	lp->timer.function = &arcnet_timer;    /* timer handler */
-	add_timer(&lp->timer);
-#endif
+	/* we're started */
+	START=1;
 
 #ifdef MODULE
 	MOD_INC_USE_COUNT;
@@ -874,32 +972,33 @@
 }
 
 
-/* The inverse routine to arcnet_open(). */
+/* The inverse routine to arcnet_open - shuts down the card.
+ */
 static int
 arcnet_close(struct device *dev)
 {
-	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
 	int ioaddr = dev->base_addr;
-#ifdef EXTRA_DELAYS
-	int delayval;
-#endif
-
-/*	lp->open_time = 0;*/
+	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
 
-	dev->tbusy = 1;
-	dev->start = 0;
+	TBUSY=1;
+	START=0;
 	
-	/* release the timer */
-	del_timer(&lp->timer);
-
 	/* Flush the Tx and disable Rx here.     */
-	/* resetting the card should do the job. */
-	/*inb(RESET);*/
 
 	outb(0,INTMASK);	/* no IRQ's */
 	outb(NOTXcmd,COMMAND);  /* disable transmit */
-	XJIFFER(ACKtime);
 	outb(NORXcmd,COMMAND);	/* disable receive */
+	
+	/* do NOT free lp->adev!!  It's static! */
+	lp->adev=NULL;
+	
+	/* free the Windows protocol device */
+	lp->wdev->start=0;
+	lp->wdev->priv=NULL;
+	unregister_netdev(lp->wdev);
+	kfree(lp->wdev->name);
+	kfree(lp->wdev);
+	lp->wdev=NULL;
 
 	/* Update the statistics here. */
 	
@@ -911,20 +1010,36 @@
 }
 
 
+
+/****************************************************************************
+ *                                                                          *
+ * Transmitter routines                                                     *
+ *                                                                          *
+ ****************************************************************************/
+
+
+/* Called by the kernel in order to transmit a packet.
+ */
 static int
-arcnet_send_packet(struct sk_buff *skb, struct device *dev)
+arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
 {
 	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
 	int ioaddr=dev->base_addr;
-/*	short daddr;*/
 
 	lp->intx++;
-
+	
 	BUGLVL(D_DURING)
 		printk("arcnet: transmit requested (status=%Xh, inTX=%d)\n",
 			inb(STATUS),lp->intx);
+			
+	if (lp->in_txhandler)
+	{
+		printk("arcnet: send_packet called while in txhandler!\n");
+		lp->intx--;
+		return 1;
+	}
 
-	if (dev->tbusy || lp->in_txhandler)
+	if (IF_TBUSY)
 	{
 		/* If we get here, some higher level has decided we are broken.
 		   There should really be a "kick me" function call instead. */
@@ -932,18 +1047,6 @@
 		int recbuf=lp->recbuf;
 		int status=inb(STATUS);
 		
-		/* resume any stopped tx's */
-#if 0
-		if (lp->txready && (inb(STATUS)&TXFREEflag))
-		{
-			printk("arcnet: kickme: starting a TX (status=%Xh)\n",
-				inb(STATUS));
-			arcnet_go_tx(dev);
-			lp->intx--;
-			return 1;
-		}
-#endif
-		
 		if (tickssofar < 5) 
 		{
 			BUGLVL(D_DURING)
@@ -955,27 +1058,36 @@
 			return 1;
 		}
 
-		BUGLVL(D_INIT)
-			printk("arcnet: transmit timed out (status=%Xh, inTX=%d, tickssofar=%d)\n",
-				status,lp->intx,tickssofar);
+		BUGLVL(D_EXTRA)
+			printk("arcnet: transmit timed out (status=%Xh, inTX=%d, inTXh=%d, tickssofar=%d)\n",
+				status,lp->intx,lp->in_txhandler,tickssofar);
+				
+		lp->stats.tx_errors++;
 
 		/* Try to restart the adaptor. */
 		/*arcnet_reset(dev);*/
 		
+		outb(0,INTMASK);
 		if (status&NORXflag) EnableReceiver();
 		if (!(status&TXFREEflag)) outb(NOTXcmd,COMMAND);
 		dev->trans_start = jiffies;
 
 		if (lp->outgoing.skb)
+		{
 			dev_kfree_skb(lp->outgoing.skb,FREE_WRITE);
+			lp->stats.tx_dropped++;
+		}
 		lp->outgoing.skb=NULL;
 
-		dev->tbusy=0;
-		mark_bh(NET_BH);
-		lp->intx=0;
-		lp->in_txhandler=0;
+		TBUSY=0;
+		lp->intx--;
+		/*lp->intx=0;*/
+		/*lp->in_txhandler=0;*/
 		lp->txready=0;
 		lp->sending=0;
+		mark_bh(NET_BH);
+
+		outb(NORXflag|RECON_flag,INTMASK);
 
 		return 1;
 	}
@@ -984,7 +1096,7 @@
 	   we are passed NULL. Caution: dev_tint() handles the cli()/sti()
 	   itself. */
 	if (skb == NULL) {
-		BUGLVL(D_INIT)
+		BUGLVL(D_NORMAL)
 			printk("arcnet: tx passed null skb (status=%Xh, inTX=%d, tickssofar=%ld)\n",
 				inb(STATUS),lp->intx,jiffies-dev->trans_start);
 		dev_tint(dev);
@@ -994,9 +1106,16 @@
 	
 	if (lp->txready)	/* transmit already in progress! */
 	{
-		printk("arcnet: trying to start new packet while busy!\n");
-		printk("arcnet: marking as not ready.\n");
-		lp->txready=0;
+		printk("arcnet: trying to start new packet while busy! (status=%Xh)\n",
+			inb(STATUS));
+		/*printk("arcnet: marking as not ready.\n");*/
+		outb(0,INTMASK);
+		outb(NOTXcmd,COMMAND); /* abort current send */
+		arcnet_inthandler(dev); /* fake an interrupt */
+		lp->stats.tx_errors++;
+		lp->intx--;
+		lp->txready=0;	/* we definitely need this line! */
+		
 		return 1;
 	}
 
@@ -1011,10 +1130,15 @@
         }
 	else {
 		struct Outgoing *out=&(lp->outgoing);
-		out->length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+		
+		TBUSY=1;
+		
+		out->length = 1 < skb->len ? skb->len : 1;
 		out->hdr=(struct ClientData*)skb->data;
 		out->skb=skb;
-		BUGLVL( D_DATA ) {
+		
+		BUGLVL(D_SKB)
+		{
 			short i;
 			for( i=0; i< skb->len; i++)
 			{
@@ -1024,25 +1148,25 @@
 			printk("\n");
 		}
 
-#ifdef IRQ_XMIT
-		if (lp->txready && inb(STATUS)&TXFREEflag)
-			arcnet_go_tx(dev);
-#endif
+		out->hdr->sequence=(lp->sequence++);
 
+		if (lp->txready && inb(STATUS)&TXFREEflag)
+			arcnetA_go_tx(dev);
 		
-		if (out->length<=XMTU)	/* fits in one packet? */
+		/* fits in one packet? */
+		if (out->length-EXTRA_CLIENTDATA<=XMTU)
 		{
-			BUGLVL(D_TX) printk("arcnet: not splitting %d-byte packet. (split_flag=%d)\n",
+			BUGLVL(D_DURING)
+				printk("arcnet: not splitting %d-byte packet. (split_flag=%d)\n",
 					out->length,out->hdr->split_flag);
-			BUGLVL(D_INIT) if (out->hdr->split_flag)
+			BUGLVL(D_EXTRA) if (out->hdr->split_flag)
 				printk("arcnet: short packet has split_flag set?! (split_flag=%d)\n",
 					out->hdr->split_flag);
 			out->numsegs=1;
 			out->segnum=1;
-			arcnet_prepare_tx(dev,out->hdr,
+			arcnetA_prepare_tx(dev,out->hdr,
 				out->length-sizeof(struct ClientData),
 				((char *)skb->data)+sizeof(struct ClientData));
-			careful_xmit_wait(dev);
 
 			/* done right away */
 			dev_kfree_skb(out->skb,FREE_WRITE);
@@ -1050,16 +1174,16 @@
 					
 			if (!lp->sending)
 			{
-				arcnet_go_tx(dev);
+				arcnetA_go_tx(dev);
 				
 				/* inform upper layers */
-				dev->tbusy=0;
+				TBUSY=0;
 				mark_bh(NET_BH);
 			}
 		}
 		else			/* too big for one - split it */
 		{
-			int maxsegsize=XMTU-sizeof(struct ClientData);
+			int maxsegsize=XMTU-4;
 
 			out->data=(u_char *)skb->data
 					+ sizeof(struct ClientData);
@@ -1071,23 +1195,22 @@
 			BUGLVL(D_TX) printk("arcnet: packet (%d bytes) split into %d fragments:\n",
 				out->length,out->numsegs);
 
-#ifdef IRQ_XMIT
 			/* if a packet waiting, launch it */
 			if (lp->txready && inb(STATUS)&TXFREEflag)
-				arcnet_go_tx(dev);
+				arcnetA_go_tx(dev);
 
 			if (!lp->txready)
 			{
 				/* prepare a packet, launch it and prepare
                                  * another.
                                  */
-				arcnet_continue_tx(dev);
+				arcnetA_continue_tx(dev);
 				if (!lp->sending)
 				{
-					arcnet_go_tx(dev);
-					arcnet_continue_tx(dev);
+					arcnetA_go_tx(dev);
+					arcnetA_continue_tx(dev);
 					if (!lp->sending)
-						arcnet_go_tx(dev);
+						arcnetA_go_tx(dev);
 				}
 			}
 			
@@ -1101,29 +1224,7 @@
 				if (out->skb)
 					dev_kfree_skb(out->skb,FREE_WRITE);
 				out->skb=NULL;
-#if 0
-				/* inform upper layers */
-				dev->tbusy=0;
-				mark_bh(NET_BH);
-#endif
-			}
-			
-#else /* non-irq xmit */
-			while (out->segnum<out->numsegs)
-			{
-				arcnet_continue_tx(dev);
-				careful_xmit_wait(dev);
-				arcnet_go_tx(dev);
-				dev->trans_start=jiffies;
 			}
-
-			dev_kfree_skb(out->skb,FREE_WRITE);
-			out->skb=NULL;
-
-			/* inform upper layers */
-			dev->tbusy = 0;
-			mark_bh(NET_BH);
-#endif
 		}
 	}
 
@@ -1133,10 +1234,15 @@
 	return 0;
 }
 
-static void arcnet_continue_tx(struct device *dev)
+/* After an RFC1201 split packet has been set up, this function calls
+ * arcnetA_prepare_tx to load the next segment into the card.  This function
+ * does NOT automatically call arcnetA_go_tx to allow for easier double-
+ * buffering.
+ */
+static void arcnetA_continue_tx(struct device *dev)
 {
 	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-	int maxsegsize=XMTU-sizeof(struct ClientData);
+	int maxsegsize=XMTU-4;
 	struct Outgoing *out=&(lp->outgoing);
 	
 	if (lp->txready)
@@ -1163,43 +1269,21 @@
 		out->segnum+1,out->seglen,out->numsegs,
 		out->length,out->hdr->split_flag);
 
-	arcnet_prepare_tx(dev,out->hdr,out->seglen,out->data);
+	arcnetA_prepare_tx(dev,out->hdr,out->seglen,out->data);
 		
 	out->dataleft-=out->seglen;
 	out->data+=out->seglen;
 	out->segnum++;
 }
 
-#ifdef CAREFUL_XMIT
-static void careful_xmit_wait(struct device *dev)
-{
-	int ioaddr=dev->base_addr;
-	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-
-	/* wait patiently for tx to become available again */
-	while ( !(inb(STATUS)&TXFREEflag) )
-	{
-		if (jiffies-dev->trans_start > 20 || !dev->tbusy)
-		{
-			BUGLVL(D_INIT)
-				printk("arcnet: CAREFUL_XMIT timeout. (busy=%d, status=%Xh)\n",
-					dev->tbusy,inb(STATUS));
-			lp->stats.tx_errors++;
-			
-			outb(NOTXcmd,COMMAND);
-			return;
-		}
-	}
-	BUGLVL(D_TX) printk("arcnet: transmit completed successfully. (status=%Xh)\n",
-				inb(STATUS));
-}
-#endif
 
+/* Given an skb, copy a packet into the ARCnet buffers for later transmission
+ * by arcnetA_go_tx.
+ */
 static void
-arcnet_prepare_tx(struct device *dev,struct ClientData *hdr,short length,
+arcnetA_prepare_tx(struct device *dev,struct ClientData *hdr,short length,
 		char *data)
 {
-/*	int ioaddr = dev->base_addr;*/
 	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
 	struct ClientData *arcsoft;
 	union ArcPacket *arcpacket = 
@@ -1210,10 +1294,10 @@
 	
 	lp->txbuf=lp->txbuf^1;	/* XOR with 1 to alternate between 2 and 3 */
 	
-	length+=sizeof(struct ClientData);
+	length+=4;
 
 	BUGLVL(D_TX)
-		printk("arcnet: arcnet_prep_tx: hdr:%ph, length:%d, data:%ph\n",
+		printk("arcnet: arcnetA_prep_tx: hdr:%ph, length:%d, data:%ph\n",
 			hdr,length,data);
 
 	/* clean out the page to make debugging make more sense :) */
@@ -1227,8 +1311,7 @@
 	{
 		pkttype=NORMAL;
 			
-		arcpacket->hardheader.offset1=offset=256-length
-				+ EXTRA_CLIENTDATA;
+		arcpacket->hardheader.offset1=offset=256-length;
 		arcsoft=(struct ClientData *)
 			(&arcpacket->raw[offset-EXTRA_CLIENTDATA]);
 	}
@@ -1237,8 +1320,7 @@
 		pkttype=EXTENDED;
 		
 		arcpacket->hardheader.offset1=0;
-		arcpacket->hardheader.offset2=offset=512-length
-			+ EXTRA_CLIENTDATA;
+		arcpacket->hardheader.offset2=offset=512-length;
 		arcsoft=(struct ClientData *)
 			(&arcpacket->raw[offset-EXTRA_CLIENTDATA]);
 	}
@@ -1247,8 +1329,7 @@
 		pkttype=EXCEPTION;
 		
 		arcpacket->hardheader.offset1=0;
-		arcpacket->hardheader.offset2=offset=512-length-4
-			+ EXTRA_CLIENTDATA;
+		arcpacket->hardheader.offset2=offset=512-length-4;
 		arcsoft=(struct ClientData *)
 			(&arcpacket->raw[offset+4-EXTRA_CLIENTDATA]);
 		
@@ -1267,11 +1348,9 @@
 	 *  - the first bytes of ClientData header are skipped
 	 */
 	memcpy((u_char*)arcsoft+EXTRA_CLIENTDATA,
-		(u_char*)hdr+EXTRA_CLIENTDATA,
-		sizeof(struct ClientData)-EXTRA_CLIENTDATA);
+		(u_char*)hdr+EXTRA_CLIENTDATA,4);
 	memcpy((u_char*)arcsoft+sizeof(struct ClientData),
-		data,
-		length-sizeof(struct ClientData));
+		data,length-4);
 		
 	BUGLVL(D_DURING) printk("arcnet: transmitting packet to station %02Xh (%d bytes, type=%d)\n",
 			daddr,length,pkttype);
@@ -1292,35 +1371,18 @@
 		
 		printk("\n");
 	}
-#ifdef CAREFUL_XMIT
- #if 0
-	careful_xmit_wait(dev);
-
-	/* if we're not broadcasting, make sure the xmit was ack'd.
-	 * if it wasn't, there is probably no card with that
-	 * address... or else it missed our tx somehow.
-	 */
-	if (daddr && !(inb(STATUS)&TXACKflag))
-	{	
-		BUGLVL(D_INIT)
-			printk("arcnet: transmit not acknowledged. (status=%Xh, daddr=%02Xh)\n",
-				inb(STATUS),daddr);
-		lp->stats.tx_errors++;
-		return -ENONET; /* "machine is not on the network" */
-	}
- #endif
-#endif
-	lp->txready=lp->txbuf;	/* packet is ready for sending */
 
-#if 0
-#ifdef IRQ_XMIT
-	if (inb(STATUS)&TXFREEflag) arcnet_go_tx(dev);
-#endif
+#ifdef VERIFY_ACK
+	lp->outgoing.lastload_dest=hdr->daddr;
 #endif
+	lp->txready=lp->txbuf;	/* packet is ready for sending */
 }
 
+/* Actually start transmitting a packet that was placed in the card's
+ * buffer by arcnetA_prepare_tx.
+ */
 static void
-arcnet_go_tx(struct device *dev)
+arcnetA_go_tx(struct device *dev)
 {
 	struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
 	int ioaddr=dev->base_addr;
@@ -1334,47 +1396,203 @@
 	/* start sending */
 	outb(TXcmd|(lp->txready<<3),COMMAND);
 
-#ifdef IRQ_XMIT
-	outb(TXFREEflag|NORXflag,INTMASK);
-#endif
+	outb(TXFREEflag|NORXflag|RECON_flag,INTMASK);
 
 	dev->trans_start = jiffies;
 	lp->txready=0;
 	lp->sending++;
+#ifdef VERIFY_ACK	
+	lp->outgoing.lasttrans_dest=lp->outgoing.lastload_dest;
+	lp->outgoing.lastload_dest=0;
+#endif
 }
 
-
-/* The typical workload of the driver:
-   Handle the network interface interrupts. */
+
+/* Called by the kernel in order to transmit a "Windows" packet.
+ */
+static int
+arcnetW_send_packet(struct sk_buff *skb, struct device *dev)
+{
+	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+	
+	BUGLVL(D_DURING)
+		printk("%s: in arcnetW_send_packet (skb=%p)\n",dev->name,skb);
+
+	if (IF_TBUSY)
+	{
+		/* If we get here, some higher level has decided we are broken.
+		   There should really be a "kick me" function call instead. */
+		int tickssofar = jiffies - dev->trans_start;
+		if (tickssofar < 10)
+			return 1;
+		printk("%s: transmit timed out\n",dev->name);
+		
+		/* Try to restart the adaptor. */
+		TBUSY=0;
+		dev->trans_start = jiffies;
+		return 0;
+	}
+
+	/* If some higher layer thinks we've missed an tx-done interrupt
+	   we are passed NULL. Caution: dev_tint() handles the cli()/sti()
+	   itself. */
+	if (skb == NULL)
+	{
+		dev_tint(dev);
+		return 0;
+	}
+
+	/* Block a timer-based transmit from overlapping.  This could better be
+	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+	if (set_bit(0, (void*)&dev->tbusy) != 0)
+		printk("%s: Transmitter access conflict.\n", dev->name);
+	else
+	{
+		union ArcPacket *arcpacket = 
+			(union ArcPacket *)(dev->mem_start+512*(lp->txbuf^1));
+		u_char *arcsoft,daddr;
+		short offset,length=skb->len+1;
+		
+		TBUSY=1;
+		
+		if (length>XMTU)
+		{
+			printk("arcnet: MTU for %s and %s must be <= 493 for Windows protocol.\n",
+				lp->adev->name,lp->wdev->name);
+			printk("arcnet: transmit aborted.\n");
+
+			dev_kfree_skb(skb,FREE_WRITE);
+			return 0;
+		}
+		
+		BUGLVL(D_DURING)
+			printk("arcnet: starting tx sequence...\n");
+
+		lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate btw 2 & 3 */
+
+		/* clean out the page to make debugging make more sense :) */
+		BUGLVL(D_DURING)
+			memset((void *)dev->mem_start+lp->txbuf*512,0x42,512);
+
+		/* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */
+		if (((struct ethhdr*)(skb->data))->h_dest[0] == 0xFF)
+			daddr=arcpacket->hardheader.destination=0;
+		else
+			daddr=arcpacket->hardheader.destination=
+				((struct ethhdr*)(skb->data))->h_dest[5];
+
+		/* load packet into shared memory */
+		offset=512-length;
+		if (length>MTU)		/* long/exception packet */
+		{
+			if (length<MinTU) offset-=3;
+			arcpacket->hardheader.offset1=0;
+			arcpacket->hardheader.offset2=offset;
+		}
+		else			/* short packet */
+		{
+			arcpacket->hardheader.offset1=(offset-=256);
+		}
+		
+		BUGLVL(D_DURING)
+			printk("arcnet: length=%Xh, offset=%Xh, offset1=%Xh, offset2=%Xh\n",
+				length,offset,arcpacket->hardheader.offset1,
+				arcpacket->hardheader.offset2);
+		
+		arcsoft=&arcpacket->raw[offset];
+		arcsoft[0]=ARC_P_MS_TCPIP;
+		arcsoft++;
+		
+		/* copy the packet into ARCnet shmem
+		 *  - the first bytes of ClientData header are skipped
+		 */
+		BUGLVL(D_DURING) printk("arcnet: ready to memcpy\n");
+		
+		memcpy(arcsoft,skb->data,skb->len);
+			
+		BUGLVL(D_DURING)
+			printk("arcnet: transmitting packet to station %02Xh (%d bytes)\n",
+				daddr,length);
+				
+		BUGLVL(D_TX)
+		{
+			int countx,county;
+			
+			printk("arcnet: packet dump [tx] follows:");
+
+	 		for (county=0; county<16+(length>=240)*16; county++)
+			{
+				printk("\n[%04X] ",county*16);
+				for (countx=0; countx<16; countx++)
+					printk("%02X ",
+						arcpacket->raw[county*16+countx]);
+			}
+			
+			printk("\n");
+		}
+
+	#ifdef VERIFY_ACK
+		lp->outgoing.lastload_dest=daddr;
+	#endif
+		lp->txready=lp->txbuf;	/* packet is ready for sending */
+
+		arcnetA_go_tx(dev);
+		dev->trans_start = jiffies;
+	}
+
+	dev_kfree_skb(skb,FREE_WRITE);
+
+	return 0;
+}
+
+
+/****************************************************************************
+ *                                                                          *
+ * Interrupt handler                                                        *
+ *                                                                          *
+ ****************************************************************************/
+
+
+/* The typical workload of the driver:  Handle the network interface
+ * interrupts.  This doesn't do much right now except call arcnet_inthandler,
+ * which takes different parameters but is sometimes called from other places
+ * as well.
+ */
 static void
 arcnet_interrupt(int irq,struct pt_regs *regs)
 {
 	struct device *dev = (struct device *)(irq2dev_map[irq]);
 
-	if (dev == NULL) {
-		if (net_debug >= D_DURING)
+	if (dev==NULL || !dev->start)
+	{
+		BUGLVL(D_EXTRA)
 			printk("arcnet: irq %d for unknown device.\n", irq);
 		return;
 	}
-	
+
 	arcnet_inthandler(dev);
 }
 
+
+/* The actual interrupt handler routine - handle various IRQ's generated
+ * by the card.
+ */
 static void
 arcnet_inthandler(struct device *dev)
 {	
 	struct arcnet_local *lp;
 	int ioaddr, status, boguscount = 3, didsomething;
 	
+	if (dev->interrupt)
+		printk("arcnet: DRIVER PROBLEM!  Nested arcnet interrupts!\n");
+	
 	dev->interrupt = 1;
-	sti();
 
 	ioaddr = dev->base_addr;
 	lp = (struct arcnet_local *)dev->priv;
 
-#ifdef IRQ_XMIT
 	outb(0,INTMASK);
-#endif
+	sti();
 	
 	BUGLVL(D_DURING)
 		printk("arcnet: in net_interrupt (status=%Xh)\n",inb(STATUS));
@@ -1386,13 +1604,12 @@
 	
 		if (!dev->start)
 		{
-			BUGLVL(D_EXTRA)
+			BUGLVL(D_DURING)
 				printk("arcnet: ARCnet not yet initialized.  irq ignored. (status=%Xh)\n",
 					status);
-#ifdef IRQ_XMIT
 			if (!(status&NORXflag))
-				outb(NORXflag,INTMASK);
-#endif
+				outb(NORXflag|RECON_flag,INTMASK);
+
 			dev->interrupt=0;
 			return;
 		}
@@ -1402,14 +1619,22 @@
 		 */
 		if (status & RESETflag)
 		{
+			outb(CFLAGScmd|RESETclear,COMMAND);
 			BUGLVL(D_INIT)
 				printk("arcnet: reset irq (status=%Xh)\n",
 					status);
-			dev->interrupt=0;
-			return;
 		}
+#ifdef DETECT_RECONFIGS
+		if (status & RECONflag)
+		{
+			outb(CFLAGScmd|CONFIGclear,COMMAND);
+			BUGLVL(D_EXTRA)
+				printk("arcnet: Network reconfiguration detected (status=%Xh)\n",
+					status);
+			lp->stats.tx_carrier_errors++;
+		}
+#endif
 
-#if 1	/* yes, it's silly to disable this part but it makes good testing */
 		/* RX is inhibited - we must have received something. */
 		if (status & NORXflag)
 		{
@@ -1427,8 +1652,7 @@
 			
 			didsomething++;
 		}
-#endif
-#ifdef IRQ_XMIT
+
 		/* it can only be an xmit-done irq if we're xmitting :) */
 		if (status&TXFREEflag && !lp->in_txhandler && lp->sending)
 		{
@@ -1441,10 +1665,31 @@
 				printk("arcnet: TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
 					status,out->numsegs,out->segnum,out->skb);
 					
+#ifdef VERIFY_ACK
+			if (!(status&TXACKflag))
+			{
+				if (lp->outgoing.lasttrans_dest != 0)
+				{
+					BUGLVL(D_NORMAL)
+						printk("arcnet: transmit was not acknowledged! (status=%Xh, dest=%d)\n",
+							status,
+							lp->outgoing.lasttrans_dest);
+					lp->stats.tx_errors++;
+				}
+				else
+				{
+					BUGLVL(D_DURING)
+						printk("arcnet: broadcast was not acknowledged; that's normal (status=%Xh, dest=%d)\n",
+							status,
+							lp->outgoing.lasttrans_dest);
+				}
+			}
+#endif
+					
 			/* send packet if there is one */
 			if (lp->txready)
 			{
-				arcnet_go_tx(dev);
+				arcnetA_go_tx(dev);
 				didsomething++;
 			}
 			
@@ -1460,9 +1705,9 @@
 					printk("arcnet: TX IRQ done: no split to continue.\n");
 				
 				/* inform upper layers */
-				if (!lp->txready && dev->tbusy)
+				if (!lp->txready && IF_TBUSY)
 				{
-					dev->tbusy=0;
+					TBUSY=0;
 					mark_bh(NET_BH);
 				}
 				
@@ -1476,9 +1721,9 @@
 			 * are done, then continue xmit.
 			 */
 			if (out->segnum<out->numsegs)
-				arcnet_continue_tx(dev);
+				arcnetA_continue_tx(dev);
 			if (lp->txready && !lp->sending)
-				arcnet_go_tx(dev);
+				arcnetA_go_tx(dev);
 
 			/* if segnum==numsegs, the transmission is finished;
 			 * free the skb.
@@ -1492,9 +1737,9 @@
 				out->skb=NULL;
 
 				/* inform upper layers */
-				if (!lp->txready && dev->tbusy)
+				if (!lp->txready && IF_TBUSY)
 				{
-					dev->tbusy=0;
+					TBUSY=0;
 					mark_bh(NET_BH);
 				}
 			}
@@ -1502,49 +1747,52 @@
 			
 			lp->in_txhandler--;
 		}
-#endif /* IRQ_XMIT */
+
 	} while (--boguscount && didsomething);
 
 	BUGLVL(D_DURING)
-		printk("arcnet: net_interrupt complete (status=%Xh)\n",
+		printk("arcnet: net_interrupt complete (status=%Xh)\n\n",
 			inb(STATUS));
 
-#ifdef IRQ_XMIT
 	if (dev->start && lp->sending )
-		outb(NORXflag|TXFREEflag,INTMASK);
+		outb(NORXflag|TXFREEflag|RECON_flag,INTMASK);
 	else
-		outb(NORXflag,INTMASK);
-#endif
+		outb(NORXflag|RECON_flag,INTMASK);
 
 	dev->interrupt=0;
 }
 
+
+/****************************************************************************
+ *                                                                          *
+ * Receiver routines                                                        *
+ *                                                                          *
+ ****************************************************************************/
+
+
 /* A packet has arrived; grab it from the buffers and possibly unsplit it.
+ * This is a generic packet receiver that calls arcnet??_rx depending on the
+ * protocol ID found.
  */
 static void
 arcnet_rx(struct device *dev,int recbuf)
 {
 	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
 	int ioaddr = dev->base_addr;
-/*	int status = inb(STATUS);*/
-
-	struct sk_buff *skb;
-
 	union ArcPacket *arcpacket=
 		(union ArcPacket *)(dev->mem_start+recbuf*512);
-	struct ClientData *soft,*arcsoft;
+	u_char *arcsoft;
 	short length,offset;
-	u_char pkttype,daddr,saddr;
+	u_char daddr,saddr;
 
-	daddr=arcpacket->hardheader.destination;
 	saddr=arcpacket->hardheader.source;
+	daddr=arcpacket->hardheader.destination;
 	
-	/* if source is 0, it's not a "used" packet! */
+	/* if source is 0, it's a "used" packet! */
 	if (saddr==0)
 	{
-		/*BUGLVL(D_DURING)*/
-			printk("arcnet: discarding old packet. (status=%Xh)\n",
-				inb(STATUS));
+		printk("arcnet: discarding old packet. (status=%Xh)\n",
+			inb(STATUS));
 		lp->stats.rx_errors++;
 		return;
 	}
@@ -1553,30 +1801,91 @@
 	if (arcpacket->hardheader.offset1) /* Normal Packet */
 	{
 		offset=arcpacket->hardheader.offset1;
-		arcsoft=(struct ClientData *)
-			(&arcpacket->raw[offset-EXTRA_CLIENTDATA]);
-		length=256-offset+EXTRA_CLIENTDATA;
-		pkttype=NORMAL;
+		arcsoft=&arcpacket->raw[offset];
+		length=256-offset;
 	}
 	else		/* ExtendedPacket or ExceptionPacket */
 	{
 		offset=arcpacket->hardheader.offset2;
-		arcsoft=(struct ClientData *)
-			(&arcpacket->raw[offset-EXTRA_CLIENTDATA]);
+		arcsoft=&arcpacket->raw[offset];
 
-		if (arcsoft->split_flag!=0xFF)  /* Extended Packet */
-		{
-			length=512-offset+EXTRA_CLIENTDATA;
-			pkttype=EXTENDED;
-		}
-		else				/* Exception Packet */
-		{
-			/* skip over 4-byte junkola */
-			arcsoft=(struct ClientData *)
-				((u_char *)arcsoft + 4);
-			length=512-offset+EXTRA_CLIENTDATA-4;
-			pkttype=EXCEPTION;
-		}
+		length=512-offset;
+	}
+	
+       	BUGLVL(D_DURING)
+		printk("arcnet: received packet from %02Xh to %02Xh (%d bytes)\n",
+       			saddr,daddr,length);
+
+	/* call the right receiver for the protocol */
+	switch (arcsoft[0])
+	{
+	case ARC_P_IP:
+	case ARC_P_ARP:
+	case ARC_P_RARP:
+	case ARC_P_IPX:
+		arcnetA_rx(dev,(struct ClientData*)arcsoft,
+			length,saddr,daddr);
+		break;
+	case ARC_P_MS_TCPIP:
+		arcnetW_rx(dev,arcsoft,length,saddr,daddr);
+		break;		
+	default:
+		printk("arcnet: received unknown protocol %d (%Xh)\n",
+			arcsoft[0],arcsoft[0]);
+		break;
+	}
+
+        BUGLVL(D_RX)
+	{
+        	int countx,county;
+        	
+        	printk("arcnet: rx packet dump follows:");
+
+       		for (county=0; county<16+(length>240)*16; county++)
+       		{
+       			printk("\n[%04X] ",county*16);
+       			for (countx=0; countx<16; countx++)
+       				printk("%02X ",
+       					arcpacket->raw[county*16+countx]);
+       		}
+       		
+       		printk("\n");
+       	}
+
+
+	/* If any worth-while packets have been received, a mark_bh(NET_BH)
+	 * has been done by netif_rx and Linux will handle them after we
+	 * return.
+	 */
+}
+
+
+/* Packet receiver for "standard" RFC1201-style packets
+ */
+static void
+arcnetA_rx(struct device *dev,struct ClientData *arcsoft,
+	int length,u_char saddr, u_char daddr)
+{
+	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+	struct sk_buff *skb;
+	struct ClientData *soft;
+	
+	BUGLVL(D_DURING)
+		printk("arcnet: it's an RFC1201 packet (length=%d)\n",
+			length);
+			
+	arcsoft=(struct ClientData *)((u_char *)arcsoft-EXTRA_CLIENTDATA);
+	length+=EXTRA_CLIENTDATA;
+
+	if (arcsoft->split_flag==0xFF)  /* Exception Packet */
+	{
+		BUGLVL(D_DURING)
+			printk("arcnet: compensating for exception packet\n");
+
+		/* skip over 4-byte junkola */
+		arcsoft=(struct ClientData *)
+			((u_char *)arcsoft + 4);
+		length-=4;
 	}
 	
 	if (!arcsoft->split_flag)		/* not split */
@@ -1586,26 +1895,28 @@
 		BUGLVL(D_RX) printk("arcnet: incoming is not split (splitflag=%d)\n",
 			arcsoft->split_flag);
 			
-        if (in->skb)	/* already assembling one! */
+		if (in->skb)	/* already assembling one! */
         	{
-        		BUGLVL(D_INIT) printk("arcnet: aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
+        		BUGLVL(D_EXTRA) printk("arcnet: aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
         			in->sequence,arcsoft->split_flag,
         			arcsoft->sequence);
         		kfree_skb(in->skb,FREE_WRITE);
+			lp->stats.tx_dropped++;
+        		lp->stats.rx_errors++;
         		in->skb=NULL;
         	}
         	
         	in->sequence=arcsoft->sequence;
 
-         	skb = dev_alloc_skb(length);
+         	skb = alloc_skb(length, GFP_ATOMIC);
          	if (skb == NULL) {
-         		printk("%s: Memory squeeze, dropping packet.\n", 
-         			dev->name);
+         		printk("arcnet: Memory squeeze, dropping packet.\n");
          		lp->stats.rx_dropped++;
          		return;
          	}
-         	soft=(struct ClientData *)skb_put(skb,length);
+         	soft=(struct ClientData *)skb->data;
          	
+         	skb->len = length;
          	skb->dev = dev;
          	
          	memcpy((u_char *)soft+EXTRA_CLIENTDATA,
@@ -1614,30 +1925,10 @@
          	soft->daddr=daddr;
          	soft->saddr=saddr;
          	
-         	BUGLVL(D_DURING)
-         		printk("arcnet: received packet from %02Xh to %02Xh (%d bytes, type=%d)\n",
-         			saddr,daddr,length,pkttype);
-         	BUGLVL(D_RX)
-        	{
-        		int countx,county;
-        		
-        		printk("arcnet: packet dump [rx-unsplit] follows:");
-
-         		for (county=0; county<16+(pkttype!=NORMAL)*16; county++)
-        		{
-        			printk("\n[%04X] ",county*16);
-        			for (countx=0; countx<16; countx++)
-        				printk("%02X ",
-        					arcpacket->raw[county*16+countx]);
-        		}
-        		
-        		printk("\n");
-        	}
-
          	/* ARP packets have problems when sent from DOS.
-         	 * source address is always 0!  So we take the hardware
-         	 * source addr (which is impossible to fumble) and insert
-         	 * it ourselves.
+         	 * source address is always 0 on some systems!  So we take
+         	 * the hardware source addr (which is impossible to fumble)
+         	 * and insert it ourselves.
          	 */
          	if (soft->protocol_id == ARC_P_ARP)
          	{
@@ -1651,7 +1942,7 @@
          			
          			if (!*cptr)	/* is saddr = 00? */
          			{
-         				BUGLVL(D_DURING)
+         				BUGLVL(D_EXTRA)
          					printk("arcnet: ARP source address was 00h, set to %02Xh.\n",
          						saddr);
          				*cptr=saddr;
@@ -1666,9 +1957,23 @@
          		{
          			printk("arcnet: funny-shaped ARP packet. (%Xh, %Xh)\n",
          				arp->ar_hln,arp->ar_pln);
+         			lp->stats.rx_frame_errors++;
          		}
          	}
-		skb->protocol=arc_type_trans(skb,dev);
+         	
+		BUGLVL(D_SKB)
+		{
+	            short i;
+	               	for( i=0; i< skb->len; i++)
+               		{
+                       		if( i%16 == 0 ) printk("\n[%04hX] ",i);
+                       		printk("%02hX ",((unsigned char*)skb->data)[i]);
+               		}
+               		printk("\n");
+            	}
+
+		skb->protocol=arcnetA_type_trans(skb,dev);
+
          	netif_rx(skb);
          	lp->stats.rx_packets++;
          }
@@ -1698,11 +2003,13 @@
 
 		if (in->skb && in->sequence!=arcsoft->sequence)
 		{
-			BUGLVL(D_INIT) printk("arcnet: wrong seq number, aborting assembly (expected=%d, seq=%d, splitflag=%d)\n",	
+			BUGLVL(D_EXTRA) printk("arcnet: wrong seq number, aborting assembly (expected=%d, seq=%d, splitflag=%d)\n",	
 				in->sequence,arcsoft->sequence,
 				arcsoft->split_flag);
 	        	kfree_skb(in->skb,FREE_WRITE);
 	        	in->skb=NULL;
+			lp->stats.tx_dropped++;
+	        	lp->stats.rx_fifo_errors++;
 	        	in->lastpacket=in->numpackets=0;
 	        }
 	          
@@ -1712,9 +2019,11 @@
 	        		arcsoft->split_flag);
 	        	if (in->skb)	/* already assembling one! */
 	        	{
-	        		BUGLVL(D_INIT) printk("arcnet: aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
+	        		BUGLVL(D_EXTRA) printk("arcnet: aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
 	        			in->sequence,arcsoft->split_flag,
 	        			arcsoft->sequence);
+				lp->stats.tx_dropped++;
+	        		lp->stats.rx_over_errors++;
 	        		kfree_skb(in->skb,FREE_WRITE);
 	        	}
 
@@ -1724,14 +2033,15 @@
 	        	
 	        	if (in->numpackets>16)
 	        	{
-	        		printk("arcnet: incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
+	        		BUGLVL(D_EXTRA) printk("arcnet: incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
 	        			arcsoft->split_flag);
 	        		lp->stats.rx_dropped++;
 	        		return;
 	        	}
 	        
-                	in->skb=skb=dev_alloc_skb(508*in->numpackets
-                			+ sizeof(struct ClientData));
+                	in->skb=skb=alloc_skb(508*in->numpackets
+                			+ sizeof(struct ClientData),
+	                		GFP_ATOMIC);
                 	if (skb == NULL) {
                 		printk("%s: (split) memory squeeze, dropping packet.\n", 
                 			dev->name);
@@ -1744,8 +2054,9 @@
 	                 */
 	                skb->free=1;
 	                
-                	soft=(struct ClientData *)skb_put(skb,sizeof(struct ClientData));
+                	soft=(struct ClientData *)skb->data;
                 	
+                	skb->len=sizeof(struct ClientData);
                 	skb->dev=dev;
 
 	         	memcpy((u_char *)soft+EXTRA_CLIENTDATA,
@@ -1762,8 +2073,9 @@
 			 */			
 			if (!in->skb)
 			{
-				BUGLVL(D_INIT) printk("arcnet: can't continue split without starting first! (splitflag=%d, seq=%d)\n",
+				BUGLVL(D_EXTRA) printk("arcnet: can't continue split without starting first! (splitflag=%d, seq=%d)\n",
 					arcsoft->split_flag,arcsoft->sequence);
+				lp->stats.rx_errors++;
 				return;
 			}
 
@@ -1773,53 +2085,37 @@
 				/* harmless duplicate? ignore. */
 				if (packetnum<=in->lastpacket-1)
 				{
-					BUGLVL(D_INIT) printk("arcnet: duplicate splitpacket ignored! (splitflag=%d)\n",
+					BUGLVL(D_EXTRA) printk("arcnet: duplicate splitpacket ignored! (splitflag=%d)\n",
 						arcsoft->split_flag);
 					return;
 				}
 				
 				/* "bad" duplicate, kill reassembly */
-				BUGLVL(D_INIT) printk("arcnet: out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",	
+				BUGLVL(D_EXTRA) printk("arcnet: out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",	
 					in->sequence,arcsoft->split_flag,
 					arcsoft->sequence);
 	        		kfree_skb(in->skb,FREE_WRITE);
 	        		in->skb=NULL;
+				lp->stats.tx_dropped++;
+	        		lp->stats.rx_fifo_errors++;
 	        		in->lastpacket=in->numpackets=0;
 	        		return;
 	        	}
 
-	               	soft=(struct ClientData *)skb->data;
+	               	soft=(struct ClientData *)in->skb->data;
 	        }
 	        
 	        skb=in->skb;
 	        
-	        memcpy(skb_put(skb,length-sizeof(struct ClientData)),
+	        memcpy(skb->data+skb->len,
 	               (u_char *)arcsoft+sizeof(struct ClientData),
 	               length-sizeof(struct ClientData));
 
+         	skb->len+=length-sizeof(struct ClientData);
+         	
          	soft->daddr=daddr;
          	soft->saddr=saddr;
          	
-         	BUGLVL(D_DURING)
-         		printk("arcnet: received packet from %02Xh to %02Xh (%d bytes, type=%d)\n",
-         			saddr,daddr,length,pkttype);
-         	BUGLVL(D_RX)
-        	{
-        		int countx,county;
-        		
-        		printk("arcnet: packet dump [rx-split] follows:");
-
-         		for (county=0; county<16+(pkttype!=NORMAL)*16; county++)
-        		{
-        			printk("\n[%04X] ",county*16);
-        			for (countx=0; countx<16; countx++)
-        				printk("%02X ",
-        					arcpacket->raw[county*16+countx]);
-        		}
-        		
-        		printk("\n");
-        	}
-         	
          	/* are we done? */
          	if (in->lastpacket == in->numpackets)
          	{
@@ -1828,75 +2124,102 @@
          				skb,in->skb);
          		in->skb=NULL;
          		in->lastpacket=in->numpackets=0;
-			skb->protocol=arc_type_trans(skb,dev);         		
+			
+			BUGLVL(D_SKB)
+			{
+	        	    short i;
+	        	       	for( i=0; i< skb->len; i++)
+               			{
+                	       		if( i%16 == 0 ) printk("\n[%04hX] ",i);
+                	       		printk("%02hX ",((unsigned char*)skb->data)[i]);
+               			}
+               			printk("\n");
+            		}
+
+			skb->protocol=arcnetA_type_trans(skb,dev);
+
 	         	netif_rx(skb);
         	 	lp->stats.rx_packets++;
         	}
          }
-	
-	/* If any worth-while packets have been received, netif_rx()
-	   has done a mark_bh(NET_BH) for us and will work on them
-	   when we get to the bottom-half routine. */
 }
 
 
-#ifdef USE_TIMER_HANDLER
-/* this function is called every once in a while to make sure the ARCnet
- * isn't stuck.
- *
- * If we miss a receive IRQ, the receiver (and IRQ) is permanently disabled
- * and we might never receive a packet again!  This will check if this
- * is the case, and if so, re-enable the receiver.
+/* Packet receiver for non-standard Windows-style packets
  */
 static void
-arcnet_timer(unsigned long arg)
+arcnetW_rx(struct device *dev,u_char *arcsoft,
+	int length,u_char saddr, u_char daddr)
 {
-	struct device *dev=(struct device *)arg;
 	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-	short ioaddr=dev->base_addr;
-	int status=inb(STATUS);
+	struct sk_buff *skb;
+	
+	BUGLVL(D_DURING)
+		printk("arcnet: it's a Windows packet (length=%d)\n",
+			length);
 
-	/* if we didn't interrupt the IRQ handler, and RX's are still
-	 * disabled, and we're not resetting the card... then we're stuck!
-	 */
-	if (!dev->interrupt && dev->start
-	  && status&NORXflag && !status&RESETflag)
-	{
-		BUGLVL(D_INIT)
-			printk("arcnet: timer: ARCnet was stuck!  (status=%Xh)\n",
-				status);
-		
-		arcnet_inthandler(dev);
-	}
+       	skb = alloc_skb(length, GFP_ATOMIC);
+       	if (skb == NULL) {
+       		printk("arcnet: Memory squeeze, dropping packet.\n");
+       		lp->stats.rx_dropped++;
+       		return;
+       	}
+       	
+       	skb->len = length;
+       	skb->dev = lp->wdev;
+       	
+       	memcpy(skb->data,(u_char *)arcsoft+1,length-1);
 
-	/* requeue ourselves */
-	init_timer(&lp->timer);
-	lp->timer.expires=TIMERval;
-	add_timer(&lp->timer);
+        BUGLVL(D_SKB)
+        {
+		short i;
+		printk("arcnet: rx skb dump follows:\n");
+                for(i=0; i<skb->len; i++)
+                {
+			if (i%16==0)
+				printk("\n[%04hX] ",i);
+			else
+                        	printk("%02hX ",((u_char *)skb->data)[i]);
+		}
+                printk("\n");
+        }
+        
+	skb->protocol=eth_type_trans(skb,dev);
+        
+        netif_rx(skb);
+        lp->stats.rx_packets++;
 }
-#endif
+
+
+/****************************************************************************
+ *                                                                          *
+ * Miscellaneous routines                                                   *
+ *                                                                          *
+ ****************************************************************************/
+
 
 /* Get the current statistics.	This may be called with the card open or
-   closed. */
+ * closed.
+ */
+
 static struct enet_statistics *
 arcnet_get_stats(struct device *dev)
 {
 	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-/*	short ioaddr = dev->base_addr;*/
 
 	return &lp->stats;
 }
 
 /* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1	Promiscuous mode, receive all packets
-   num_addrs == 0	Normal mode, clear multicast list
-   num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-			best-effort filtering.
+ * num_addrs == -1	Promiscuous mode, receive all packets
+ * num_addrs == 0	Normal mode, clear multicast list
+ * num_addrs > 0	Multicast mode, receive normal and MC packets, and do
+ *			best-effort filtering.
  */
 static void
 set_multicast_list(struct device *dev, int num_addrs, void *addrs)
 {
-#if 0	  /* no promiscuous mode at all */
+#if 0	  /* no promiscuous mode at all on most ARCnet models */
 	struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
 
 	short ioaddr = dev->base_addr;
@@ -1907,74 +2230,17 @@
 #endif
 }
 
-int arcnet_reset(struct device *dev)
-{
-	struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
-	short ioaddr=dev->base_addr;
-	int delayval,recbuf=lp->recbuf;
-	
-	outb(0,INTMASK);	/* no IRQ's, please! */
-	
-	BUGLVL(D_INIT)
-		printk("arcnet: Resetting %s (status=%Xh)\n",
-			dev->name,inb(STATUS));
-
-	inb(RESET);		/* Reset by reading this port */
-	JIFFER(RESETtime);
-
-	outb(CFLAGScmd|RESETclear, COMMAND); /* clear flags & end reset */
-	outb(CFLAGScmd|CONFIGclear,COMMAND);
-
-	/* after a reset, the first byte of shared mem is TESTvalue and the
-	 * second byte is our 8-bit ARCnet address
-	 */
-	{
-		u_char *cardmem = (u_char *) dev->mem_start;
-		if (cardmem[0] != TESTvalue)
-		{
-			BUGLVL(D_INIT)
-				printk("arcnet: reset failed: TESTvalue not present.\n");
-			return 1;
-		}
-		lp->arcnum=cardmem[1];  /* save address for later use */
-	}
-	
-	/* clear out status variables */
-	recbuf=lp->recbuf=0;
-	lp->txbuf=2;
-	/*dev->tbusy=0;*/
-
-	/* enable extended (512-byte) packets */
-	outb(CONFIGcmd|EXTconf,COMMAND);
-	XJIFFER(ACKtime);
-	
-	/* clean out all the memory to make debugging make more sense :) */
-	BUGLVL(D_DURING)
-		memset((void *)dev->mem_start,0x42,2048);
-	
-	/* and enable receive of our first packet to the first buffer */
-	EnableReceiver();
-
-	/* re-enable interrupts */
-	outb(NORXflag,INTMASK);
-	
-	/* done!  return success. */
-	return 0;
-}
-
-
-/*
- *	 Create the ARCnet ClientData header for an arbitrary protocol layer
+/* Create the ARCnet ClientData header for an arbitrary protocol layer
  *
- *	saddr=NULL	means use device source address (always will anyway)
- *	daddr=NULL	means leave destination address (eg unresolved arp)
+ * saddr=NULL	means use device source address (always will anyway)
+ * daddr=NULL	means leave destination address (eg unresolved arp)
  */
-int arc_header(struct sk_buff *skb,struct device *dev,unsigned short type,
+int arcnetA_header(struct sk_buff *skb,struct device *dev,unsigned short type,
 		void *daddr,void *saddr,unsigned len)
 {
 	struct ClientData *head = (struct ClientData *)
 		skb_push(skb,dev->hard_header_len);
-	struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
+/*	struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);*/
 
 	/* set the protocol ID according to RFC-1201 */
 	switch(type)
@@ -2000,18 +2266,18 @@
 		return 0;
 	}	
 
-#if 1
 	/*
-	 *	Set the source hardware address.
-	 *	AVE: we can't do this, so we don't.  Code below is directly
-	 *	     stolen from eth.c driver and won't work.
-	 ** TM: but for debugging I would like to have saddr in the header
+	 * Set the source hardware address.
+	 *
+	 * This is pretty pointless for most purposes, but it can help
+	 * in debugging.  saddr is stored in the ClientData header and
+	 * removed before sending the packet (since ARCnet does not allow
+	 * us to change the source address in the actual packet sent)
 	 */
 	if(saddr)
 		head->saddr=((u_char*)saddr)[0];
 	else
 		head->saddr=((u_char*)(dev->dev_addr))[0];
-#endif
 
 #if 0
 	/*
@@ -2028,7 +2294,7 @@
 #endif
 
 	head->split_flag=0;	/* split packets are done elsewhere */
-	head->sequence=(lp->sequence++);
+	head->sequence=0;	/* so are sequence numbers */
 
 	/* supposedly if daddr is NULL, we should ignore it... */
 	if(daddr)
@@ -2043,18 +2309,17 @@
 }
 
 
-/*
- *	Rebuild the ARCnet ClientData header. This is called after an ARP
- *	(or in future other address resolution) has completed on this
- *	sk_buff. We now let ARP fill in the other fields.
+/* Rebuild the ARCnet ClientData header. This is called after an ARP
+ * (or in future other address resolution) has completed on this
+ * sk_buff. We now let ARP fill in the other fields.
  */
-int arc_rebuild_header(void *buff,struct device *dev,unsigned long dst,
+int arcnetA_rebuild_header(void *buff,struct device *dev,unsigned long dst,
 		struct sk_buff *skb)
 {
 	struct ClientData *head = (struct ClientData *)buff;
 
 	/*
-	 *	Only ARP/IP is currently supported
+	 * Only ARP and IP are currently supported
 	 */
 	 
 	if(head->protocol_id != ARC_P_IP) 
@@ -2067,7 +2332,7 @@
 	}
 
 	/*
-	 *	Try and get ARP to resolve the header.
+	 * Try and get ARP to resolve the header.
 	 */
 #ifdef CONFIG_INET	 
 	return arp_find(&(head->daddr), dst, dev, dev->pa_addr, skb)? 1 : 0;
@@ -2076,25 +2341,22 @@
 #endif	
 }
 		
-/*
- *	Determine the packet's protocol ID.
+/* Determine a packet's protocol ID.
  *
- *	With ARCnet we have to convert everything to Ethernet-style stuff.
+ * With ARCnet we have to convert everything to Ethernet-style stuff.
  */
-unsigned short arc_type_trans(struct sk_buff *skb,struct device *dev)
+unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev)
 {
 	struct ClientData *head = (struct ClientData *) skb->data;
+	struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
 
-	/*
-	 *	Pull off the arcnet header.
-	 */
-	 
+	/* Pull off the arcnet header. */
 	skb->mac.raw=skb->data;
 	skb_pull(skb,dev->hard_header_len);
 	
 	if (head->daddr==0)
 		skb->pkt_type=PACKET_BROADCAST;
-	else if(dev->flags&IFF_PROMISC)
+	else if (dev->flags&IFF_PROMISC)
 	{
 		/* if we're not sending to ourselves :) */
 		if (head->daddr != dev->dev_addr[0])
@@ -2108,50 +2370,61 @@
 	case ARC_P_ARP:		return htons(ETH_P_ARP);
 	case ARC_P_RARP:	return htons(ETH_P_RARP);
 	case ARC_P_IPX:		return htons(ETH_P_IPX);
-	case ARC_P_ATALK:   	return htons(ETH_P_ATALK);	/* Doesn't work yet */
+	case ARC_P_ATALK:   return htons(ETH_P_ATALK); /* untested appletalk */
 	case ARC_P_LANSOFT: /* don't understand.  fall through. */
 	default:
-		BUGLVL(D_DURING)
+		BUGLVL(D_EXTRA)
 			printk("arcnet: received packet of unknown protocol id %d (%Xh)\n",
 				head->protocol_id,head->protocol_id);
+		lp->stats.rx_frame_errors++;
 		return 0;
 	}
+
 	return htons(ETH_P_IP);
 }
 
+
+
+/****************************************************************************
+ *                                                                          *
+ * Kernel Loadable Module Support                                           *
+ *                                                                          *
+ ****************************************************************************/
+
+
 #ifdef MODULE
 char kernel_version[] = UTS_RELEASE;
-static struct device thisARCnet = {
-  "      ",/* if blank, device name inserted by /linux/drivers/net/net_init.c */
+static struct device thiscard = {
+  "       ",/* if blank, device name inserted by /linux/drivers/net/net_init.c */
   0, 0, 0, 0,
   0, 0,  /* I/O address, IRQ */
   0, 0, 0, NULL, arcnet_probe };
 	
 	
 int io=0x0;	/* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
-int irqnum=0;	/* or use the insmod io= irq= shmem= options */
+int irqnum=0;	/* or use the insmod io= irqnum= shmem= options */
 int shmem=0;
-int num=0;	/* number of device (ie for arc0, arc1, arc2...) */
+int num=0;	/* number of device (ie for 0 for arc0, 1 for arc1...) */
 
 int
 init_module(void)
 {
-	sprintf(thisARCnet.name,"arc%d",num);
+	sprintf(thiscard.name,"arc%d",num);
 
-	thisARCnet.base_addr=io;
+	thiscard.base_addr=io;
 
-	thisARCnet.irq=irqnum;
-	if (thisARCnet.irq==2) thisARCnet.irq=9;
+	thiscard.irq=irqnum;
+	if (thiscard.irq==2) thiscard.irq=9;
 
 	if (shmem)
 	{
-		thisARCnet.mem_start=shmem;
-		thisARCnet.mem_end=thisARCnet.mem_start+512*4-1;
-		thisARCnet.rmem_start=thisARCnet.mem_start+512*0;
-		thisARCnet.rmem_end=thisARCnet.mem_start+512*2-1;
+		thiscard.mem_start=shmem;
+		thiscard.mem_end=thiscard.mem_start+512*4-1;
+		thiscard.rmem_start=thiscard.mem_start+512*0;
+		thiscard.rmem_end=thiscard.mem_start+512*2-1;
 	}
 
-	if (register_netdev(&thisARCnet) != 0)
+	if (register_netdev(&thiscard) != 0)
 		return -EIO;
 	return 0;
 }
@@ -2159,15 +2432,18 @@
 void
 cleanup_module(void)
 {
-  if (MOD_IN_USE) {
-    printk("%s: device busy, remove delayed\n",thisARCnet.name);
-  } else {
-    if (thisARCnet.start) arcnet_close(&thisARCnet);
-    if (thisARCnet.irq) free_irq(thisARCnet.irq);
-    if (thisARCnet.base_addr) release_region(thisARCnet.base_addr,
-    						ETHERCARD_TOTAL_SIZE);
-    unregister_netdev(&thisARCnet);
-  }
+	if (MOD_IN_USE)
+	{
+		printk("%s: device busy, remove delayed\n",thiscard.name);
+	}
+	else
+	{
+		if (thiscard.start) arcnet_close(&thiscard);
+		if (thiscard.irq) free_irq(thiscard.irq);
+		if (thiscard.base_addr) release_region(thiscard.base_addr,
+						ARCNET_TOTAL_SIZE);
+		unregister_netdev(&thiscard);
+	}
 }
 
 #endif /* MODULE */
@@ -2176,10 +2452,10 @@
 
 /*
  * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c"
+ *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c arcnet.c"
  *  version-control: t
  *  kept-new-versions: 5
- *  tab-width: 4
+ *  tab-width: 8
  * End:
  */
 
diff -u --recursive --new-file v1.3.9/linux/drivers/net/eql.c linux/drivers/net/eql.c
--- v1.3.9/linux/drivers/net/eql.c	Fri Jun 30 16:22:27 1995
+++ linux/drivers/net/eql.c	Wed Jul 12 06:41:58 1995
@@ -249,7 +249,7 @@
   dev->pa_addr    = 0;
   dev->pa_brdaddr = 0;
   dev->pa_mask    = 0;
-  dev->pa_alen    = sizeof (unsigned long);
+  dev->pa_alen    = 4;
 
   dev->type       = ARPHRD_SLIP;
 
diff -u --recursive --new-file v1.3.9/linux/drivers/net/loopback.c linux/drivers/net/loopback.c
--- v1.3.9/linux/drivers/net/loopback.c	Fri Jun 30 16:22:28 1995
+++ linux/drivers/net/loopback.c	Wed Jul 12 06:41:58 1995
@@ -139,7 +139,7 @@
 	dev->pa_addr		= in_aton("127.0.0.1");
 	dev->pa_brdaddr	= in_aton("127.255.255.255");
 	dev->pa_mask		= in_aton("255.0.0.0");
-	dev->pa_alen		= sizeof(unsigned long);
+	dev->pa_alen		= 4;
 #endif  
 	dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
 	memset(dev->priv, 0, sizeof(struct enet_statistics));
diff -u --recursive --new-file v1.3.9/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v1.3.9/linux/drivers/net/net_init.c	Fri Jun 30 16:22:28 1995
+++ linux/drivers/net/net_init.c	Wed Jul 12 18:24:18 1995
@@ -194,6 +194,7 @@
 	dev->hard_header	= eth_header;
 	dev->rebuild_header = eth_rebuild_header;
 	dev->set_mac_address = eth_mac_addr;
+	dev->header_cache = eth_header_cache;
 
 	dev->type		= ARPHRD_ETHER;
 	dev->hard_header_len = ETH_HLEN;
@@ -209,7 +210,7 @@
 	dev->pa_addr	= 0;
 	dev->pa_brdaddr = 0;
 	dev->pa_mask	= 0;
-	dev->pa_alen	= sizeof(unsigned long);
+	dev->pa_alen	= 4;
 }
 
 #ifdef CONFIG_TR
@@ -239,7 +240,7 @@
 	dev->pa_addr	= 0;
 	dev->pa_brdaddr = 0;
 	dev->pa_mask	= 0;
-	dev->pa_alen	= sizeof(unsigned long);
+	dev->pa_alen	= 4;
 }
 
 #endif
diff -u --recursive --new-file v1.3.9/linux/drivers/net/pi2.c linux/drivers/net/pi2.c
--- v1.3.9/linux/drivers/net/pi2.c	Fri Jul  7 08:54:48 1995
+++ linux/drivers/net/pi2.c	Wed Jul 12 06:41:58 1995
@@ -1442,7 +1442,7 @@
     dev->pa_addr = 0;
     dev->pa_brdaddr = 0;
     dev->pa_mask = 0;
-    dev->pa_alen = sizeof(unsigned long);
+    dev->pa_alen = 4;
 
     return 0;
 }
diff -u --recursive --new-file v1.3.9/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v1.3.9/linux/drivers/net/ppp.c	Fri Jul  7 08:54:48 1995
+++ linux/drivers/net/ppp.c	Wed Jul 12 06:41:59 1995
@@ -295,7 +295,7 @@
   dev->pa_addr    = 0;
   dev->pa_brdaddr = 0;
   dev->pa_mask    = 0;
-  dev->pa_alen    = sizeof(unsigned long);
+  dev->pa_alen    = 4;
 
   return 0;
 }
@@ -1144,7 +1144,7 @@
  sendit:
   if (ppp_debug_netpackets) {
     struct iphdr *iph = (struct iphdr *) c;
-    PRINTK ((KERN_INFO "%s <--    src %lx dst %lx len %d\n", ppp->dev->name, 
+    PRINTK ((KERN_INFO "%s <--    src %x dst %x len %d\n", ppp->dev->name, 
 	     iph->saddr, iph->daddr, count))
   }
 
@@ -1251,9 +1251,8 @@
 
   CHECK_PPP(-ENXIO);
 
-  PRINTKN (4,(KERN_DEBUG "ppp_read: called %x num %u\n",
-	      (unsigned int) buf,
-	      nr));
+  PRINTKN (4,(KERN_DEBUG "ppp_read: called %p num %u\n",
+	      buf, nr));
 
   do {
     /* try to acquire read lock */
@@ -1323,8 +1322,8 @@
 {
   int curpt = ppp->xhead - ppp->xbuff;
   if ((curpt < 0) || (curpt > 3000)) {
-    PRINTK ((KERN_DEBUG "ppp_stuff_char: %x %x %d\n",
-	     (unsigned int) ppp->xbuff, (unsigned int) ppp->xhead, curpt))
+    PRINTK ((KERN_DEBUG "ppp_stuff_char: %p %p %d\n",
+	     ppp->xbuff, ppp->xhead, curpt))
   }
   if (in_xmap (ppp, c)) {
     *ppp->xhead++ = PPP_ESC;
@@ -1402,8 +1401,8 @@
   if (ppp_debug >= 6)
     ppp_print_buffer ("xmit buffer", ppp->xbuff, ppp->xhead - ppp->xbuff, KERNEL_DS);
   else {
-    PRINTKN (4,(KERN_DEBUG
-		"ppp_write: writing %d chars\n", ppp->xhead - ppp->xbuff));
+    PRINTKN (4,(KERN_DEBUG "ppp_write: writing %d chars\n",
+		(int) (ppp->xhead - ppp->xbuff)));
   }
 
   /* packet is ready-to-go */
@@ -1471,7 +1470,7 @@
     if (error == 0) {
       put_user (ppp->xmit_async_map[0], (int *) l);
       PRINTKN (3,(KERN_INFO "ppp_ioctl: get asyncmap: addr %lx asyncmap %lx\n",
-		  l, ppp->xmit_async_map[0]));
+		  l, (unsigned long) ppp->xmit_async_map[0]));
     }
     break;
 
@@ -1482,7 +1481,7 @@
       bset (ppp->xmit_async_map, PPP_FLAG);
       bset (ppp->xmit_async_map, PPP_ESC);
       PRINTKN (3,(KERN_INFO "ppp_ioctl: set xmit asyncmap %lx\n",
-		  ppp->xmit_async_map[0]));
+		  (unsigned long) ppp->xmit_async_map[0]));
     }
     break;
 
@@ -1491,7 +1490,7 @@
     if (error == 0) {
       ppp->recv_async_map = get_user ((int *) l);
       PRINTKN (3,(KERN_INFO "ppp_ioctl: set recv asyncmap %lx\n",
-		  ppp->recv_async_map));
+		  (unsigned long) ppp->recv_async_map));
     }
     break;
 
@@ -1573,7 +1572,7 @@
     error = verify_area (VERIFY_READ, (void *) l,
 			 sizeof (ppp->xmit_async_map));
     if (error == 0) {
-      unsigned long temp_tbl [8];
+      __u32 temp_tbl [8];
 
       memcpy_fromfs (temp_tbl, (void *) l, sizeof (ppp->xmit_async_map));
       temp_tbl[1]  =  0x00000000; /* must not escape 0x20 - 0x3f */
@@ -1831,8 +1830,8 @@
   if (ppp_debug >= 6)
     ppp_print_buffer ("xmit buffer", ppp->xbuff, ppp->xhead - ppp->xbuff, KERNEL_DS);
   else {
-    PRINTKN (4,(KERN_DEBUG
-		"ppp_write: writing %d chars\n", ppp->xhead - ppp->xbuff));
+    PRINTKN (4,(KERN_DEBUG "ppp_write: writing %d chars\n",
+		(int) (ppp->xhead - ppp->xbuff)));
   }
 
   ppp_kick_tty(ppp);
diff -u --recursive --new-file v1.3.9/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v1.3.9/linux/drivers/net/slip.c	Fri Jul  7 08:54:48 1995
+++ linux/drivers/net/slip.c	Wed Jul 12 06:41:59 1995
@@ -1141,7 +1141,7 @@
 	dev->pa_addr		= 0;
 	dev->pa_brdaddr	        = 0;
 	dev->pa_mask		= 0;
-	dev->pa_alen		= sizeof(unsigned long);
+	dev->pa_alen		= 4;
 
 	return 0;
 }
diff -u --recursive --new-file v1.3.9/linux/drivers/net/tunnel.c linux/drivers/net/tunnel.c
--- v1.3.9/linux/drivers/net/tunnel.c	Fri Jun 30 16:22:29 1995
+++ linux/drivers/net/tunnel.c	Wed Jul 12 18:24:18 1995
@@ -244,7 +244,9 @@
 #ifdef TUNNEL_DEBUG
 	printk("tunnel: calling ip_forward()\n");
 #endif
-	ip_forward(skb2, dev, 0, iph->daddr, 0);
+	if(ip_forward(skb2, dev, 0, iph->daddr, 0))
+		kfree_skb(skb2, FREE_WRITE);
+
  
 #ifdef TUNNEL_DEBUG
 	printk("Packet sent through tunnel interface!\n");
@@ -255,8 +257,6 @@
 #ifdef TUNNEL_DEBUG
 	printk("tunnel: Updated usage statistics.\n");
 #endif
-	/* Clean up and return okay. */
-	kfree_skb(skb2, FREE_WRITE);
 	dev->tbusy=0;
 	return 0;
 }
Binary files v1.3.9/linux/drivers/scsi/aic7770 and linux/drivers/scsi/aic7770 differ
diff -u --recursive --new-file v1.3.9/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c
--- v1.3.9/linux/drivers/scsi/scsi_proc.c	Tue Jul 11 10:02:50 1995
+++ linux/drivers/scsi/scsi_proc.c	Thu Jul 13 07:57:03 1995
@@ -105,7 +105,6 @@
 extern int dispatch_scsi_info(int ino, char *buffer, char **start, 
 			      off_t offset, int length, int func)
 {
-    int retval;
     struct Scsi_Host *hpnt = scsi_hostlist;
 
     if(func != 2) {    
diff -u --recursive --new-file v1.3.9/linux/drivers/sound/pas2_card.c linux/drivers/sound/pas2_card.c
--- v1.3.9/linux/drivers/sound/pas2_card.c	Tue Jul 11 10:02:53 1995
+++ linux/drivers/sound/pas2_card.c	Wed Jul 12 18:38:10 1995
@@ -57,6 +57,7 @@
 /*
  * to support other than the default base address
  */
+extern void mix_write (unsigned char data, int ioaddr);
 
 unsigned char
 pas_read (int ioaddr)
@@ -367,7 +368,7 @@
   if (detect_pas_hw (hw_config))
     {
 
-      if (pas_model = pas_read (CHIP_REV))
+      if ((pas_model = pas_read (CHIP_REV)))
 	{
 	  printk (" <%s rev %d>", pas_model_names[(int) pas_model], pas_read (BOARD_REV_ID));
 	}
diff -u --recursive --new-file v1.3.9/linux/drivers/sound/sound_config.h linux/drivers/sound/sound_config.h
--- v1.3.9/linux/drivers/sound/sound_config.h	Tue Jul 11 10:02:54 1995
+++ linux/drivers/sound/sound_config.h	Wed Jul 12 18:38:10 1995
@@ -103,6 +103,10 @@
 
 #define FM_MONO		0x388	/* This is the I/O address used by AdLib */
 
+#ifndef PAS_BASE
+#define PAS_BASE	0x388
+#endif
+
 /* SEQ_MAX_QUEUE is the maximum number of sequencer events buffered by the
    driver. (There is no need to alter this) */
 #define SEQ_MAX_QUEUE	1024
diff -u --recursive --new-file v1.3.9/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v1.3.9/linux/fs/ext2/namei.c	Tue Jul 11 10:02:58 1995
+++ linux/fs/ext2/namei.c	Wed Jul 12 06:41:59 1995
@@ -766,7 +766,7 @@
 	for (l = 0; l < inode->i_sb->s_blocksize - 1 &&
 	     symname [l]; l++)
 		;
-	if (l >= EXT2_N_BLOCKS * sizeof (__u32)) {
+	if (l >= sizeof (inode->u.ext2_i.i_data)) {
 
 		ext2_debug ("l=%d, normal symlink\n", l);
 
diff -u --recursive --new-file v1.3.9/linux/include/asm-alpha/a.out.h linux/include/asm-alpha/a.out.h
--- v1.3.9/linux/include/asm-alpha/a.out.h	Fri Jun 16 22:02:55 1995
+++ linux/include/asm-alpha/a.out.h	Wed Jul 12 06:41:59 1995
@@ -1,27 +1,76 @@
 #ifndef __ALPHA_A_OUT_H__
 #define __ALPHA_A_OUT_H__
 
-/* OSF/1 pseudo-a.out header */
+/*
+ * OSF/1 ECOFF header structs.  ECOFF files consist of:
+ * 	- a file header (struct filehdr),
+ *	- an a.out header (struct aouthdr),
+ *	- one or more section headers (struct scnhdr). 
+ *	  The filhdr's "f_nscns" field contains the
+ *	  number of section headers.
+ */
+
+struct filehdr
+{
+	/* OSF/1 "file" header */
+	__u16 f_magic, f_nscns;
+	__u32 f_timdat;
+	__u64 f_symptr;
+	__u32 f_nsyms;
+	__u16 f_opthdr, f_flags;
+};
+
+struct aouthdr
+{
+	__u64 info;		/* after that it looks quite normal.. */
+	__u64 tsize;
+	__u64 dsize;
+	__u64 bsize;
+	__u64 entry;
+	__u64 text_start;	/* with a few additions that actually make sense */
+	__u64 data_start;
+	__u64 bss_start;
+	__u32 gprmask, fprmask;	/* but what are these? */
+	__u64 gpvalue;
+};
+
+struct scnhdr
+{
+	char	s_name[8];
+	__u64	s_paddr;
+	__u64	s_vaddr;
+	__u64	s_size;
+	__u64	s_scnptr;
+	__u64	s_relptr;
+	__u64	s_lnnoptr;
+	__u16	s_nreloc;
+	__u16	s_nlnno;
+	__u32	s_flags;
+};
+
 struct exec
 {
 	/* OSF/1 "file" header */
-	unsigned short f_magic, f_nscns;
-	unsigned int f_timdat;
-	unsigned long f_symptr;
-	unsigned int f_nsyms;
-	unsigned short f_opthdr, f_flags;
-	/* followed by a more normal "a.out" header */
-	unsigned long a_info;		/* after that it looks quite normal.. */
-	unsigned long a_text;
-	unsigned long a_data;
-	unsigned long a_bss;
-	unsigned long a_entry;
-	unsigned long a_textstart;	/* with a few additions that actually make sense */
-	unsigned long a_datastart;
-	unsigned long a_bssstart;
-	unsigned int  a_gprmask, a_fprmask;	/* but what are these? */
-	unsigned long a_gpvalue;
+	struct filehdr		fh;
+	struct aouthdr		ah;
 };
+
+/*
+ * Define's so that the kernel exec code can access the a.out header
+ * fields...
+ */
+#define	a_info		ah.info
+#define	a_text		ah.tsize
+#define a_data		ah.dsize
+#define a_bss		ah.bsize
+#define a_entry		ah.entry
+#define a_textstart	ah.text_start
+#define	a_datastart	ah.data_start
+#define	a_bssstart	ah.bss_start
+#define	a_gprmask	ah.gprmask
+#define a_fprmask	ah.fprmask
+#define a_gpvalue	ah.gpvalue
+
 #define N_TXTADDR(x) ((x).a_textstart)
 #define N_DATADDR(x) ((x).a_datastart)
 #define N_BSSADDR(x) ((x).a_bssstart)
@@ -29,12 +78,13 @@
 #define N_TRSIZE(x) 0
 #define N_SYMSIZE(x) 0
 
-#define SCNHSZ		64		/* XXX should be sizeof(scnhdr) */
+#define AOUTHSZ		sizeof(struct aouthdr)
+#define SCNHSZ		sizeof(struct scnhdr)
 #define SCNROUND	16
 
 #define N_TXTOFF(x) \
   ((long) N_MAGIC(x) == ZMAGIC ? 0 : \
-   (sizeof(struct exec) + (x).f_nscns*SCNHSZ + SCNROUND - 1) & ~(SCNROUND - 1))
+   (sizeof(struct exec) + (x).fh.f_nscns*SCNHSZ + SCNROUND - 1) & ~(SCNROUND - 1))
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v1.3.9/linux/include/asm-alpha/lca.h linux/include/asm-alpha/lca.h
--- v1.3.9/linux/include/asm-alpha/lca.h	Fri Jul  7 08:54:53 1995
+++ linux/include/asm-alpha/lca.h	Wed Jul 12 06:41:59 1995
@@ -304,8 +304,15 @@
 #define inb_p inb
 #define outb_p outb
 
-#define readl(addr)	__readl(addr)
-#define writel(b,addr)	__writel(b,addr)
+extern inline unsigned long readl(unsigned long addr)
+{
+	return __readl(addr);
+}
+
+extern inline void writel(unsigned int b, unsigned long addr)
+{
+	__writel(b, addr);
+}
 
 #undef vuip
 
diff -u --recursive --new-file v1.3.9/linux/include/asm-alpha/termios.h linux/include/asm-alpha/termios.h
--- v1.3.9/linux/include/asm-alpha/termios.h	Tue Jun 27 14:11:44 1995
+++ linux/include/asm-alpha/termios.h	Thu Jul 13 09:56:25 1995
@@ -333,4 +333,59 @@
 #define N_MOUSE		2
 #define N_PPP		3
 
-#endif
+#ifdef __KERNEL__
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+extern inline void trans_from_termio(struct termio * termio,
+	struct termios * termios)
+{
+#define SET_LOW_BITS(x,y)	((x) = (0xffff0000 & (x)) | (y))
+	SET_LOW_BITS(termios->c_iflag, termio->c_iflag);
+	SET_LOW_BITS(termios->c_oflag, termio->c_oflag);
+	SET_LOW_BITS(termios->c_cflag, termio->c_cflag);
+	SET_LOW_BITS(termios->c_lflag, termio->c_lflag);
+#undef SET_LOW_BITS
+	termios->c_cc[VINTR] = termio->c_cc[_VINTR];
+	termios->c_cc[VQUIT] = termio->c_cc[_VQUIT];
+	termios->c_cc[VERASE]= termio->c_cc[_VERASE];
+	termios->c_cc[VKILL] = termio->c_cc[_VKILL];
+	termios->c_cc[VEOF]  = termio->c_cc[_VEOF];
+	termios->c_cc[VMIN]  = termio->c_cc[_VMIN];
+	termios->c_cc[VEOL]  = termio->c_cc[_VEOL];
+	termios->c_cc[VTIME] = termio->c_cc[_VTIME];
+	termios->c_cc[VEOL2] = termio->c_cc[_VEOL2];
+	termios->c_cc[VSWTC] = termio->c_cc[_VSWTC];
+}
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ *
+ * Note the "fun" _VMIN overloading.
+ */
+extern inline void trans_to_termio(struct termios * termios,
+	struct termio * termio)
+{
+	termio->c_iflag = termios->c_iflag;
+	termio->c_oflag = termios->c_oflag;
+	termio->c_cflag = termios->c_cflag;
+	termio->c_lflag = termios->c_lflag;
+	termio->c_line	= termios->c_line;
+	termio->c_cc[_VINTR] = termios->c_cc[VINTR];
+	termio->c_cc[_VQUIT] = termios->c_cc[VQUIT];
+	termio->c_cc[_VERASE]= termios->c_cc[VERASE];
+	termio->c_cc[_VKILL] = termios->c_cc[VKILL];
+	termio->c_cc[_VEOF]  = termios->c_cc[VEOF];
+	termio->c_cc[_VEOL]  = termios->c_cc[VEOL];
+	termio->c_cc[_VEOL2] = termios->c_cc[VEOL2];
+	termio->c_cc[_VSWTC] = termios->c_cc[VSWTC];
+	if (!(termios->c_lflag & ICANON)) {
+		termio->c_cc[_VMIN]  = termios->c_cc[VMIN];
+		termio->c_cc[_VTIME] = termios->c_cc[VTIME];
+	}
+}
+
+#endif	/* __KERNEL__ */
+
+#endif	/* _ALPHA_TERMIOS_H */
diff -u --recursive --new-file v1.3.9/linux/include/asm-i386/termios.h linux/include/asm-i386/termios.h
--- v1.3.9/linux/include/asm-i386/termios.h	Sat Jun 10 18:35:54 1995
+++ linux/include/asm-i386/termios.h	Thu Jul 13 09:56:25 1995
@@ -263,4 +263,37 @@
 #define N_MOUSE		2
 #define N_PPP		3
 
-#endif
+#ifdef __KERNEL__
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+extern inline void trans_from_termio(struct termio * termio,
+	struct termios * termios)
+{
+#define SET_LOW_BITS(x,y)	((x) = (0xffff0000 & (x)) | (y))
+	SET_LOW_BITS(termios->c_iflag, termio->c_iflag);
+	SET_LOW_BITS(termios->c_oflag, termio->c_oflag);
+	SET_LOW_BITS(termios->c_cflag, termio->c_cflag);
+	SET_LOW_BITS(termios->c_lflag, termio->c_lflag);
+#undef SET_LOW_BITS
+	memcpy(termios->c_cc, termio->c_cc, NCC);
+}
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+extern inline void trans_to_termio(struct termios * termios,
+	struct termio * termio)
+{
+	termio->c_iflag = termios->c_iflag;
+	termio->c_oflag = termios->c_oflag;
+	termio->c_cflag = termios->c_cflag;
+	termio->c_lflag = termios->c_lflag;
+	termio->c_line	= termios->c_line;
+	memcpy(termio->c_cc, termios->c_cc, NCC);
+}
+
+#endif	/* __KERNEL__ */
+
+#endif	/* _I386_TERMIOS_H */
diff -u --recursive --new-file v1.3.9/linux/include/linux/etherdevice.h linux/include/linux/etherdevice.h
--- v1.3.9/linux/include/linux/etherdevice.h	Tue Jul 11 10:02:59 1995
+++ linux/include/linux/etherdevice.h	Thu Jul 13 13:05:10 1995
@@ -34,8 +34,10 @@
 extern int		eth_rebuild_header(void *buff, struct device *dev,
 			unsigned long dst, struct sk_buff *skb);
 extern unsigned short	eth_type_trans(struct sk_buff *skb, struct device *dev);
+extern void 		eth_header_cache(struct device *dev, struct sock *sk, unsigned long saddr, unsigned long daddr);
 extern void		eth_copy_and_sum(struct sk_buff *dest,
 				unsigned char *src, int length, int base);
+extern void 		eth_header_cache(struct device *dev, struct sock *sk, unsigned long saddr, unsigned long daddr);
 
 #endif
 
diff -u --recursive --new-file v1.3.9/linux/include/linux/fdreg.h linux/include/linux/fdreg.h
--- v1.3.9/linux/include/linux/fdreg.h	Thu Oct  6 08:45:21 1994
+++ linux/include/linux/fdreg.h	Wed Jul 12 18:32:59 1995
@@ -44,7 +44,7 @@
 #define ST0_DS		0x03		/* drive select mask */
 #define ST0_HA		0x04		/* Head (Address) */
 #define ST0_NR		0x08		/* Not Ready */
-#define ST0_ECE		0x10		/* Equipment chech error */
+#define ST0_ECE		0x10		/* Equipment check error */
 #define ST0_SE		0x20		/* Seek end */
 #define ST0_INTR	0xC0		/* Interrupt code mask */
 
diff -u --recursive --new-file v1.3.9/linux/include/linux/icmp.h linux/include/linux/icmp.h
--- v1.3.9/linux/include/linux/icmp.h	Wed Dec  1 14:44:15 1993
+++ linux/include/linux/icmp.h	Wed Jul 12 06:41:59 1995
@@ -59,15 +59,15 @@
 
 
 struct icmphdr {
-  unsigned char		type;
-  unsigned char		code;
-  unsigned short	checksum;
+  __u8		type;
+  __u8		code;
+  __u16		checksum;
   union {
 	struct {
-		unsigned short	id;
-		unsigned short	sequence;
+		__u16	id;
+		__u16	sequence;
 	} echo;
-	unsigned long gateway;
+	__u32	gateway;
   } un;
 };
 
diff -u --recursive --new-file v1.3.9/linux/include/linux/if_ppp.h linux/include/linux/if_ppp.h
--- v1.3.9/linux/include/linux/if_ppp.h	Tue Jun  6 11:22:11 1995
+++ linux/include/linux/if_ppp.h	Wed Jul 12 06:41:59 1995
@@ -95,17 +95,17 @@
  */
 
 struct ppp_lqp_packet_hdr {
-  unsigned long		LastOutLQRs;	/* Copied from PeerOutLQRs	 */
-  unsigned long		LastOutPackets; /* Copied from PeerOutPackets	 */
-  unsigned long		LastOutOctets;	/* Copied from PeerOutOctets	 */
-  unsigned long		PeerInLQRs;	/* Copied from SavedInLQRs	 */
-  unsigned long		PeerInPackets;	/* Copied from SavedInPackets	 */
-  unsigned long		PeerInDiscards; /* Copied from SavedInDiscards	 */
-  unsigned long		PeerInErrors;	/* Copied from SavedInErrors	 */
-  unsigned long		PeerInOctets;	/* Copied from SavedInOctets	 */
-  unsigned long		PeerOutLQRs;	/* Copied from OutLQRs, plus 1	 */
-  unsigned long		PeerOutPackets; /* Current ifOutUniPackets, + 1	 */
-  unsigned long		PeerOutOctets;	/* Current ifOutOctets + LQR	 */
+  __u32		LastOutLQRs;	/* Copied from PeerOutLQRs	 */
+  __u32		LastOutPackets; /* Copied from PeerOutPackets	 */
+  __u32		LastOutOctets;	/* Copied from PeerOutOctets	 */
+  __u32		PeerInLQRs;	/* Copied from SavedInLQRs	 */
+  __u32		PeerInPackets;	/* Copied from SavedInPackets	 */
+  __u32		PeerInDiscards; /* Copied from SavedInDiscards	 */
+  __u32		PeerInErrors;	/* Copied from SavedInErrors	 */
+  __u32		PeerInOctets;	/* Copied from SavedInOctets	 */
+  __u32		PeerOutLQRs;	/* Copied from OutLQRs, plus 1	 */
+  __u32		PeerOutPackets; /* Current ifOutUniPackets, + 1	 */
+  __u32		PeerOutOctets;	/* Current ifOutOctets + LQR	 */
   };
 
 /*
@@ -114,11 +114,11 @@
  */
 
 struct ppp_lqp_packet_trailer {
-  unsigned long		SaveInLQRs;	/* Current InLQRs on reception	 */
-  unsigned long		SaveInPackets;	/* Current ifInUniPackets	 */
-  unsigned long		SaveInDiscards; /* Current ifInDiscards		 */
-  unsigned long		SaveInErrors;	/* Current ifInErrors		 */
-  unsigned long		SaveInOctets;	/* Current ifInOctects		 */
+  __u32		SaveInLQRs;	/* Current InLQRs on reception	 */
+  __u32		SaveInPackets;	/* Current ifInUniPackets	 */
+  __u32		SaveInDiscards; /* Current ifInDiscards		 */
+  __u32		SaveInErrors;	/* Current ifInErrors		 */
+  __u32		SaveInOctets;	/* Current ifInOctects		 */
 };
 
 /*
@@ -128,7 +128,7 @@
  */
 
 struct ppp_lpq_packet {
-  unsigned long			magic;	/* current magic value		 */
+  __u32				magic;	/* current magic value		 */
   struct ppp_lqp_packet_hdr	hdr;	/* Header fields for structure	 */
   struct ppp_lqp_packet_trailer tail;	/* Trailer fields (not sent)	 */
 };
@@ -138,21 +138,21 @@
  */
 
 struct ppp_stats {
-  unsigned long		rbytes;		/* bytes received		 */
-  unsigned long		rcomp;		/* compressed packets received	 */
-  unsigned long		runcomp;	/* uncompressed packets received */
-  unsigned long		rothers;	/* non-ip frames received	 */
-  unsigned long		rerrors;	/* received errors		 */
-  unsigned long		roverrun;	/* "buffer overrun" counter	 */
-  unsigned long		tossed;		/* packets discarded		 */
-  unsigned long		runts;		/* frames too short to process	 */
-  unsigned long		rgiants;	/* frames too large to process	 */
-  unsigned long		sbytes;		/* bytes sent			 */
-  unsigned long		scomp;		/* compressed packets sent	 */
-  unsigned long		suncomp;	/* uncompressed packets sent	 */
-  unsigned long		sothers;	/* non-ip frames sent		 */
-  unsigned long		serrors;	/* transmitter errors		 */
-  unsigned long		sbusy;		/* "transmitter busy" counter	 */
+  __u32		rbytes;		/* bytes received		 */
+  __u32		rcomp;		/* compressed packets received	 */
+  __u32		runcomp;	/* uncompressed packets received */
+  __u32		rothers;	/* non-ip frames received	 */
+  __u32		rerrors;	/* received errors		 */
+  __u32		roverrun;	/* "buffer overrun" counter	 */
+  __u32		tossed;		/* packets discarded		 */
+  __u32		runts;		/* frames too short to process	 */
+  __u32		rgiants;	/* frames too large to process	 */
+  __u32		sbytes;		/* bytes sent			 */
+  __u32		scomp;		/* compressed packets sent	 */
+  __u32		suncomp;	/* uncompressed packets sent	 */
+  __u32		sothers;	/* non-ip frames sent		 */
+  __u32		serrors;	/* transmitter errors		 */
+  __u32		sbusy;		/* "transmitter busy" counter	 */
 };
 
 /*
@@ -172,17 +172,17 @@
   int			magic;		/* magic value for structure	*/
 
   /* Bitmapped flag fields. */
-  char			inuse;		/* are we allocated?		*/
   char			sending;	/* "channel busy" indicator	*/
   char			escape;		/* 0x20 if prev char was PPP_ESC*/
   char			toss;		/* toss this frame		*/
+  unsigned long		inuse;		/* are we allocated?		*/
 
   unsigned int		flags;		/* miscellany			*/
 
-  unsigned long		xmit_async_map[8]; /* 1 bit means that given control 
+  __u32			xmit_async_map[8]; /* 1 bit means that given control 
 					   character is quoted on output*/
 
-  unsigned long		recv_async_map; /* 1 bit means that given control 
+  __u32			recv_async_map; /* 1 bit means that given control 
 					   character is ignored on input*/
   int			mtu;		/* maximum xmit frame size	*/
   int			mru;		/* maximum receive frame size	*/
@@ -193,7 +193,7 @@
   struct tty_struct	*tty;		/* ptr to TTY structure		*/
   struct device		*dev;		/* easy for intr handling	*/
   struct slcompress	*slcomp;	/* for header compression	*/
-  unsigned long		last_xmit;	/* time of last transmission	*/
+  __u32			last_xmit;	/* time of last transmission	*/
 
   /* These are pointers to the malloc()ed frame buffers.
      These buffers are used while processing a packet.	If a packet
@@ -216,7 +216,7 @@
   unsigned char		*us_rbuff_end;	/* end of allocated space	*/
   unsigned char		*us_rbuff_head; /* head of waiting packets	*/
   unsigned char		*us_rbuff_tail; /* tail of waiting packets	*/
-  unsigned char		us_rbuff_lock;	/* lock: bit 0 head bit 1 tail	*/
+  unsigned long		us_rbuff_lock;	/* lock: bit 0 head bit 1 tail	*/
   int			inp_sig;	/* input ready signal for pgrp	*/
   int			inp_sig_pid;	/* process to get notified	*/
 
diff -u --recursive --new-file v1.3.9/linux/include/linux/in.h linux/include/linux/in.h
--- v1.3.9/linux/include/linux/in.h	Fri Jul  7 08:54:54 1995
+++ linux/include/linux/in.h	Thu Jul 13 07:44:23 1995
@@ -118,4 +118,12 @@
 
 #include <asm/byteorder.h> 
 
+/* Some random defines to make it easier in the kernel.. */
+#ifdef __KERNEL__
+
+#define LOOPBACK(x)	(((x) & htonl(0xff000000)) == htonl(0x7f000000))
+#define MULTICAST(x)	(((x) & htonl(0xf0000000)) == htonl(0xe0000000))
+
+#endif
+
 #endif	/* _LINUX_IN_H */
diff -u --recursive --new-file v1.3.9/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v1.3.9/linux/include/linux/netdevice.h	Fri Jul  7 08:54:54 1995
+++ linux/include/linux/netdevice.h	Thu Jul 13 13:05:10 1995
@@ -156,7 +156,7 @@
   int			  (*do_ioctl)(struct device *dev, struct ifreq *ifr, int cmd);
 #define HAVE_SET_CONFIG
   int			  (*set_config)(struct device *dev, struct ifmap *map);
-  int			  (*header_cache)(struct device *dev, struct sock *sk, unsigned long saddr, unsigned long daddr);  
+  void			  (*header_cache)(struct device *dev, struct sock *sk, unsigned long saddr, unsigned long daddr);
 };
 
 
diff -u --recursive --new-file v1.3.9/linux/include/linux/sched.h linux/include/linux/sched.h
--- v1.3.9/linux/include/linux/sched.h	Fri Jul  7 13:42:58 1995
+++ linux/include/linux/sched.h	Wed Jul 12 06:29:19 1995
@@ -147,7 +147,7 @@
 	unsigned long blocked;	/* bitmap of masked signals */
 	unsigned long flags;	/* per process flags, defined below */
 	int errno;
-	int debugreg[8];  /* Hardware debugging registers */
+	long debugreg[8];  /* Hardware debugging registers */
 	struct exec_domain *exec_domain;
 /* various fields */
 	struct linux_binfmt *binfmt;
diff -u --recursive --new-file v1.3.9/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v1.3.9/linux/include/linux/skbuff.h	Fri Jul  7 08:54:54 1995
+++ linux/include/linux/skbuff.h	Wed Jul 12 18:24:18 1995
@@ -90,8 +90,13 @@
   unsigned char 		*end;			/* End pointer					*/
 };
 
+#ifdef CONFIG_SKB_LARGE
+#define SK_WMEM_MAX	65535
+#define SK_RMEM_MAX	65535
+#else
 #define SK_WMEM_MAX	32767
 #define SK_RMEM_MAX	32767
+#endif
 
 #if CONFIG_SKB_CHECK
 #define SK_FREED_SKB	0x0DE2C0DE
diff -u --recursive --new-file v1.3.9/linux/include/linux/symtab_begin.h linux/include/linux/symtab_begin.h
--- v1.3.9/linux/include/linux/symtab_begin.h	Thu Jun 29 19:02:55 1995
+++ linux/include/linux/symtab_begin.h	Wed Jul 12 06:41:59 1995
@@ -1,19 +1,23 @@
+#include <linux/config.h>
 #include <linux/linkage.h>
-#ifdef CONFIG_MODVERSIONS /* CONFIG_MODVERSIONS */
-#undef _set_ver
-#undef X
-#ifndef __GENKSYMS__
-#ifdef MODULE
-#define _set_ver(sym,ver) \
+
+#ifdef CONFIG_MODVERSIONS
+# undef _set_ver
+# undef X
+
+# ifndef __GENKSYMS__
+#  ifdef MODULE
+#    define _set_ver(sym,ver) \
 	{ (void *) & sym ## _R ## ver, SYMBOL_NAME_STR(sym) "_R" #ver }
-#else /* MODULE */
-#define _set_ver(sym,ver) \
+#  else /* MODULE */
+#    define _set_ver(sym,ver) \
 	{ (void *) & sym, SYMBOL_NAME_STR(sym) "_R" #ver }
-#endif /* MODULE */
-#define X(a) a
-#endif /* __GENKSYMS__ */
+#  endif /* MODULE */
+#  define X(a) a
+# endif /* !__GENKSYMS__ */
 #else /* CONFIG_MODVERSIONS */
-#define X(sym) { (void *) & sym, SYMBOL_NAME_STR(sym)}
+# define X(sym) { (void *) & sym, SYMBOL_NAME_STR(sym)}
 #endif /* CONFIG_MODVERSIONS */
+
 #define EMPTY {0,0}
 	0, 0, 0, {
diff -u --recursive --new-file v1.3.9/linux/include/net/eth.h linux/include/net/eth.h
--- v1.3.9/linux/include/net/eth.h	Fri Jun 30 16:22:30 1995
+++ linux/include/net/eth.h	Wed Jul 12 18:24:18 1995
@@ -32,6 +32,6 @@
 extern void		eth_add_arp(unsigned long addr, struct sk_buff *skb,
 				    struct device *dev);
 extern unsigned short	eth_type_trans(struct sk_buff *skb, struct device *dev);
-extern int		eth_header_cache(struct device *dev, struct sock *sk, unsigned long saddr, unsigned long daddr);
+extern void		eth_header_cache(struct device *dev, struct sock *sk, unsigned long saddr, unsigned long daddr);
 
 #endif	/* _ETH_H */
diff -u --recursive --new-file v1.3.9/linux/include/net/head_explode.h linux/include/net/head_explode.h
--- v1.3.9/linux/include/net/head_explode.h	Tue Jun  6 11:22:17 1995
+++ linux/include/net/head_explode.h	Thu Jan  1 02:00:00 1970
@@ -1,140 +0,0 @@
-/*
- *	Header exploders. We inline those only appearing once.
- *
- *	We assume 8 bit bytes.
- *
- *	This is oriented to getting good code out of GCC. It may need
- *	tuning for other processors.
- *
- *	Note only IGMP uses this so far. Just as an experiment.
- */
- 
- 
-extern __inline__ unsigned char *exp_getu16(unsigned char *bp, unsigned short *u)
-{
-	*u=(*bp<<8)|bp[1];
-	return bp+2;
-}
-
-extern __inline__ unsigned char *exp_getn16(unsigned char *bp, unsigned short *u)
-{
-	unsigned char *tp=(unsigned char *)u;
-	*tp++=*bp++;
-	*tp++=*bp++;
-	return bp;
-}
-
-extern __inline__ unsigned char *imp_putu16(unsigned char *bp, unsigned short n)
-{
-	*bp=(n>>8);
-	bp[1]=n&0xFF;
-	return bp+2;
-}
-
-extern __inline__ unsigned char *imp_putn16(unsigned char *bp, unsigned short n)
-{
-	unsigned char *sp=(unsigned char *)&n;
-	*bp++=*sp++;
-	*bp++=*sp++;
-	return bp;
-}
-
-extern __inline__ unsigned char *exp_getu32(unsigned char *bp, unsigned long *u)
-{
-	*u=(bp[0]<<24)|(bp[1]<<16)|(bp[2]<<8)|bp[3];
-	return bp+4;
-}
-
-extern __inline__ unsigned char *exp_getn32(unsigned char *bp, unsigned long *u)
-{
-	unsigned char *tp=(unsigned char *)u;
-	*tp++=*bp++;
-	*tp++=*bp++;
-	*tp++=*bp++;
-	*tp++=*bp++;
-	return bp;
-}
-
-extern __inline__ unsigned char *imp_putu32(unsigned char *bp, unsigned long n)
-{
-	bp[0]=n>>24;
-	bp[1]=(n>>16)&0xFF;
-	bp[2]=(n>>8)&0xFF;
-	bp[3]=n&0xFF;
-	return bp+4;
-}
-
-extern __inline__ unsigned char *imp_putn32(unsigned char *bp, unsigned long n)
-{
-	unsigned char *sp=(unsigned char *)&n;
-	*bp++=*sp++;
-	*bp++=*sp++;
-	*bp++=*sp++;
-	*bp++=*sp++;
-	return bp;
-}
-
-#if 0
-
-extern __inline__ unsigned char *ip_explode(unsigned char *iph, struct ip_header *ip)
-{
-	ip->version=*iph>>4;		/* Avoid the shift. We do our equality checks shifted too */
-	ip->ihl=(*iph++)&0xF;		/* Length in long words */
-	ip->tos=*iph++;			/* Service type */
-	iph=exp_getu16(iph,&ip->tot_len);	/* Length of packet */
-	iph=exp_getu16(iph,&ip->id);		/* Packet identity */
-	iph=exp_getu16(iph,&ip->frag_off);	/* Fragment offset */
-	ip->ttl=*iph++;
-	ip->protocol=*iph++;
-	iph=exp_getn16(iph,&ip->check);
-	iph=exp_getn32(iph,&ip->saddr);
-	iph=exp_getn32(iph,&ip->daddr);
-	return iph;
-}
-
-extern __inline__ unsigned char *icmp_explode(unsigned char *icmph, struct icmp_header *icmp)
-{
-	icmp->type=*icmp++;
-	icmp->code=*icmp++;
-	icmph=exp_getn16(icmph,&icmp->checksum);
-	/* These two pairs are a union... expand both */
-	exp_getu32(icmph,&icmp->gateway);	
-	icmph=exp_getu16(icmph,&icmp->id);
-	icmph=exp_getu16(icmph,&icmp->sequence);
-	return icmph;
-}
-
-#endif
-
-extern __inline__ unsigned char *igmp_explode(unsigned char *igmph, struct igmp_header *igmp)
-{
-	igmp->type=*igmph++;
-	igmph++;	/* unused */
-	igmph=exp_getn16(igmph,&igmp->csum);
-	igmph=exp_getn32(igmph,&igmp->group);
-	return igmph;
-}
-
-#if 0
-extern __inline__ unsigned char *tcp_explode(unsigned char *tcph, struct tcp_header *tcp)
-{
-	tcph=exp_getu16(tcph,&tcp->source);
-	tcph=exp_getu16(tcph,&tcp->dest);
-	tcph=exp_getu32(tcph,&tcp->seq);
-	tcph=exp_getu32(tcph,&tcp->ack_seq);
-	tcph=exp_getu16(tcph,&tcp->u.bitmask);
-	tcph=exp_getu16(tcph,&tcp->window);
-	tcph=exp_getn16(tcph,&tcp->check);
-	tcph=exp_getu16(tcph,&tcp->urg_ptr);
-	return tcph;
-}
-
-extern __inline__ unsigned char *udp_explode(unsigned char *udph, struct udp_header *udp)
-{
-	udph=exp_getu16(tcph,&udp->source);
-	udph=exp_getu16(udph,&udp->dest);
-	udph=exp_getu16(udph,&udp->len);
-	udph=exp_getn16(udph,&udp->check);
-	return udph;
-}
-#endif
diff -u --recursive --new-file v1.3.9/linux/include/net/ip.h linux/include/net/ip.h
--- v1.3.9/linux/include/net/ip.h	Tue Jun  6 11:22:17 1995
+++ linux/include/net/ip.h	Thu Jul 13 07:44:23 1995
@@ -44,7 +44,6 @@
 extern void		ip_mc_dropsocket(struct sock *);
 extern void		ip_mc_dropdevice(struct device *dev);
 extern int		ip_mc_procinfo(char *, char **, off_t, int);
-#define MULTICAST(x)	(IN_MULTICAST(htonl(x)))
 #endif
  
 
@@ -89,7 +88,7 @@
 /*extern unsigned short	ip_compute_csum(unsigned char * buff, int len);*/
 extern int		ip_rcv(struct sk_buff *skb, struct device *dev,
 			       struct packet_type *pt);
-extern void		ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned long target_addr, int target_strict);			     
+extern int		ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned long target_addr, int target_strict);			     
 extern void		ip_send_check(struct iphdr *ip);
 extern int		ip_id_count;			  
 extern void		ip_queue_xmit(struct sock *sk,
diff -u --recursive --new-file v1.3.9/linux/include/net/tcp.h linux/include/net/tcp.h
--- v1.3.9/linux/include/net/tcp.h	Fri Jul  7 08:54:55 1995
+++ linux/include/net/tcp.h	Wed Jul 12 18:24:18 1995
@@ -24,7 +24,9 @@
 #define MAX_FIN_SIZE	40 + MAX_HEADER + 15
 #define MAX_ACK_SIZE	40 + MAX_HEADER + 15
 #define MAX_RESET_SIZE	40 + MAX_HEADER + 15
-#define MAX_WINDOW	16384
+#define MAX_WINDOW	32767		/* Never offer a window over 32767 without using
+					   window scaling (not yet supported). Some poor
+					   stacks do signed 16bit maths! */
 #define MIN_WINDOW	2048
 #define MAX_ACK_BACKLOG	2
 #define MIN_WRITE_SPACE	2048
diff -u --recursive --new-file v1.3.9/linux/mm/vmalloc.c linux/mm/vmalloc.c
--- v1.3.9/linux/mm/vmalloc.c	Tue Jun 27 14:11:47 1995
+++ linux/mm/vmalloc.c	Wed Jul 12 08:32:17 1995
@@ -167,6 +167,89 @@
 	return 0;
 }
 
+static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+	unsigned long offset)
+{
+	unsigned long end;
+
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	do {
+		if (!pte_none(*pte))
+			printk("remap_area_pte: page already exists\n");
+		*pte = mk_pte(offset, PAGE_KERNEL);
+		address += PAGE_SIZE;
+		offset += PAGE_SIZE;
+		pte++;
+	} while (address < end);
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
+	unsigned long offset)
+{
+	unsigned long end;
+
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	offset -= address;
+	do {
+		pte_t * pte = pte_alloc_kernel(pmd, address);
+		if (!pte)
+			return -ENOMEM;
+		remap_area_pte(pte, address, end - address, address + offset);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address < end);
+	return 0;
+}
+
+static int remap_area_pages(unsigned long address, unsigned long offset, unsigned long size)
+{
+	pgd_t * dir;
+	unsigned long end = address + size;
+
+	offset -= address;
+	dir = pgd_offset(&init_task, address);
+	while (address < end) {
+		pmd_t *pmd = pmd_alloc_kernel(dir, address);
+		if (!pmd)
+			return -ENOMEM;
+		if (remap_area_pmd(pmd, address, end - address, offset + address))
+			return -ENOMEM;
+		set_pgdir(address, *dir);
+		address = (address + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
+	}
+	invalidate();
+	return 0;
+}
+
+static struct vm_struct * get_vm_area(unsigned long size)
+{
+	void *addr;
+	struct vm_struct **p, *tmp, *area;
+
+	area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
+	if (!area)
+		return NULL;
+	addr = (void *) VMALLOC_START;
+	area->size = size + PAGE_SIZE;
+	area->next = NULL;
+	for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {
+		if (size + (unsigned long) addr < (unsigned long) tmp->addr)
+			break;
+		addr = (void *) (tmp->size + (unsigned long) tmp->addr);
+	}
+	area->addr = addr;
+	area->next = *p;
+	*p = area;
+	return area;
+}
+
 void vfree(void * addr)
 {
 	struct vm_struct **p, *tmp;
@@ -191,26 +274,44 @@
 void * vmalloc(unsigned long size)
 {
 	void * addr;
-	struct vm_struct **p, *tmp, *area;
+	struct vm_struct *area;
 
 	size = PAGE_ALIGN(size);
 	if (!size || size > high_memory)
 		return NULL;
-	area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
+	area = get_vm_area(size);
 	if (!area)
 		return NULL;
-	addr = (void *) VMALLOC_START;
-	area->size = size + PAGE_SIZE;
-	area->next = NULL;
-	for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {
-		if (size + (unsigned long) addr < (unsigned long) tmp->addr)
-			break;
-		addr = (void *) (tmp->size + (unsigned long) tmp->addr);
-	}
-	area->addr = addr;
-	area->next = *p;
-	*p = area;
+	addr = area->addr;
 	if (alloc_area_pages(VMALLOC_VMADDR(addr), size)) {
+		vfree(addr);
+		return NULL;
+	}
+	return addr;
+}
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ */
+void * vremap(unsigned long offset, unsigned long size)
+{
+	void * addr;
+	struct vm_struct * area;
+
+	if (offset < high_memory)
+		return NULL;
+	if (offset & ~PAGE_MASK)
+		return NULL;
+	size = PAGE_ALIGN(size);
+	if (!size || size > offset + size)
+		return NULL;
+	area = get_vm_area(size);
+	if (!area)
+		return NULL;
+	addr = area->addr;
+	if (remap_area_pages(VMALLOC_VMADDR(addr), offset, size)) {
 		vfree(addr);
 		return NULL;
 	}
diff -u --recursive --new-file v1.3.9/linux/net/Changes linux/net/Changes
--- v1.3.9/linux/net/Changes	Fri Jul  7 08:54:56 1995
+++ linux/net/Changes	Thu Jul 13 13:05:10 1995
@@ -53,39 +53,39 @@
 o	RTF_REJECT routing support			[TESTED]
 o	Fixed 0 length fragment bug			[TESTED]
 o	Fixed overlapping reasm bug			[TESTED]
-o	Newest AX.25 code from John Naylor		[IN]
-o	NetROM from John Naylor				[IN]
+o	Newest AX.25 code from John Naylor		[TESTED]
+o	NetROM from John Naylor				[TESTED]
 o	Routerless DDP fixes from Wesley		[TESTED]
 
 ------->>>>> ALPHA 005 <<<<<----------
 
-o	Several compile and bugfixes from Jakko		[IN]
+o	Several compile and bugfixes from Jakko		[TESTED]
 o	Connect fix from Matt Day (+ fix to fix)	[TESTED]
 o	RTT, memory leak and other netrom/ax.25 cures	
-			-- John Naylor			[IN]
-o	IP source route via broadcast now illegal	[IN]
+			-- John Naylor			[TESTED]
+o	IP source route via broadcast now illegal	[TESTED]
 
 ------->>>>> ALPHA 006 <<<<<----------
 
-o	Yet more NetROM/AX.25 improvements		[IN]
+o	Yet more NetROM/AX.25 improvements		[TESTED]
 		-- John Naylor
 o	Fixed a _stupid_ appletalk bug			[TESTED]
-o	Missing include					[IN]
+o	Missing include					[TESTED]
 		-- Lots of people
-o	Can drop all source routes			[IN]
+o	Can drop all source routes			[TESTED]
 o	Printing fixes for ip_fw			[IN]
-o	UDP checksum fix (Gerhard)			[IN]
+o	UDP checksum fix (Gerhard)			[TESTED]
 o	Newer 3c505 driver from Juha Laiho		[IN]
-o	Security fix to axassociate			[IN]
+o	Security fix to axassociate			[TESTED]
 o	Loopback driver debugged (fixes named)		[TESTED]
-o	SCC driver from Joerg Reuter			[IN]
-o	IP Firewall accounting zero bug			[IN]
+o	SCC driver from Joerg Reuter			[TESTED]
+o	IP Firewall accounting zero bug			[TESTED]
 
 ////////////////////////////1.3.0/////////////////////////// 
 
 
 o	Merged loadable firewall code			[NOT INCLUDED YET]
-o	New buffers used totally non optimally		[SEEMS OK]
+o	New buffers used totally non optimally		[TESTED]
 o	Fast ip_forwarding (needs changing)		[NOT INCLUDED YET]
 o	Fixed connection hang bug in new SWS code	[TESTED]
 o	Buffer management hack putting skbuff control
@@ -93,10 +93,10 @@
 	totally cache non-optimal			[TESTED]
 o	Faster checksum [Tom May]			[IN]
 o	Appletalk router fixes [Michael Callahan]	[IN]
-o	TCP state error fixes [Mark Tamsky]		[IN]
-o	Verify area fixes [Heiko Eissfeldt]		[IN]
+o	TCP state error fixes [Mark Tamsky]		[TESTED]
+o	Verify area fixes [Heiko Eissfeldt]		[TESTED]
 o	Routes use metric field	[John Naylor]		[IN]
-o	Major AX.25/NetROM fixes [John Nalor]		[IN]
+o	Major AX.25/NetROM fixes [John Nalor]		[TESTED]
 
 ------->>>>>  NET3 030  <<<<<----------
 
@@ -104,18 +104,47 @@
 		(less helpful than I'd have liked)
 o	Fixed variable length header support to really work	[TESTED]
 o	Mend appletalk/ipx partially			[IN]
-o	Start playing with input checksum & copy	[IN]
+o	Start playing with input checksum & copy	[TESTED]
 o	Fixed PPP and other oddments			[IN]
 o	Mended IPIP					[Might work ;)]
 
 ------->>>>>    1.3.7   <<<<<----------
 
+o	Checksum bug fixed				[TESTED]
+o	Lance driver panic cured			[BROKEN]
+o	DEC ALPHA stuff (Linus)				[ASK HIM NOT ME]
+o	Always try to keep output packet order
+	(eg for vat and BSD fast path tcp)		[TESTED]
+o	Copy the mac pointer in skb_clone		[TESTED]
+o	Fix tcpdump panic				[IN]
+o	Fix dev_alloc_skb NULL deref bug		[TESTED]
+o	Fix Security error in SIGURG stuff		[TESTED]
+o	Missing 15 byte slack on ip_loopback		[IN, still has mcast bugs left!]
+
+------->>>>>    1.3.8   <<<<<----------
+
+o	UDP snmp count fixed				[IN]
+o	IP snmp out count fixed				[IN]  (fragment still wrong)
+o	First bit of Dave Bonn's fast forwarding	[IN]
+o	Fix leaks and double free in firewalling	[IN]
+o	Fix memory scribble in ip_build_xmit		[TESTED]
+o	Do fast cases of ip_build_xmit first
+	slows fragmented I/O down, speeds up smaller
+	packets. UDP send ttcp can now touch 7.5Mbyte/sec
+	with nothing else going on. UDP recv is slower 8( [TESTED]
+o	Fixed and enabled ethernet header caches	[IN]
+o	Removed junk from igmp				[IN]
+o	Obscure UDP/copy&sum bug fix			[IN]
+o	Fixed multicast					[IN]
+o	TCP does rerouting for most cases		[NOT WORKING YET]
+
+------->>>>>    1.3.?  <<<<<----------
+
 o	Finish merging the bridge code
 o	Device locking
 o	SIOCSLEEPRT patch
 o	Options support in ip_build_xmit		[PENDING]
 o	Fast checksum/copy on outgoing TCP
-o	Explode/implode headers for alpha,mips etc.
 o	Fast dev_grab_next() transmit reload function
 	and dev_push_failed() ??
 o	Faster ip_forward				[PENDING]
@@ -127,6 +156,7 @@
 o	Clean up RAW AX.25 sockets.
 o	Finish 802.2 Class I code to be compliant to the oddities of 802.2
 o	Full variable length AX.25 support		[JSN doing]
+o	Tidy BPQ support
 
 0.2
 ---
@@ -139,6 +169,7 @@
 o	Loadable firewall extensions.
 o	Screend loadable firewall module
 o	LZ SLIP				[Done, resolving patent issues]
+o	AXIP
 
 0.3
 ---
@@ -198,7 +229,7 @@
 
 10.	Frame Relay/WAN/ISDN drivers [I'm working on the sonix EuroISDN board
 driver but thats for an internal project and its general release is still
-a maybe (so is finishing it ;))].
+a maybe (so is finishing it ;))][Someone is working on Frame Relay].
 
 11.	IP over SCSI.
 
diff -u --recursive --new-file v1.3.9/linux/net/core/datagram.c linux/net/core/datagram.c
--- v1.3.9/linux/net/core/datagram.c	Tue Jun  6 12:16:43 1995
+++ linux/net/core/datagram.c	Wed Jul 12 18:24:18 1995
@@ -72,8 +72,10 @@
 		if(sk->err)
 		{
 			release_sock(sk);
+			cli();
 			*err=-sk->err;
 			sk->err=0;
+			restore_flags(intflags);
 			return NULL;
 		}
 
@@ -163,8 +165,6 @@
 
 void skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
 {
-	/* We will know all about the fraglist options to allow >4K receives
-	   but not this release */
 	memcpy_tofs(to,skb->h.raw+offset,size);
 }
 
diff -u --recursive --new-file v1.3.9/linux/net/core/dev.c linux/net/core/dev.c
--- v1.3.9/linux/net/core/dev.c	Fri Jul  7 13:42:58 1995
+++ linux/net/core/dev.c	Wed Jul 12 18:24:18 1995
@@ -312,7 +312,6 @@
 void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
 {
 	unsigned long flags;
-	int nitcount;
 	struct packet_type *ptype;
 	int where = 0;		/* used to say if the packet should go	*/
 				/* at the front or the back of the	*/
@@ -367,7 +366,7 @@
 	restore_flags(flags);
 
 	/* copy outgoing packets to any sniffer packet handlers */
-	if(!where)
+	if(!where && dev_nit)
 	{
 		skb->stamp=xtime;
 		for (ptype = ptype_all; ptype!=NULL; ptype = ptype->next) 
@@ -384,7 +383,6 @@
 				skb2->h.raw = skb2->data + dev->hard_header_len;
 				skb2->mac.raw = skb2->data;
 				ptype->func(skb2, skb->dev, ptype);
-				nitcount--;
 			}
 		}
 	}
@@ -458,7 +456,7 @@
 	 */
 
 #ifdef CONFIG_NET_RUNONIRQ	/* Dont enable yet, needs some driver mods */
-	inet_bh();
+	net_bh();
 #else
 	mark_bh(NET_BH);
 #endif
@@ -616,7 +614,8 @@
 	/*
 	 *	Can we send anything now? We want to clear the
 	 *	decks for any more sends that get done as we
-	 *	process the input.
+	 *	process the input. This also minimises the
+	 *	latency on a transmit interrupt bh.
 	 */
 
 	dev_transmit();
@@ -676,7 +675,7 @@
 		
 		for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next) 
 		{
-			if ((ptype->type == type || ptype->type == htons(ETH_P_ALL)) && (!ptype->dev || ptype->dev==skb->dev))
+			if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev))
 			{
 				/*
 				 *	We already have a match queued. Deliver
diff -u --recursive --new-file v1.3.9/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v1.3.9/linux/net/ipv4/af_inet.c	Fri Jul  7 13:42:58 1995
+++ linux/net/ipv4/af_inet.c	Thu Jul 13 13:05:10 1995
@@ -40,6 +40,9 @@
  *					(eg for big web sites), but only if
  *					specifically application requested.
  *		Alan Cox	:	New buffering throughout IP. Used dumbly.
+ *		Alan Cox	:	New buffering now used smartly.
+ *		Alan Cox	:	BSD rather than common sense interpretation of
+ *					listen.
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -491,6 +494,8 @@
 	 * else does..
 	 * Now truncate to 128 not 5. 
 	 */
+	if ((unsigned) backlog == 0)	/* BSDism */
+		backlog = 1;
 	if ((unsigned) backlog > 128)
 		backlog = 128;
 	sk->max_ack_backlog = backlog;
diff -u --recursive --new-file v1.3.9/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v1.3.9/linux/net/ipv4/icmp.c	Fri Jul  7 08:54:57 1995
+++ linux/net/ipv4/icmp.c	Thu Jul 13 13:05:10 1995
@@ -33,7 +33,7 @@
  *		Peter Belding	:	Tightened up ICMP redirect handling
  *		Alan Cox	:	Tightened even more.
  *		Arnt Gulbrandsen:	Misplaced #endif with net redirect and break
- *
+ *		A.N.Kuznetsov	:	ICMP timestamp still used skb+1
  * 
  *
  *		This program is free software; you can redistribute it and/or
@@ -544,7 +544,7 @@
 	 *	Build ICMP_TIMESTAMP Response message. 
 	 */
 
-	icmphr = (struct icmphdr *) ((char *) (skb2 + 1) + offset);
+	icmphr = (struct icmphdr *) (skb2->data + offset);
 	memcpy((char *) icmphr, (char *) icmph, 12);
 	icmphr->type = ICMP_TIMESTAMPREPLY;
 	icmphr->code = icmphr->checksum = 0;
diff -u --recursive --new-file v1.3.9/linux/net/ipv4/igmp.c linux/net/ipv4/igmp.c
--- v1.3.9/linux/net/ipv4/igmp.c	Fri Jun 30 16:22:31 1995
+++ linux/net/ipv4/igmp.c	Thu Jul 13 13:05:10 1995
@@ -14,6 +14,7 @@
  *		Alan Cox	:	Added lots of __inline__ to optimise
  *					the memory usage of all the tiny little
  *					functions.
+ *		Alan Cox	:	Dumped the header building experiment.
  */
  
  
@@ -36,7 +37,6 @@
 #include <net/sock.h>
 #include <linux/igmp.h>
 #include <net/checksum.h>
-#include <net/head_explode.h>
 
 #ifdef CONFIG_IP_MULTICAST
 
@@ -84,7 +84,7 @@
 {
 	struct sk_buff *skb=alloc_skb(MAX_IGMP_SIZE, GFP_ATOMIC);
 	int tmp;
-	unsigned char *dp;
+	struct igmphdr *ih;
 	
 	if(skb==NULL)
 		return;
@@ -95,15 +95,12 @@
 		kfree_skb(skb, FREE_WRITE);
 		return;
 	}
-	dp=skb->data+tmp;
-	skb_put(skb,sizeof(struct igmphdr));
-	
-	*dp++=type;
-	*dp++=0;
-	skb->h.raw=dp;
-	dp=imp_putu16(dp,0);		/* checksum */
-	dp=imp_putn32(dp,address);	/* Address (already in net order) */
-	imp_putn16(skb->h.raw,ip_compute_csum(skb->data+tmp,sizeof(struct igmphdr)));	/* Checksum fill */
+	ih=(struct igmphdr *)skb_put(skb,sizeof(struct igmphdr));
+	ih->type=IGMP_HOST_MEMBERSHIP_REPORT;
+	ih->unused=0;
+	ih->csum=0;
+	ih->group=address;
+	ih->csum=ip_compute_csum((void *)ih,sizeof(struct igmphdr));	/* Checksum fill */
 	ip_queue_xmit(NULL,dev,skb,1);
 }
 
@@ -204,21 +201,20 @@
 	struct inet_protocol *protocol)
 {
 	/* This basically follows the spec line by line -- see RFC1112 */
-	struct igmp_header igh;
-	
-	/* Pull the IGMP header */
-	igmp_explode(skb->h.raw,&igh);
+	struct igmphdr *ih;
 	
+	ih=(struct igmphdr *)skb->data;
+		
 	if(skb->len <sizeof(struct igmphdr) || skb->ip_hdr->ttl!=1 || ip_compute_csum((void *)skb->h.raw,sizeof(struct igmphdr)))
 	{
 		kfree_skb(skb, FREE_READ);
 		return 0;
 	}
 	
-	if(igh.type==IGMP_HOST_MEMBERSHIP_QUERY && daddr==IGMP_ALL_HOSTS)
+	if(ih->type==IGMP_HOST_MEMBERSHIP_QUERY && daddr==IGMP_ALL_HOSTS)
 		igmp_heard_query(dev);
-	if(igh.type==IGMP_HOST_MEMBERSHIP_REPORT && daddr==igh.group)
-		igmp_heard_report(dev,igh.group);
+	if(ih->type==IGMP_HOST_MEMBERSHIP_REPORT && daddr==ih->group)
+		igmp_heard_report(dev,ih->group);
 	kfree_skb(skb, FREE_READ);
 	return 0;
 }
diff -u --recursive --new-file v1.3.9/linux/net/ipv4/ip.c linux/net/ipv4/ip.c
--- v1.3.9/linux/net/ipv4/ip.c	Tue Jul 11 10:03:00 1995
+++ linux/net/ipv4/ip.c	Thu Jul 13 13:09:52 1995
@@ -82,6 +82,9 @@
  *		Alan Cox	:	Stopped broadcast source route explosions.
  *		Alan Cox	:	Can disable source routing
  *		Takeshi Sone    :	Masquerading didn't work.
+ *	Dave Bonn,Alan Cox	:	Faster IP forwarding whenever possible.
+ *		Alan Cox	:	Memory leaks, tramples, misc debugging.
+ *		Alan Cox	:	Fixed multicast (by popular demand 8))
  *
  *  
  *
@@ -142,7 +145,6 @@
 extern void sort_send(struct sock *sk);
 
 #define min(a,b)	((a)<(b)?(a):(b))
-#define LOOPBACK(x)	(((x) & htonl(0xff000000)) == htonl(0x7f000000))
 
 /*
  *	SNMP management statistics
@@ -1007,7 +1009,7 @@
  *	Forward an IP datagram to its next destination.
  */
 
-void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned long target_addr, int target_strict)
+int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned long target_addr, int target_strict)
 {
 	struct device *dev2;	/* Output device */
 	struct iphdr *iph;	/* Our header */
@@ -1037,7 +1039,7 @@
 			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
 			/* fall thru */
 		default:
-			return;
+			return -1;
 		}
 	}
 #endif
@@ -1070,7 +1072,7 @@
 	{
 		/* Tell the sender its packet died... */
 		icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, dev);
-		return;
+		return -1;
 	}
 
 	/*
@@ -1086,7 +1088,7 @@
 		 *	ICMP is screened later.
 		 */
 		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);
-		return;
+		return -1;
 	}
 
 
@@ -1109,8 +1111,7 @@
 		if(target_strict)
 		{
 			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0, dev);
-			kfree_skb(skb, FREE_READ);
-			return;
+			return -1;
 		}
 	
 		/*
@@ -1125,7 +1126,7 @@
 			 *	Tell the sender its packet cannot be delivered...
 			 */
 			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
-			return;
+			return -1;
 		}
 		if (rt->rt_gateway != 0)
 			raddr = rt->rt_gateway;
@@ -1145,12 +1146,12 @@
 	 *	we calculated.
 	 */
 #ifndef CONFIG_IP_NO_ICMP_REDIRECT
-	if (dev == dev2 && !((iph->saddr^iph->daddr)&dev->pa_mask) && rt->rt_flags&RTF_MODIFIED)
+	if (dev == dev2 && !((iph->saddr^iph->daddr)&dev->pa_mask) && (rt->rt_flags&RTF_MODIFIED))
 		icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, raddr, dev);
 #endif		
 
 	/*
-	 * We now allocate a new buffer, and copy the datagram into it.
+	 * We now may allocate a new buffer, and copy the datagram into it.
 	 * If the indicated interface is up and running, kick it.
 	 */
 
@@ -1165,13 +1166,9 @@
 			ip_fw_masquerade(&skb, dev2);
 #endif
 
-		/*
-		 *	Current design decrees we copy the packet. For identical header
-		 *	lengths we could avoid it. The new skb code will let us push
-		 *	data so the problem goes away then.
-		 */
-
-		skb2 = alloc_skb(dev2->hard_header_len + skb->len + 15, GFP_ATOMIC);
+		if(skb_headroom(skb)<dev2->hard_header_len)
+			skb2 = alloc_skb(dev2->hard_header_len + skb->len + 15, GFP_ATOMIC);
+		else skb2=skb;
 		
 		/*
 		 *	This is rare and since IP is tolerant of network failures
@@ -1181,22 +1178,29 @@
 		if (skb2 == NULL)
 		{
 			NETDEBUG(printk("\nIP: No memory available for IP forward\n"));
-			return;
+			return -1;
 		}
 		
 
 		/* Now build the MAC header. */
 		(void) ip_send(skb2, raddr, skb->len, dev2, dev2->pa_addr);
 
-		ptr = skb_put(skb2,skb->len);
-		skb2->free = 1;
-		skb2->h.raw = ptr;
-
 		/*
-		 *	Copy the packet data into the new buffer.
+		 *	We have to copy the bytes over as the new header wouldn't fit
+		 *	the old buffer. This should be very rare.
 		 */
-		memcpy(ptr, skb->h.raw, skb->len);
+		 
+		if(skb2!=skb)
+		{
+			ptr = skb_put(skb2,skb->len);
+			skb2->free = 1;
+			skb2->h.raw = ptr;
 
+			/*
+			 *	Copy the packet data into the new buffer.
+			 */
+			memcpy(ptr, skb->h.raw, skb->len);
+		}
 
 		ip_statistics.IpForwDatagrams++;
 
@@ -1234,6 +1238,16 @@
 				dev_queue_xmit(skb2, dev2, SOPRI_NORMAL);
 		}
 	}
+	else
+		return -1;
+	
+	/*
+	 *	Tell the caller if their buffer is free.
+	 */
+	 
+	if(skb==skb2)
+		return 0;
+	return 1;
 }
 
 
@@ -1293,6 +1307,7 @@
 	/*
 	 *	Our transport medium may have padded the buffer out. Now we know it
 	 *	is IP we can trim to the true length of the frame.
+	 *	Note this now means skb->len holds ntohs(iph->tot_len).
 	 */
 
 	skb_trim(skb,ntohs(iph->tot_len));
@@ -1480,8 +1495,8 @@
 		if (ip_fw_demasquerade(skb)) 
 		{
 			struct iphdr *iph=skb->h.iph;
-			ip_forward(skb, dev, is_frag|4, iph->daddr, 0);
-			kfree_skb(skb, FREE_WRITE);
+			if(ip_forward(skb, dev, is_frag|4, iph->daddr, 0))
+				kfree_skb(skb, FREE_WRITE);
 			return(0);
 		}
 #endif
@@ -1620,15 +1635,7 @@
 	}
 
 	/*
-	 *	Do any IP forwarding required.  chk_addr() is expensive -- avoid it someday.
-	 *
-	 *	This is inefficient. While finding out if it is for us we could also compute
-	 *	the routing table entry. This is where the great unified cache theory comes
-	 *	in as and when someone implements it
-	 *
-	 *	For most hosts over 99% of packets match the first conditional
-	 *	and don't go via ip_chk_addr. Note: brd is set to IS_MYADDR at
-	 *	function entry.
+	 *	Do any IP forwarding required.
 	 */
 	
 	/*
@@ -1646,18 +1653,14 @@
 	 */
 
 #ifdef CONFIG_IP_FORWARD
-	ip_forward(skb, dev, is_frag, target_addr, target_strict);
+	if(ip_forward(skb, dev, is_frag, target_addr, target_strict))
+		kfree_skb(skb, FREE_WRITE);
 #else
 /*	printk("Machine %lx tried to use us as a forwarder to %lx but we have forwarding disabled!\n",
 			iph->saddr,iph->daddr);*/
 	ip_statistics.IpInAddrErrors++;
-#endif
-	/*
-	 *	The forwarder is inefficient and copies the packet. We
-	 *	free the original now.
-	 */
-
 	kfree_skb(skb, FREE_WRITE);
+#endif
 	return(0);
 }
 	
@@ -1694,7 +1697,7 @@
 	/*
 	 *	Add the rest of the data space.	
 	 */
-	newskb->ip_hdr=(struct iphdr *)skb_put(skb, len);
+	newskb->ip_hdr=(struct iphdr *)skb_put(newskb, len);
 	/*
 	 *	Copy the data
 	 */
@@ -1894,7 +1897,7 @@
 		}
 	}
 #endif
-	if((dev->flags&IFF_BROADCAST) && iph->daddr==dev->pa_brdaddr && !(dev->flags&IFF_LOOPBACK))
+	if((dev->flags&IFF_BROADCAST) && (iph->daddr==dev->pa_brdaddr||iph->daddr==0xFFFFFFFF) && !(dev->flags&IFF_LOOPBACK))
 		ip_loopback(dev,skb);
 		
 	if (dev->flags & IFF_UP)
@@ -1974,7 +1977,6 @@
 }
 
 
-#endif	
 /*
  *	Socket option code for IP. This is the end of the line after any TCP,UDP etc options on
  *	an IP socket.
@@ -1997,6 +1999,8 @@
 	return NULL;
 }
 
+#endif
+
 int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
 {
 	int val,err;
@@ -2343,6 +2347,8 @@
 	struct iphdr *iph;
 	int local=0;
 	struct device *dev;
+	
+	ip_statistics.IpOutRequests++;
 
 
 #ifdef CONFIG_INET_MULTICAST	
@@ -2420,7 +2426,70 @@
 	/*
 	 *	Now compute the buffer space we require
 	 */ 
-
+	 
+	/*
+	 *	Try the simple case first. This leaves broadcast, multicast, fragmented frames, and by
+	 *	choice RAW frames within 20 bytes of maximum size(rare) to the long path
+	 */
+	 
+	if(length+20 <= dev->mtu && !MULTICAST(daddr) && daddr!=0xFFFFFFFF && daddr!=dev->pa_brdaddr)
+	{	
+		int error;
+		struct sk_buff *skb=sock_alloc_send_skb(sk, length+20+15+dev->hard_header_len,0,&error);
+		if(skb==NULL)
+			return error;
+		skb->dev=dev;
+		skb->free=1;
+		skb->when=jiffies;
+		skb->sk=sk;
+		skb->arp=0;
+		skb->saddr=saddr;
+		length+=20;	/* We do this twice so the subtract once is quicker */
+		skb->raddr=(rt&&rt->rt_gateway)?rt->rt_gateway:daddr;
+		skb_reserve(skb,(dev->hard_header_len+15)&~15);
+		if(sk->ip_hcache_state>0)
+		{
+			memcpy(skb_push(skb,dev->hard_header_len),sk->ip_hcache_data,dev->hard_header_len);
+			skb->arp=1;
+		}
+		else if(dev->hard_header)
+		{
+			if(dev->hard_header(skb,dev,ETH_P_IP,NULL,NULL,0)>0)
+				skb->arp=1;
+		}
+		skb->ip_hdr=iph=(struct iphdr *)skb_put(skb,length);
+		if(type!=IPPROTO_RAW)
+		{
+			iph->version=4;
+			iph->ihl=5;
+			iph->tos=sk->ip_tos;
+			iph->tot_len = htons(length);
+			iph->id=htons(ip_id_count++);
+			iph->frag_off = 0;
+			iph->ttl=sk->ip_ttl;
+			iph->protocol=type;
+			iph->saddr=saddr;
+			iph->daddr=daddr;
+			iph->check=0;
+			iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+			getfrag(frag,saddr,(void *)(iph+1),0, length-20);
+		}
+		else
+			getfrag(frag,saddr,(void *)iph,0,length);
+#ifdef CONFIG_IP_ACCT
+		ip_fw_chk((void *)skb->data,dev,ip_acct_chain, IP_FW_F_ACCEPT,1);
+#endif		
+		if(dev->flags&IFF_UP)
+			dev_queue_xmit(skb,dev,sk->priority);
+		else
+		{
+			ip_statistics.IpOutDiscards++;
+			kfree_skb(skb, FREE_WRITE);
+		}
+		return 0;
+	}
+			
+			
 	fragheaderlen = dev->hard_header_len;
 	if(type != IPPROTO_RAW)
 		fragheaderlen += 20;
@@ -2512,7 +2581,7 @@
 		 
 		if(sk->ip_hcache_state>0)
 		{
-			memcpy(skb->data,sk->ip_hcache_data, dev->hard_header_len);
+			memcpy(skb_push(skb,dev->hard_header_len),sk->ip_hcache_data, dev->hard_header_len);
 			skb->arp=1;
 		}
 		else if (dev->hard_header)
@@ -2526,7 +2595,7 @@
 		 *	Find where to start putting bytes.
 		 */
 		 
-		iph = (struct iphdr *)data;
+		skb->ip_hdr = iph = (struct iphdr *)data;
 
 		/*
 		 *	Only write IP header onto non-raw packets 
@@ -2620,6 +2689,13 @@
 				kfree_skb(skb, FREE_READ);
 		}
 #endif
+		/*
+		 *	BSD loops broadcasts
+		 */
+		 
+		if((dev->flags&IFF_BROADCAST) && (daddr==0xFFFFFFFF || daddr==dev->pa_brdaddr) && !(dev->flags&IFF_LOOPBACK))
+			ip_loopback(dev,skb);
+
 		/*
 		 *	Now queue the bytes into the device.
 		 */
diff -u --recursive --new-file v1.3.9/linux/net/ipv4/ipip.c linux/net/ipv4/ipip.c
--- v1.3.9/linux/net/ipv4/ipip.c	Fri Jun 16 22:02:56 1995
+++ linux/net/ipv4/ipip.c	Wed Jul 12 18:24:18 1995
@@ -56,8 +56,8 @@
 #ifdef TUNNEL_DEBUG
 	printk("ipip_rcv: got a packet!\n");
 #endif
-	ip_forward(skb, dev, 0, daddr, 0);
-	kfree_skb(skb, FREE_READ);
+	if(ip_forward(skb, dev, 0, daddr, 0))
+		kfree_skb(skb, FREE_READ);
 	MOD_DEC_USE_COUNT;
 	return(0);
 }
diff -u --recursive --new-file v1.3.9/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v1.3.9/linux/net/ipv4/route.c	Fri Jun 30 16:22:32 1995
+++ linux/net/ipv4/route.c	Thu Jul 13 13:05:10 1995
@@ -29,6 +29,7 @@
  *		Alan Cox	:	RTF_REJECT support.
  *		Alan Cox	:	TCP irtt support.
  *		Jonathan Naylor	:	Added Metric support.
+ *	Miquel van Smoorenburg	:	BSD API fixes.
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -314,8 +315,7 @@
 	while ((r = *rp) != NULL) 
 	{
 		if (r->rt_dst != dst || 
-		    r->rt_mask != mask ||
-		    r->rt_metric < metric)
+		    r->rt_mask != mask)
 		{
 			rp = &r->rt_next;
 			continue;
@@ -381,6 +381,7 @@
 	char * devname;
 	struct device * dev = NULL;
 	unsigned long flags, daddr, mask, gw;
+	unsigned char metric;
 
 	/*
 	 *	If a device is specified find it.
@@ -406,13 +407,14 @@
 
 	/*
 	 *	Make local copies of the important bits
+	 *	We decrement the metric by one for BSD compatibility.
 	 */
 	 
 	flags = r->rt_flags;
 	daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr;
 	mask = ((struct sockaddr_in *) &r->rt_genmask)->sin_addr.s_addr;
 	gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
-
+	metric = r->rt_metric > 0 ? r->rt_metric - 1 : 0;
 
 	/*
 	 *	BSD emulation: Permits route add someroute gw one-of-my-addresses
@@ -475,7 +477,7 @@
 	 *	Add the route
 	 */
 	 
-	ip_rt_add(flags, daddr, mask, gw, dev, r->rt_mss, r->rt_window, r->rt_irtt, r->rt_metric);
+	ip_rt_add(flags, daddr, mask, gw, dev, r->rt_mss, r->rt_window, r->rt_irtt, metric);
 	return 0;
 }
 
diff -u --recursive --new-file v1.3.9/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v1.3.9/linux/net/ipv4/udp.c	Fri Jul  7 08:54:57 1995
+++ linux/net/ipv4/udp.c	Thu Jul 13 13:05:10 1995
@@ -45,6 +45,8 @@
  *	Arnt Gulbrandsen 	:	New udp_send and stuff
  *		Alan Cox	:	Cache last socket
  *		Alan Cox	:	Route cache
+ *		Alan Cox	:	Checksum precompute is bogus is some lame
+ *					software is padding its udp frames in IP!
  *
  *
  *		This program is free software; you can redistribute it and/or
@@ -273,7 +275,10 @@
 	else
 		a = ip_build_xmit(sk, udp_getfrag, &ufh, ulen, 
 			sin->sin_addr.s_addr, rt, IPPROTO_UDP);
-	return(a<0 ? a : len);
+	if(a<0)
+		return a;
+	udp_statistics.UdpOutDatagrams++;
+	return len;
 }
 
 
@@ -532,6 +537,9 @@
 	 */
 	 
 	ulen = ntohs(uh->len);
+	
+	if(ulen!=len)
+		skb->ip_summed=0;	/* Bogoid padded frame */
 
 	if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh)) 
 	{
