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