]> git.neil.brown.name Git - history.git/commitdiff
Import 1.1.95 1.1.95
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:56 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:56 +0000 (15:09 -0500)
97 files changed:
Makefile
arch/alpha/kernel/entry.S
arch/alpha/kernel/head.S
arch/alpha/kernel/irq.c
arch/alpha/kernel/process.c
arch/alpha/kernel/setup.c
arch/alpha/kernel/traps.c
arch/alpha/mm/fault.c
arch/i386/Makefile
arch/i386/kernel/irq.c
arch/i386/kernel/process.c
arch/i386/kernel/ptrace.c
arch/i386/kernel/setup.c
arch/sparc/config.in
arch/sparc/kernel/head.S
arch/sparc/kernel/probe.c
arch/sparc/kernel/process.c
arch/sparc/kernel/promops.c
arch/sparc/kernel/setup.c
arch/sparc/mm/fault.c
arch/sparc/mm/init.c
drivers/block/README.ide
drivers/block/floppy.c
drivers/block/ide.c
drivers/block/sonycd535.c
drivers/char/ChangeLog
drivers/char/console.c
drivers/char/cyclades.c
drivers/char/defkeymap.c
drivers/char/defkeymap.map
drivers/char/keyboard.c
drivers/char/serial.c
drivers/net/3c503.c
drivers/net/Makefile
drivers/net/arcnet.c
drivers/net/depca.c
drivers/net/ppp.c
drivers/net/slip.c
drivers/scsi/qlogic.c
drivers/scsi/seagate.c
drivers/scsi/sr.c
fs/ext2/balloc.c
fs/ext2/dir.c
fs/ext2/fsync.c
fs/ext2/ialloc.c
fs/ext2/inode.c
fs/ext2/super.c
fs/ext2/truncate.c
fs/msdos/inode.c
fs/proc/array.c
include/asm-alpha/pgtable.h
include/asm-alpha/processor.h
include/asm-alpha/system.h
include/asm-alpha/unistd.h
include/asm-i386/pgtable.h
include/asm-i386/processor.h
include/asm-i386/unistd.h
include/asm-sparc/asi.h
include/asm-sparc/asi4m.h [new file with mode: 0644]
include/asm-sparc/head.h
include/asm-sparc/page.h
include/asm-sparc/pgtable.h
include/asm-sparc/processor.h
include/asm-sparc/system.h
include/asm-sparc/unistd.h
include/linux/ext2_fs.h
include/linux/ext2_fs_i.h
include/linux/fs.h
include/linux/in.h
include/linux/ip_fw.h
include/linux/keyboard.h
include/linux/major.h
include/linux/mm.h
include/linux/msdos_fs.h
include/linux/net.h
include/linux/pci.h
include/linux/sched.h
include/linux/string.h
include/linux/tasks.h
include/linux/tty.h
init/main.c
ipc/shm.c
kernel/fork.c
kernel/ksyms.c
kernel/sys.c
lib/string.c
lib/vsprintf.c
mm/memory.c
mm/mmap.c
mm/swap.c
net/inet/af_inet.c
net/inet/arp.c
net/inet/dev_mcast.c
net/inet/ip.c
net/inet/ip_fw.c
net/inet/ipx.c
net/socket.c

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