]> git.neil.brown.name Git - history.git/commitdiff
Import 1.3.10 1.3.10
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:06 +0000 (15:10 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:06 +0000 (15:10 -0500)
57 files changed:
CREDITS
Makefile
Rules.make
arch/alpha/boot/bootloader.lds [new file with mode: 0644]
arch/alpha/kernel/Makefile
arch/alpha/kernel/entry.S
arch/alpha/kernel/process.c
arch/alpha/kernel/ptrace.c
arch/alpha/kernel/traps.c
arch/alpha/vmlinux.lds [new file with mode: 0644]
arch/i386/config.in
drivers/block/cdu31a.c
drivers/block/genhd.c
drivers/char/selection.c
drivers/char/tty_ioctl.c
drivers/net/README.arcnet
drivers/net/README.arcnet-jumpers
drivers/net/arcnet.c
drivers/net/eql.c
drivers/net/loopback.c
drivers/net/net_init.c
drivers/net/pi2.c
drivers/net/ppp.c
drivers/net/slip.c
drivers/net/tunnel.c
drivers/scsi/scsi_proc.c
drivers/sound/pas2_card.c
drivers/sound/sound_config.h
fs/ext2/namei.c
include/asm-alpha/a.out.h
include/asm-alpha/lca.h
include/asm-alpha/termios.h
include/asm-i386/termios.h
include/linux/etherdevice.h
include/linux/fdreg.h
include/linux/icmp.h
include/linux/if_ppp.h
include/linux/in.h
include/linux/netdevice.h
include/linux/sched.h
include/linux/skbuff.h
include/linux/symtab_begin.h
include/net/eth.h
include/net/head_explode.h [deleted file]
include/net/ip.h
include/net/tcp.h
mm/vmalloc.c
net/Changes
net/core/datagram.c
net/core/dev.c
net/ipv4/af_inet.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/ip.c
net/ipv4/ipip.c
net/ipv4/route.c
net/ipv4/udp.c

diff --git a/CREDITS b/CREDITS
index db66597c51eea5f813ae708df6a4d4b3ba42db24..a9af3c60427d58c7c9c6e54aa3c0c7f56c7c95b3 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -172,13 +172,20 @@ S: East Malvern, Victoria, 3145
 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
index 423cd2c21c45f2e5e21ba5438d9ae72bdff5d8f6..85a18c3ed0e8ee56a1ead675b92bc6eec015ade9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 9
+SUBLEVEL = 10
 
 ARCH = i386
 
@@ -283,3 +283,5 @@ else
 dummy:
 
 endif
+
+include Rules.make
index ed11861f491fccf4aec360f9e066946bf4d8876d..df4c868d5f13576d7c439d9976eeeee0a5423d29 100644 (file)
@@ -6,7 +6,7 @@
 # Common rules
 #
 .c.s:
-       $(CC) $(CFLAGS) -S $<
+       $(CC) $(CFLAGS) -S $< -o $@
 
 #
 # A rule to do nothing
diff --git a/arch/alpha/boot/bootloader.lds b/arch/alpha/boot/bootloader.lds
new file mode 100644 (file)
index 0000000..5f459ca
--- /dev/null
@@ -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 = .;
+}
index 4be7ca7fb71559129c8800366ba7310de60de535..d21f4d0fbe8b4f24a1a912519e27ba18a32d1436 100644 (file)
@@ -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
 
index 4c832fadc40bb56736c0ac6845452b01a431749d..a2606cb33c29b36508a5a31848ff65a786f1d9f8 100644 (file)
 
 .text
 .set noat
+#ifdef __linux__
+  .set singlegp
+#endif
 
 .align 3
 .globl entInt
@@ -191,9 +194,11 @@ kernel_fork:
        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 @@ do_switch_stack:
        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 @@ undo_switch_stack:
        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 @@ entUna:
 .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 @@ sys_fork:
 .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 @@ restore_all:
 .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 @@ sys_sigreturn:
        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 @@ sys_sigreturn:
 .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 @@ sys_call_table:
        .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
index 257f431a5662ed1b53a410ecd57c791dfbdf405f..b9d91d424d7945ab692c539784b35270744cf5a2 100644 (file)
@@ -123,7 +123,6 @@ void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
        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;
index e9458210a56498c49216bf87fd3037048efddac3..fd5e8487424358174f3846497faabea377faacce 100644 (file)
 #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
 
  * 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.
  * 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 @@ static int map_reg_to_offset[] = {
    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 @@ static unsigned long get_long(struct vm_area_struct * vma, unsigned long addr)
        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 @@ repeat:
  * 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 @@ static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigne
  * 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 @@ static int read_long(struct task_struct * tsk, unsigned long addr,
        } 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 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
        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 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
           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 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
                        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 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
                           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 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
                                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 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
                case PTRACE_KILL: {
                        child->state = TASK_RUNNING;
                        child->exit_code = SIGKILL;
-                       unset_singlestep(child);
+                       ptrace_cancel_bpt(child);
                        return 0;
                }
 
@@ -595,8 +716,11 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
                           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 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
                        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;
                }
 
index 7d4f146e9d92755f001c05202b95b198ab1b7e61..d1a3e3e2476ca0ce71eeec7150bb4fdf7d5f9bdf 100644 (file)
@@ -19,10 +19,10 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err)
        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 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err)
                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 @@ asmlinkage void do_entIF(unsigned long type, unsigned long a1, unsigned long a2,
        unsigned long a3, unsigned long a4, unsigned long a5,
        struct pt_regs regs)
 {
+       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 void do_entUna(void * va, unsigned long opcode, unsigned long reg,
 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 --git a/arch/alpha/vmlinux.lds b/arch/alpha/vmlinux.lds
new file mode 100644 (file)
index 0000000..bc6c6b6
--- /dev/null
@@ -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 = .;
+}
index c6fefb30ab26f0deef6e983767a7a02fcf3c3911..c7ee4638e0413c3a87b80d81e94df2c3c285001e 100644 (file)
@@ -60,6 +60,7 @@ bool 'IP: Reverse ARP' CONFIG_INET_RARP n
 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
index 06847baf14cc5829ee58ca5c37b661c759634dc1..e6d9d5a5f56797970e160ffc9113b0b9af6cf988 100644 (file)
 
 #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 @@ cdu31a_interrupt(int irq, struct pt_regs *regs)
 static inline void
 sony_sleep(void)
 {
+   unsigned long flags;
+
    if (irq_used <= 0)
    {
       current->state = TASK_INTERRUPTIBLE;
@@ -388,10 +390,11 @@ sony_sleep(void)
    }
    else /* Interrupt driven */
    {
+      save_flags(flags);
       cli();
       enable_interrupts();
       interruptible_sleep_on(&cdu31a_irq_wait);
-      sti();
+      restore_flags(flags);
    }
 }
 
@@ -516,6 +519,18 @@ set_drive_params(void)
    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 @@ do_sony_cd_cmd(unsigned char cmd,
    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 @@ do_sony_cd_cmd(unsigned char cmd,
    {
       recursive_call = 1;
    }
-   sti();
+   restore_flags(flags);
 
    num_retries = 0;
 retry_cd_operation:
@@ -1356,24 +1373,31 @@ do_cdu31a_request(void)
    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 @@ try_read_again:
             }
             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 @@ read_audio(struct cdrom_read_audio *ra,
    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 @@ read_audio(struct cdrom_read_audio *ra,
    }
    sony_inuse = 1;
    has_cd_task = current;
-   sti();
+   restore_flags(flags);
 
    if (!sony_spun_up)
    {
@@ -2167,8 +2194,20 @@ exit_read_audio:
 /*
  * 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 @@ scd_ioctl(struct inode *inode,
    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 @@ scd_ioctl(struct inode *inode,
        * 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 @@ scd_ioctl(struct inode *inode,
       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 @@ scd_ioctl(struct inode *inode,
          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 @@ scd_ioctl(struct inode *inode,
       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 @@ scd_ioctl(struct inode *inode,
          }
          
          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 @@ scd_ioctl(struct inode *inode,
          }
          
          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 @@ scd_ioctl(struct inode *inode,
             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 @@ scd_ioctl(struct inode *inode,
          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 @@ scd_ioctl(struct inode *inode,
       {
          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 @@ scd_ioctl(struct inode *inode,
             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)
          {
index 005c3a2462721fb00b4e1a7cbfb88e30f83ff113..00124b71fc4c3b3fdbe80777c4d2f86a188698ee 100644 (file)
@@ -114,7 +114,9 @@ static int msdos_partition(struct gendisk *hd, unsigned int dev, unsigned long f
        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 @@ read_mbr:
                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 @@ read_mbr:
         */
        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) */
index d9c341ebbba0c8f9db2da3e3dd981f3474b52f09..86ad6e9c512357967f4739f8382b28e7b25f6f1e 100644 (file)
@@ -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 @@ clear_selection(void) {
  * 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 sel_loadlut(const unsigned long arg)
        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;
 }
 
index bb029c97da2c53c3415e1136d631bc445a05fa06..f712fc28ffba8d2a568aa92f22efccd6d5a6ea24 100644 (file)
@@ -94,48 +94,13 @@ static void unset_locked_termios(struct termios *termios,
                        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 @@ static int set_termios(struct tty_struct * tty, unsigned long arg, int opt)
 
        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 @@ static int get_termio(struct tty_struct * tty, struct termio * termio)
        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 @@ static unsigned long inq_canon(struct tty_struct * tty)
        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 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
                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));
index faf3562a6e4dc6bedeaeaa725c7a4476e5ebe69f..9fa6967ee44413c0670944f5fd8a2709ea701214 100644 (file)
@@ -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 @@ Anyway, enough complaining.  Let's get started:
                        
 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 @@ How do I get it to work with...?
 --------------------------------
 
 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 @@ It works: what now?
 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 @@ with "arcnet:" and has shown up since the last reboot) in your mail.
 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?
index 5f38ac755fe34111dd4fafafa4279a3e7b0cedf9..09c4a696039dcec2b0ef5f5447994132c2e00145 100644 (file)
@@ -6,7 +6,7 @@ driver configuration help.
 
 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 @@ e-mail me to say so.
 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 @@ Cards Listed in this file:
        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 @@ Unclassified Stuff
   
   - 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 @@ Unclassified Stuff
      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 @@ Quick Briefing:
 ---------------
 
 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 @@ All ARCnet cards should have a total of four different settings:
 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 @@ PC500, PC600 (16-bit cards)
 
                DO NOT SET THIS TO 0 OR 255 (0xFF)!
 
+
 *****************************************************************************
 
 ** Standard Microsystems Corp (SMC) **
@@ -270,7 +282,7 @@ Setting the Node ID
 
 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 @@ Setting the I/O Base Address
 ----------------------------
 
 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 @@ of eight possible I/O Base addresses using the following table
    -------|--------
    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 @@ positions, determined by the offset, switches 7 and 8 of group S1.
    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 @@ parameters. These two jumpers are normally left open.
 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 @@ board activity:
  -------|-------------------   ---------|-------------------
   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 @@ Setting the Node ID
 
 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 @@ Setting the I/O Base Address
 ----------------------------
 
 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 @@ of 32 possible I/O Base addresses using the following table
    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,10 +646,119 @@ board activity:
  -------|-------------------   ---------|-------------------
   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 **
@@ -690,7 +811,7 @@ further information is welcome.]
 
 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 @@ DIP Switches:
 ------------------------
   - from Juergen Seifert <seifert@htwm.de>
 
+
 CNET TECHNOLOGY INC. (CNet) ARCNET 120A SERIES
 ==============================================
 
@@ -856,7 +978,7 @@ 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 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 @@ 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 following table
+of eight possible I/O Base addresses using the followig table
 
 
    Switch      | Hex I/O
@@ -904,7 +1026,7 @@ of eight possible I/O Base addresses using the following table
    ------------|--------
    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 @@ Switches 1-5 of switch block SW1 select the Memory Base 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  (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 @@ Switches 1-5 of switch block SW1 select the Memory Base address.
 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 @@ 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 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 @@ Setting the I/O Base Address
 ----------------------------
 
 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 @@ JP3 through JP13 using the following table:
     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 @@ NONAME 8-BIT ARCNET
 ===================
 
 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 @@ ET1, ET2    Extended Timeout Select
 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 @@ Setting the Node ID
 
 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 @@ Setting the I/O Base Address
 ----------------------------
 
 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 @@ positions, determined by the offset, switches 7 and 8 of group SW2.
    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 @@ Setting Interrupt Request Lines (IRQ)
 -------------------------------------
 
 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 @@ The manual of my 8-Bit NONAME ARCnet Card contains another description
 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 @@ Setting the Node ID
 
 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 @@ Setting the I/O Base Address
 ----------------------------
 
 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 @@ positions, determined by the offset, switches 4 and 5 of group SW1.
    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 @@ Setting the Timeouts
 
 *****************************************************************************
 
+** 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.
index c4bc8c37514b6de3598be1d6f044512638120391..60fee1f881c97712d01417608c3f2a15f29c4e5f 100644 (file)
@@ -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
         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 @@ static char *version =
 #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
+/* 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_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
+#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 @@ extern struct device *irq2dev_map[16];
 #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 @@ extern struct device *irq2dev_map[16];
 #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 @@ extern struct device *irq2dev_map[16];
         * 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 @@ union ArcPacket
         */
 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 @@ struct Outgoing
              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 @@ struct arcnet_local {
              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 @@ extern int arcnet_probe(struct device *dev);
 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 @@ void cleanup_module(void);
 
 #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                                                 *
+ *                                                                          *
+ ****************************************************************************/
 
-\f
 /* 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 @@ arcnet_probe(struct device *dev)
        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 @@ arcnet_probe(struct device *dev)
        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 @@ arcnet_probe(struct device *dev)
         }
         
        /* 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 @@ arcnet_probe(struct device *dev)
        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 @@ arcnet_probe(struct device *dev)
        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 arcnet_ioprobe(struct device *dev, short ioaddr)
        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 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
                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 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
                        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 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
        /* 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 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
         * 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 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
        {
                /* 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 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
        }
        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 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
 
 /* 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 @@ int arcnet_memprobe(struct device *dev,u_char *addr)
                
        dev->mem_start=0;
 
-#ifdef STRICT_MEM_DETECT /* probably better. */
        /* ARCnet memory byte 0 is TESTvalue */
        if (addr[0]!=TESTvalue)
        {
@@ -786,15 +821,6 @@ int arcnet_memprobe(struct device *dev,u_char *addr)
                                (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 @@ int arcnet_memprobe(struct device *dev,u_char *addr)
 
 #endif /* MODULE */
 
-\f
-/* 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 @@ arcnet_open(struct device *dev)
 }
 
 
-/* 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 @@ arcnet_close(struct device *dev)
 }
 
 
+
+/****************************************************************************
+ *                                                                          *
+ * 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 @@ arcnet_send_packet(struct sk_buff *skb, struct device *dev)
                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 @@ arcnet_send_packet(struct sk_buff *skb, struct device *dev)
                        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 @@ arcnet_send_packet(struct sk_buff *skb, struct device *dev)
           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 @@ arcnet_send_packet(struct sk_buff *skb, struct device *dev)
        
        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 @@ arcnet_send_packet(struct sk_buff *skb, struct device *dev)
         }
        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 @@ arcnet_send_packet(struct sk_buff *skb, struct device *dev)
                        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 @@ arcnet_send_packet(struct sk_buff *skb, struct device *dev)
                                        
                        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 @@ arcnet_send_packet(struct sk_buff *skb, struct device *dev)
                        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 @@ arcnet_send_packet(struct sk_buff *skb, struct device *dev)
                                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 @@ arcnet_send_packet(struct sk_buff *skb, struct device *dev)
        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 @@ static void arcnet_continue_tx(struct device *dev)
                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 @@ arcnet_prepare_tx(struct device *dev,struct ClientData *hdr,short length,
        
        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 @@ arcnet_prepare_tx(struct device *dev,struct ClientData *hdr,short length,
        {
                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 @@ arcnet_prepare_tx(struct device *dev,struct ClientData *hdr,short length,
                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 @@ arcnet_prepare_tx(struct device *dev,struct ClientData *hdr,short length,
                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 @@ arcnet_prepare_tx(struct device *dev,struct ClientData *hdr,short length,
         *  - 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 @@ arcnet_prepare_tx(struct device *dev,struct ClientData *hdr,short length,
                
                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
+#ifdef VERIFY_ACK
+       lp->outgoing.lastload_dest=hdr->daddr;
 #endif
        lp->txready=lp->txbuf;  /* packet is ready for sending */
-
-#if 0
-#ifdef IRQ_XMIT
-       if (inb(STATUS)&TXFREEflag) arcnet_go_tx(dev);
-#endif
-#endif
 }
 
+/* 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 @@ arcnet_go_tx(struct device *dev)
        /* 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
 }
 
-\f
-/* 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 @@ arcnet_inthandler(struct device *dev)
        
                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 @@ arcnet_inthandler(struct device *dev)
                 */
                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 @@ arcnet_inthandler(struct device *dev)
                        
                        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 @@ arcnet_inthandler(struct device *dev)
                                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 @@ arcnet_inthandler(struct device *dev)
                                        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 @@ arcnet_inthandler(struct device *dev)
                         * 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 @@ arcnet_inthandler(struct device *dev)
                                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 @@ arcnet_inthandler(struct device *dev)
                        
                        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 @@ arcnet_rx(struct device *dev,int recbuf)
        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 @@ arcnet_rx(struct device *dev,int recbuf)
                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 @@ arcnet_rx(struct device *dev,int recbuf)
                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 @@ arcnet_rx(struct device *dev,int recbuf)
                                
                                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 @@ arcnet_rx(struct device *dev,int recbuf)
                        {
                                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 @@ arcnet_rx(struct device *dev,int recbuf)
 
                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 @@ arcnet_rx(struct device *dev,int recbuf)
                                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 @@ arcnet_rx(struct device *dev,int recbuf)
                        
                        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 @@ arcnet_rx(struct device *dev,int recbuf)
                         */
                        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 @@ arcnet_rx(struct device *dev,int recbuf)
                         */                     
                        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 @@ arcnet_rx(struct device *dev,int recbuf)
                                /* 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 @@ arcnet_rx(struct device *dev,int recbuf)
                                        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);
+
+               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);
+
+        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++;
+}
 
-       /* 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);
-       }
 
-       /* requeue ourselves */
-       init_timer(&lp->timer);
-       lp->timer.expires=TIMERval;
-       add_timer(&lp->timer);
-}
-#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 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
 #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 @@ int arc_header(struct sk_buff *skb,struct device *dev,unsigned short type,
                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 @@ int arc_header(struct sk_buff *skb,struct device *dev,unsigned short type,
 #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 @@ int arc_header(struct sk_buff *skb,struct device *dev,unsigned short type,
 }
 
 
-/*
- *     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 @@ int arc_rebuild_header(void *buff,struct device *dev,unsigned long dst,
        }
 
        /*
-        *      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 @@ int arc_rebuild_header(void *buff,struct device *dev,unsigned long dst,
 #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 @@ unsigned short arc_type_trans(struct sk_buff *skb,struct device *dev)
        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 @@ init_module(void)
 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 @@ cleanup_module(void)
 \f
 /*
  * 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:
  */
 
index 80294cc0e2e7c8fc5111a6391626e4d3a45184bb..a2760478c8bcae724e9bb38746e7a64665dbcd9f 100644 (file)
@@ -249,7 +249,7 @@ eql_init(struct device *dev)
   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;
 
index 7f16317c3e70a13d809627ebbbd8604cea1005c6..00bf67d961185144c027a276bb578dd092da13e0 100644 (file)
@@ -139,7 +139,7 @@ int loopback_init(struct device *dev)
        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));
index d7fcb93633885d5447fdaaa60a6ab989115d3e96..7e3fd03213c045997436f475ce223d18e1e10904 100644 (file)
@@ -194,6 +194,7 @@ void ether_setup(struct device *dev)
        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 @@ void ether_setup(struct device *dev)
        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 @@ void tr_setup(struct device *dev)
        dev->pa_addr    = 0;
        dev->pa_brdaddr = 0;
        dev->pa_mask    = 0;
-       dev->pa_alen    = sizeof(unsigned long);
+       dev->pa_alen    = 4;
 }
 
 #endif
index 2d5511b98f0db04af8bd8a71f0af52fc69e64f34..aa7b641144cf5dec3ac5b3dde81d43015cfa15a5 100644 (file)
@@ -1442,7 +1442,7 @@ static int pi_probe(struct device *dev, int card_type)
     dev->pa_addr = 0;
     dev->pa_brdaddr = 0;
     dev->pa_mask = 0;
-    dev->pa_alen = sizeof(unsigned long);
+    dev->pa_alen = 4;
 
     return 0;
 }
index ca73b6a671f7a00ff4ba6ca051cbec07ad063c8b..0556270df477b71be08ebde9f83350d5bce0006c 100644 (file)
@@ -295,7 +295,7 @@ ppp_init(struct device *dev)
   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 @@ ppp_do_ip (struct ppp *ppp, unsigned short proto, unsigned char *c,
  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 @@ ppp_read(struct tty_struct *tty, struct file *file, unsigned char *buf, unsigned
 
   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 @@ ppp_stuff_char(struct ppp *ppp, unsigned char c)
 {
   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 @@ ppp_write(struct tty_struct *tty, struct file *file, unsigned char *buf, unsigne
   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 @@ ppp_ioctl(struct tty_struct *tty, struct file *file, unsigned int i,
     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 @@ ppp_ioctl(struct tty_struct *tty, struct file *file, unsigned int i,
       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 @@ ppp_ioctl(struct tty_struct *tty, struct file *file, unsigned int i,
     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 @@ ppp_ioctl(struct tty_struct *tty, struct file *file, unsigned int i,
     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 @@ ppp_xmit(struct sk_buff *skb, struct device *dev)
   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);
index 8e60cfb644f918fc6bbb89aaed95942d17a4ce9f..1540b17757bd1e6e038670933a31af6b5214c956 100644 (file)
@@ -1141,7 +1141,7 @@ slip_init(struct device *dev)
        dev->pa_addr            = 0;
        dev->pa_brdaddr         = 0;
        dev->pa_mask            = 0;
-       dev->pa_alen            = sizeof(unsigned long);
+       dev->pa_alen            = 4;
 
        return 0;
 }
index c8ec55f6e3947ef5ea48a83a417da76c09e52785..c880d644611ad6c35666db6e3b40699e2df6574d 100644 (file)
@@ -244,7 +244,9 @@ print_ip(iph);
 #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 @@ print_ip(iph);
 #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;
 }
index e82bccc4b9c65513ddd9f84a47433b8c779ffe51..4ccfb431d8a67eb4b05cc35942c0ada8574b80b8 100644 (file)
@@ -105,7 +105,6 @@ int generic_proc_info(char *buffer, char **start, off_t offset,
 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) {    
index 3b00688f6e8d036719b1c80801f3f875d130d0ac..5dcefcf9a825f21e7292682e6975df32dbd62b2a 100644 (file)
@@ -57,6 +57,7 @@ static char    *pas_model_names[] =
 /*
  * 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 @@ attach_pas_card (long mem_start, struct address_info *hw_config)
   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));
        }
index f70cf68a081b35f65a2ae5d8c2478142393f8475..d1d86bd1fe264661be7e6d57bce9a2a2546bd285 100644 (file)
 
 #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
index 776000cd76cc81bf1e756eb9e91fce224f2227a0..0b36a6a35ed50fe4b6bafa21e5c6f78ee647587f 100644 (file)
@@ -766,7 +766,7 @@ int ext2_symlink (struct inode * dir, const char * name, int len,
        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);
 
index 238e81c6c309a063c6470255fd71ce6dbc4cba78..a760b4b68d62a4cae835c381d894035f50b75ad5 100644 (file)
@@ -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 @@ struct exec
 #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__
 
index 82b5225749fe5311ac02895d1dc9590532f2570a..09805fee4cbc95681acc2686bc6cfcbc06ed9627 100644 (file)
@@ -304,8 +304,15 @@ extern void writew(unsigned short b, unsigned long addr);
 #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
 
index 003103b9aacb9a4e7ccd3a461d8865c13542f7c6..ae5c30e792da07ebd1a057cd8217d3383a1accfb 100644 (file)
@@ -333,4 +333,59 @@ struct termios {
 #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 */
index ee89e14a1a46dedeb4a06f5a3ed2a075e8060cbe..867b597f3a3c979f16174cd73f483a9f2649f3a1 100644 (file)
@@ -263,4 +263,37 @@ struct termios {
 #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 */
index 9707bfe429c3ee89ef45e4b7f7f2e0f65925d0ca..8319d3fe496ddb4b41e11261fe24393aece1d4ec 100644 (file)
@@ -34,8 +34,10 @@ extern int           eth_header(struct sk_buff *skb, struct device *dev,
 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
 
index 245647bbf11e53a4f41d358f1f6af5a0e00291f2..0a32499664a89a1da0a6b9c10cedc3d39b428ad1 100644 (file)
@@ -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 */
 
index ca1e8c6bf07a66ad25431f441bfcfb426f60d0af..b83513410b26ca03adf306157e1fb91a382de165 100644 (file)
 
 
 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;
 };
 
index 51389df7189bd41f066b11939e0700bdec2af889..f1eeb35ed7971b0d0c982c135e7e8972088902be 100644 (file)
  */
 
 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_hdr {
  */
 
 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_lqp_packet_trailer {
  */
 
 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_lpq_packet {
  */
 
 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 @@ struct ppp {
   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 ppp {
   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 @@ struct ppp {
   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      */
 
index ffc291cfcf694a45311e75dc2ec18bf5e578052d..db4496d8869d4348b58fd88ba103be2a6745f2e3 100644 (file)
@@ -118,4 +118,12 @@ struct sockaddr_in {
 
 #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 */
index c30e89129507cf32363f6bffb931ccfd495cd496..bc65dba9e67c778bc370f4bf8c1a5a653bd3952a 100644 (file)
@@ -156,7 +156,7 @@ struct device
   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);
 };
 
 
index 45cc578b767fa11852d5c83b88b1385ab3c11c56..bc27ec820a23a9f42c0e0aef22edb8c0a44520e3 100644 (file)
@@ -147,7 +147,7 @@ struct task_struct {
        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;
index 5a3c637c356081b15175249777734fb169172676..42621078247cbfded2a616083d47f809ef038a6b 100644 (file)
@@ -90,8 +90,13 @@ struct sk_buff {
   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
index bfeb0702608ef972641e2db1b2954698a44acc94..a30074c488157d8ede4e8fdc4a751ecf3941fdda 100644 (file)
@@ -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, {
index 99d37e9e78ad9946a3cbba0eb3191af40324fee7..f440d3a9070b371c3aaf063c5f10493b4ec4bcf3 100644 (file)
@@ -32,6 +32,6 @@ extern int            eth_rebuild_header(void *buff, struct device *dev,
 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 --git a/include/net/head_explode.h b/include/net/head_explode.h
deleted file mode 100644 (file)
index 90276fa..0000000
+++ /dev/null
@@ -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
index 6726e8a485e84c36cee259572fcb00f5da382df9..7ef99401b22e34507a0e961eb51014f54422ffcd 100644 (file)
@@ -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 int            ip_build_header(struct sk_buff *skb,
 /*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,
index 15e26800d8bcb859c55c5075fcdb554df79ef287..44609cd5977a0f825d2b1767a2087eaa2dbad67a 100644 (file)
@@ -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
index 8012774cc4c293e2587f1c162c09c89f3a9942a3..1155e981043e5352a5b2c3208548fca9265f5343 100644 (file)
@@ -167,6 +167,89 @@ static int alloc_area_pages(unsigned long address, unsigned long size)
        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,25 +274,15 @@ void vfree(void * addr)
 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;
@@ -217,6 +290,34 @@ void * vmalloc(unsigned long size)
        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;
+       }
+       return addr;
+}
+
 int vread(char *buf, char *addr, int count)
 {
        struct vm_struct **p, *tmp;
index 347d5fd6c24ebce3c7032c9eced0a7b8f59f1c4c..9ae4131fad5fa82d980da0122c314316cacc1b58 100644 (file)
@@ -53,39 +53,39 @@ o   TCP irtt support                                [TESTED]
 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 @@ o   Buffer management hack putting skbuff control
        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 @@ o Long word align ethernet IP headers (64byte align for pentium) [TESTED]
                (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   AX.25 set protocol type
 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   PPP for Sonix ISDN.
 o      Loadable firewall extensions.
 o      Screend loadable firewall module
 o      LZ SLIP                         [Done, resolving patent issues]
+o      AXIP
 
 0.3
 ---
@@ -198,7 +229,7 @@ problem.
 
 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.
 
index ce08e543c34009fb47bc1815bdd65de2449a3fcb..3fa9a6ac43a2b6bcd1a78dda7378f58eca5be92c 100644 (file)
@@ -72,8 +72,10 @@ restart:
                if(sk->err)
                {
                        release_sock(sk);
+                       cli();
                        *err=-sk->err;
                        sk->err=0;
+                       restore_flags(intflags);
                        return NULL;
                }
 
@@ -163,8 +165,6 @@ void skb_free_datagram(struct sk_buff *skb)
 
 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);
 }
 
index d83e01a19ffa4440793f64fc9b76827621663cdf..d3fef83e0dfc940640478b415fca33076f71213a 100644 (file)
@@ -312,7 +312,6 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
 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 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
        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 @@ void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
                                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 @@ void netif_rx(struct sk_buff *skb)
         */
 
 #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 @@ void net_bh(void *tmp)
        /*
         *      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 @@ void net_bh(void *tmp)
                
                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
index e3f6256682b72cfd2559a1a2ff0fd40f029aaf4b..9972411688e459aab32303f66a20087b78e5412c 100644 (file)
@@ -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 @@ static int inet_listen(struct socket *sock, int backlog)
         * 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;
index f6ef72a5b661f460f07f24e5f412436564fad5cc..1301f4b585e675329b368b0c6b61840433fdae9e 100644 (file)
@@ -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 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, struct de
         *      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;
index a971ec56b7253034f0c0e9a1d6b63b87193cc50a..a92fe9afc2d57afa5f4a387544fb51e38d145986 100644 (file)
@@ -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 @@ static void igmp_send_report(struct device *dev, unsigned long address, int type
 {
        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 @@ static void igmp_send_report(struct device *dev, unsigned long address, int type
                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 @@ int igmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        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;
 }
index 2fa53ec72b2361320ad7e96e3f21f6b0236442d0..7c7eeb4130284d12f43a2331fca2db5c83e8e780 100644 (file)
@@ -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 int last_retran;
 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 @@ void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int i
  *     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 @@ void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned l
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
                        /* fall thru */
                default:
-                       return;
+                       return -1;
                }
        }
 #endif
@@ -1070,7 +1072,7 @@ void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned l
        {
                /* Tell the sender its packet died... */
                icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, dev);
-               return;
+               return -1;
        }
 
        /*
@@ -1086,7 +1088,7 @@ void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned l
                 *      ICMP is screened later.
                 */
                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);
-               return;
+               return -1;
        }
 
 
@@ -1109,8 +1111,7 @@ void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned l
                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 @@ void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned l
                         *      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 @@ void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned l
         *      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 @@ void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned l
                        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 @@ void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned l
                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 @@ void ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, unsigned l
                                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 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        /*
         *      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 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
                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 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        }
 
        /*
-        *      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 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
         */
 
 #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 @@ static void ip_loopback(struct device *old_dev, struct sk_buff *skb)
        /*
         *      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 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
                }
        }
 #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 @@ int ip_mc_procinfo(char *buffer, char **start, off_t offset, int length)
 }
 
 
-#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 @@ static struct device *ip_mc_find_devfor(unsigned long addr)
        return NULL;
 }
 
+#endif
+
 int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
 {
        int val,err;
@@ -2343,6 +2347,8 @@ int ip_build_xmit(struct sock *sk,
        struct iphdr *iph;
        int local=0;
        struct device *dev;
+       
+       ip_statistics.IpOutRequests++;
 
 
 #ifdef CONFIG_INET_MULTICAST   
@@ -2420,7 +2426,70 @@ int ip_build_xmit(struct sock *sk,
        /*
         *      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 @@ int ip_build_xmit(struct sock *sk,
                 
                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 @@ int ip_build_xmit(struct sock *sk,
                 *      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 @@ int ip_build_xmit(struct sock *sk,
                                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.
                 */
index 5b91410cc618cf2d5873da9438903762b18e80bd..f689a76d2df943e5b6ddaddeb526be62bb9f1b39 100644 (file)
@@ -56,8 +56,8 @@ int ipip_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
 #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);
 }
index 48b4c7f5cf153d34a280e2e4807e9f71f0f87297..16fe5002082c8ad1645de39b7ffa12ea7a4f2d6f 100644 (file)
@@ -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 @@ void ip_rt_add(short flags, unsigned long dst, unsigned long mask,
        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 @@ static int rt_new(struct rtentry *r)
        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 @@ static int rt_new(struct rtentry *r)
 
        /*
         *      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 @@ static int rt_new(struct rtentry *r)
         *      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;
 }
 
index 889ab43dea4b452a45d03e9989a53ce06735abc2..76382aa421132e1e472ae9f525160b6693705f27 100644 (file)
@@ -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 @@ static int udp_send(struct sock *sk, struct sockaddr_in *sin,
        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 @@ int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
         */
         
        ulen = ntohs(uh->len);
+       
+       if(ulen!=len)
+               skb->ip_summed=0;       /* Bogoid padded frame */
 
        if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh)) 
        {