]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.13pre2 2.3.13pre2
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:26:37 +0000 (15:26 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:26:37 +0000 (15:26 -0500)
102 files changed:
Documentation/Configure.help
arch/arm/kernel/entry-armo.S
arch/arm/kernel/entry-armv.S
arch/arm/kernel/fiq.c
arch/arm/kernel/process.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/signal.c
arch/arm/kernel/traps.c
arch/arm/lib/getconsdata.c
arch/arm/mm/fault-armv.c
arch/arm/mm/fault-common.c
arch/arm/mm/mm-rpc.c
arch/arm/mm/proc-arm6,7.S
arch/arm/mm/proc-sa110.S
arch/i386/kernel/apm.c
arch/i386/kernel/io_apic.c
arch/i386/kernel/process.c
arch/i386/kernel/smp.c
arch/i386/mm/fault.c
arch/i386/vmlinux.lds
arch/i386/vmlinux.lds.S
drivers/acorn/block/fd1772.c
drivers/acorn/char/mouse_rpc.c
drivers/acorn/net/ether3.c
drivers/acorn/scsi/acornscsi.c
drivers/acorn/scsi/fas216.c
drivers/acorn/scsi/fas216.h
drivers/block/Makefile
drivers/block/genhd.c
drivers/block/hd.c
drivers/block/rd.c
drivers/char/Config.in
drivers/char/Makefile
drivers/char/adbmouse.c
drivers/char/amigamouse.c
drivers/char/atarimouse.c
drivers/char/atixlmouse.c
drivers/char/busmouse.c
drivers/char/busmouse.h [new file with mode: 0644]
drivers/char/logibusmouse.c [new file with mode: 0644]
drivers/char/macmouse.c [new file with mode: 0644]
drivers/char/misc.c
drivers/char/msbusmouse.c
drivers/char/pc_keyb.c
drivers/net/eepro100.c
drivers/parport/Config.in
drivers/parport/Makefile
drivers/parport/ieee1284_ops.c
drivers/parport/parport_pc.c
drivers/usb/CREDITS
drivers/usb/Config.in
drivers/usb/README.acm [new file with mode: 0644]
drivers/usb/acm.c
drivers/usb/printer.c
drivers/usb/uhci.c
drivers/usb/usb.c
drivers/usb/usb.h
drivers/video/imsttfb.c
drivers/video/vgacon.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/binfmt_em86.c
fs/binfmt_misc.c
fs/binfmt_script.c
fs/exec.c
include/asm-alpha/parport.h [new file with mode: 0644]
include/asm-arm/arch-arc/ide.h
include/asm-arm/mmu_context.h
include/asm-arm/parport.h [new file with mode: 0644]
include/asm-arm/proc-armo/processor.h
include/asm-arm/proc-armv/domain.h [new file with mode: 0644]
include/asm-arm/proc-armv/pgtable.h
include/asm-arm/proc-armv/processor.h
include/asm-arm/proc-armv/uaccess.h
include/asm-arm/proc-fns.h
include/asm-arm/processor.h
include/asm-arm/resource.h
include/asm-arm/system.h
include/asm-i386/bugs.h
include/asm-i386/init.h
include/asm-i386/parport.h
include/asm-i386/unistd.h
include/asm-sparc64/parport.h
include/linux/binfmts.h
include/linux/blk.h
include/linux/busmouse.h [deleted file]
include/linux/ioport.h
include/linux/kernel.h
include/linux/logibusmouse.h [new file with mode: 0644]
include/linux/parport_pc.h
include/linux/personality.h
include/linux/proc_fs.h
init/main.c
ipc/shm.c
kernel/ksyms.c
kernel/panic.c
kernel/printk.c
kernel/resource.c
mm/memory.c
mm/vmscan.c
net/ethernet/eth.c
scripts/mkdep.c

index 276e5d74b52c452ba5ce0f05ea13f47c991fbc11..e8aaa312d80d4b1b071bd98c719ed809bdcb0a32 100644 (file)
@@ -11938,10 +11938,15 @@ CONFIG_USB_AUDIO
   This driver will eventually handle audio devices, such 
   as USB speakers.
 
-USB Abstract Control Model support (Preliminary)
+USB Communications Device Class (ACM) support (Preliminary)
 CONFIG_USB_ACM
-  This driver allows for devices which support the Abstract Control Model,
-  including many USB-based modems, ISDN adapters, and network adapters.
+  This driver handles devices which support the Abstract Control Model,
+  a subtype of the USB Communications Device Class. This includes many
+  USB-based modems and ISDN adapters. Add special files with:
+  mknod /dev/ttyACM0 c 166 0 
+  mknod /dev/ttyACM1 c 166 1
+  mknod /dev/ttyACM2 c 166 2
+  mknod /dev/ttyACM3 c 166 3
 
 USB /proc filesystem entry support (Preliminary)
 CONFIG_USB_PROC
index 758163f07b8ba804b472badc276dae3b92769161..9aa1ee8411b8bc1be2faf2b26710c1b534b0b59a 100644 (file)
@@ -649,6 +649,15 @@ Ldata_ldcstc_pre:
 #endif
                b       SYMBOL_NAME(do_DataAbort)
 
+/*
+ * Register switch for older 26-bit only ARMs
+ */
+ENTRY(__switch_to)
+               stmfd   sp!, {r4 - r9, fp, lr}          @ Store most regs on stack
+               str     sp, [r0, #TSS_SAVE]             @ Save sp_SVC
+               ldr     sp, [r1, #TSS_SAVE]             @ Get saved sp_SVC
+               ldmfd   sp!, {r4 - r9, fp, pc}^         @ Load all regs saved previously
+
 /*
  *=============================================================================
  *             Low-level interface code
index ef9c8fea66c7d1507914389825d14e17ab5c5185..da32c1012e00915fbb0132769c8221119ebd0c7a 100644 (file)
@@ -455,7 +455,7 @@ __dabt_svc: sub     sp, sp, #S_FRAME_SIZE
                mov     r0, r2
                ldr     r2, .LCprocfns
                mov     lr, pc
-               ldr     pc, [r2, #8]                    @ call processor specific code
+               ldr     pc, [r2, #4]                    @ call processor specific code
                mov     r3, sp
                bl      SYMBOL_NAME(do_DataAbort)
                ldr     r0, [sp, #S_PSR]
@@ -542,7 +542,7 @@ __dabt_usr: sub     sp, sp, #S_FRAME_SIZE           @ Allocate frame size in one go
                msr     cpsr, r2
                ldr     r2, .LCprocfns
                mov     lr, pc
-               ldr     pc, [r2, #8]                    @ call processor specific code
+               ldr     pc, [r2, #4]                    @ call processor specific code
                mov     r3, sp
                adrsvc  al, lr, ret_from_sys_call
                b       SYMBOL_NAME(do_DataAbort)
@@ -655,6 +655,23 @@ __pabt_usr:        sub     sp, sp, #S_FRAME_SIZE           @ Allocate frame size in one go
                movs    pc, lr
 #endif
 
+/*
+ * Register switch for ARMv3 and ARMv4 processors
+ * r0 = previous, r1 = next, return previous.
+ * previous and next are guaranteed not to be the same.
+ */
+ENTRY(__switch_to)
+               stmfd   sp!, {r4 - r9, fp, lr}          @ Store most regs on stack
+               mrs     ip, cpsr
+               stmfd   sp!, {ip}                       @ Save cpsr_SVC
+               ldr     r2, [r1, #TSS_DOMAIN]
+               str     sp, [r0, #TSS_SAVE]             @ Save sp_SVC
+               ldr     sp, [r1, #TSS_SAVE]             @ Get saved sp_SVC
+               mcr     p15, 0, r2, c3, c0              @ Set domain register
+               ldmfd   sp!, {ip}
+               msr     spsr, ip                        @ Save tasks CPSR into SPSR for this return
+               ldmfd   sp!, {r4 - r9, fp, pc}^         @ Load all regs saved previously
+
                .section ".text.init",#alloc,#execinstr
 /*
  * Vector stubs.  NOTE that we only align 'vector_IRQ' to a cache line boundary,
index e3e87469fa5133dbc143cbcbb8f083af1a316f2c..5d8fa9bead9946692e6e17cff133e568665134d0 100644 (file)
@@ -53,15 +53,12 @@ static unsigned long no_fiq_insn;
 #ifdef CONFIG_CPU_32
 static inline void unprotect_page_0(void)
 {
-       __asm__ __volatile__("mcr       p15, 0, %0, c3, c0" :
-                       : "r" (DOMAIN_USER_MANAGER |
-                              DOMAIN_KERNEL_CLIENT |
-                              DOMAIN_IO_CLIENT));
+       modify_domain(DOMAIN_USER, DOMAIN_MANAGER);
 }
 
 static inline void protect_page_0(void)
 {
-       set_fs(get_fs());
+       modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
 }
 #else
 
index c456777669ea303182853d0b23889818ca14f7dd..71dd07af7fc14ca504cd4b3a959b25ce59076ce9 100644 (file)
@@ -207,9 +207,7 @@ void exit_thread(void)
 
 void flush_thread(void)
 {
-       int i;
-
-       memset(&current->tss.debug, 0, sizeof(current->tss.debug));
+       memset(&current->thread.debug, 0, sizeof(current->thread.debug));
        current->used_math = 0;
        current->flags &= ~PF_USEDFPU;
 }
@@ -231,7 +229,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
 
        save = ((struct context_save_struct *)(childregs)) - 1;
        init_thread_css(save);
-       p->tss.save = save;
+       p->thread.save = save;
 
        return 0;
 }
@@ -244,7 +242,7 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
        int fpvalid = 0;
 
        if (current->used_math)
-               memcpy (fp, &current->tss.fpstate.soft, sizeof (fp));
+               memcpy (fp, &current->thread.fpstate.soft, sizeof (fp));
 
        return fpvalid;
 }
@@ -262,11 +260,11 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
        dump->u_dsize = (current->mm->brk - current->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT;
        dump->u_ssize = 0;
 
-       dump->u_debugreg[0] = current->tss.debug.bp[0].address;
-       dump->u_debugreg[1] = current->tss.debug.bp[1].address;
-       dump->u_debugreg[2] = current->tss.debug.bp[0].insn;
-       dump->u_debugreg[3] = current->tss.debug.bp[1].insn;
-       dump->u_debugreg[4] = current->tss.debug.nsaved;
+       dump->u_debugreg[0] = current->thread.debug.bp[0].address;
+       dump->u_debugreg[1] = current->thread.debug.bp[1].address;
+       dump->u_debugreg[2] = current->thread.debug.bp[0].insn;
+       dump->u_debugreg[3] = current->thread.debug.bp[1].insn;
+       dump->u_debugreg[4] = current->thread.debug.nsaved;
 
        if (dump->start_stack < 0x04000000)
                dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT;
index 28874f2831ef57b610236b90af36535a9264d3a5..2efe76217a0c829fbc85be4e89778aba5376b5f6 100644 (file)
@@ -28,7 +28,7 @@
 
 /*
  * this routine will get a word off of the processes privileged stack.
- * the offset is how far from the base addr as stored in the TSS.
+ * the offset is how far from the base addr as stored in the THREAD.
  * this routine assumes that all the privileged stacks are in our
  * data space.
  */
@@ -43,7 +43,7 @@ static inline long get_stack_long(struct task_struct *task, int offset)
 
 /*
  * this routine will put a word on the processes privileged stack.
- * the offset is how far from the base addr as stored in the TSS.
+ * the offset is how far from the base addr as stored in the THREAD.
  * this routine assumes that all the privileged stacks are in our
  * data space.
  */
@@ -334,7 +334,7 @@ add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long
 
 int ptrace_set_bpt (struct task_struct *child)
 {
-       struct debug_info *dbg = &child->tss.debug;
+       struct debug_info *dbg = &child->thread.debug;
        unsigned long insn, pc, alt;
        int res;
 
@@ -363,7 +363,7 @@ int ptrace_set_bpt (struct task_struct *child)
  */
 int ptrace_cancel_bpt (struct task_struct *child)
 {
-       struct debug_info *dbg = &child->tss.debug;
+       struct debug_info *dbg = &child->thread.debug;
        unsigned long tmp;
        int i, nsaved = dbg->nsaved;
 
@@ -514,7 +514,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        ret = -EIO;
                        if ((unsigned long) data > _NSIG)
                                goto out;
-                       child->tss.debug.nsaved = -1;
+                       child->thread.debug.nsaved = -1;
                        child->flags &= ~PF_TRACESYS;
                        wake_up_process(child);
                        child->exit_code = data;
index fe8b5c502fb37fc3d9299ae1a53fcef668b054e6..7b2f430c14c5518d6d19dd0e8a82a9e61c4158f0 100644 (file)
@@ -273,8 +273,8 @@ setup_sigcontext(struct sigcontext *sc, /*struct _fpstate *fpstate,*/
        err |= __put_user (regs->ARM_cpsr, &sc->arm_cpsr);
 #endif
 
-       err |= __put_user (current->tss.trap_no, &sc->trap_no);
-       err |= __put_user (current->tss.error_code, &sc->error_code);
+       err |= __put_user (current->thread.trap_no, &sc->trap_no);
+       err |= __put_user (current->thread.error_code, &sc->error_code);
        err |= __put_user (mask, &sc->oldmask);
 
        return err;
index 50c1a003c60432419e0a6cf2bce4ab99cb1485de..8177054382b0bd47f0628417872c724edad8a6fe 100644 (file)
@@ -198,8 +198,8 @@ void bad_user_access_alignment(const void *ptr)
 {
        printk(KERN_ERR "bad user access alignment: ptr = %p, pc = %p\n", ptr, 
                __builtin_return_address(0));
-       current->tss.error_code = 0;
-       current->tss.trap_no = 11;
+       current->thread.error_code = 0;
+       current->thread.trap_no = 11;
        force_sig(SIGBUS, current);
 /*     die_if_kernel("Oops - bad user access alignment", regs, mode);*/
 }
@@ -210,8 +210,8 @@ asmlinkage void do_undefinstr(int address, struct pt_regs *regs, int mode)
        printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n",
                current->comm, current->pid, instruction_pointer(regs));
 #endif
-       current->tss.error_code = 0;
-       current->tss.trap_no = 6;
+       current->thread.error_code = 0;
+       current->thread.trap_no = 6;
        force_sig(SIGILL, current);
        die_if_kernel("Oops - undefined instruction", regs, mode);
 }
@@ -222,8 +222,8 @@ asmlinkage void do_excpt(int address, struct pt_regs *regs, int mode)
        printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n",
                current->comm, current->pid, instruction_pointer(regs));
 #endif
-       current->tss.error_code = 0;
-       current->tss.trap_no = 11;
+       current->thread.error_code = 0;
+       current->thread.trap_no = 11;
        force_sig(SIGBUS, current);
        die_if_kernel("Oops - address exception", regs, mode);
 }
@@ -367,7 +367,7 @@ asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs
        {
                pgd_t *pgd;
 
-               printk ("current->tss.memmap = %08lX\n", current->tss.memmap);
+               printk ("current->thread.memmap = %08lX\n", current->thread.memmap);
                pgd = pgd_offset(current->mm, addr);
                printk ("*pgd = %08lx", pgd_val (*pgd));
                if (!pgd_none (*pgd)) {
index 27f4ca2efc9b3d379c0075482c2ec403cc0f1c34..9c317b63988502897ab77c833433d0345ebd3994 100644 (file)
@@ -32,11 +32,13 @@ unsigned long TSK_USED_MATH = OFF_TSK(used_math);
 unsigned long MM = OFF_TSK(mm);
 unsigned long PGD = OFF_MM(pgd);
 
-unsigned long TSS_MEMMAP = OFF_TSK(tss.memmap);
-unsigned long TSS_SAVE = OFF_TSK(tss.save);
-unsigned long TSS_FPESAVE = OFF_TSK(tss.fpstate.soft.save);
+unsigned long TSS_SAVE = OFF_TSK(thread.save);
+unsigned long TSS_FPESAVE = OFF_TSK(thread.fpstate.soft.save);
 #ifdef CONFIG_CPU_26
-unsigned long TSS_MEMCMAP = OFF_TSK(tss.memcmap);
+unsigned long TSS_MEMMAP = OFF_TSK(thread.memmap);
+unsigned long TSS_MEMCMAP = OFF_TSK(thread.memcmap);
+#elif defined(CONFIG_CPU_32)
+unsigned long TSS_DOMAIN = OFF_TSK(thread.domain);
 #endif
 
 #ifdef _PAGE_PRESENT
index d57d4fb20fb71cbc4f0c0612562bea7754cfec80..95a354a68328f8be4d1588755f62ece5af465917 100644 (file)
 
 #include "fault-common.c"
 
+/*
+ * need to get a 16k page for level 1
+ */
 pgd_t *get_pgd_slow(void)
 {
-       /*
-        * need to get a 16k page for level 1
-        */
        pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL,2);
        pgd_t *init;
+       pmd_t *new_pmd;
 
        if (pgd) {
                init = pgd_offset(&init_mm, 0);
@@ -46,8 +47,32 @@ pgd_t *get_pgd_slow(void)
                memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
                        (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
                clean_cache_area(pgd, PTRS_PER_PGD * BYTES_PER_PTR);
+
+               /*
+                * On ARM, first page must always be allocated
+                */
+               if (!pmd_alloc(pgd, 0))
+                       goto nomem;
+               else {
+                       pmd_t *old_pmd = pmd_offset(init, 0);
+                       new_pmd = pmd_offset(pgd, 0);
+
+                       if (!pte_alloc(new_pmd, 0))
+                               goto nomem_pmd;
+                       else {
+                               pte_t *new_pte = pte_offset(new_pmd, 0);
+                               pte_t *old_pte = pte_offset(old_pmd, 0);
+
+                               set_pte (new_pte, *old_pte);
+                       }
+               }
        }
        return pgd;
+
+nomem_pmd:
+       pmd_free(new_pmd);
+nomem:
+       return NULL;
 }
 
 pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
index 219fb34a94e615db4c972ce91fb3e1d5a7bcb164..a536515af7e632d95269512a8017c041c53ebb7d 100644 (file)
@@ -85,7 +85,10 @@ kernel_page_fault(unsigned long addr, int mode, struct pt_regs *regs,
 
        printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n",
                reason, addr);
-       printk(KERN_ALERT "memmap = %08lX, pgd = %p\n", tsk->tss.memmap, mm->pgd);
+       if (!mm)
+               mm = &init_mm;
+
+       printk(KERN_ALERT "pgd = %p\n", mm->pgd);
        show_pte(mm, addr);
        die("Oops", regs, mode);
 
@@ -151,8 +154,8 @@ bad_area:
 
        /* User mode accesses just cause a SIGSEGV */
        if (mode & FAULT_CODE_USER) {
-               tsk->tss.error_code = mode;
-               tsk->tss.trap_no = 14;
+               tsk->thread.error_code = mode;
+               tsk->thread.trap_no = 14;
 #ifdef CONFIG_DEBUG_USER
                printk("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
                        tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
@@ -186,8 +189,8 @@ do_sigbus:
         * Send a sigbus, regardless of whether we were in kernel
         * or user mode.
         */
-       tsk->tss.error_code = mode;
-       tsk->tss.trap_no = 14;
+       tsk->thread.error_code = mode;
+       tsk->thread.trap_no = 14;
        force_sig(SIGBUS, tsk);
 
        /* Kernel mode? Handle exceptions or die */
index 1c755faaf6e8bcc78a66a97105014de1619e4c49..d95256ffb25b487398a98998901e5fcf92cea9d1 100644 (file)
@@ -85,8 +85,6 @@ init_dram_banks(struct param_struct *params))
 
        rambank[FIRST_VRAM_BANK].phys_offset = 0xd6000000;
        rambank[FIRST_VRAM_BANK].virt_addr   = 0xd8000000;
-
-       current->tss.memmap = __virt_to_phys((unsigned long)swapper_pg_dir);
 }
 
 #define MAPPING \
index d1f31e35d0aa0d9667b864d8c9aadaebf1b5ced3..1cb5140b3403e8de3dc42467ac96dcff9eb0b1a5 100644 (file)
@@ -52,41 +52,6 @@ _arm6_7_flush_tlb_area:
                blt     1b
                mov     pc, lr
 
-/*
- * Function: arm6_7_switch_to (struct task_struct *prev, struct task_struct *next)
- *
- * Params  : prev      Old task structure
- *        : next       New task structure for process to run
- *
- * Returns : prev
- *
- * Purpose : Perform a task switch, saving the old processes state, and restoring
- *          the new.
- *
- * Notes   : We don't fiddle with the FP registers here - we postpone this until
- *          the new task actually uses FP.  This way, we don't swap FP for tasks
- *          that do not require it.
- */
-_arm6_7_switch_to:
-               stmfd   sp!, {r4 - r9, fp, lr}          @ Store most regs on stack
-               mrs     ip, cpsr
-               stmfd   sp!, {ip}                       @ Save cpsr_SVC
-               str     sp, [r0, #TSS_SAVE]             @ Save sp_SVC
-               ldr     sp, [r1, #TSS_SAVE]             @ Get saved sp_SVC
-               ldr     r2, [r1, #TSK_ADDR_LIMIT]
-               ldr     r3, [r1, #TSS_MEMMAP]           @ Page table pointer
-               teq     r2, #0
-               moveq   r2, #DOM_KERNELDOMAIN
-               movne   r2, #DOM_USERDOMAIN
-               mcr     p15, 0, r2, c3, c0              @ Set domain reg
-               mov     r1, #0
-               mcr     p15, 0, r1, c7, c0, 0           @ flush cache
-               mcr     p15, 0, r3, c2, c0, 0           @ update page table ptr
-               mcr     p15, 0, r1, c5, c0, 0           @ flush TLBs
-               ldmfd   sp!, {ip}
-               msr     spsr, ip                        @ Save tasks CPSR into SPSR for this return
-               ldmfd   sp!, {r4 - r9, fp, pc}^         @ Load all regs saved previously
-
 /*
  * Function: arm6_7_data_abort ()
  *
@@ -340,6 +305,19 @@ _arm6_7_proc_init:
 _arm6_7_proc_fin:
                mov     pc, lr
 
+/*
+ * Function: arm6_7_set_pgd(unsigned long pgd_phys)
+ * Params  : pgd_phys  Physical address of page table
+ * Purpose : Perform a task switch, saving the old processes state, and restoring
+ *          the new.
+ */
+_arm6_7_set_pgd:
+               mov     r1, #0
+               mcr     p15, 0, r1, c7, c0, 0           @ flush cache
+               mcr     p15, 0, r0, c2, c0, 0           @ update page table ptr
+               mcr     p15, 0, r1, c5, c0, 0           @ flush TLBs
+               mov     pc, lr
+
 /*
  * Function: arm6_set_pmd ()
  *
@@ -421,19 +399,19 @@ _arm6_name:       .ascii  "arm6\0"
 
 ENTRY(arm6_processor_functions)
                .word   _arm6_name                      @  0
-               .word   _arm6_7_switch_to               @  4
-               .word   _arm6_data_abort                @  8
-               .word   _arm6_7_check_bugs              @ 12
-               .word   _arm6_7_proc_init               @ 16
-               .word   _arm6_7_proc_fin                @ 20
+               .word   _arm6_data_abort                @  4
+               .word   _arm6_7_check_bugs              @  8
+               .word   _arm6_7_proc_init               @ 12
+               .word   _arm6_7_proc_fin                @ 16
 
+               .word   _arm6_7_flush_cache             @ 20
                .word   _arm6_7_flush_cache             @ 24
                .word   _arm6_7_flush_cache             @ 28
-               .word   _arm6_7_flush_cache             @ 32
-               .word   _arm6_7_null                    @ 36
-               .word   _arm6_7_flush_cache             @ 40
-               .word   _arm6_7_flush_tlb_all           @ 44
-               .word   _arm6_7_flush_tlb_area          @ 48
+               .word   _arm6_7_null                    @ 32
+               .word   _arm6_7_flush_cache             @ 36
+               .word   _arm6_7_flush_tlb_all           @ 40
+               .word   _arm6_7_flush_tlb_area          @ 44
+               .word   _arm6_7_set_pgd                 @ 48
                .word   _arm6_set_pmd                   @ 52
                .word   _arm6_7_set_pte                 @ 56
                .word   _arm6_7_reset                   @ 60
@@ -451,19 +429,19 @@ _arm7_name:       .ascii  "arm7\0"
 
 ENTRY(arm7_processor_functions)
                .word   _arm7_name                      @  0
-               .word   _arm6_7_switch_to               @  4
-               .word   _arm7_data_abort                @  8
-               .word   _arm6_7_check_bugs              @ 12
-               .word   _arm6_7_proc_init               @ 16
-               .word   _arm6_7_proc_fin                @ 20
+               .word   _arm7_data_abort                @  4
+               .word   _arm6_7_check_bugs              @  8
+               .word   _arm6_7_proc_init               @ 12
+               .word   _arm6_7_proc_fin                @ 16
 
+               .word   _arm6_7_flush_cache             @ 20
                .word   _arm6_7_flush_cache             @ 24
                .word   _arm6_7_flush_cache             @ 28
-               .word   _arm6_7_flush_cache             @ 32
-               .word   _arm6_7_null                    @ 36
-               .word   _arm6_7_flush_cache             @ 40
-               .word   _arm6_7_flush_tlb_all           @ 44
-               .word   _arm6_7_flush_tlb_area          @ 48
+               .word   _arm6_7_null                    @ 32
+               .word   _arm6_7_flush_cache             @ 36
+               .word   _arm6_7_flush_tlb_all           @ 40
+               .word   _arm6_7_flush_tlb_area          @ 44
+               .word   _arm6_7_set_pgd                 @ 48
                .word   _arm7_set_pmd                   @ 52
                .word   _arm6_7_set_pte                 @ 56
                .word   _arm6_7_reset                   @ 60
index be9fad45e5ab756fd99196d93f4e51ac40893c69..b70e7ffa8958a7fee0136d24e8f86f4bdcbd622d 100644 (file)
@@ -207,40 +207,35 @@ _sa110_flush_icache_area:
                mcr     p15, 0, r0, c7, c10, 4          @ drain WB
                mcr     p15, 0, r0, c7, c5, 0           @ flush I cache
                mov     pc, lr
+
 /*
- * Function: sa110_switch_to (struct task_struct *prev, struct task_struct *next)
- * Params  : prev      Old task structure
- *        : next       New task structure for process to run
- * Returns : prev
- * Purpose : Perform a task switch, saving the old processes state, and restoring
- *          the new.
- * Notes   : We don't fiddle with the FP registers here - we postpone this until
- *          the new task actually uses FP.  This way, we don't swap FP for tasks
- *          that do not require it.
+ * Function: sa110_data_abort ()
+ * Params  : r0 = address of aborted instruction
+ * Purpose : obtain information about current aborted instruction
+ * Returns : r0 = address of abort
+ *        : r1 = FSR
+ *        : r2 != 0 if writing
  */
                .align  5
-_sa110_switch_to:
-               stmfd   sp!, {r4 - r9, fp, lr}          @ Store most regs on stack
-               mrs     ip, cpsr
-               stmfd   sp!, {ip}                       @ Save cpsr_SVC
-               ldr     r2, [r0, #TSS_MEMMAP]           @ Get old page tables
-               str     sp, [r0, #TSS_SAVE]             @ Save sp_SVC
-               ldr     sp, [r1, #TSS_SAVE]             @ Get saved sp_SVC
-               ldr     r5, [r1, #TSK_ADDR_LIMIT]
-               ldr     r4, [r1, #TSS_MEMMAP]           @ Page table pointer
-               teq     r5, #0
-               moveq   r5, #DOM_KERNELDOMAIN
-               movne   r5, #DOM_USERDOMAIN
-               mcr     p15, 0, r5, c3, c0              @ Set segment
+_sa110_data_abort:
+               ldr     r2, [r0]                        @ read instruction causing problem
+               mrc     p15, 0, r0, c6, c0, 0           @ get FAR
+               mov     r2, r2, lsr #19                 @ b1 = L
+               and     r3, r2, #0x69 << 2
+               and     r2, r2, #2
+               mrc     p15, 0, r1, c5, c0, 0           @ get FSR
+               and     r1, r1, #255
+               mov     pc, lr
+
+               .align  5
 /*
- * Flushing the cache is nightmarishly slow, so we take any excuse
- * to get out of it.  If the old page table is the same as the new,
- * this is a CLONE_VM relative of the old task and there is no need
- * to flush.  The overhead of the tests isn't even on the radar
- * compared to the cost of the flush itself.
+ * Function: sa110_set_pgd(unsigned long pgd_phys)
+ * Params  : pgd_phys  Physical address of page table
+ * Purpose : Perform a task switch, saving the old processes state, and restoring
+ *          the new.
  */
-               teq     r4, r2
-               beq     2f
+               .align  5
+_sa110_set_pgd:
                ldr     r3, =Lclean_switch
                ldr     r2, [r3]
                ands    r2, r2, #1
@@ -255,29 +250,8 @@ _sa110_switch_to:
                mov     r1, #0
                mcr     p15, 0, r1, c7, c5, 0           @ flush I cache
                mcr     p15, 0, r1, c7, c10, 4          @ drain WB
-               mcr     p15, 0, r4, c2, c0, 0           @ load page table pointer
+               mcr     p15, 0, r0, c2, c0, 0           @ load page table pointer
                mcr     p15, 0, r1, c8, c7, 0           @ flush TLBs
-2:             ldmfd   sp!, {ip}
-               msr     spsr, ip                        @ Save tasks CPSR into SPSR for this return
-               ldmfd   sp!, {r4 - r9, fp, pc}^         @ Load all regs saved previously
-
-/*
- * Function: sa110_data_abort ()
- * Params  : r0 = address of aborted instruction
- * Purpose : obtain information about current aborted instruction
- * Returns : r0 = address of abort
- *        : r1 = FSR
- *        : r2 != 0 if writing
- */
-               .align  5
-_sa110_data_abort:
-               ldr     r2, [r0]                        @ read instruction causing problem
-               mrc     p15, 0, r0, c6, c0, 0           @ get FAR
-               mov     r2, r2, lsr #19                 @ b1 = L
-               and     r3, r2, #0x69 << 2
-               and     r2, r2, #2
-               mrc     p15, 0, r1, c5, c0, 0           @ get FSR
-               and     r1, r1, #255
                mov     pc, lr
 
 /*
@@ -362,20 +336,20 @@ _sa110_name:      .ascii  "sa110\0"
 
 ENTRY(sa110_processor_functions)
                .word   _sa110_name                     @  0
-               .word   _sa110_switch_to                @  4
-               .word   _sa110_data_abort               @  8
-               .word   _sa110_check_bugs               @ 12
-               .word   _sa110_proc_init                @ 16
-               .word   _sa110_proc_fin                 @ 20
+               .word   _sa110_data_abort               @  4
+               .word   _sa110_check_bugs               @  8
+               .word   _sa110_proc_init                @ 12
+               .word   _sa110_proc_fin                 @ 16
 
-               .word   _sa110_flush_cache_all          @ 24
-               .word   _sa110_flush_cache_area         @ 28
-               .word   _sa110_flush_cache_entry        @ 32
-               .word   _sa110_clean_cache_area         @ 36
-               .word   _sa110_flush_ram_page           @ 40
-               .word   _sa110_flush_tlb_all            @ 44
-               .word   _sa110_flush_tlb_area           @ 48
+               .word   _sa110_flush_cache_all          @ 20
+               .word   _sa110_flush_cache_area         @ 24
+               .word   _sa110_flush_cache_entry        @ 28
+               .word   _sa110_clean_cache_area         @ 32
+               .word   _sa110_flush_ram_page           @ 36
+               .word   _sa110_flush_tlb_all            @ 40
+               .word   _sa110_flush_tlb_area           @ 44
 
+               .word   _sa110_set_pgd                  @ 48
                .word   _sa110_set_pmd                  @ 52
                .word   _sa110_set_pte                  @ 56
                .word   _sa110_reset                    @ 60
index d23127d6ebf2a7ec008745289644b63f0bcedeb9..e853719827d2f32b1c8f3ddc25c0c5235afa10a1 100644 (file)
@@ -540,6 +540,45 @@ static int apm_set_power_state(u_short state)
        return set_power_state(0x0001, state);
 }
 
+/*
+ * If no process has been interested in this
+ * CPU for some time, we want to wake up the
+ * power management thread - we probably want
+ * to conserve power.
+ */
+#define HARD_IDLE_TIMEOUT (HZ/3)
+
+/*
+ * This is the idle thing.
+ */
+void apm_cpu_idle(void)
+{
+       unsigned int start_idle;
+
+       start_idle = jiffies;
+       while (1) {
+               if (!current->need_resched) {
+                       if (jiffies - start_idle < HARD_IDLE_TIMEOUT) {
+                               if (!current_cpu_data.hlt_works_ok)
+                                       continue;
+                               if (hlt_counter)
+                                       continue;
+                               asm volatile("sti ; hlt" : : : "memory");
+                               continue;
+                       }
+
+                       /*
+                        * Ok, do some power management - we've been idle for too long
+                        */
+                       powermanagement_idle();
+               }
+
+               schedule();
+               check_pgt_cache();
+               start_idle = jiffies;
+       }
+}
+
 void apm_power_off(void)
 {
        /*
index cae25555adc0fc41674db149fdcfd0b31f906a4e..7e1b9236aae566ce3908ec61b6ba92b1aaea8070 100644 (file)
@@ -242,41 +242,43 @@ static void clear_IO_APIC (void)
 int pirq_entries [MAX_PIRQS];
 int pirqs_enabled;
 
-void __init ioapic_setup(char *str, int *ints)
+static void __init ioapic_setup(char *str, int *ints)
 {
        extern int skip_ioapic_setup;   /* defined in arch/i386/kernel/smp.c */
 
        skip_ioapic_setup = 1;
+       return 1;
 }
 
-void __init ioapic_pirq_setup(char *str, int *ints)
+__setup("noapic", ioapic_setup);
+
+static void __init ioapic_pirq_setup(char *str)
 {
        int i, max;
+       int ints[11];
+
+       get_options(str, ints);
 
        for (i = 0; i < MAX_PIRQS; i++)
                pirq_entries[i] = -1;
 
-       if (!ints) {
-               pirqs_enabled = 0;
-               printk("PIRQ redirection, trusting MP-BIOS.\n");
-
-       } else {
-               pirqs_enabled = 1;
-               printk("PIRQ redirection, working around broken MP-BIOS.\n");
-               max = MAX_PIRQS;
-               if (ints[0] < MAX_PIRQS)
-                       max = ints[0];
+       pirqs_enabled = 1;
+       printk("PIRQ redirection, working around broken MP-BIOS.\n");
+       max = MAX_PIRQS;
+       if (ints[0] < MAX_PIRQS)
+               max = ints[0];
 
-               for (i = 0; i < max; i++) {
-                       printk("... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
-                       /*
-                        * PIRQs are mapped upside down, usually.
-                        */
-                       pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
-               }
+       for (i = 0; i < max; i++) {
+               printk("... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
+               /*
+                * PIRQs are mapped upside down, usually.
+                */
+               pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
        }
 }
 
+__setup("pirq=", ioapic_pirq_setup);
+
 /*
  * Find the IRQ entry number of a certain pin.
  */
index afdc0cd54ad0aae4ca856543a31505dd84346a37..3fc5640ddb03fc21cc2d45fa36eaf8fa1c997b95 100644 (file)
@@ -72,13 +72,22 @@ void enable_hlt(void)
        hlt_counter--;
 }
 
-/*
- * If no process has been interested in this
- * CPU for some time, we want to wake up the
- * power management thread - we probably want
- * to conserve power.
- */
-#define HARD_IDLE_TIMEOUT (HZ/3)
+static void default_idle(void)
+{
+       while (1) {
+               while (!current->need_resched) {
+                       if (!current_cpu_data.hlt_works_ok)
+                               continue;
+                       if (hlt_counter)
+                               continue;
+                       asm volatile("sti ; hlt" : : : "memory");
+               }
+               schedule();
+               check_pgt_cache();
+       }
+}      
+
+void (*idle)(void) = default_idle;
 
 /*
  * The idle thread. There's no useful work to be
@@ -86,37 +95,13 @@ void enable_hlt(void)
  * low exit latency (ie sit in a loop waiting for
  * somebody to say that they'd like to reschedule)
  */
-int cpu_idle(void *unused)
+void cpu_idle(void)
 {
-       unsigned int start_idle;
-
        /* endless idle loop with no priority at all */
        init_idle();
        current->priority = 0;
        current->counter = -100;
-
-       start_idle = jiffies;
-       while (1) {
-               if (!current->need_resched) {
-                       if (jiffies - start_idle < HARD_IDLE_TIMEOUT) {
-                               if (!current_cpu_data.hlt_works_ok)
-                                       continue;
-                               if (hlt_counter)
-                                       continue;
-                               asm volatile("sti ; hlt" : : : "memory");
-                               continue;
-                       }
-
-                       /*
-                        * Ok, do some power management - we've been idle for too long
-                        */
-                       powermanagement_idle();
-               }
-
-               schedule();
-               check_pgt_cache();
-               start_idle = jiffies;
-       }
+       idle();
 }
 
 /*
@@ -129,7 +114,7 @@ static long no_idt[2] = {0, 0};
 static int reboot_mode = 0;
 static int reboot_thru_bios = 0;
 
-__initfunc(void reboot_setup(char *str, int *ints))
+static int __init reboot_setup(char *str)
 {
        while(1) {
                switch (*str) {
@@ -151,8 +136,10 @@ __initfunc(void reboot_setup(char *str, int *ints))
                else
                        break;
        }
+       return 1;
 }
 
+__setup("reboot=", reboot_setup);
 
 /* The following code and data reboots the machine by switching to real
    mode and jumping to the BIOS reset entry point, as if the CPU has
index 0402d822e327dde41e9ec2d5c5fee41d1c0938cf..adaf730dfc5308ba637ed671d029a1a842fc0303 100644 (file)
@@ -172,6 +172,26 @@ void __init smp_setup(char *str, int *ints)
                max_cpus = 0;
 }
 
+static int __init nosmp(char *str)
+{
+       max_cpus = 0;
+       return 1;
+}
+
+__setup("nosmp", nosmp);
+
+static int __init maxcpus(char *str)
+{
+       int ints[11];
+
+       get_options(str, ints);
+       if (ints[0] > 0)
+               max_cpus = ints[1];
+       return 1;
+}
+
+__setup("maxcpus", maxcpus);
+
 void ack_APIC_irq(void)
 {
        /* Clear the IPI */
@@ -875,7 +895,7 @@ void __init smp_callin(void)
 
 int cpucount = 0;
 
-extern int cpu_idle(void * unused);
+extern int cpu_idle(void);
 
 /*
  *     Activate a secondary processor.
@@ -891,7 +911,7 @@ int __init start_secondary(void *unused)
        smp_callin();
        while (!atomic_read(&smp_commenced))
                /* nothing */ ;
-       return cpu_idle(NULL);
+       return cpu_idle();
 }
 
 /*
index 7fb594f9acc5193beb1cb99355af35ddcea85e19..1f787900511e56c45fe4b28be822efd9d98b5ba9 100644 (file)
@@ -245,6 +245,7 @@ no_context:
        printk(" at virtual address %08lx\n",address);
        printk(" printing eip:\n");
        printk("%08lx\n", regs->eip);
+       asm("movl %%cr3,%0":"=r" (page));
        page = ((unsigned long *) __va(page))[address >> 22];
        printk(KERN_ALERT "*pde = %08lx\n", page);
        if (page & 1) {
index ecf90c27c44f30c4f6cb73522f028a9dca528609..088441e5f51b03cd5209824a8e432cfe94e3a8e3 100644 (file)
@@ -42,15 +42,21 @@ SECTIONS
   __init_begin = .;
   .text.init : { *(.text.init) }
   .data.init : { *(.data.init) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
   . = ALIGN(4096);
   __init_end = .;
 
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
   . = ALIGN(4096);
   .data.page_aligned : { *(.data.idt) }
 
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
   __bss_start = .;             /* BSS */
   .bss : {
index 347a058a3e28a614f5a1bf6008ac37c8d0552a32..9a9ff07e7f2a561c6856becc7feb3b9cd53ed697 100644 (file)
@@ -42,15 +42,21 @@ SECTIONS
   __init_begin = .;
   .text.init : { *(.text.init) }
   .data.init : { *(.data.init) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
   . = ALIGN(4096);
   __init_end = .;
 
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
   . = ALIGN(4096);
   .data.page_aligned : { *(.data.idt) }
 
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
   __bss_start = .;             /* BSS */
   .bss : {
index 8ee368ac95c54666883758199ccee6791fb5d586..59030ebd58dac95589a87239677ad0eaa54c8554 100644 (file)
  *     16/11/96 - Fiddled and frigged for 2.0.18
  *
  * DAG 30/01/99 - Started frobbing for 2.2.1
+ * DAG 20/06/99 - A little more frobbing:
+ *     Included include/asm/uaccess.h for get_user/put_user
  */
 
 #include <linux/sched.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/segment.h>
+#include <asm/uaccess.h>
+
 
 #define MAJOR_NR FLOPPY_MAJOR
 #define FLOPPY_DMA 0
@@ -1600,7 +1604,7 @@ static struct file_operations floppy_fops =
 };
 
 
-int floppy_init(void)
+int fd1772_init(void)
 {
        int i;
 
index 4eecd0cc1ed87303d807a4f0cc84ae7983930a57..fcaf57c5cdf4b65bcc3348e1f6b26ddaffbe83f8 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/io.h>
 #include <asm/iomd.h>
 
-#include "../../char/mouse.h"
+#include "../../char/busmouse.h"
 
 static short old_x, old_y, old_b;
 static int mousedev;
index ea6c13da5f6a678ea344f381c15cc5b8b9da785b..7026f311ef3a921776fd6687d856d8de837514a8 100644 (file)
@@ -100,9 +100,17 @@ typedef enum {
  * The SEEQ8005 doesn't like us writing to it's registers
  * too quickly.
  */
-#define ether3_outb(v,r)       { outb((v),(r)); udelay(1); }
-#define ether3_outw(v,r)       { outw((v),(r)); udelay(1); }
+static inline void ether3_outb(int v, const int r)
+{
+       outb(v, r);
+       udelay(1);
+}
 
+static inline void ether3_outw(int v, const int r)
+{
+       outw(v, r);
+       udelay(1);
+}
 #define ether3_inb(r)          ({ unsigned int __v = inb((r)); udelay(1); __v; })
 #define ether3_inw(r)          ({ unsigned int __v = inw((r)); udelay(1); __v; })
 
index 1e83bbead353e44bbb95811a2a6d6e7f6711af05..e8a136753d032fdfe9780bc73c89d15dc8988af6 100644 (file)
@@ -2982,7 +2982,7 @@ char *acornscsi_info(struct Scsi_Host *host)
 
     p = string;
     
-    p += sprintf(string, "%s at port %X irq %d v%d.%d.%d"
+    p += sprintf(string, "%s at port %08lX irq %d v%d.%d.%d"
 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
     " SYNC"
 #endif
index c89b74f1e53284553173fedd11d024323884348f..b54080ead9a09a3eeaef8796e0d280e837be66e4 100644 (file)
@@ -100,11 +100,16 @@ static int ptr;
 
 static void fas216_dumpstate(FAS216_Info *info)
 {
+       unsigned char is, stat, inst;
+
+       is   = inb(REG_IS(info));
+       stat = inb(REG_STAT(info));
+       inst = inb(REG_INST(info));
+       
        printk("FAS216: CTCL=%02X CTCM=%02X CMD=%02X STAT=%02X"
               " INST=%02X IS=%02X CFIS=%02X",
                inb(REG_CTCL(info)), inb(REG_CTCM(info)),
-               inb(REG_CMD(info)),  inb(REG_STAT(info)),
-               inb(REG_INST(info)), inb(REG_IS(info)),
+               inb(REG_CMD(info)),  stat, inst, is,
                inb(REG_CFIS(info)));
        printk(" CNTL1=%02X CNTL2=%02X CNTL3=%02X CTCH=%02X\n",
                inb(REG_CNTL1(info)), inb(REG_CNTL2(info)),
@@ -623,36 +628,18 @@ fas216_pio(FAS216_Info *info, fasdmadir_t direction)
 {
        unsigned int residual;
        char *ptr;
-       int correction = 0;
 
        fas216_checkmagic(info, "fas216_pio");
 
        residual = info->scsi.SCp.this_residual;
        ptr = info->scsi.SCp.ptr;
 
-       if (direction == DMA_OUT) {
-//             while (residual > 0) {
-//                     if ((inb(REG_CFIS(info)) & CFIS_CF) < 8) {
-                               outb(*ptr++, REG_FF(info));
-                               residual -= 1;
-//                     }
-//                     if (inb(REG_STAT(info)) & STAT_INT)
-//                             break;
-//             }
-//             correction = inb(REG_CFIS(info)) & CFIS_CF;
-       } else {
-//             while (residual > 0) {
-//                     if ((inb(REG_CFIS(info)) & CFIS_CF) != 0) {
-                               *ptr++ = inb(REG_FF(info));
-                               residual -= 1;
-//                     }
-//                     if (inb(REG_STAT(info)) & STAT_INT)
-//                             break;
-//             }
-       }
+       if (direction == DMA_OUT)
+               outb(*ptr++, REG_FF(info));
+       else
+               *ptr++ = inb(REG_FF(info));
 
-       ptr -= correction;
-       residual += correction;
+       residual -= 1;
 
        if (residual == 0) {
                if (info->scsi.SCp.buffers_residual) {
@@ -1035,26 +1022,59 @@ fas216_finish_reconnect(FAS216_Info *info)
 #endif
 }
 
-static unsigned char fas216_get_msg_byte(FAS216_Info *info)
+static int fas216_wait_cmd(FAS216_Info *info, int cmd)
 {
        int tout;
+       int stat;
 
-       outb(CMD_MSGACCEPTED, REG_CMD(info));
-       for (tout = 1000000; tout; tout --)
-               if (inb(REG_STAT(info)) & STAT_INT)
+       outb(cmd, REG_CMD(info));
+
+       for (tout = 1000; tout; tout -= 1) {
+               stat = inb(REG_STAT(info));
+               if (stat & STAT_INT)
                        break;
+               udelay(1);
+       }
+
+       return stat;
+}
+
+static int fas216_get_msg_byte(FAS216_Info *info)
+{
+       int stat;
+
+       stat = fas216_wait_cmd(info, CMD_MSGACCEPTED);
+
+       if ((stat & STAT_INT) == 0)
+               goto timedout;
+
+       if ((stat & STAT_BUSMASK) != STAT_MESGIN)
+               goto unexpected_phase_change;
 
        inb(REG_INST(info));
 
-       outb(CMD_TRANSFERINFO, REG_CMD(info));
+       stat = fas216_wait_cmd(info, CMD_TRANSFERINFO);
 
-       for (tout = 1000000; tout; tout --)
-               if (inb(REG_STAT(info)) & STAT_INT)
-                       break;
+       if ((stat & STAT_INT) == 0)
+               goto timedout;
+
+       if ((stat & STAT_BUSMASK) != STAT_MESGIN)
+               goto unexpected_phase_change;
 
        inb(REG_INST(info));
 
        return inb(REG_FF(info));
+
+timedout:
+       printk("scsi%d.%c: timed out waiting for message byte\n",
+               info->host->host_no, fas216_target(info));
+       return -1;
+
+unexpected_phase_change:
+       printk("scsi%d.%c: unexpected phase change: status = %02X\n",
+               info->host->host_no, fas216_target(info), stat);
+
+       return -2;
 }
 
 /* Function: void fas216_message(FAS216_Info *info)
@@ -1063,20 +1083,33 @@ static unsigned char fas216_get_msg_byte(FAS216_Info *info)
  */
 static void fas216_message(FAS216_Info *info)
 {
-       unsigned char message[16];
-       unsigned int msglen = 1;
+       unsigned char *message = info->scsi.message;
+       unsigned int msglen = 1, i;
+       int msgbyte = 0;
 
        fas216_checkmagic(info, "fas216_message");
 
        message[0] = inb(REG_FF(info));
 
        if (message[0] == EXTENDED_MESSAGE) {
-               message[1] = fas216_get_msg_byte(info);
+               msgbyte = fas216_get_msg_byte(info);
+
+               if (msgbyte >= 0) {
+                       message[1] = msgbyte;
 
-               for (msglen = 2; msglen < message[1] + 2; msglen++)
-                       message[msglen] = fas216_get_msg_byte(info);
+                       for (msglen = 2; msglen < message[1] + 2; msglen++) {
+                               msgbyte = fas216_get_msg_byte(info);
+
+                               if (msgbyte >= 0)
+                                       message[msglen] = msgbyte;
+                               else
+                                       break;
+                       }
+               }
        }
 
+       info->scsi.msglen = msglen;
+
 #ifdef DEBUG_MESSAGES
        {
                int i;
@@ -1098,12 +1131,18 @@ static void fas216_message(FAS216_Info *info)
 
        switch (message[0]) {
        case COMMAND_COMPLETE:
+               if (msglen != 1)
+                       goto unrecognised;
+
                printk(KERN_ERR "scsi%d.%c: command complete with no "
                        "status in MESSAGE_IN?\n",
                        info->host->host_no, fas216_target(info));
                break;
 
        case SAVE_POINTERS:
+               if (msglen != 1)
+                       goto unrecognised;
+
                /*
                 * Save current data pointer to SAVED data pointer
                 * SCSI II standard says that we must not acknowledge
@@ -1122,6 +1161,9 @@ static void fas216_message(FAS216_Info *info)
                break;
 
        case RESTORE_POINTERS:
+               if (msglen != 1)
+                       goto unrecognised;
+
                /*
                 * Restore current data pointer from SAVED data pointer
                 */
@@ -1134,10 +1176,16 @@ static void fas216_message(FAS216_Info *info)
                break;
 
        case DISCONNECT:
+               if (msglen != 1)
+                       goto unrecognised;
+
                info->scsi.phase = PHASE_MSGIN_DISCONNECT;
                break;
 
        case MESSAGE_REJECT:
+               if (msglen != 1)
+                       goto unrecognised;
+
                switch (fas216_get_last_msg(info, info->scsi.msgin_fifo)) {
                case EXTENDED_MESSAGE | EXTENDED_SDTR << 8:
                        fas216_handlesync(info, message);
@@ -1158,13 +1206,19 @@ static void fas216_message(FAS216_Info *info)
                break;
 
        case SIMPLE_QUEUE_TAG:
-               /* handled above */
+               if (msglen < 2)
+                       goto unrecognised;
+
+               /* handled above - print a warning since this is untested */
                printk("scsi%d.%c: reconnect queue tag %02X\n",
                        info->host->host_no, fas216_target(info),
                        message[1]);
                break;
 
        case EXTENDED_MESSAGE:
+               if (msglen < 3)
+                       goto unrecognised;
+
                switch (message[2]) {
                case EXTENDED_SDTR:     /* Sync transfer negociation request/reply */
                        fas216_handlesync(info, message);
@@ -1175,28 +1229,38 @@ static void fas216_message(FAS216_Info *info)
                        break;
 
                default:
-                       printk("scsi%d.%c: unrecognised extended message %02X, rejecting\n",
-                               info->host->host_no, fas216_target(info),
-                               message[2]);
-                       goto reject_message;
+                       goto unrecognised;
                }
                break;
 
        default:
-               printk("scsi%d.%c: unrecognised message %02X, rejecting\n",
-                       info->host->host_no, fas216_target(info),
-                       message[0]);
-               goto reject_message;
+               goto unrecognised;
        }
        outb(CMD_MSGACCEPTED, REG_CMD(info));
        return;
 
+unrecognised:
+       printk("scsi%d.%c: unrecognised message, rejecting\n",
+               info->host->host_no, fas216_target(info));
+       printk("scsi%d.%c: message was", info->host->host_no, fas216_target(info));
+       for (i = 0; i < msglen; i++)
+               printk("%s%02X", i & 31 ? " " : "\n  ", message[i]);
+       printk("\n");
+
 reject_message:
+       /*
+        * Something strange seems to be happening here -
+        * I can't use SETATN since the chip gives me an
+        * invalid command interrupt when I do.  Weird.
+        */
+outb(CMD_NOP, REG_CMD(info));
+fas216_dumpstate(info);
        outb(CMD_SETATN, REG_CMD(info));
-       outb(CMD_MSGACCEPTED, REG_CMD(info));
        msgqueue_flush(&info->scsi.msgs);
        msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
        info->scsi.phase = PHASE_MSGOUT_EXPECT;
+fas216_dumpstate(info);
+       outb(CMD_MSGACCEPTED, REG_CMD(info));
 }
 
 /* Function: void fas216_send_command(FAS216_Info *info)
@@ -1269,156 +1333,182 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
        printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n",
                info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase);
 #endif
-       switch (ssr & IS_BITS) {
-       case IS_MSGBYTESENT:            /* select with ATN and stop steps completed     */
-       case IS_COMPLETE:                       /* last action completed                */
-               outb(CMD_NOP, REG_CMD(info));
+
+       switch (info->scsi.phase) {
+       case PHASE_SELECTION:
+               if ((ssr & IS_BITS) != 1)
+                       goto bad_is;
+               break;
+
+       case PHASE_SELSTEPS:
+               switch (ssr & IS_BITS) {
+               case IS_SELARB:
+               case IS_MSGBYTESENT:
+                       goto bad_is;
+
+               case IS_NOTCOMMAND:
+               case IS_EARLYPHASE:
+                       if ((stat & STAT_BUSMASK) == STAT_MESGIN)
+                               break;
+                       goto bad_is;
+
+               case IS_COMPLETE:
+                       break;
+               }
+
+       default:
+               break;
+       }
+
+       outb(CMD_NOP, REG_CMD(info));
 
 #define STATE(st,ph) ((ph) << 3 | (st))
-               /* This table describes the legal SCSI state transitions,
-                * as described by the SCSI II spec.
+       /* This table describes the legal SCSI state transitions,
+        * as described by the SCSI II spec.
+        */
+       switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) {
+                                               /* Reselmsgin   -> Data In      */
+       case STATE(STAT_DATAIN, PHASE_RECONNECTED):
+               fas216_finish_reconnect(info);
+       case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In      */
+       case STATE(STAT_DATAIN, PHASE_DATAIN):  /* Data In      -> Data In      */
+       case STATE(STAT_DATAIN, PHASE_MSGOUT):  /* Message Out  -> Data In      */
+       case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command      -> Data In      */
+       case STATE(STAT_DATAIN, PHASE_MSGIN):   /* Message In   -> Data In      */
+               fas216_starttransfer(info, DMA_IN, 0);
+               return;
+
+       case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out     -> Data Out     */
+               fas216_starttransfer(info, DMA_OUT, 0);
+               return;
+
+                                               /* Reselmsgin   -> Data Out     */
+       case STATE(STAT_DATAOUT, PHASE_RECONNECTED):
+               fas216_finish_reconnect(info);
+       case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out     */
+       case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out  -> Data Out     */
+       case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command      -> Data Out     */
+       case STATE(STAT_DATAOUT, PHASE_MSGIN):  /* Message In   -> Data Out     */
+               fas216_starttransfer(info, DMA_OUT, 1);
+               return;
+
+                                               /* Reselmsgin   -> Status       */
+       case STATE(STAT_STATUS, PHASE_RECONNECTED):
+               fas216_finish_reconnect(info);
+               goto status;
+       case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out     -> Status       */
+       case STATE(STAT_STATUS, PHASE_DATAIN):  /* Data In      -> Status       */
+               fas216_stoptransfer(info);
+       case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status       */
+       case STATE(STAT_STATUS, PHASE_MSGOUT):  /* Message Out  -> Status       */
+       case STATE(STAT_STATUS, PHASE_COMMAND): /* Command      -> Status       */
+       case STATE(STAT_STATUS, PHASE_MSGIN):   /* Message In   -> Status       */
+       status:
+               outb(CMD_INITCMDCOMPLETE, REG_CMD(info));
+               info->scsi.phase = PHASE_STATUS;
+               return;
+
+       case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out     -> Message In   */
+       case STATE(STAT_MESGIN, PHASE_DATAIN):  /* Data In      -> Message In   */
+               fas216_stoptransfer(info);
+       case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In   */
+       case STATE(STAT_MESGIN, PHASE_MSGOUT):  /* Message Out  -> Message In   */
+               info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
+               outb(CMD_FLUSHFIFO, REG_CMD(info));
+               outb(CMD_TRANSFERINFO, REG_CMD(info));
+               info->scsi.phase = PHASE_MSGIN;
+               return;
+
+                                               /* Reselmsgin   -> Message In   */
+       case STATE(STAT_MESGIN, PHASE_RECONNECTED):
+       case STATE(STAT_MESGIN, PHASE_MSGIN):
+               info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
+               outb(CMD_TRANSFERINFO, REG_CMD(info));
+               return;
+
+                                               /* Reselmsgin   -> Command      */
+       case STATE(STAT_COMMAND, PHASE_RECONNECTED):
+               fas216_finish_reconnect(info);
+       case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out  -> Command      */
+       case STATE(STAT_COMMAND, PHASE_MSGIN):  /* Message In   -> Command      */
+               fas216_send_command(info);
+               info->scsi.phase = PHASE_COMMAND;
+               return;
+                                               /* Selection    -> Message Out  */
+       case STATE(STAT_MESGOUT, PHASE_SELECTION):
+               fas216_send_messageout(info, 1);
+               return;
+                                               /* Any          -> Message Out  */
+       case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT):
+               fas216_send_messageout(info, 0);
+               return;
+
+       /* Error recovery rules.
+        *   These either attempt to abort or retry the operation.
+        * TODO: we need more of these
+        */
+       case STATE(STAT_COMMAND, PHASE_COMMAND):/* Command      -> Command      */
+               /* error - we've sent out all the command bytes
+                * we have.
+                * NOTE: we need SAVE DATA POINTERS/RESTORE DATA POINTERS
+                * to include the command bytes sent for this to work
+                * correctly.
                 */
-               switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) {
-                                                       /* Reselmsgin   -> Data In      */
-               case STATE(STAT_DATAIN, PHASE_RECONNECTED):
-                       fas216_finish_reconnect(info);
-               case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In      */
-               case STATE(STAT_DATAIN, PHASE_DATAIN):  /* Data In      -> Data In      */
-               case STATE(STAT_DATAIN, PHASE_MSGOUT):  /* Message Out  -> Data In      */
-               case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command      -> Data In      */
-               case STATE(STAT_DATAIN, PHASE_MSGIN):   /* Message In   -> Data In      */
-                       fas216_starttransfer(info, DMA_IN, 0);
-                       return;
-
-               case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out     -> Data Out     */
-                       fas216_starttransfer(info, DMA_OUT, 0);
-                       return;
-
-                                                       /* Reselmsgin   -> Data Out     */
-               case STATE(STAT_DATAOUT, PHASE_RECONNECTED):
-                       fas216_finish_reconnect(info);
-               case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out     */
-               case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out  -> Data Out     */
-               case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command      -> Data Out     */
-               case STATE(STAT_DATAOUT, PHASE_MSGIN):  /* Message In   -> Data Out     */
-                       fas216_starttransfer(info, DMA_OUT, 1);
-                       return;
-
-                                                       /* Reselmsgin   -> Status       */
-               case STATE(STAT_STATUS, PHASE_RECONNECTED):
-                       fas216_finish_reconnect(info);
-                       goto status;
-               case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out     -> Status       */
-               case STATE(STAT_STATUS, PHASE_DATAIN):  /* Data In      -> Status       */
-                       fas216_stoptransfer(info);
-               case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status       */
-               case STATE(STAT_STATUS, PHASE_MSGOUT):  /* Message Out  -> Status       */
-               case STATE(STAT_STATUS, PHASE_COMMAND): /* Command      -> Status       */
-               case STATE(STAT_STATUS, PHASE_MSGIN):   /* Message In   -> Status       */
-               status:
-                       outb(CMD_INITCMDCOMPLETE, REG_CMD(info));
-                       info->scsi.phase = PHASE_STATUS;
-                       return;
-
-               case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out     -> Message In   */
-               case STATE(STAT_MESGIN, PHASE_DATAIN):  /* Data In      -> Message In   */
-                       fas216_stoptransfer(info);
-               case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In   */
-               case STATE(STAT_MESGIN, PHASE_MSGOUT):  /* Message Out  -> Message In   */
-                       info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
-                       outb(CMD_TRANSFERINFO, REG_CMD(info));
-                       info->scsi.phase = PHASE_MSGIN;
-                       return;
+               printk(KERN_ERR "scsi%d.%c: "
+                       "target trying to receive more command bytes\n",
+                       info->host->host_no, fas216_target(info));
+               outb(CMD_SETATN, REG_CMD(info));
+               outb(15, REG_STCL(info));
+               outb(0, REG_STCM(info));
+               outb(0, REG_STCH(info));
+               outb(CMD_PADBYTES | CMD_WITHDMA, REG_CMD(info));
+               msgqueue_flush(&info->scsi.msgs);
+               msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
+               info->scsi.phase = PHASE_MSGOUT_EXPECT;
+               return;
 
-                                                       /* Reselmsgin   -> Message In   */
-               case STATE(STAT_MESGIN, PHASE_RECONNECTED):
-               case STATE(STAT_MESGIN, PHASE_MSGIN):
-                       info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
-                       outb(CMD_TRANSFERINFO, REG_CMD(info));
-                       return;
-
-                                                       /* Reselmsgin   -> Command      */
-               case STATE(STAT_COMMAND, PHASE_RECONNECTED):
-                       fas216_finish_reconnect(info);
-               case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out  -> Command      */
-               case STATE(STAT_COMMAND, PHASE_MSGIN):  /* Message In   -> Command      */
-                       fas216_send_command(info);
-                       info->scsi.phase = PHASE_COMMAND;
-                       return;
-                                                       /* Selection    -> Message Out  */
-               case STATE(STAT_MESGOUT, PHASE_SELECTION):
-                       fas216_send_messageout(info, 1);
-                       return;
-                                                       /* Any          -> Message Out  */
-               case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT):
-                       fas216_send_messageout(info, 0);
-                       return;
-
-               /* Error recovery rules.
-                *   These either attempt to abort or retry the operation.
-                * TODO: we need more of these
+                                               /* Selection    -> Message Out  */
+       case STATE(STAT_MESGOUT, PHASE_SELSTEPS):
+       case STATE(STAT_MESGOUT, PHASE_MSGOUT): /* Message Out  -> Message Out  */
+               /* If we get another message out phase, this
+                * usually means some parity error occurred.
+                * Resend complete set of messages.  If we have
+                * more than 1 byte to send, we need to assert
+                * ATN again.
                 */
-               case STATE(STAT_COMMAND, PHASE_COMMAND):/* Command      -> Command      */
-                       /* error - we've sent out all the command bytes
-                        * we have.
-                        * NOTE: we need SAVE DATA POINTERS/RESTORE DATA POINTERS
-                        * to include the command bytes sent for this to work
-                        * correctly.
-                        */
-                       printk(KERN_ERR "scsi%d.%c: "
-                               "target trying to receive more command bytes\n",
-                               info->host->host_no, fas216_target(info));
+               if (msgqueue_msglength(&info->scsi.msgs) > 1)
                        outb(CMD_SETATN, REG_CMD(info));
-                       outb(15, REG_STCL(info));
-                       outb(0, REG_STCM(info));
-                       outb(0, REG_STCH(info));
-                       outb(CMD_PADBYTES | CMD_WITHDMA, REG_CMD(info));
-                       msgqueue_flush(&info->scsi.msgs);
-                       msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
-                       info->scsi.phase = PHASE_MSGOUT_EXPECT;
-                       return;
-
-                                                       /* Selection    -> Message Out  */
-               case STATE(STAT_MESGOUT, PHASE_SELSTEPS):
-               case STATE(STAT_MESGOUT, PHASE_MSGOUT): /* Message Out  -> Message Out  */
-                       /* If we get another message out phase, this
-                        * usually means some parity error occurred.
-                        * Resend complete set of messages.  If we have
-                        * more than 1 byte to send, we need to assert
-                        * ATN again.
-                        */
-                       if (msgqueue_msglength(&info->scsi.msgs) > 1)
-                               outb(CMD_SETATN, REG_CMD(info));
 
-                       fas216_send_messageout(info, 0);
-                       return;
-               }
-
-               if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) {
-                       printk(KERN_ERR "scsi%d.%c: disconnect message received, but bus service %s?\n",
-                               info->host->host_no, fas216_target(info),
-                               fas216_bus_phase(stat));
-                       msgqueue_flush(&info->scsi.msgs);
-                       outb(CMD_SETATN, REG_CMD(info));
-                       msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
-                       info->scsi.phase = PHASE_MSGOUT_EXPECT;
-                       info->scsi.aborting = 1;
-                       outb(CMD_TRANSFERINFO, REG_CMD(info));
-                       return;
-               }
-               printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n",
-                       info->host->host_no, fas216_target(info),
-                       fas216_bus_phase(stat),
-                       fas216_drv_phase(info));
-               print_debug_list();
+               fas216_send_messageout(info, 0);
                return;
+       }
 
-       default:
-               printk("scsi%d.%c: bus service at step %d?\n",
+       if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) {
+               printk(KERN_ERR "scsi%d.%c: disconnect message received, but bus service %s?\n",
                        info->host->host_no, fas216_target(info),
-                       ssr & IS_BITS);
-               print_debug_list();
+                       fas216_bus_phase(stat));
+               msgqueue_flush(&info->scsi.msgs);
+               outb(CMD_SETATN, REG_CMD(info));
+               msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
+               info->scsi.phase = PHASE_MSGOUT_EXPECT;
+               info->scsi.aborting = 1;
+               outb(CMD_TRANSFERINFO, REG_CMD(info));
+               return;
        }
+       printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n",
+               info->host->host_no, fas216_target(info),
+               fas216_bus_phase(stat),
+               fas216_drv_phase(info));
+       print_debug_list();
+       return;
+
+bad_is:
+       printk("scsi%d.%c: bus service at step %d?\n",
+               info->host->host_no, fas216_target(info),
+               ssr & IS_BITS);
+       print_debug_list();
+
+       fas216_done(info, DID_ERROR);
 }
 
 /* Function: void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr)
@@ -1895,7 +1985,7 @@ int fas216_command(Scsi_Cmnd *SCpnt)
 }
 
 /* Prototype: void fas216_reportstatus(Scsi_Cmnd **SCpntp1,
- *                                    Scsi_Cmnd **SCpntp2, int result)
+ *                                    Scsi_Cmnd **SCpntp2, int result, int no_report)
  * Purpose  : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2
  * Params   : SCpntp1 - pointer to command to return
  *           SCpntp2 - pointer to command to check
@@ -1904,7 +1994,7 @@ int fas216_command(Scsi_Cmnd *SCpnt)
  *           structure as *SCpntp2.
  */
 static void fas216_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2,
-                               int result)
+                               int result, int no_report)
 {
        Scsi_Cmnd *SCpnt = *SCpntp1;
 
@@ -1912,7 +2002,8 @@ static void fas216_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2,
                *SCpntp1 = NULL;
 
                SCpnt->result = result;
-               SCpnt->scsi_done(SCpnt);
+               if (!no_report || SCpnt != *SCpntp2)
+                       SCpnt->scsi_done(SCpnt);
        }
 
        if (SCpnt == *SCpntp2)
@@ -2199,6 +2290,7 @@ int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
        FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
        Scsi_Cmnd *SCptr;
        int result = 0;
+       int synchronous = reset_flags & SCSI_RESET_SYNCHRONOUS;
 
        fas216_checkmagic(info, "fas216_reset");
 
@@ -2258,10 +2350,10 @@ int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
        /*
         * Signal all commands in progress have been reset
         */
-       fas216_reportstatus(&info->SCpnt, &SCpnt, DID_RESET << 16);
+       fas216_reportstatus(&info->SCpnt, &SCpnt, DID_RESET << 16, synchronous);
 
        while ((SCptr = queue_remove(&info->queues.disconnected)) != NULL)
-               fas216_reportstatus(&SCptr, &SCpnt, DID_RESET << 16);
+               fas216_reportstatus(&SCptr, &SCpnt, DID_RESET << 16, synchronous);
 
        if (SCpnt) {
                /*
@@ -2274,7 +2366,8 @@ int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
                queue_removecmd(&info->queues.issue, SCpnt);
 
                SCpnt->result = DID_RESET << 16;
-               SCpnt->scsi_done(SCpnt);
+               if (!synchronous)
+                       SCpnt->scsi_done(SCpnt);
        }
 
        return result | SCSI_RESET_SUCCESS;
index 351666638edce50f314ca238add371ac5be06e4d..dede53ba976315d2cbc2f3a13d1b6b31639e55b3 100644 (file)
@@ -237,6 +237,8 @@ typedef struct {
 
                unsigned int    async_stp;              /* Async transfer STP value             */
                unsigned char   msgin_fifo;             /* bytes in fifo at time of message in  */
+               unsigned char   message[256];           /* last message received from device    */
+               unsigned int    msglen;                 /* length of last message received      */
 
                unsigned char   disconnectable:1;       /* this command can be disconnected     */
                unsigned char   aborting:1;             /* aborting command                     */
index bb03a3200240585ad248696e094c0cd64a57b35b..cf5c12227d0a8e0cce4dab860bbdd7e20a5b65cb 100644 (file)
@@ -206,6 +206,14 @@ ifeq ($(CONFIG_BLK_DEV_HPT34X),y)
 IDE_OBJS += hpt34x.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_IDE_ICSIDE),y)
+IDE_OBJS += icside.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_IDE_RAPIDE),y)
+IDE_OBJS += rapide.o
+endif
+
 ### if CONFIG_BLK_DEV_IDE is n, IDE_OBJS will be ignored
 
 ifeq ($(CONFIG_PROC_FS),y)
index c3ac37354de9008457f4067ee225374bcec4e600..934ddd06e692d6080044e23f997819fda37c52c8 100644 (file)
@@ -1383,7 +1383,7 @@ static inline void setup_dev(struct gendisk *dev)
                resetup_one_dev(dev, drive);
 }
 
-void __init device_setup(void)
+static int __init device_setup(void)
 {
        extern void console_map_init(void);
        extern void cpqarray_init(void);
@@ -1441,8 +1441,11 @@ void __init device_setup(void)
 #ifdef CONFIG_MD_BOOT
         md_setup_drive();
 #endif
+       return 0;
 }
 
+__initcall(device_setup);
+
 #ifdef CONFIG_PROC_FS
 int get_partition_list(char * page)
 {
index 164835bfc1613e4e63f0c03e0a308fddfc270e91..389bf168eb8903808bea7a3ea6140751ff4917d5 100644 (file)
@@ -21,6 +21,7 @@
  *  Removed 99% of above. Use Mark's ide driver for those options.
  *  This is now a lightweight ST-506 driver. (Paul Gortmaker)
  *
+ *  Modified 1995 Russell King for ARM processor.
  */
   
 /* Uncomment the following if you want verbose error reports. */
 #define MAJOR_NR HD_MAJOR
 #include <linux/blk.h>
 
+#ifdef __arm__
+#undef  HD_IRQ
+#include <asm/irq.h>
+#define HD_IRQ IRQ_HARDDISK
+#endif
+
 static int revalidate_hddisk(kdev_t, int);
 
 #define        HD_DELAY        0
@@ -64,14 +71,14 @@ static int revalidate_hddisk(kdev_t, int);
 static void recal_intr(void);
 static void bad_rw_intr(void);
 
-static char recalibrate[MAX_HD] = { 0, };
-static char special_op[MAX_HD] = { 0, };
-static int access_count[MAX_HD] = {0, };
-static char busy[MAX_HD] = {0, };
+static char recalibrate[MAX_HD];
+static char special_op[MAX_HD];
+static int access_count[MAX_HD];
+static char busy[MAX_HD];
 static DECLARE_WAIT_QUEUE_HEAD(busy_wait);
 
-static int reset = 0;
-static int hd_error = 0;
+static int reset;
+static int hd_error;
 
 #define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0)
 
@@ -86,13 +93,14 @@ struct hd_i_struct {
 static struct hd_i_struct hd_info[] = { HD_TYPE };
 static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
 #else
-static struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
-static int NR_HD = 0;
+static struct hd_i_struct hd_info[MAX_HD];
+static int NR_HD;
 #endif
 
-static struct hd_struct hd[MAX_HD<<6]={{0,0},};
-static int hd_sizes[MAX_HD<<6] = {0, };
-static int hd_blocksizes[MAX_HD<<6] = {0, };
+static struct hd_struct hd[MAX_HD<<6];
+static int hd_sizes[MAX_HD<<6];
+static int hd_blocksizes[MAX_HD<<6];
+static int hd_hardsectsizes[MAX_HD<<6];
 
 #if (HD_DELAY > 0)
 unsigned long last_req;
@@ -611,7 +619,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
                                        (long *) arg);
 
                case BLKRRPART: /* Re-read partition tables */
-                       if (!capable(CAP_SYS_ADMIN)) 
+                       if (!capable(CAP_SYS_ADMIN))
                                return -EACCES;
                        return revalidate_hddisk(inode->i_rdev, 1);
 
@@ -746,6 +754,17 @@ static void hd_geninit(struct gendisk *ignored)
                }
        }
 #endif /* __i386__ */
+#ifdef __arm__
+       if (!NR_HD) {
+               /* We don't know anything about the drive.  This means
+                * that you *MUST* specify the drive parameters to the
+                * kernel yourself.
+                */
+               printk("hd: no drives specified - use hd=cyl,head,sectors"
+                       " on kernel command line\n");
+       }
+#endif
+
        for (drive=0 ; drive < NR_HD ; drive++) {
                hd[drive<<6].nr_sects = hd_info[drive].head *
                        hd_info[drive].sect * hd_info[drive].cyl;
@@ -764,9 +783,12 @@ static void hd_geninit(struct gendisk *ignored)
        }
        hd_gendisk.nr_real = NR_HD;
 
-       for(drive=0; drive < (MAX_HD << 6); drive++)
+       for(drive=0; drive < (MAX_HD << 6); drive++) {
                hd_blocksizes[drive] = 1024;
+               hd_hardsectsizes[drive] = 512;
+       }
        blksize_size[MAJOR_NR] = hd_blocksizes;
+       hardsect_size[MAJOR_NR] = hd_hardsectsizes;
 }
 
 static struct file_operations hd_fops = {
index 6c2768b279455adf4f9c7e91d474634cdae1971d..307a9fa0ef7c962f53864967c72466f213281355 100644 (file)
@@ -116,6 +116,7 @@ static int rd_kbsize[NUM_RAMDISKS];         /* Size in blocks of 1024 bytes */
 int rd_size = 4096;            /* Size of the RAM disks */
 
 #ifndef MODULE
+
 int rd_doload = 0;             /* 1 = load RAM disk, 0 = don't load */
 int rd_prompt = 1;             /* 1 = prompt for RAM disk, 0 = don't prompt */
 int rd_image_start = 0;                /* starting block # of image */
@@ -123,7 +124,48 @@ int rd_image_start = 0;            /* starting block # of image */
 unsigned long initrd_start,initrd_end;
 int mount_initrd = 1;          /* zero if initrd should not be mounted */
 int initrd_below_start_ok = 0;
+
+static int __init no_initrd(char *str)
+{
+       mount_initrd = 0;
+       return 1;
+}
+
+__setup("noinitrd", no_initrd);
+
 #endif
+
+static int __init ramdisk_start_setup(char *str)
+{
+       rd_image_start = simple_strtol(str,NULL,0);
+       return 1;
+}
+
+static int __init load_ramdisk(char *str)
+{
+       rd_doload = simple_strtol(str,NULL,0) & 3;
+       return 1;
+}
+
+static int __init prompt_ramdisk(char *str)
+{
+       rd_prompt = simple_strtol(str,NULL,0) & 1;
+       return 1;
+}
+
+static int __init ramdisk_size(char *str)
+{
+       rd_size = simple_strtol(str,NULL,0);
+       return 1;
+}
+
+
+__setup("ramdisk_start=", ramdisk_start_setup);
+__setup("load_ramdisk=", load_ramdisk);
+__setup("prompt_ramdisk=", prompt_ramdisk);
+__setup("ramdisk=", ramdisk_size);
+__setup("ramdisk_size=", ramdisk_size);
+
 #endif
 
 /*
index d68e307460ef03954093237a2fcafe6836b7d3cc..0d7b843c464edc9c0dc77b0f31f5f31f92f63a89 100644 (file)
@@ -60,18 +60,22 @@ if [ "$CONFIG_PARPORT" != "n" ]; then
   dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT
 fi
 
-bool 'Mouse Support (not serial mice)' CONFIG_MOUSE
-if [ "$CONFIG_MOUSE" = "y" ]; then
-       mainmenu_option next_comment
-       comment 'Mice'
-       tristate 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE
-       tristate 'Logitech busmouse support' CONFIG_BUSMOUSE
-       tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE
+mainmenu_option next_comment
+comment 'Mice'
+tristate 'Bus Mouse Support' CONFIG_BUSMOUSE
+if [ "$CONFIG_BUSMOUSE" != "n" ]; then
+  dep_tristate 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE
+  dep_tristate 'Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE
+  dep_tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE
+fi
+
+tristate 'Mouse Support (not serial and bus mice)' CONFIG_MOUSE
+if [ "$CONFIG_MOUSE" != "n" ]; then
        bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
        tristate 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
        tristate 'PC110 digitizer pad support' CONFIG_PC110_PAD
-       endmenu
 fi
+endmenu
 
 tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE
 if [ "$CONFIG_QIC02_TAPE" != "n" ]; then
index 23af66b2eb796222bda2070fa3a9bac7095628fe..86f513a7aa4be94ca6712dc62440f8e96dadf0fa 100644 (file)
@@ -164,11 +164,11 @@ else
   endif
 endif
 
-ifeq ($(CONFIG_BUSMOUSE),y)
-L_OBJS += busmouse.o
+ifeq ($(CONFIG_LOGIBUSMOUSE),y)
+L_OBJS += logibusmouse.o
 else
-  ifeq ($(CONFIG_BUSMOUSE),m)
-  M_OBJS += busmouse.o
+  ifeq ($(CONFIG_LOGIBUSMOUSE),m)
+  M_OBJS += logibusmouse.o
   endif
 endif
 
@@ -190,6 +190,16 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_MOUSE),y)
+M = y
+LX_OBJS += busmouse.o
+else
+  ifeq ($(CONFIG_MOUSE),m)
+  MM = m
+  MX_OBJS += busmouse.o
+  endif
+endif
+
 ifeq ($(CONFIG_DTLK),y)
 L_OBJS += dtlk.o
 else
index 77bbbbd69a99ad60f510fe12d2620ee2007e7803..83f806c4c3fab6823d0ccd8054ade31287cb36f9 100644 (file)
@@ -21,6 +21,9 @@
  * 1996/02/11 Andreas Schwab
  * Module support
  * Allow multiple open's
+ *
+ * Converted to use new generic busmouse code.  11 July 1998
+ *   Russell King <rmk@arm.uk.linux.org>
  */
 
 #include <linux/module.h>
@@ -34,7 +37,6 @@
 #include <linux/init.h>
 
 #include <asm/adb_mouse.h>
-#include <asm/uaccess.h>
 #ifdef __powerpc__
 #include <asm/processor.h>
 #endif
 #include <asm/setup.h>
 #endif
 
-static struct mouse_status mouse;
+#include "busmouse.h"
+
+static int msedev;
 static unsigned char adb_mouse_buttons[16];
 
 extern void (*adb_mouse_interrupt_hook)(unsigned char *, int);
 extern int adb_emulate_buttons;
 extern int adb_button2_keycode;
 extern int adb_button3_keycode;
-
 extern int console_loglevel;
 
 /*
- *     XXX: need to figure out what ADB mouse packets mean ... 
- *     This is the stuff stolen from the Atari driver ...
+ *    XXX: need to figure out what ADB mouse packets mean ... 
+ *      This is the stuff stolen from the Atari driver ...
  */
 static void adb_mouse_interrupt(unsigned char *buf, int nb)
 {
-    int buttons, id;
+       int buttons, id;
+       char dx, dy;
 
-/*
-    Handler 1 -- 100cpi original Apple mouse protocol.
-    Handler 2 -- 200cpi original Apple mouse protocol.
-
-    For Apple's standard one-button mouse protocol the data array will
-    contain the following values:
-
-                BITS    COMMENTS
-    data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd.
-    data[1] = bxxx xxxx First button and x-axis motion.
-    data[2] = byyy yyyy Second button and y-axis motion.
-
-    Handler 4 -- Apple Extended mouse protocol.
-
-    For Apple's 3-button mouse protocol the data array will contain the
-    following values:
-
-               BITS    COMMENTS
-    data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd.
-    data[1] = bxxx xxxx Left button and x-axis motion.
-    data[2] = byyy yyyy Second button and y-axis motion.
-    data[3] = byyy bxxx Third button and fourth button.  
-             Y is additional high bits of y-axis motion.  
-             X is additional high bits of x-axis motion.
-
-    This procedure also gets called from the keyboard code if we
-    are emulating mouse buttons with keys.  In this case data[0] == 0
-    (data[0] cannot be 0 for a real ADB packet).
-
-    'buttons' here means 'button down' states!
-    Button 1 (left)  : bit 2, busmouse button 3
-    Button 2 (middle): bit 1, busmouse button 2
-    Button 3 (right) : bit 0, busmouse button 1
-*/
-
-    /* x/y and buttons swapped */
-    
-    if (console_loglevel >= 8)
-       printk("KERN_DEBUG adb_mouse: %s data; ", buf[0]? "real": "fake"); 
-
-    id = (buf[0] >> 4) & 0xf;
-    buttons = adb_mouse_buttons[id];
-
-    /* button 1 (left, bit 2) */
-    buttons = (buttons&3) | (buf[1] & 0x80 ? 4 : 0); /* 1+2 unchanged */
-
-    /* button 2 (middle) */
-    buttons = (buttons&5) | (buf[2] & 0x80 ? 2 : 0); /* 2+3 unchanged */
-
-    /* button 3 (right) present?
-     *  on a logitech mouseman, the right and mid buttons sometimes behave
-     *  strangely until they both have been pressed after booting. */
-    /* data valid only if extended mouse format ! */
-    if (nb >= 4)
-       buttons = (buttons&6) | (buf[3] & 0x80 ? 1 : 0); /* 1+3 unchanged */
-
-    add_mouse_randomness(((~buttons&7) << 16) + ((buf[2]&0x7f) << 8) + (buf[1]&0x7f));
-
-    adb_mouse_buttons[id] = buttons;
-    /* a button is down if it is down on any mouse */
-    for (id = 0; id < 16; ++id)
-       buttons &= adb_mouse_buttons[id];
-
-    mouse.buttons = buttons;
-    mouse.dx += ((buf[2]&0x7f) < 64 ? (buf[2]&0x7f) : (buf[2]&0x7f)-128 );
-    mouse.dy -= ((buf[1]&0x7f) < 64 ? (buf[1]&0x7f) : (buf[1]&0x7f)-128 );
-
-    if (console_loglevel >= 8)
-        printk(" %X %X %X buttons %x dx %d dy %d \n", 
-               buf[1], buf[2], buf[3], mouse.buttons, mouse.dx, mouse.dy);
-    mouse.ready = 1;
-    wake_up_interruptible(&mouse.wait);
-    if (mouse.fasyncptr)
-       kill_fasync(mouse.fasyncptr, SIGIO);
-}
+       /*
+          Handler 1 -- 100cpi original Apple mouse protocol.
+          Handler 2 -- 200cpi original Apple mouse protocol.
 
-static int fasync_mouse(int fd, struct file *filp, int on)
-{
-       int retval;
+          For Apple's standard one-button mouse protocol the data array will
+          contain the following values:
 
-       retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
-       if (retval < 0)
-               return retval;
-       return 0;
-}
+                      BITS    COMMENTS
+          data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd.
+          data[1] = bxxx xxxx First button and x-axis motion.
+          data[2] = byyy yyyy Second button and y-axis motion.
 
-static int release_mouse(struct inode *inode, struct file *file)
-{
-    fasync_mouse(-1, file, 0);
-    if (--mouse.active)
-      return 0;
+          Handler 4 -- Apple Extended mouse protocol.
 
-    adb_mouse_interrupt_hook = NULL;
-    MOD_DEC_USE_COUNT;
-    return 0;
-}
+          For Apple's 3-button mouse protocol the data array will contain the
+          following values:
 
-static int open_mouse(struct inode *inode, struct file *file)
-{
-    int id;
+                      BITS    COMMENTS
+          data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd.
+          data[1] = bxxx xxxx Left button and x-axis motion.
+          data[2] = byyy yyyy Second button and y-axis motion.
+          data[3] = byyy bxxx Third button and fourth button.  
+                  Y is additiona. high bits of y-axis motion.  
+                  X is additional high bits of x-axis motion.
 
-    if (mouse.active++)
-       return 0;
-       
-    mouse.ready = 0;
-
-    mouse.dx = mouse.dy = 0;
-    for (id = 0; id < 16; ++id)
-       adb_mouse_buttons[id] = 7;      /* all buttons up */
-    MOD_INC_USE_COUNT;
-    adb_mouse_interrupt_hook = adb_mouse_interrupt;
-    return 0;
-}
+          'buttons' here means 'button down' states!
+          Button 1 (left)  : bit 2, busmouse button 3
+          Button 2 (right) : bit 0, busmouse button 1
+          Button 3 (middle): bit 1, busmouse button 2
+        */
 
-static ssize_t write_mouse(struct file *file, const char *buffer,
-                          size_t count, loff_t *ppos)
-{
-    return -EINVAL;
+       /* x/y and buttons swapped */
+
+       id = (buf[0] >> 4) & 0xf;
+
+       buttons = adb_mouse_buttons[id];
+
+       /* button 1 (left, bit 2) */
+       buttons = (buttons & 3) | (buf[1] & 0x80 ? 4 : 0); /* 1+2 unchanged */
+
+       /* button 2 (middle) */
+       buttons = (buttons & 5) | (buf[2] & 0x80 ? 2 : 0); /* 2+3 unchanged */
+
+       /* button 3 (right) present?
+        *  on a logitech mouseman, the right and mid buttons sometimes behave
+        *  strangely until they both have been pressed after booting. */
+       /* data valid only if extended mouse format ! */
+       if (nb >= 4)
+               buttons = (buttons & 6) | (buf[3] & 0x80 ? 1 : 0); /* 1+3 unchanged */
+
+       adb_mouse_buttons[id] = buttons;
+
+       /* a button is down if it is down on any mouse */
+       for (id = 0; id < 16; ++id)
+               buttons &= adb_mouse_buttons[id];
+
+       dx = ((buf[2] & 0x7f) < 64 ? (buf[2] & 0x7f) : (buf[2] & 0x7f) - 128);
+       dy = ((buf[1] & 0x7f) < 64 ? (buf[1] & 0x7f) : (buf[1] & 0x7f) - 128);
+       busmouse_add_movementbuttons(msedev, dx, -dy, buttons);
+
+       if (console_loglevel >= 8)
+               printk(" %X %X %X dx %d dy %d \n",
+                      buf[1], buf[2], buf[3], dx, dy);
 }
 
-static ssize_t read_mouse(struct file *file, char *buffer, size_t count,
-                         loff_t *ppos)
+static int release_mouse(struct inode *inode, struct file *file)
 {
-    int dx, dy, buttons;
-
-    if (count < 3)
-       return -EINVAL;
-    if (!mouse.ready)
-       return -EAGAIN;
-    dx = mouse.dx;
-    dy = mouse.dy;
-    buttons = mouse.buttons;
-    if (dx > 127)
-       dx = 127;
-    else if (dx < -128)
-       dx = -128;
-    if (dy > 127)
-       dy = 127;
-    else if (dy < -128)
-       dy = -128;
-    mouse.dx -= dx;
-    mouse.dy -= dy;
-    if (mouse.dx == 0 && mouse.dy == 0)
-       mouse.ready = 0;
-    if (put_user(buttons | 0x80, buffer++) ||
-       put_user((char) dx, buffer++) ||
-       put_user((char) dy, buffer++))
-       return -EFAULT;
-    if (count > 3)
-       if (clear_user(buffer, count - 3))
-           return -EFAULT;
-    return count;
+       adb_mouse_interrupt_hook = NULL;
+       MOD_DEC_USE_COUNT;
+       return 0;
 }
 
-static unsigned int mouse_poll(struct file *file, poll_table *wait)
+static int open_mouse(struct inode *inode, struct file *file)
 {
-       poll_wait(file, &mouse.wait, wait);
-       if (mouse.ready)
-               return POLLIN | POLLRDNORM;
+       MOD_INC_USE_COUNT;
+       adb_mouse_interrupt_hook = adb_mouse_interrupt;
        return 0;
 }
 
-struct file_operations adb_mouse_fops = {
-    NULL,              /* mouse_seek */
-    read_mouse,
-    write_mouse,
-    NULL,              /* mouse_readdir */
-    mouse_poll,
-    NULL,              /* mouse_ioctl */
-    NULL,              /* mouse_mmap */
-    open_mouse,
-    NULL,              /* flush */
-    release_mouse,
-    NULL,
-    fasync_mouse,
-};
-
-#define ADB_MOUSE_MINOR        10
-
-static struct miscdevice adb_mouse = {
-    ADB_MOUSE_MINOR, "adbmouse", &adb_mouse_fops
+static struct busmouse adb_mouse =
+{
+       ADB_MOUSE_MINOR, "adbmouse", open_mouse, close_mouse, 7
 };
 
 __initfunc(int adb_mouse_init(void))
 {
-    mouse.active = 0;
-    mouse.ready = 0;
-    init_waitqueue_head(&mouse.wait);
-
 #ifdef __powerpc__
-    if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
-           return -ENODEV;
+       if ((_machine != _MACH_chrp) && (_machine != _MACH_Pmac))
+               return -ENODEV;
 #endif
 #ifdef __mc68000__
-    if (!MACH_IS_MAC)
-       return -ENODEV;
+       if (!MACH_IS_MAC)
+               return -ENODEV;
 #endif
-    printk(KERN_INFO "Macintosh ADB mouse driver installed.\n");
-    misc_register(&adb_mouse);
-    return 0;
-}
 
+       msedev = register_busmouse(&adb_mouse);
+       if (msedev < 0)
+               printk(KERN_WARNING "Unable to register ADB mouse driver.\n");
+       else
+               printk(KERN_INFO "Macintosh ADB mouse driver installed.\n");
+
+       return msedev < 0 ? msedev : 0;
+}
 
 /*
  * XXX this function is misnamed.
@@ -286,11 +190,12 @@ __initfunc(void adb_mouse_setup(char *str, int *ints))
 
 int init_module(void)
 {
-    return adb_mouse_init();
+       return adb_mouse_init();
 }
 
 void cleanup_module(void)
 {
-    misc_deregister(&adb_mouse);
+       unregister_busmouse(msedev);
 }
+
 #endif
index 70e20b887065e4f721f034d708eb3947c840cc9d..090e1d9a470851ad1e0635b3abb3436732acff71 100644 (file)
@@ -30,6 +30,9 @@
  * Moved the isr-allocation to the mouse_{open,close} calls, as there
  *   is no reason to service the mouse in the vertical blank isr if
  *   the mouse is not in use.             Jes Sorensen
+ *
+ * Converted to use new generic busmouse code.  5 Apr 1998
+ *   Russell King <rmk@arm.uk.linux.org>
  */
 
 #include <linux/module.h>
@@ -44,7 +47,7 @@
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/busmouse.h>
+#include <linux/logibusmouse.h>
 
 #include <asm/setup.h>
 #include <asm/system.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 
+#include "busmouse.h"
+
+#if 0
 #define AMI_MSE_INT_ON()       mouseint_allowed = 1
 #define AMI_MSE_INT_OFF()      mouseint_allowed = 0
-
-
-static struct mouse_status mouse;
-
 static int mouseint_allowed;
+#endif
+
+static int msedev;
 
 static void mouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
@@ -70,9 +75,11 @@ static void mouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
 
        unsigned short joy0dat, potgor;
 
+#if 0
        if(!mouseint_allowed)
                return;
        AMI_MSE_INT_OFF();
+#endif
 
        /*
         *  This routine assumes, just like Kickstart, that the mouse
@@ -128,44 +135,10 @@ static void mouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
                  (potgor & 0x0400 ? 1 : 0);    /* right button */
 
 
-       if (dx != 0 || dy != 0 || buttons != mouse.buttons) {
-         add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
-         mouse.buttons = buttons;
-         mouse.dx += dx;
-         mouse.dy -= dy;
-         mouse.ready = 1;
-         wake_up_interruptible(&mouse.wait);
-
-         /*
-          * keep dx/dy reasonable, but still able to track when X (or
-          * whatever) must page or is busy (i.e. long waits between
-          * reads)
-          */
-         if (mouse.dx < -2048)
-             mouse.dx = -2048;
-         else
-         if (mouse.dx >  2048)
-             mouse.dx =  2048;
-
-         if (mouse.dy < -2048)
-             mouse.dy = -2048;
-         else
-         if (mouse.dy >  2048)
-             mouse.dy =  2048;
-
-         if (mouse.fasyncptr)
-             kill_fasync(mouse.fasyncptr, SIGIO);
-       }
+       busmouse_add_movementbuttons(msedev, dx, -dy, buttons);
+#if 0
        AMI_MSE_INT_ON();
-}
-
-static int fasync_mouse(int fd, struct file *filp, int on)
-{
-       int retval;
-       retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
-       if (retval < 0)
-               return retval;
-       return 0;
+#endif
 }
 
 /*
@@ -174,11 +147,10 @@ static int fasync_mouse(int fd, struct file *filp, int on)
 
 static int release_mouse(struct inode * inode, struct file * file)
 {
-       fasync_mouse(-1, file, 0);
-       if (--mouse.active)
-               return 0;
        free_irq(IRQ_AMIGA_VERTB, mouse_interrupt);
+#if 0
        AMI_MSE_INT_OFF();
+#endif
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -190,123 +162,25 @@ static int release_mouse(struct inode * inode, struct file * file)
 
 static int open_mouse(struct inode * inode, struct file * file)
 {
-       if (!mouse.present)
-               return -EINVAL;
-       if (mouse.active++)
-               return 0;
        /*
         *  use VBL to poll mouse deltas
         */
 
        if(request_irq(IRQ_AMIGA_VERTB, mouse_interrupt, 0,
                       "Amiga mouse", mouse_interrupt)) {
-               mouse.present = 0;
                printk(KERN_INFO "Installing Amiga mouse failed.\n");
                return -EIO;
        }
 
-       mouse.ready = 0;
-       mouse.dx = 0;
-       mouse.dy = 0;
-       mouse.buttons = 0x87;
-       mouse.active = 1;
        MOD_INC_USE_COUNT;
+#if 0
        AMI_MSE_INT_ON();
+#endif
        return 0;
 }
 
-/*
- * writes are disallowed
- */
-
-static ssize_t write_mouse(struct file * file, const char * buffer,
-                          size_t count, loff_t *ppos)
-{
-       return -EINVAL;
-}
-
-/*
- * read mouse data.  Currently never blocks.
- */
-
-static ssize_t read_mouse(struct file * file, char * buffer,
-                         size_t count, loff_t *ppos)
-{
-       int dx;
-       int dy;
-       unsigned char buttons; 
-
-       if (count < 3)
-               return -EINVAL;
-       if (!mouse.ready)
-               return -EAGAIN;
-
-       /*
-        * Obtain the current mouse parameters and limit as appropriate for
-        * the return data format.  Interrupts are only disabled while 
-        * obtaining the parameters, NOT during the puts_user() calls,
-        * so paging in put_user() does not effect mouse tracking.
-        */
-
-       AMI_MSE_INT_OFF();
-       dx = mouse.dx;
-       dy = mouse.dy;
-       if (dx < -127)
-           dx = -127;
-       else
-       if (dx > 127)
-           dx = 127;
-       if (dy < -127)
-           dy = -127;
-       else
-       if (dy > 127)
-           dy = 127;
-       buttons = mouse.buttons;
-       mouse.dx -= dx;
-       mouse.dy -= dy;
-       mouse.ready = 0;
-       AMI_MSE_INT_ON();
-
-       if (put_user(buttons | 0x80, buffer++) ||
-           put_user((char)dx, buffer++) ||
-           put_user((char)dy, buffer++))
-               return -EINVAL;
-
-       if (count > 3)
-               if (clear_user(buffer, count - 3))
-                       return -EFAULT;
-       return count;
-}
-
-/*
- * poll for mouse input
- */
-
-static unsigned int mouse_poll(struct file *file, poll_table * wait)
-{
-       poll_wait(file, &mouse.wait, wait);
-       if (mouse.ready)
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-struct file_operations amiga_mouse_fops = {
-       NULL,           /* mouse_seek */
-       read_mouse,
-       write_mouse,
-       NULL,           /* mouse_readdir */
-       mouse_poll,     /* mouse_poll */
-       NULL,           /* mouse_ioctl */
-       NULL,           /* mouse_mmap */
-       open_mouse,
-       NULL,           /* flush */
-       release_mouse,
-       NULL,
-       fasync_mouse,
-};
-
-static struct miscdevice amiga_mouse = {
-       AMIGAMOUSE_MINOR, "amigamouse", &amiga_mouse_fops
+static struct busmouse amigamouse = {
+       AMIGAMOUSE_MINOR, "amigamouse", open_mouse, release_mouse, 7
 };
 
 int __init amiga_mouse_init(void)
@@ -315,21 +189,15 @@ int __init amiga_mouse_init(void)
                return -ENODEV;
 
        custom.joytest = 0;     /* reset counters */
-
+#if 0
        AMI_MSE_INT_OFF();
-
-       mouse.active = 0;
-       mouse.ready = 0;
-       mouse.buttons = 0x87;
-       mouse.dx = 0;
-       mouse.dy = 0;
-       mouse.wait = NULL;
-
-       mouse.present = 1;
-
-       printk(KERN_INFO "Amiga mouse installed.\n");
-       misc_register(&amiga_mouse);
-       return 0;
+#endif
+       msedev = register_busmouse(&amigamouse);
+       if (msedev < 0)
+               printk(KERN_WARNING "Unable to install Amiga mouse driver.\n");
+       else
+               printk(KERN_INFO "Amiga mouse installed.\n");
+       return msedev < 0 ? msedev : 0;
 }
 
 #ifdef MODULE
@@ -341,6 +209,6 @@ int init_module(void)
 
 void cleanup_module(void)
 {
-       misc_deregister(&amiga_mouse);
+       unregsiter_busmouse(msedev);
 }
 #endif
index b813510eb08bd12f115d58bd52818095c3b43e5f..486030cf3f9cb691200b907e92ca9d5e35292a2f 100644 (file)
@@ -10,6 +10,9 @@
  * 1996/02/11 Andreas Schwab
  * Module support
  * Allow multiple open's
+ *
+ * Converted to use new generic busmouse code.  5 Apr 1998
+ *   Russell King <rmk@arm.uk.linux.org>
  */
 
 #include <linux/module.h>
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/busmouse.h>
+#include <linux/logibusmouse.h>
 
 #include <asm/setup.h>
 #include <asm/atarikb.h>
 #include <asm/uaccess.h>
 
-static struct mouse_status mouse;
+#include "busmouse.h"
+
+static int msedev;
 static int mouse_threshold[2] = {2,2};
 MODULE_PARM(mouse_threshold, "2i");
 extern int atari_mouse_buttons;
@@ -42,32 +47,13 @@ static void atari_mouse_interrupt(char *buf)
               | (buf[0] & 2 ? 4 : 0)
               | (atari_mouse_buttons & 2));
     atari_mouse_buttons = buttons;
-    add_mouse_randomness((buttons << 16) + (buf[2] << 8) + buf[1]);
-    mouse.buttons = ~buttons & 7;
-    mouse.dx += buf[1];
-    mouse.dy -= buf[2];
-    mouse.ready = 1;
-    wake_up_interruptible(&mouse.wait);
-    if (mouse.fasyncptr)
-       kill_fasync(mouse.fasyncptr, SIGIO);
 
+    busmouse_add_movementbuttons(msedev, buf[1], -buf[2], buttons);
 /*    ikbd_mouse_rel_pos(); */
 }
 
-static int fasync_mouse(int fd, struct file *filp, int on)
-{
-       int retval;
-       retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
-       if (retval < 0)
-               return retval;
-       return 0;
-}
-
 static int release_mouse(struct inode *inode, struct file *file)
 {
-    fasync_mouse(-1, file, 0);
-    if (--mouse.active)
-      return 0;
     ikbd_mouse_disable();
 
     atari_mouse_interrupt_hook = NULL;
@@ -77,10 +63,6 @@ static int release_mouse(struct inode *inode, struct file *file)
 
 static int open_mouse(struct inode *inode, struct file *file)
 {
-    if (mouse.active++)
-       return 0;
-    mouse.ready = 0;
-    mouse.dx = mouse.dy = 0;
     atari_mouse_buttons = 0;
     ikbd_mouse_y0_top ();
     ikbd_mouse_thresh (mouse_threshold[0], mouse_threshold[1]);
@@ -90,92 +72,20 @@ static int open_mouse(struct inode *inode, struct file *file)
     return 0;
 }
 
-static ssize_t write_mouse(struct file *file, const char *buffer,
-                         size_t count, loff_t *ppos)
-{
-    return -EINVAL;
-}
-
-static ssize_t read_mouse(struct file * file, char * buffer,
-                         size_t count, loff_t *ppos)
-{
-    int dx, dy, buttons;
-
-    if (count < 3)
-       return -EINVAL;
-    if (!mouse.ready)
-       return -EAGAIN;
-    /* ikbd_mouse_disable */
-    dx = mouse.dx;
-    dy = mouse.dy;
-    buttons = mouse.buttons;
-    if (dx > 127)
-      dx = 127;
-    else if (dx < -128)
-      dx = -128;
-    if (dy > 127)
-      dy = 127;
-    else if (dy < -128)
-      dy = -128;
-    mouse.dx -= dx;
-    mouse.dy -= dy;
-    if (mouse.dx == 0 && mouse.dy == 0)
-      mouse.ready = 0;
-    /* ikbd_mouse_rel_pos(); */
-    if (put_user(buttons | 0x80, buffer++) ||
-       put_user((char) dx, buffer++) ||
-       put_user((char) dy, buffer++))
-       return -EFAULT;
-    if (count > 3)
-       if (clear_user(buffer, count - 3))
-           return -EFAULT;
-    return count;
-}
-
-static unsigned int mouse_poll(struct file *file, poll_table *wait)
-{
-       poll_wait(file, &mouse.wait, wait);
-       if (mouse.ready)
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-struct file_operations atari_mouse_fops = {
-    NULL,              /* mouse_seek */
-    read_mouse,
-    write_mouse,
-    NULL,              /* mouse_readdir */
-    mouse_poll,
-    NULL,              /* mouse_ioctl */
-    NULL,              /* mouse_mmap */
-    open_mouse,
-    NULL,              /* flush */
-    release_mouse,
-    NULL,
-    fasync_mouse,
-};
-
-static struct miscdevice atari_mouse = {
-    ATARIMOUSE_MINOR, "atarimouse", &atari_mouse_fops
+static struct busmouse atarimouse = {
+       ATARIMOUSE_MINOR, "atarimouse", open_mouse, release_mouse, 0
 };
 
 int __init atari_mouse_init(void)
 {
-       int r;
-
-       if (!MACH_IS_ATARI)
-               return -ENODEV;
-
-       mouse.active = 0;
-       mouse.ready = 0;
-       mouse.wait = NULL;
-
-       r = misc_register(&atari_mouse);
-       if (r)
-               return r;
-
-       printk(KERN_INFO "Atari mouse installed.\n");
-       return 0;
+    if (!MACH_IS_ATARI)
+       return -ENODEV;
+    msedev = register_busmouse(&atarimouse);
+    if (msedev < 0)
+       printk(KERN_WARNING "Unable to register Atari mouse driver.\n");
+    else
+       printk(KERN_INFO "Atari mouse installed.\n");
+    return msedev < 0 ? msedev : 0;
 }
 
 
@@ -215,6 +125,6 @@ int init_module(void)
 
 void cleanup_module(void)
 {
-  misc_deregister(&atari_mouse);
+       unregister_busmouse(msedev);
 }
 #endif
index ecddff26ce3c3ff174bf4bd8c03abcde5cdd5bcc..1ab9a211f721a992274ea15b3fc2b68cacd364f9 100644 (file)
@@ -7,6 +7,9 @@
  * Modified by Chris Colohan (colohan@eecg.toronto.edu)
  * Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
  *
+ * Converted to use new generic busmouse code.  5 Apr 1998
+ *   Russell King <rmk@arm.uk.linux.org>
+ *
  * version 0.3a
  */
 
@@ -26,6 +29,8 @@
 #include <asm/system.h>
 #include <asm/irq.h>
 
+#include "busmouse.h"
+
 #define ATIXL_MOUSE_IRQ                5 /* H/W interrupt # set up on ATIXL board */
 #define ATIXL_BUSMOUSE         3 /* Minor device # (mknod c 10 3 /dev/bm) */
 
 
 /* Same general mouse structure */
 
-static struct mouse_status {
-       char buttons;
-       char latch_buttons;
-       int dx;
-       int dy;
-       int present;
-       int ready;
-       int active;
-       wait_queue_head_t wait;
-       struct fasync_struct *fasync;
-} mouse;
+static int msedev;
 
 void mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
@@ -82,35 +77,13 @@ void mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        dy = inb( ATIXL_MSE_DATA_PORT);
        outb(ATIXL_MSE_READ_BUTTONS, ATIXL_MSE_CONTROL_PORT); /* Select IR0 - Button Status */
        buttons = inb( ATIXL_MSE_DATA_PORT);
-       if (dx != 0 || dy != 0 || buttons != mouse.latch_buttons) {
-               add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
-               mouse.latch_buttons |= buttons;
-               mouse.dx += dx;
-               mouse.dy += dy;
-               mouse.ready = 1;
-               wake_up_interruptible(&mouse.wait);
-               if (mouse.fasync)
-                       kill_fasync(mouse.fasync, SIGIO);
-       }
+       busmouse_add_movementbuttons(msedev, dx, -dy, buttons);
        ATIXL_MSE_ENABLE_UPDATE();
 }
 
-static int fasync_mouse(int fd, struct file *filp, int on)
-{
-       int retval;
-       retval = fasync_helper(fd, filp, on, &mouse.fasync);
-       if (retval < 0)
-               return retval;
-       return 0;
-}
-
 static int release_mouse(struct inode * inode, struct file * file)
 {
-       fasync_mouse(-1, file, 0);
-       if (--mouse.active)
-               return 0;
        ATIXL_MSE_INT_OFF(); /* Interrupts are really shut down here */
-       mouse.ready = 0;
        free_irq(ATIXL_MOUSE_IRQ, NULL);
        MOD_DEC_USE_COUNT;
        return 0;
@@ -118,90 +91,17 @@ static int release_mouse(struct inode * inode, struct file * file)
 
 static int open_mouse(struct inode * inode, struct file * file)
 {
-       if (!mouse.present)
-               return -EINVAL;
-       if (mouse.active++)
-               return 0;
-       if (request_irq(ATIXL_MOUSE_IRQ, mouse_interrupt, 0, "ATIXL mouse", NULL)) {
-               mouse.active--;
+       if (request_irq(ATIXL_MOUSE_IRQ, mouse_interrupt, 0, "ATIXL mouse", NULL))
                return -EBUSY;
-       }
-       mouse.ready = 0;
-       mouse.dx = 0;
-       mouse.dy = 0;
-       mouse.buttons = mouse.latch_buttons = 0;
        ATIXL_MSE_INT_ON(); /* Interrupts are really enabled here */
        MOD_INC_USE_COUNT;
        return 0;
 }
 
-
-static ssize_t write_mouse(struct file * file, const char * buffer,
-       size_t count, loff_t *ppos)
-{
-       return -EINVAL;
-}
-
-static ssize_t read_mouse(struct file * file, char * buffer,
-       size_t count, loff_t *ppos)
-{
-       ssize_t i;
-
-       if (count < 3)
-               return -EINVAL;
-       if (!mouse.ready)
-               return -EAGAIN;
-       ATIXL_MSE_DISABLE_UPDATE();
-       /* Allowed interrupts to occur during data gathering - shouldn't hurt */
-       put_user((char)(~mouse.latch_buttons&7) | 0x80 , buffer);
-       if (mouse.dx < -127)
-               mouse.dx = -127;
-       if (mouse.dx > 127)
-               mouse.dx =  127;
-       put_user((char)mouse.dx, buffer + 1);
-       if (mouse.dy < -127)
-               mouse.dy = -127;
-       if (mouse.dy > 127)
-               mouse.dy =  127;
-       put_user((char)-mouse.dy, buffer + 2);
-       for(i = 3; i < count; i++)
-               put_user(0x00, buffer + i);
-       mouse.dx = 0;
-       mouse.dy = 0;
-       mouse.latch_buttons = mouse.buttons;
-       mouse.ready = 0;
-       ATIXL_MSE_ENABLE_UPDATE();
-       return i; /* i data bytes returned */
-}
-
-static unsigned int mouse_poll(struct file *file, poll_table * wait)
-{
-       poll_wait(file, &mouse.wait, wait);
-       if (mouse.ready)
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-struct file_operations atixl_busmouse_fops = {
-       NULL,           /* mouse_seek */
-       read_mouse,
-       write_mouse,
-       NULL,           /* mouse_readdir */
-       mouse_poll,     /* mouse_poll */
-       NULL,           /* mouse_ioctl */
-       NULL,           /* mouse_mmap */
-       open_mouse,
-       NULL,           /* flush */
-       release_mouse,
-       NULL,
-       fasync_mouse,
+static struct busmouse atixlmouse = {
+       ATIXL_BUSMOUSE, "atixl", open_mouse, release_mouse, 0
 };
 
-static struct miscdevice atixl_mouse = { 
-       ATIXL_BUSMOUSE, "atixl", &atixl_busmouse_fops
-};
-
-
 int __init atixl_busmouse_init(void)
 {
        unsigned char a,b,c;
@@ -211,22 +111,18 @@ int __init atixl_busmouse_init(void)
        c = inb( ATIXL_MSE_SIGNATURE_PORT );
        if (( a != b ) && ( a == c ))
                printk(KERN_INFO "\nATI Inport ");
-       else{
-               mouse.present = 0;
+       else
                return -EIO;
-       }
        outb(0x80, ATIXL_MSE_CONTROL_PORT);     /* Reset the Inport device */
        outb(0x07, ATIXL_MSE_CONTROL_PORT);     /* Select Internal Register 7 */
        outb(0x0a, ATIXL_MSE_DATA_PORT);        /* Data Interrupts 8+, 1=30hz, 2=50hz, 3=100hz, 4=200hz rate */
-       mouse.present = 1;
-       mouse.active = 0;
-       mouse.ready = 0;
-       mouse.buttons = mouse.latch_buttons = 0;
-       mouse.dx = mouse.dy = 0;
-       init_waitqueue_head(&mouse.wait);
-       printk("Bus mouse detected and installed.\n");
-       misc_register(&atixl_mouse);
-       return 0;
+
+       msedev = register_busmouse(&atixlmouse);
+       if (msedev < 0)
+               printk("Bus mouse initialisation error.\n");
+       else
+               printk("Bus mouse detected and installed.\n");
+       return msedev < 0 ? msedev : 0;
 }
 
 #ifdef MODULE
@@ -238,6 +134,6 @@ int init_module(void)
 
 void cleanup_module(void)
 {
-       misc_deregister(&atixl_mouse);
+       unregister_busmouse(msedev);
 }
 #endif
index 70b75ecc13cb70f3c690af693437f7781096fb80..e3bbf306edc05817b9b025868cd02cc3c621557b 100644 (file)
 /*
- * Logitech Bus Mouse Driver for Linux
- * by James Banks
+ * linux/drivers/char/mouse.c
  *
- * Mods by Matthew Dillon
- *   calls verify_area()
- *   tracks better when X is busy or paging
+ * Copyright (C) 1995 - 1998 Russell King
+ *  Protocol taken from busmouse.c
+ *  read() waiting taken from psaux.c
  *
- * Heavily modified by David Giller
- *   changed from queue- to counter- driven
- *   hacked out a (probably incorrect) mouse_select
+ * Medium-level interface for quadrature or bus mice.
  *
- * Modified again by Nathan Laredo to interface with
- *   0.96c-pl1 IRQ handling changes (13JUL92)
- *   didn't bother touching select code.
+ * Currently, the majority of kernel busmice drivers in the
+ * kernel common code to talk to userspace.  This driver
+ * attempts to rectify this situation by presenting a
+ * simple and safe interface to the mice and user.
  *
- * Modified the select() code blindly to conform to the VFS
- *   requirements. 92.07.14 - Linus. Somebody should test it out.
- *
- * Modified by Johan Myreen to make room for other mice (9AUG92)
- *   removed assignment chr_fops[10] = &mouse_fops; see mouse.c
- *   renamed mouse_fops => bus_mouse_fops, made bus_mouse_fops public.
- *   renamed this file mouse.c => busmouse.c
- *
- * Minor addition by Cliff Matthews
- *   added fasync support
- *
- * Modularised 6-Sep-95 Philip Blundell <pjb27@cam.ac.uk> 
- *
- * Replaced dumb busy loop with udelay()  16 Nov 95
- *   Nathan Laredo <laredo@gnu.ai.mit.edu>
- *
- * Track I/O ports with request_region().  12 Dec 95 Philip Blundell 
+ * This driver:
+ *  - is SMP safe
+ *  - handles multiple opens
+ *  - handles the wakeups and locking
+ *  - has optional blocking reads
  */
 
 #include <linux/module.h>
-
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/busmouse.h>
 #include <linux/signal.h>
+#include <linux/malloc.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/poll.h>
 #include <linux/miscdevice.h>
 #include <linux/random.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
 #include <linux/init.h>
 
-#include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
-#include <asm/irq.h>
+#include <asm/io.h>
 
-static struct mouse_status mouse;
-static int mouse_irq = MOUSE_IRQ;
+#include "busmouse.h"
 
-#ifdef MODULE
-MODULE_PARM(mouse_irq, "i");
-#endif
+/* Uncomment this if your mouse drivers expect the kernel to
+ * return with EAGAIN if the mouse does not have any events
+ * available, even if the mouse is opened in nonblocking mode.
+ *
+ * Should this be on a per-mouse basis?  If so, add an entry to
+ * the struct busmouse structure and add the relevent flag to
+ * the drivers.
+ */
+/*#define BROKEN_MOUSE*/
+
+extern int adb_mouse_init(void);
+extern int bus_mouse_init(void);
+extern int ms_bus_mouse_init(void);
+extern int atixl_busmouse_init(void);
+extern int amiga_mouse_init(void);
+extern int atari_mouse_init(void);
+extern int sun_mouse_init(void);
+extern void mouse_rpc_init (void);
+
+struct busmouse_data {
+       struct miscdevice       miscdev;
+       struct busmouse         *ops;
+       spinlock_t              lock;
+
+       wait_queue_head_t       wait;
+       struct fasync_struct    *fasyncptr;
+       char                    active;
+       char                    buttons;
+       char                    latch_buttons;
+       char                    ready;
+       int                     dxpos;
+       int                     dypos;
+};
+
+#define NR_MICE                        15
+#define FIRST_MOUSE            0
+#define DEV_TO_MOUSE(dev)      MINOR_TO_MOUSE(MINOR(dev))
+#define MINOR_TO_MOUSE(minor)  ((minor) - FIRST_MOUSE)
+
+static struct busmouse_data *busmouse_data[NR_MICE];
 
-void __init bmouse_setup(char *str, int *ints)
+/* a mouse driver just has to interface with these functions
+ *  These are !!!OLD!!!  Do not use!!!
+ */
+void add_mouse_movement(int dx, int dy)
+{
+       struct busmouse_data *mse = busmouse_data[MINOR_TO_MOUSE(6)];
+
+       mse->dxpos += dx;
+       mse->dypos += dy;
+       mse->ready = 1;
+       wake_up(&mse->wait);
+}
+
+int add_mouse_buttonchange(int set, int value)
 {
-       if (ints[0] > 0)
-               mouse_irq=ints[1];
+       struct busmouse_data *mse = busmouse_data[MINOR_TO_MOUSE(6)];
+
+       mse->buttons = (mse->buttons & ~set) ^ value;
+       mse->ready = 1;
+       wake_up(&mse->wait);
+       return mse->buttons;
 }
 
-static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+/* New interface.  !!! Use this one !!!
+ * These routines will most probably be called from interrupt.
+ */
+void
+busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons)
 {
-       char dx, dy;
-       unsigned char buttons;
-
-       outb(MSE_READ_X_LOW, MSE_CONTROL_PORT);
-       dx = (inb(MSE_DATA_PORT) & 0xf);
-       outb(MSE_READ_X_HIGH, MSE_CONTROL_PORT);
-       dx |= (inb(MSE_DATA_PORT) & 0xf) << 4;
-       outb(MSE_READ_Y_LOW, MSE_CONTROL_PORT );
-       dy = (inb(MSE_DATA_PORT) & 0xf);
-       outb(MSE_READ_Y_HIGH, MSE_CONTROL_PORT);
-       buttons = inb(MSE_DATA_PORT);
-       dy |= (buttons & 0xf) << 4;
-       buttons = ((buttons >> 5) & 0x07);
-       if (dx != 0 || dy != 0 || buttons != mouse.buttons) {
-         add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
-         mouse.buttons = buttons;
-         mouse.dx += dx;
-         mouse.dy -= dy;
-         mouse.ready = 1;
-         wake_up_interruptible(&mouse.wait);
-
-         /*
-          * keep dx/dy reasonable, but still able to track when X (or
-          * whatever) must page or is busy (i.e. long waits between
-          * reads)
-          */
-         if (mouse.dx < -2048)
-             mouse.dx = -2048;
-         if (mouse.dx >  2048)
-             mouse.dx =  2048;
-
-         if (mouse.dy < -2048)
-             mouse.dy = -2048;
-         if (mouse.dy >  2048)
-             mouse.dy =  2048;
-
-         if (mouse.fasyncptr)
-             kill_fasync(mouse.fasyncptr, SIGIO);
+       struct busmouse_data *mse = busmouse_data[mousedev];
+       int changed;
+
+       spin_lock(&mse->lock);
+       changed = (dx != 0 || dy != 0 || mse->buttons != buttons);
+
+       if (changed) {
+               add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
+
+               mse->buttons = buttons;
+//             mse->latch_buttons |= buttons;
+               mse->dxpos += dx;
+               mse->dypos += dy;
+               mse->ready = 1;
+
+               /*
+                * keep dx/dy reasonable, but still able to track when X (or
+                * whatever) must page or is busy (i.e. long waits between
+                * reads)
+                */
+               if (mse->dxpos < -2048)
+                       mse->dxpos = -2048;
+               if (mse->dxpos > 2048)
+                       mse->dxpos = 2048;
+               if (mse->dypos < -2048)
+                       mse->dypos = -2048;
+               if (mse->dypos > 2048)
+                       mse->dypos = 2048;
        }
-       MSE_INT_ON();
+
+       spin_unlock(&mse->lock);
+
+       if (changed) {
+               wake_up(&mse->wait);
+
+               if (mse->fasyncptr)
+                       kill_fasync(mse->fasyncptr, SIGIO);
+       }
+}
+
+void
+busmouse_add_movement(int mousedev, int dx, int dy)
+{
+       struct busmouse_data *mse = busmouse_data[mousedev];
+
+       busmouse_add_movementbuttons(mousedev, dx, dy, mse->buttons);
 }
 
-static int fasync_mouse(int fd, struct file *filp, int on)
+void
+busmouse_add_buttons(int mousedev, int clear, int eor)
 {
+       struct busmouse_data *mse = busmouse_data[mousedev];
+
+       busmouse_add_movementbuttons(mousedev, 0, 0, (mse->buttons & ~clear) ^ eor);
+}
+
+static int
+busmouse_fasync(int fd, struct file *filp, int on)
+{
+       struct busmouse_data *mse = (struct busmouse_data *)filp->private_data;
        int retval;
 
-       retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
+       retval = fasync_helper(fd, filp, on, &mse->fasyncptr);
        if (retval < 0)
                return retval;
        return 0;
 }
 
-/*
- * close access to the mouse
- */
-
-static int close_mouse(struct inode * inode, struct file * file)
+static int
+busmouse_release(struct inode *inode, struct file *file)
 {
-       fasync_mouse(-1, file, 0);
-       if (--mouse.active)
-               return 0;
-       MSE_INT_OFF();
-       free_irq(mouse_irq, NULL);
-       MOD_DEC_USE_COUNT;
-       return 0;
-}
+       struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
+       int ret = 0;
 
-/*
- * open access to the mouse
- */
+       busmouse_fasync(-1, file, 0);
 
-static int open_mouse(struct inode * inode, struct file * file)
+       if (--mse->active == 0) {
+               if (mse->ops &&
+                   mse->ops->release)
+                       ret = mse->ops->release(inode, file);
+
+               mse->ready = 0;
+
+               MOD_DEC_USE_COUNT;
+       }
+
+       return ret;
+}
+
+static int
+busmouse_open(struct inode *inode, struct file *file)
 {
-       if (!mouse.present)
+       struct busmouse_data *mse;
+       unsigned long flags;
+       unsigned int mousedev;
+       int ret = 0;
+
+       mousedev = DEV_TO_MOUSE(inode->i_rdev);
+       if (mousedev >= NR_MICE)
                return -EINVAL;
-       if (mouse.active++)
+       mse = busmouse_data[mousedev];
+       if (!mse)
+               /* shouldn't happen, but... */
+               return -ENODEV;
+
+       if (mse->ops &&
+           mse->ops->open)
+               ret = mse->ops->open(inode, file);
+
+       if (ret)
+               return ret;
+
+       file->private_data = mse;
+
+       if (mse->active++)
                return 0;
-       if (request_irq(mouse_irq, mouse_interrupt, 0, "busmouse", NULL)) {
-               mouse.active--;
-               return -EBUSY;
-       }
-       mouse.ready = 0;
-       mouse.dx = 0;
-       mouse.dy = 0;
-       mouse.buttons = 0x87;
+
        MOD_INC_USE_COUNT;
-       MSE_INT_ON();
+
+       spin_lock_irqsave(&mse->lock, flags);
+
+       mse->ready   = 0;
+       mse->dxpos   = 0;
+       mse->dypos   = 0;
+       if (mse->ops)
+               mse->buttons = mse->ops->init_button_state;
+       else
+               mse->buttons = 7;
+
+       spin_unlock_irqrestore(&mse->lock, flags);
+
        return 0;
 }
 
-/*
- * writes are disallowed
- */
-
-static ssize_t write_mouse(struct file * file,
-       const char * buffer, size_t count, loff_t *ppos)
+static ssize_t
+busmouse_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
        return -EINVAL;
 }
 
-/*
- * read mouse data.  Currently never blocks.
- */
-
-static ssize_t read_mouse(struct file * file,
-       char * buffer, size_t count, loff_t *ppos)
+static ssize_t
+busmouse_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
-       int r;
-       int dx;
-       int dy;
-       unsigned char buttons; 
-       /* long flags; */
+       struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
+       unsigned long flags;
+       int dxpos, dypos, buttons;
 
        if (count < 3)
                return -EINVAL;
-       if ((r = verify_area(VERIFY_WRITE, buffer, count)))
-               return r;
-       if (!mouse.ready)
+
+       spin_lock_irqsave(&mse->lock, flags);
+
+       if (!mse->ready) {
+#ifdef BROKEN_MOUSE
+               spin_unlock_irqrestore(&mse->lock, flags);
                return -EAGAIN;
+#else
+               if (file->f_flags & O_NONBLOCK) {
+                       spin_unlock_irqrestore(&mse->lock, flags);
+                       return -EAGAIN;
+               }
+
+               add_wait_queue(&mse->wait, &wait);
+repeat:
+               current->state = TASK_INTERRUPTIBLE;
+               if (!mse->ready && !signal_pending(current)) {
+                       spin_unlock_irqrestore(&mse->lock, flags);
+                       schedule();
+                       spin_lock_irqsave(&mse->lock, flags);
+                       goto repeat;
+               }
+
+               current->state = TASK_RUNNING;
+               remove_wait_queue(&mse->wait, &wait);
+
+               if (signal_pending(current)) {
+                       spin_unlock_irqrestore(&mse->lock, flags);
+                       return -ERESTARTSYS;
+               }
+#endif
+       }
 
-       /*
-        * Obtain the current mouse parameters and limit as appropriate for
-        * the return data format.  Interrupts are only disabled while 
-        * obtaining the parameters, NOT during the puts_fs_byte() calls,
-        * so paging in put_user() does not effect mouse tracking.
+       dxpos = mse->dxpos;
+       dypos = mse->dypos;
+       buttons = mse->buttons;
+//     mse->latch_buttons = mse->buttons;
+
+       if (dxpos < -127)
+               dxpos =- 127;
+       if (dxpos > 127)
+               dxpos = 127;
+       if (dypos < -127)
+               dypos =- 127;
+       if (dypos > 127)
+               dypos = 127;
+
+       mse->dxpos -= dxpos;
+       mse->dypos -= dypos;
+
+       /* This is something that many drivers have apparantly
+        * forgotten...  If the X and Y positions still contain
+        * information, we still have some info ready for the
+        * user program...
         */
+       mse->ready = mse->dxpos || mse->dypos;
+
+       spin_unlock_irqrestore(&mse->lock, flags);
+
+       /* Write out data to the user.  Format is:
+        *   byte 0 - identifer (0x80) and (inverted) mouse buttons
+        *   byte 1 - X delta position +/- 127
+        *   byte 2 - Y delta position +/- 127
+        */
+       if (put_user((char)buttons | 128, buffer) ||
+           put_user((char)dxpos, buffer + 1) ||
+           put_user((char)dypos, buffer + 2))
+               return -EFAULT;
+
+       if (count > 3 && clear_user(buffer + 3, count - 3))
+               return -EFAULT;
 
-       /* save_flags(flags); cli(); */
-       disable_irq(mouse_irq);
-       dx = mouse.dx;
-       dy = mouse.dy;
-       if (dx < -127)
-           dx = -127;
-       if (dx > 127)
-           dx = 127;
-       if (dy < -127)
-           dy = -127;
-       if (dy > 127)
-           dy = 127;
-       buttons = mouse.buttons;
-       mouse.dx -= dx;
-       mouse.dy -= dy;
-       mouse.ready = 0;
-       enable_irq(mouse_irq);
-       /* restore_flags(flags); */
-
-       put_user(buttons | 0x80, buffer);
-       put_user((char)dx, buffer + 1);
-       put_user((char)dy, buffer + 2);
-       for (r = 3; r < count; r++)
-           put_user(0x00, buffer + r);
-       return r;
+       file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+
+       return count;
 }
 
-/*
- * poll for mouse input
- */
-static unsigned int mouse_poll(struct file *file, poll_table * wait)
+static unsigned int
+busmouse_poll(struct file *file, poll_table *wait)
 {
-       poll_wait(file, &mouse.wait, wait);
-       if (mouse.ready)
+       struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
+
+       poll_wait(file, &mse->wait, wait);
+
+       if (mse->ready)
                return POLLIN | POLLRDNORM;
+
        return 0;
 }
 
-struct file_operations bus_mouse_fops = {
-       NULL,           /* mouse_seek */
-       read_mouse,
-       write_mouse,
-       NULL,           /* mouse_readdir */
-       mouse_poll,     /* mouse_poll */
-       NULL,           /* mouse_ioctl */
-       NULL,           /* mouse_mmap */
-       open_mouse,
-       NULL,           /* flush */
-       close_mouse,
+struct file_operations busmouse_fops=
+{
+       NULL,                   /* busmouse_seek */
+       busmouse_read,
+       busmouse_write,
+       NULL,                   /* busmouse_readdir */
+       busmouse_poll,
+       NULL,                   /* busmouse_ioctl */
+       NULL,                   /* busmouse_mmap */
+       busmouse_open,
+       NULL,                   /* busmouse_flush */
+       busmouse_release,
        NULL,
-       fasync_mouse,
+       busmouse_fasync,
 };
 
-static struct miscdevice bus_mouse = {
-       LOGITECH_BUSMOUSE, "busmouse", &bus_mouse_fops
-};
+int
+register_busmouse(struct busmouse *ops)
+{
+       unsigned int msedev = MINOR_TO_MOUSE(ops->minor);
+       struct busmouse_data *mse;
+       int ret;
+
+       if (msedev >= NR_MICE) {
+               printk(KERN_ERR "busmouse: trying to allocate mouse on minor %d\n",
+                      ops->minor);
+               return -EINVAL;
+       }
+
+       if (busmouse_data[msedev])
+               return -EBUSY;
+
+       mse = kmalloc(GFP_KERNEL, sizeof(*mse));
+       if (!mse)
+               return -ENOMEM;
 
-int __init bus_mouse_init(void)
+       memset(mse, 0, sizeof(*mse));
+
+       mse->miscdev.minor = ops->minor;
+       mse->miscdev.name = ops->name;
+       mse->miscdev.fops = &busmouse_fops;
+       mse->ops = ops;
+       mse->lock = (spinlock_t)SPIN_LOCK_UNLOCKED;
+       init_waitqueue_head(&mse->wait);
+
+       busmouse_data[msedev] = mse;
+
+       ret = misc_register(&mse->miscdev);
+       if (!ret)
+               ret = msedev;
+
+       return ret;
+}
+
+int
+unregister_busmouse(int mousedev)
 {
-       if (check_region(LOGIBM_BASE, LOGIBM_EXTENT)) {
-         mouse.present = 0;
-         return -EIO;
+       if (mousedev < 0)
+               return 0;
+       if (mousedev >= NR_MICE) {
+               printk(KERN_ERR "busmouse: trying to free mouse on"
+                      " mousedev %d\n", mousedev);
+               return -EINVAL;
        }
 
-       outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT);
-       outb(MSE_SIGNATURE_BYTE, MSE_SIGNATURE_PORT);
-       udelay(100L);   /* wait for reply from mouse */
-       if (inb(MSE_SIGNATURE_PORT) != MSE_SIGNATURE_BYTE) {
-               mouse.present = 0;
-               return -EIO;
+       if (!busmouse_data[mousedev]) {
+               printk(KERN_WARNING "busmouse: trying to free free mouse"
+                      " on mousedev %d\n", mousedev);
+               return -EINVAL;
+       }
+
+       if (busmouse_data[mousedev]->active) {
+               printk(KERN_ERR "busmouse: trying to free active mouse"
+                      " on mousedev %d\n", mousedev);
+               return -EINVAL;
        }
-       outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT);
-       MSE_INT_OFF();
-       
-       request_region(LOGIBM_BASE, LOGIBM_EXTENT, "busmouse");
-
-       mouse.present = 1;
-       mouse.active = 0;
-       mouse.ready = 0;
-       mouse.buttons = 0x87;
-       mouse.dx = 0;
-       mouse.dy = 0;
-       init_waitqueue_head(&mouse.wait);
-       printk(KERN_INFO "Logitech bus mouse detected, using IRQ %d.\n",
-              mouse_irq);
-       misc_register(&bus_mouse);
+
+       misc_deregister(&busmouse_data[mousedev]->miscdev);
+
+       kfree(busmouse_data[mousedev]);
+       busmouse_data[mousedev] = NULL;
        return 0;
 }
 
-#ifdef MODULE
+__initfunc(int
+bus_mouse_init(void))
+{
+#ifdef CONFIG_BUSMOUSE
+       bus_mouse_init();
+#endif
+#ifdef CONFIG_MS_BUSMOUSE
+       ms_bus_mouse_init();
+#endif
+#ifdef CONFIG_ATIXL_BUSMOUSE
+       atixl_busmouse_init();
+#endif
+#ifdef CONFIG_AMIGAMOUSE
+       amiga_mouse_init();
+#endif
+#ifdef CONFIG_ATARIMOUSE
+       atari_mouse_init();
+#endif
+#ifdef CONFIG_MAC_MOUSE
+       mac_mouse_init();
+#endif
+#ifdef CONFIG_SUN_MOUSE
+       sun_mouse_init();
+#endif
+#ifdef CONFIG_ADBMOUSE
+       adb_mouse_init();
+#endif
+#ifdef CONFIG_RPCMOUSE
+       mouse_rpc_init();
+#endif
+       return 0;
+}
+
+EXPORT_SYMBOL(busmouse_add_movement);
+EXPORT_SYMBOL(busmouse_add_buttons);
+EXPORT_SYMBOL(register_busmouse);
+EXPORT_SYMBOL(unregister_busmouse);
 
-int init_module(void)
+#ifdef MODULE
+int
+init_module(void)
 {
        return bus_mouse_init();
 }
 
-void cleanup_module(void)
+void
+cleanup_module(void)
 {
-       misc_deregister(&bus_mouse);
-       release_region(LOGIBM_BASE, LOGIBM_EXTENT);
 }
 #endif
diff --git a/drivers/char/busmouse.h b/drivers/char/busmouse.h
new file mode 100644 (file)
index 0000000..3626334
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * linux/drivers/char/mouse.h
+ *
+ * Copyright (C) 1995 - 1998 Russell King
+ *
+ * Prototypes for generic busmouse interface
+ */
+#ifndef MOUSE_H
+#define MOUSE_H
+
+struct busmouse {
+       int minor;
+       const char *name;
+       int (*open)(struct inode * inode, struct file * file);
+       int (*release)(struct inode * inode, struct file * file);
+       int init_button_state;
+};
+
+extern void busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons);
+extern void busmouse_add_movement(int mousedev, int dx, int dy);
+extern void busmouse_add_buttons(int mousedev, int clear, int eor);
+
+extern int register_busmouse(struct busmouse *ops);
+extern int unregister_busmouse(int mousedev);
+
+extern int bus_mouse_init(void);
+
+#endif
diff --git a/drivers/char/logibusmouse.c b/drivers/char/logibusmouse.c
new file mode 100644 (file)
index 0000000..02ba7a9
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Logitech Bus Mouse Driver for Linux
+ * by James Banks
+ *
+ * Mods by Matthew Dillon
+ *   calls verify_area()
+ *   tracks better when X is busy or paging
+ *
+ * Heavily modified by David Giller
+ *   changed from queue- to counter- driven
+ *   hacked out a (probably incorrect) mouse_select
+ *
+ * Modified again by Nathan Laredo to interface with
+ *   0.96c-pl1 IRQ handling changes (13JUL92)
+ *   didn't bother touching select code.
+ *
+ * Modified the select() code blindly to conform to the VFS
+ *   requirements. 92.07.14 - Linus. Somebody should test it out.
+ *
+ * Modified by Johan Myreen to make room for other mice (9AUG92)
+ *   removed assignment chr_fops[10] = &mouse_fops; see mouse.c
+ *   renamed mouse_fops => bus_mouse_fops, made bus_mouse_fops public.
+ *   renamed this file mouse.c => busmouse.c
+ *
+ * Minor addition by Cliff Matthews
+ *   added fasync support
+ *
+ * Modularised 6-Sep-95 Philip Blundell <pjb27@cam.ac.uk> 
+ *
+ * Replaced dumb busy loop with udelay()  16 Nov 95
+ *   Nathan Laredo <laredo@gnu.ai.mit.edu>
+ *
+ * Track I/O ports with request_region().  12 Dec 95 Philip Blundell
+ *
+ * Converted to use new generic busmouse code.  5 Apr 1998
+ *   Russell King <rmk@arm.uk.linux.org>
+ */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/logibusmouse.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+
+#include "busmouse.h"
+
+static int msedev;
+static int mouse_irq = MOUSE_IRQ;
+
+#ifdef MODULE
+MODULE_PARM(mouse_irq, "i");
+#endif
+
+void __init bmouse_setup(char *str, int *ints)
+{
+       if (ints[0] > 0)
+               mouse_irq=ints[1];
+}
+
+static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       char dx, dy;
+       unsigned char buttons;
+
+       outb(MSE_READ_X_LOW, MSE_CONTROL_PORT);
+       dx = (inb(MSE_DATA_PORT) & 0xf);
+       outb(MSE_READ_X_HIGH, MSE_CONTROL_PORT);
+       dx |= (inb(MSE_DATA_PORT) & 0xf) << 4;
+       outb(MSE_READ_Y_LOW, MSE_CONTROL_PORT );
+       dy = (inb(MSE_DATA_PORT) & 0xf);
+       outb(MSE_READ_Y_HIGH, MSE_CONTROL_PORT);
+       buttons = inb(MSE_DATA_PORT);
+       dy |= (buttons & 0xf) << 4;
+       buttons = ((buttons >> 5) & 0x07);
+       busmouse_add_movementbuttons(msedev, dx, -dy, buttons);
+       MSE_INT_ON();
+}
+
+/*
+ * close access to the mouse
+ */
+static int close_mouse(struct inode * inode, struct file * file)
+{
+       MSE_INT_OFF();
+       free_irq(mouse_irq, NULL);
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+/*
+ * open access to the mouse
+ */
+
+static int open_mouse(struct inode * inode, struct file * file)
+{
+       if (request_irq(mouse_irq, mouse_interrupt, 0, "busmouse", NULL))
+               return -EBUSY;
+       MOD_INC_USE_COUNT;
+       MSE_INT_ON();
+       return 0;
+}
+
+static struct busmouse busmouse = {
+       LOGITECH_BUSMOUSE, "busmouse", open_mouse, close_mouse, 7
+};
+
+int __init bus_mouse_init(void)
+{
+       if (check_region(LOGIBM_BASE, LOGIBM_EXTENT))
+               return -EIO;
+
+       outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT);
+       outb(MSE_SIGNATURE_BYTE, MSE_SIGNATURE_PORT);
+       udelay(100L);   /* wait for reply from mouse */
+       if (inb(MSE_SIGNATURE_PORT) != MSE_SIGNATURE_BYTE)
+               return -EIO;
+
+       outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT);
+       MSE_INT_OFF();
+       
+       request_region(LOGIBM_BASE, LOGIBM_EXTENT, "busmouse");
+
+       msedev = register_busmouse(&busmouse);
+       if (msedev < 0)
+               printk(KERN_WARNING "Unable to register busmouse driver.\n");
+       else
+               printk(KERN_INFO "Logitech busmouse installed.\n");
+       return msedev < 0 ? msedev : 0;
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+       return bus_mouse_init();
+}
+
+void cleanup_module(void)
+{
+       unregister_busmouse(msedev);
+       release_region(LOGIBM_BASE, LOGIBM_EXTENT);
+}
+#endif
diff --git a/drivers/char/macmouse.c b/drivers/char/macmouse.c
new file mode 100644 (file)
index 0000000..53a579f
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Macintosh ADB Mouse driver for Linux
+ *
+ * 27 Oct 1997 Michael Schmitz
+ *
+ * Apple mouse protocol according to:
+ *
+ * Device code shamelessly stolen from:
+ */
+/*
+ * Atari Mouse Driver for Linux
+ * by Robert de Vries (robert@and.nl) 19Jul93
+ *
+ * 16 Nov 1994 Andreas Schwab
+ * Compatibility with busmouse
+ * Support for three button mouse (shamelessly stolen from MiNT)
+ * third button wired to one of the joystick directions on joystick 1
+ *
+ * 1996/02/11 Andreas Schwab
+ * Module support
+ * Allow multiple open's
+ *
+ * Converted to use new generic busmouse code.  5 Apr 1998
+ *   Russell King <rmk@arm.uk.linux.org>
+ */
+
+#include <linux/module.h>
+
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+
+#include <asm/setup.h>
+#include <asm/mac_mouse.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+#include "busmouse.h"
+
+static int msedev;
+static int mac_mouse_x_threshold = 2, mac_mouse_y_threshold = 2;
+static int mac_mouse_buttons = 0;
+
+extern void (*mac_mouse_interrupt_hook) (char *, int);
+extern int mac_emulate_button2;
+extern int mac_emulate_button3;
+
+extern int console_loglevel;
+
+/*
+ *     XXX: need to figure out what ADB mouse packets mean ... 
+ *     This is the stuff stolen from the Atari driver ...
+ */
+static void mac_mouse_interrupt(char *buf, int nb)
+{
+    static int buttons = 7;    /* all mouse buttons _up_ !! */
+
+  /*
+    Handler 1 -- 100cpi original Apple mouse protocol.
+    Handler 2 -- 200cpi original Apple mouse protocol.
+
+    For Apple's standard one-button mouse protocol the data array will
+    contain the following values:
+
+                BITS    COMMENTS
+    data[0] = 0000 0000 ADB packet identifer.
+    data[1] = ???? ???? (?)
+    data[2] = ???? ??00 Bits 0-1 should be zero for a mouse device.
+    data[3] = bxxx xxxx First button and x-axis motion.
+    data[4] = byyy yyyy Second button and y-axis motion.
+
+    NOTE: data[0] is confirmed by the parent function and need not be
+    checked here.
+  */
+
+  /*
+    Handler 4 -- Apple Extended mouse protocol.
+
+    For Apple's 3-button mouse protocol the data array will contain the
+    following values:
+
+               BITS    COMMENTS
+    data[0] = 0000 0000 ADB packet identifer.
+    data[1] = 0100 0000 Extended protocol register.
+             Bits 6-7 are the device id, which should be 1.
+             Bits 4-5 are resolution which is in "units/inch".
+             The Logitech MouseMan returns these bits clear but it has
+             200/300cpi resolution.
+             Bits 0-3 are unique vendor id.
+    data[2] = 0011 1100 Bits 0-1 should be zero for a mouse device.
+             Bits 2-3 should be 8 + 4.
+                     Bits 4-7 should be 3 for a mouse device.
+    data[3] = bxxx xxxx Left button and x-axis motion.
+    data[4] = byyy yyyy Second button and y-axis motion.
+    data[5] = byyy bxxx Third button and fourth button.  
+             Y is additiona. high bits of y-axis motion.  
+             X is additional high bits of x-axis motion.
+
+    NOTE: data[0] and data[2] are confirmed by the parent function and
+    need not be checked here.
+  */
+
+    /*
+     * 'buttons' here means 'button down' states!
+     * Button 1 (left)  : bit 2, busmouse button 3
+     * Button 2 (right) : bit 0, busmouse button 1
+     * Button 3 (middle): bit 1, busmouse button 2
+     */
+
+    /* x/y and buttons swapped */
+    
+    if (buf[0] ==  0)  {                               /* real packet : use buttons? */
+#ifdef DEBUG_ADBMOUSE
+       if (console_loglevel >= 8)
+           printk("mac_mouse: real data; "); 
+#endif
+       /* button 1 (left, bit 2) : always significant ! */
+       buttons = (buttons&3) | (buf[3] & 0x80 ? 4 : 0); /* 1+2 unchanged */
+       /* button 2 (right, bit 0) present ? */
+       if ( !mac_emulate_button2 ) 
+           buttons = (buttons&6) | (buf[4] & 0x80 ? 1 : 0); /* 2+3 unchanged */
+       /* button 2 (middle) present? */
+       /* data valid only if extended mouse format ! (buf[3] = 0 else)*/
+       if ( !mac_emulate_button3 && buf[1]&0x40 )
+           buttons = (buttons&5) | (buf[5] & 0x80 ? 2 : 0); /* 1+3 unchanged */
+    } else {                                   /* fake packet : use 2+3 */
+#ifdef DEBUG_ADBMOUSE
+       if (console_loglevel >= 8)
+           printk("mac_mouse: fake data; "); 
+#endif
+       /* we only see state changes here, but the fake driver takes care
+        * to preserve state... button 1 state must stay unchanged! */
+       buttons = (buttons&4) | ((buf[4] & 0x80 ? 1 : 0) | (buf[5] & 0x80 ? 2 : 0));
+    }
+
+    busmouse_add_movementbuttons(msedev,
+                                ((buf[4]&0x7f) < 64 ? (buf[4]&0x7f) : (buf[4]&0x7f)-128 ),
+                                -((buf[3]&0x7f) < 64 ? (buf[3]&0x7f) : (buf[3]&0x7f)-128 ),
+                                buttons & 7);
+}
+
+static int release_mouse(struct inode *inode, struct file *file)
+{
+    mac_mouse_interrupt_hook = NULL;
+    MOD_DEC_USE_COUNT;
+    return 0;
+}
+
+static int open_mouse(struct inode *inode, struct file *file)
+{
+    MOD_INC_USE_COUNT;
+    mac_mouse_interrupt_hook = mac_mouse_interrupt;
+    return 0;
+}
+
+#define ADB_MOUSE_MINOR        10
+
+static struct busmouse macmouse = {
+       ADB_MOUSE_MINOR, "adbmouse", open_mouse, release_mouse, 0
+};
+
+__initfunc(int mac_mouse_init(void))
+{
+    if (!MACH_IS_MAC)
+       return -ENODEV;
+
+    msedev = register_busmouse(&macmouse);
+    if (msedev < 0)
+       printk(KERN_WARNING "Unable to register ADB mouse driver.\n");
+    else
+       printk(KERN_INFO "Macintosh ADB mouse installed.\n");
+    return msedev < 0 ? msedev : 0;
+}
+
+
+#define        MIN_THRESHOLD 1
+#define        MAX_THRESHOLD 20        /* more seems not reasonable... */
+
+__initfunc(void mac_mouse_setup(char *str, int *ints))
+{
+    if (ints[0] < 1) {
+       printk( "mac_mouse_setup: no arguments!\n" );
+       return;
+    }
+    else if (ints[0] > 2) {
+       printk( "mac_mouse_setup: too many arguments\n" );
+    }
+
+    if (ints[1] < MIN_THRESHOLD || ints[1] > MAX_THRESHOLD)
+       printk( "mac_mouse_setup: bad threshold value (ignored)\n" );
+    else {
+       mac_mouse_x_threshold = ints[1];
+       mac_mouse_y_threshold = ints[1];
+       if (ints[0] > 1) {
+           if (ints[2] < MIN_THRESHOLD || ints[2] > MAX_THRESHOLD)
+               printk("mac_mouse_setup: bad threshold value (ignored)\n" );
+           else
+               mac_mouse_y_threshold = ints[2];
+       }
+    }
+       
+}
+
+#ifdef MODULE
+#include <asm/setup.h>
+
+int init_module(void)
+{
+    return mac_mouse_init();
+}
+
+void cleanup_module(void)
+{
+    unregister_busmouse(msedev);
+}
+#endif
index 6cdd774305f4d1a7964f5a607625ae0173799eaa..ff17cd842474f8496aae696f504b462c8d878dc5 100644 (file)
@@ -28,7 +28,7 @@
  *  corrected by Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
  * Changes for kmod (from kerneld):
      Cyrus Durgin <cider@speakeasy.org>
*     Cyrus Durgin <cider@speakeasy.org>
  */
 
 #include <linux/module.h>
@@ -48,6 +48,8 @@
 #include <linux/selection.h>
 #include <linux/kmod.h>
 
+#include "busmouse.h"
+
 /*
  * Head entry for the doubly linked miscdevice list
  */
@@ -59,14 +61,7 @@ static struct miscdevice misc_list = { 0, "head", NULL, &misc_list, &misc_list }
 #define DYNAMIC_MINORS 64 /* like dynamic majors */
 static unsigned char misc_minors[DYNAMIC_MINORS / 8];
 
-extern int bus_mouse_init(void);
-extern int qpmouse_init(void);
-extern int ms_bus_mouse_init(void);
-extern int atixl_busmouse_init(void);
-extern int amiga_mouse_init(void);
-extern int atari_mouse_init(void);
-extern int sun_mouse_init(void);
-extern int adb_mouse_init(void);
+extern int psaux_init(void);
 #ifdef CONFIG_SGI_NEWPORT_GFX
 extern void gfx_register(void);
 #endif
@@ -86,6 +81,10 @@ extern int radio_init(void);
 extern void hfmodem_init(void);
 extern int pc110pad_init(void);
 extern int pmu_device_init(void);
+extern int qpmouse_init(void);
+extern int ds1620_init(void);
+extern int nwbutton_init(void);
+extern int nwflash_init(void);
 
 static int misc_read_proc(char *buf, char **start, off_t offset,
                          int len, int *eof, void *private)
@@ -182,37 +181,19 @@ int misc_deregister(struct miscdevice * misc)
 EXPORT_SYMBOL(misc_register);
 EXPORT_SYMBOL(misc_deregister);
 
-static struct proc_dir_entry *proc_misc;       
+static struct proc_dir_entry *proc_misc;
 
 int __init misc_init(void)
 {
        proc_misc = create_proc_entry("misc", 0, 0);
        if (proc_misc)
                proc_misc->read_proc = misc_read_proc;
-#ifdef CONFIG_BUSMOUSE
+#ifdef CONFIG_MOUSE
        bus_mouse_init();
 #endif
 #if defined CONFIG_82C710_MOUSE
        qpmouse_init();
 #endif
-#ifdef CONFIG_MS_BUSMOUSE
-       ms_bus_mouse_init();
-#endif
-#ifdef CONFIG_ATIXL_BUSMOUSE
-       atixl_busmouse_init();
-#endif
-#ifdef CONFIG_AMIGAMOUSE
-       amiga_mouse_init();
-#endif
-#ifdef CONFIG_ATARIMOUSE
-       atari_mouse_init();
-#endif
-#ifdef CONFIG_SUN_MOUSE
-       sun_mouse_init();
-#endif
-#ifdef CONFIG_ADBMOUSE
-       adb_mouse_init();
-#endif
 #ifdef CONFIG_PC110_PAD
        pc110pad_init();
 #endif
@@ -275,6 +256,15 @@ int __init misc_init(void)
 #endif
 #ifdef CONFIG_SGI
        streamable_init ();
+#endif
+#ifdef CONFIG_DS1620
+       ds1620_init();
+#endif
+#ifdef CONFIG_NWBUTTON
+       nwbutton_init();
+#endif
+#ifdef CONFIG_NWFLASH
+       nwflash_init();
 #endif
        if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
                printk("unable to get major %d for misc devices\n",
index f580be0bba2e5f108effc2fbe0827e001b09e7e2..bff280ee770fc9bdba16f20388b498f8157781e4 100644 (file)
@@ -27,6 +27,9 @@
  *
  * Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
  *
+ * Converted to use new generic busmouse code.  5 Apr 1998
+ *   Russell King <rmk@arm.uk.linux.org>
+ *
  * version 0.3b
  */
 
@@ -35,7 +38,7 @@
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
-#include <linux/busmouse.h>
+#include <linux/logibusmouse.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
@@ -48,7 +51,9 @@
 #include <asm/system.h>
 #include <asm/irq.h>
 
-static struct mouse_status mouse;
+#include "busmouse.h"
+
+static int msedev;
 static int mouse_irq = MOUSE_IRQ;
 
 #ifdef MODULE
@@ -81,35 +86,17 @@ static void ms_mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT);
        outb((inb(MS_MSE_DATA_PORT) & 0xdf), MS_MSE_DATA_PORT);
 
-       if (dx != 0 || dy != 0 || buttons != mouse.buttons || ((~buttons) & 0x07)) {
-               add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
-               mouse.buttons = buttons;
-               mouse.dx += dx;
-               mouse.dy += dy;
-               mouse.ready = 1;
-               wake_up_interruptible(&mouse.wait);
-               if (mouse.fasyncptr)
-                       kill_fasync(mouse.fasyncptr, SIGIO);
-       }
-}
-
-static int fasync_mouse(int fd, struct file *filp, int on)
-{
-       int retval;
-
-       retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
-       if (retval < 0)
-               return retval;
-       return 0;
+       /* why did the original have:
+        * if (dx != 0 || dy != 0 || buttons != mouse.buttons ||
+        *    ((~buttons) & 0x07))
+        *    ^^^^^^^^^^^^^^^^^^^ this?
+        */
+       busmouse_add_movementbuttons(msedev, dx, -dy, buttons);
 }
 
 static int release_mouse(struct inode * inode, struct file * file)
 {
-       fasync_mouse(-1, file, 0);
-       if (--mouse.active)
-               return 0;
        MS_MSE_INT_OFF();
-       mouse.ready = 0; 
        free_irq(mouse_irq, NULL);
        MOD_DEC_USE_COUNT;
        return 0;
@@ -117,86 +104,24 @@ static int release_mouse(struct inode * inode, struct file * file)
 
 static int open_mouse(struct inode * inode, struct file * file)
 {
-       if (!mouse.present)
-               return -EINVAL;
-       if (mouse.active++)
-               return 0;
-       if (request_irq(mouse_irq, ms_mouse_interrupt, 0, "MS Busmouse", NULL)) {
-               mouse.active--;
+       if (request_irq(mouse_irq, ms_mouse_interrupt, 0, "MS Busmouse", NULL))
                return -EBUSY;
-       }
-       mouse.ready = mouse.dx = mouse.dy = 0;  
-       mouse.buttons = 0x80;
+
        outb(MS_MSE_START, MS_MSE_CONTROL_PORT);
        MOD_INC_USE_COUNT;
        MS_MSE_INT_ON();        
        return 0;
 }
 
-static ssize_t write_mouse(struct file * file,
-       const char * buffer, size_t count, loff_t *ppos)
-{
-       return -EINVAL;
-}
-
-static ssize_t read_mouse(struct file * file,
-       char * buffer, size_t count, loff_t *ppos)
-{
-       int i, dx, dy;
-
-       if (count < 3)
-               return -EINVAL;
-       if (!mouse.ready)
-               return -EAGAIN;
-       put_user(mouse.buttons | 0x80, buffer);
-       dx = mouse.dx < -127 ? -127 : mouse.dx > 127 ?  127 :  mouse.dx;
-       dy = mouse.dy < -127 ?  127 : mouse.dy > 127 ? -127 : -mouse.dy;
-       put_user((char)dx, buffer + 1);
-       put_user((char)dy, buffer + 2);
-       for (i = 3; i < count; i++)
-               put_user(0x00, buffer + i);
-       mouse.dx -= dx;
-       mouse.dy += dy;
-       mouse.ready = 0;
-       return i;       
-}
-
-static unsigned int mouse_poll(struct file *file, poll_table * wait)
-{
-       poll_wait(file, &mouse.wait, wait);
-       if (mouse.ready) 
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-struct file_operations ms_bus_mouse_fops = {
-       NULL,           /* mouse_seek */
-       read_mouse,
-       write_mouse,
-       NULL,           /* mouse_readdir */
-       mouse_poll,     /* mouse_poll */
-       NULL,           /* mouse_ioctl */
-       NULL,           /* mouse_mmap */
-       open_mouse,
-       NULL,           /* flush */
-       release_mouse,
-       NULL,
-       fasync_mouse,
-};
-
-static struct miscdevice ms_bus_mouse = {
-       MICROSOFT_BUSMOUSE, "msbusmouse", &ms_bus_mouse_fops
+static struct busmouse msbusmouse = {
+       MICROSOFT_BUSMOUSE, "msbusmouse", open_mouse, release_mouse, 0
 };
 
 __initfunc(int ms_bus_mouse_init(void))
 {
+       int present = 0;
        int mse_byte, i;
 
-       mouse.present = mouse.active = mouse.ready = 0;
-       mouse.buttons = 0x80;
-       mouse.dx = mouse.dy = 0;
-       init_waitqueue_head(&mouse.wait);
-
        if (check_region(MS_MSE_CONTROL_PORT, 0x04))
                return -ENODEV;
 
@@ -207,20 +132,23 @@ __initfunc(int ms_bus_mouse_init(void))
                for (i = 0; i < 4; i++) {
                        if (inb_p(MS_MSE_SIGNATURE_PORT) == 0xde) {
                                if (inb_p(MS_MSE_SIGNATURE_PORT) == mse_byte)
-                                       mouse.present = 1;
+                                       present = 1;
                                else
-                                       mouse.present = 0;
+                                       present = 0;
                        } else
-                               mouse.present = 0;
+                               present = 0;
                }
        }
-       if (mouse.present == 0)
+       if (present == 0)
                return -EIO;
        MS_MSE_INT_OFF();
        request_region(MS_MSE_CONTROL_PORT, 0x04, "MS Busmouse");
-       printk(KERN_INFO "Microsoft BusMouse detected and installed.\n");
-       misc_register(&ms_bus_mouse);
-       return 0;
+       msedev = register_busmouse(&msbusmouse);
+       if (msedev < 0)
+               printk(KERN_WARNING "Unable to register msbusmouse driver.\n");
+       else
+               printk(KERN_INFO "Microsoft BusMouse detected and installed.\n");
+       return msedev < 0 ? msedev : 0;
 }
 
 #ifdef MODULE
@@ -231,7 +159,7 @@ int init_module(void)
 
 void cleanup_module(void)
 {
-       misc_deregister(&ms_bus_mouse);
+       unregister_busmouse(msedev);
        release_region(MS_MSE_CONTROL_PORT, 0x04);
 }
 #endif
index 1b83e5f069f4508a54dad4e15400103b7abec8fd..d75eeb1621f2ecf115756011ca0e083f00cd3624 100644 (file)
@@ -518,11 +518,14 @@ void pckbd_leds(unsigned char leds)
 #endif
 
 /* for "kbd-reset" cmdline param */
-void __init kbd_reset_setup(char *str, int *ints)
+static int __init kbd_reset_setup(char *str)
 {
        kbd_startup_reset = 1;
+       return 1;
 }
 
+__setup("kbd-reset", kbd_reset_setup);
+
 #define KBD_NO_DATA    (-1)    /* No data */
 #define KBD_BAD_DATA   (-2)    /* Parity or other error */
 
index 69d383a453c777e634c5000a5264335940341aa4..b4ebc6e42e77acf272cadd9ada1dc638d146140f 100644 (file)
@@ -1,14 +1,14 @@
-/* drivers/net/eepro100.c: An Intel i82557 Ethernet driver for Linux. */
+/* drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux. */
 /*
    NOTICE: this version tested with kernels 1.3.72 and later only!
-       Written 1996-1998 by Donald Becker.
+       Written 1996-1999 by Donald Becker.
 
        This software may be used and distributed according to the terms
        of the GNU Public License, incorporated herein by reference.
 
-       This driver is for the Intel EtherExpress Pro 100B boards.
-       It should work with other i82557 and i82558 boards.
-       To use a built-in driver, install as drivers/net/eepro100.c.
+       This driver is for the Intel EtherExpress Pro100 (Speedo3) design.
+       It should work with all i82557/558/559 boards.
+
        To use as a module, use the compile-command at the end of the file.
 
        The author may be reached as becker@CESDIS.usra.edu, or C/O
           Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771
        For updates see
                http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html
-       There is also a mailing list based at
+       For installation instructions
+               http://cesdis.gsfc.nasa.gov/linux/misc/modules.html
+       There is a Majordomo mailing list based at
                linux-eepro100@cesdis.gsfc.nasa.gov
 */
 
 static const char *version =
-"eepro100.c:v1.06 10/16/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n";
+"eepro100.c:v1.09j 7/27/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n";
 
 /* A few user-configurable values that apply to all boards.
-   First set are undocumented and spelled per Intel recommendations. */
+   First set is undocumented and spelled per Intel recommendations. */
 
 static int congenb = 0;                /* Enable congestion control in the DP83840. */
 static int txfifo = 8;         /* Tx FIFO threshold in 4 byte units, 0-15 */
@@ -38,14 +40,49 @@ static int rxdmacount = 0;
 static int rx_copybreak = 200;
 
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 200;
+static int max_interrupt_work = 20;
 
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */
-static int multicast_filter_limit = 3;
+static int multicast_filter_limit = 64;
 
-#include <linux/module.h>
+/* 'options' is used to pass a transceiver override or full-duplex flag
+   e.g. "options=16" for FD, "options=32" for 100mbps-only. */
+static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+#ifdef MODULE
+static int debug = -1;                 /* The debug level */
+#endif
 
+/* A few values that may be tweaked. */
+/* The ring sizes should be a power of two for efficiency. */
+#define TX_RING_SIZE   32              /* Effectively 2 entries fewer. */
+#define RX_RING_SIZE   32
+/* Actual number of TX packets queued, must be <= TX_RING_SIZE-2. */
+#define TX_QUEUE_LIMIT  12
+
+/* Operational parameters that usually are not changed. */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (2*HZ)
+/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/
+#define PKT_BUF_SZ             1536
+
+#if !defined(__OPTIMIZE__)  ||  !defined(__KERNEL__)
+#warning  You must compile this file with the correct options!
+#warning  See the last lines of the source file.
+#error You must compile this driver with "-O".
+#endif
+
+#include <linux/config.h>
 #include <linux/version.h>
+#include <linux/module.h>
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+
+#if LINUX_VERSION_CODE < 0x20200  &&  defined(MODVERSIONS)
+#include <linux/modversions.h>
+#endif
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/timer.h>
@@ -53,19 +90,24 @@ static int multicast_filter_limit = 3;
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
+#ifdef HAS_PCI_NETIF
+#include "pci-netif.h"
+#else
 #include <linux/pci.h>
+#if LINUX_VERSION_CODE < 0x20155
+#include <linux/bios32.h>              /* Ignore the bogus warning in 2.1.100+ */
+#endif
+#endif
+#include <asm/spinlock.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 
-#include <asm/spinlock.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-
-/*
- * Module documentation
- */
+#if LINUX_VERSION_CODE > 0x20118  &&  defined(MODULE)
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver");
 MODULE_PARM(debug, "i");
@@ -79,16 +121,39 @@ MODULE_PARM(rxdmacount, "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(multicast_filter_limit, "i");
+#endif
 
 #define RUN_AT(x) (jiffies + (x))
-
+/* Condensed bus+endian portability operations. */
+#define virt_to_le32bus(addr)  cpu_to_le32(virt_to_bus(addr))
+#define le32bus_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
+
+#if (LINUX_VERSION_CODE < 0x20123)
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#define le16_to_cpu(val) (val)
+#define cpu_to_le16(val) (val)
+#define le32_to_cpu(val) (val)
+#define cpu_to_le32(val) (val)
+#define spin_lock_irqsave(&sp->lock, flags)    save_flags(flags); cli();
+#define spin_unlock_irqrestore(&sp->lock, flags); restore_flags(flags);
+#endif
+#if LINUX_VERSION_CODE < 0x20159
+#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE);
+#else
 #define dev_free_skb(skb) dev_kfree_skb(skb);
+#endif
+#if ! defined(CAP_NET_ADMIN)
+#define capable(CAP_XXX) (suser())
+#endif
+#if ! defined(HAS_NETIF_QUEUE)
+#define netif_wake_queue(dev)  mark_bh(NET_BH);
+#endif
 
 /* The total I/O port extent of the board.
    The registers beyond 0x18 only exist on the i82558. */
 #define SPEEDO3_TOTAL_SIZE 0x20
 
-int speedo_debug = 0;
+int speedo_debug = 1;
 
 /*
                                Theory of Operation
@@ -222,15 +287,52 @@ having to sign an Intel NDA when I'm helping Intel sell their own product!
 
 */
 
-/* A few values that may be tweaked. */
-/* The ring sizes should be a power of two for efficiency. */
-#define TX_RING_SIZE   16              /* Effectively 2 entries fewer. */
-#define RX_RING_SIZE   16
-/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/
-#define PKT_BUF_SZ             1536
+/* This table drives the PCI probe routines. */
+static struct device *
+speedo_found1(int pci_bus, int pci_devfn, struct device *dev,
+                         long ioaddr, int irq, int chip_idx, int fnd_cnt);
 
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  ((800*HZ)/1000)
+#ifdef USE_IO
+#define SPEEDO_IOTYPE   PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR1
+#define SPEEDO_SIZE            32
+#else
+#define SPEEDO_IOTYPE   PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR0
+#define SPEEDO_SIZE            0x1000
+#endif
+
+#if defined(HAS_PCI_NETIF)
+struct pci_id_info static pci_tbl[] = {
+       { "Intel PCI EtherExpress Pro100",
+         { 0x12298086, 0xffffffff,}, SPEEDO_IOTYPE, SPEEDO_SIZE,
+         0, speedo_found1 },
+       {0,},                                           /* 0 terminated list. */
+};
+#else
+enum pci_flags_bit {
+       PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+       PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
+struct pci_id_info {
+       const char *name;
+       u16     vendor_id, device_id, device_id_mask, flags;
+       int io_size;
+       struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+                                                        long ioaddr, int irq, int chip_idx, int fnd_cnt);
+} static pci_tbl[] = {
+       { "Intel PCI EtherExpress Pro100",
+         0x8086, 0x1229, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 32, speedo_found1 },
+       {0,},                                           /* 0 terminated list. */
+};
+#endif
+
+#ifndef USE_IO
+#define inb readb
+#define inw readw
+#define inl readl
+#define outb writeb
+#define outw writew
+#define outl writel
+#endif
 
 /* How to wait for the command unit to accept a command.
    Typically this takes 0 ticks. */
@@ -241,10 +343,6 @@ static inline void wait_for_cmd_done(long cmd_ioaddr)
        while(inb(cmd_ioaddr) && --wait >= 0);
 }
 
-/* Operational parameter that usually are not changed. */
-
-/* The rest of these values should never change. */
-
 /* Offsets to the various registers.
    All accesses need not be longword aligned. */
 enum speedo_offsets {
@@ -257,33 +355,41 @@ enum speedo_offsets {
 };
 /* Commands that can be put in a command list entry. */
 enum commands {
-       CmdNOp = 0, CmdIASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
-       CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7,
-       CmdSuspend = 0x4000,            /* Suspend after completion. */
-       CmdIntr = 0x2000,                       /* Interrupt after completion. */
-       CmdTxFlex = 0x0008,                     /* Use "Flexible mode" for CmdTx command. */
+       CmdNOp = 0, CmdIASetup = 0x10000, CmdConfigure = 0x20000,
+       CmdMulticastList = 0x30000, CmdTx = 0x40000, CmdTDR = 0x50000,
+       CmdDump = 0x60000, CmdDiagnose = 0x70000,
+       CmdSuspend = 0x40000000,        /* Suspend after completion. */
+       CmdIntr = 0x20000000,           /* Interrupt after completion. */
+       CmdTxFlex = 0x00080000,         /* Use "Flexible mode" for CmdTx command. */
 };
+/* Do atomically if possible. */
+#if defined(__i386__) || defined(__alpha__)
+#define clear_suspend(cmd)   clear_bit(30, &(cmd)->cmd_status)
+#elif defined(__powerpc__)
+#define clear_suspend(cmd)     clear_bit(6, &(cmd)->cmd_status)
+#else
+#define clear_suspend(cmd)     (cmd)->cmd_status &= cpu_to_le32(~CmdSuspend)
+#endif
 
-/* The SCB accepts the following controls for the Tx and Rx units: */
-#define         CU_START               0x0010
-#define         CU_RESUME              0x0020
-#define         CU_STATSADDR   0x0040
-#define         CU_SHOWSTATS   0x0050  /* Dump statistics counters. */
-#define         CU_CMD_BASE    0x0060  /* Base address to add to add CU commands. */
-#define         CU_DUMPSTATS   0x0070  /* Dump then reset stats counters. */
-
-#define         RX_START       0x0001
-#define         RX_RESUME      0x0002
-#define         RX_ABORT       0x0004
-#define         RX_ADDR_LOAD   0x0006
-#define         RX_RESUMENR    0x0007
-#define INT_MASK       0x0100
-#define DRVR_INT       0x0200          /* Driver generated interrupt. */
+enum SCBCmdBits {
+     SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,
+     SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,
+     SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,
+     /* The rest are Rx and Tx commands. */
+     CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050,
+     CUCmdBase=0x0060,  /* CU Base address (set to zero) . */
+     CUDumpStats=0x0070, /* Dump then reset stats counters. */
+     RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006,
+     RxResumeNoResources=0x0007,
+};
+
+enum SCBPort_cmds {
+       PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3,
+};
 
 /* The Speedo3 Rx and Tx frame/buffer descriptors. */
 struct descriptor {                    /* A generic descriptor. */
-       s16 status;             /* Offset 0. */
-       s16 command;            /* Offset 2. */
+       s32 cmd_status;                 /* All command and status fields. */
        u32 link;                                       /* struct descriptor *  */
        unsigned char params[0];
 };
@@ -293,8 +399,7 @@ struct RxFD {                                       /* Receive frame descriptor. */
        s32 status;
        u32 link;                                       /* struct RxFD * */
        u32 rx_buf_addr;                        /* void * */
-       u16 count;
-       u16 size;
+       u32 count;
 };
 
 /* Selected elements of the Tx/RxFD.status word. */
@@ -302,7 +407,7 @@ enum RxFD_bits {
        RxComplete=0x8000, RxOK=0x2000,
        RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010,
        RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002,
-       StatusComplete=0x8000,
+       TxUnderrun=0x1000,  StatusComplete=0x8000,
 };
 
 struct TxFD {                                  /* Transmit frame descriptor set. */
@@ -338,49 +443,57 @@ struct speedo_stats {
        u32 done_marker;
 };
 
+/* Do not change the position (alignment) of the first few elements!
+   The later elements are grouped for cache locality. */
 struct speedo_private {
-       char devname[8];                        /* Used only for kernel debugging. */
-       const char *product_name;
-       struct device *next_module;
-       spinlock_t lock;
-       struct TxFD     tx_ring[TX_RING_SIZE]   /* Commands (usually CmdTxPacket). */
-                               __attribute__ ((aligned (L1_CACHE_BYTES)));;
-       /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+       struct TxFD     tx_ring[TX_RING_SIZE];  /* Commands (usually CmdTxPacket). */
+       struct RxFD *rx_ringp[RX_RING_SIZE];    /* Rx descriptor, used as ring. */
+       /* The addresses of a Tx/Rx-in-place packets/buffers. */
        struct sk_buff* tx_skbuff[TX_RING_SIZE];
-       struct descriptor  *last_cmd;   /* Last command sent. */
-       /* Rx descriptor ring & addresses of receive-in-place skbuffs. */
-       struct RxFD *rx_ringp[RX_RING_SIZE];
        struct sk_buff* rx_skbuff[RX_RING_SIZE];
+       struct descriptor  *last_cmd;   /* Last command sent. */
+       unsigned int cur_tx, dirty_tx;  /* The ring entries to be free()ed. */
+       spinlock_t lock;                                /* Group with Tx control cache line. */
+       u32 tx_threshold;                                       /* The value for txdesc.count. */
        struct RxFD *last_rxf;  /* Last command sent. */
+       unsigned int cur_rx, dirty_rx;          /* The next free ring entry */
+       long last_rx_time;                      /* Last Rx, in jiffies, to handle Rx hang. */
+       const char *product_name;
+       struct device *next_module;
+       void *priv_addr;                                        /* Unaligned address for kfree */
        struct enet_statistics stats;
        struct speedo_stats lstats;
+       int chip_id;
+       unsigned char pci_bus, pci_devfn, acpi_pwr;
        struct timer_list timer;        /* Media selection timer. */
-       long last_rx_time;                      /* Last Rx, in jiffies, to handle Rx hang. */
-       unsigned int cur_rx, cur_tx;            /* The next free ring entry */
-       unsigned int dirty_rx, dirty_tx;        /* The ring entries to be free()ed. */
        int mc_setup_frm_len;                           /* The length of an allocated.. */
        struct descriptor *mc_setup_frm;        /* ..multicast setup frame. */
        int mc_setup_busy;                                      /* Avoid double-use of setup frame. */
+       int in_interrupt;                                       /* Word-aligned dev->interrupt */
        char rx_mode;                                           /* Current PROMISC/ALLMULTI setting. */
        unsigned int tx_full:1;                         /* The Tx queue is full. */
        unsigned int full_duplex:1;                     /* Full-duplex operation requested. */
-       unsigned int default_port:1;            /* Last dev->if_port value. */
+       unsigned int flow_ctrl:1;                       /* Use 802.3x flow control. */
        unsigned int rx_bug:1;                          /* Work around receiver hang errata. */
        unsigned int rx_bug10:1;                        /* Receiver might hang at 10mbps. */
        unsigned int rx_bug100:1;                       /* Receiver might hang at 100mbps. */
+       unsigned char default_port:8;           /* Last dev->if_port value. */
        unsigned short phy[2];                          /* PHY media interfaces available. */
+       unsigned short advertising;                     /* Current PHY advertised caps. */
+       unsigned short partner;                         /* Link partner caps. */
+       long last_reset;
 };
 
 /* The parameters for a CmdConfigure operation.
    There are so many options that it would be difficult to document each bit.
    We mostly use the default or recommended settings. */
 const char i82557_config_cmd[22] = {
-       22, 0x08, 0, 0,  0, 0x80, 0x32, 0x03,  1, /* 1=Use MII  0=Use AUI */
+       22, 0x08, 0, 0,  0, 0, 0x32, 0x03,  1, /* 1=Use MII  0=Use AUI */
        0, 0x2E, 0,  0x60, 0,
        0xf2, 0x48,   0, 0x40, 0xf2, 0x80,              /* 0x40=Force full-duplex */
        0x3f, 0x05, };
 const char i82558_config_cmd[22] = {
-       22, 0x08, 0, 1,  0, 0x80, 0x22, 0x03,  1, /* 1=Use MII  0=Use AUI */
+       22, 0x08, 0, 1,  0, 0, 0x22, 0x03,  1, /* 1=Use MII  0=Use AUI */
        0, 0x2E, 0,  0x60, 0x08, 0x88,
        0x68, 0, 0x40, 0xf2, 0xBD,              /* 0xBD->0xFD=Force full-duplex */
        0x31, 0x05, };
@@ -394,16 +507,16 @@ static const char *phys[] = {
 enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
                                         S80C24, I82555, DP83840A=10, };
 static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };
+#define EE_READ_CMD            (6)
 
-static void speedo_found1(struct device *dev, long ioaddr, int irq,
-                                                 int card_idx);
-
-static int read_eeprom(long ioaddr, int location, int addr_len);
+static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);
 static int mdio_read(long ioaddr, int phy_id, int location);
 static int mdio_write(long ioaddr, int phy_id, int location, int value);
 static int speedo_open(struct device *dev);
+static void speedo_resume(struct device *dev);
 static void speedo_timer(unsigned long data);
 static void speedo_init_rx_ring(struct device *dev);
+static void speedo_tx_timeout(struct device *dev);
 static int speedo_start_xmit(struct sk_buff *skb, struct device *dev);
 static int speedo_rx(struct device *dev);
 static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
@@ -414,15 +527,6 @@ static void set_rx_mode(struct device *dev);
 
 \f
 
-/* The parameters that may be passed in... */
-/* 'options' is used to pass a transceiver override or full-duplex flag
-   e.g. "options=16" for FD, "options=32" for 100mbps-only. */
-static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-#ifdef MODULE
-static int debug = -1;                 /* The debug level */
-#endif
-
 #ifdef honor_default_port
 /* Optional driver feature to allow forcing the transceiver setting.
    Not recommended. */
@@ -433,6 +537,7 @@ static int mii_ctrl[8] = { 0x3300, 0x3100, 0x0000, 0x0100,
 /* A list of all installed Speedo devices, for removing the driver module. */
 static struct device *root_speedo_dev = NULL;
 
+#if ! defined(HAS_PCI_NETIF)
 int eepro100_init(struct device *dev)
 {
        int cards_found = 0;
@@ -443,6 +548,7 @@ int eepro100_init(struct device *dev)
 
        for (; pci_index < 8; pci_index++) {
                unsigned char pci_bus, pci_device_fn, pci_latency;
+               u32 pciaddr;
                long ioaddr;
                int irq;
 
@@ -453,13 +559,42 @@ int eepro100_init(struct device *dev)
                                                                pci_index, &pci_bus,
                                                                &pci_device_fn))
                        break;
+#if LINUX_VERSION_CODE >= 0x20155  ||  PCI_SUPPORT_1
                {
                        struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
-                       ioaddr = pdev->base_address[1];         /* Use [0] to mem-map */
+#ifdef USE_IO
+                       pciaddr = pdev->base_address[1];                /* Use [0] to mem-map */
+#else
+                       pciaddr = pdev->base_address[0];
+#endif
                        irq = pdev->irq;
                }
+#else
+               {
+                       u8 pci_irq_line;
+                       pcibios_read_config_byte(pci_bus, pci_device_fn,
+                                                                        PCI_INTERRUPT_LINE, &pci_irq_line);
+                       /* Note: BASE_ADDRESS_0 is for memory-mapping the registers. */
+#ifdef USE_IO
+                       pcibios_read_config_dword(pci_bus, pci_device_fn,
+                                                                         PCI_BASE_ADDRESS_1, &pciaddr);
+#else
+                       pcibios_read_config_dword(pci_bus, pci_device_fn,
+                                                                         PCI_BASE_ADDRESS_0, &pciaddr);
+#endif
+                       irq = pci_irq_line;
+               }
+#endif
                /* Remove I/O space marker in bit 0. */
-               ioaddr &= ~3;
+               if (pciaddr & 1) {
+                       ioaddr = pciaddr & ~3;
+                       if (check_region(ioaddr, 32))
+                               continue;
+               } else if ((ioaddr = (long)ioremap(pciaddr & ~0xf, 0x1000)) == 0) {
+                       printk(KERN_INFO "Failed to map PCI address %#x.\n",
+                                  pciaddr);
+                       continue;
+               }
                if (speedo_debug > 2)
                        printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",
                                   ioaddr, irq);
@@ -485,25 +620,29 @@ int eepro100_init(struct device *dev)
                } else if (speedo_debug > 1)
                        printk("  PCI latency timer (CFLT) is %#x.\n", pci_latency);
 
-               speedo_found1(dev, ioaddr, irq, cards_found);
+               speedo_found1(pci_bus, pci_device_fn, dev, ioaddr, irq, 0,cards_found);
                dev = NULL;
                cards_found++;
        }
 
        return cards_found;
 }
+#endif
 
-static void speedo_found1(struct device *dev, long ioaddr, int irq,
-                                                 int card_idx)
+static struct device *
+speedo_found1(int pci_bus, int pci_devfn, struct device *dev,
+                         long ioaddr, int irq, int chip_idx, int card_idx)
 {
-       static int did_version = 0;                     /* Already printed version info. */
        struct speedo_private *sp;
-       char *product;
+       const char *product;
        int i, option;
-       u16 eeprom[0x40];
-
+       u16 eeprom[0x100];
+       int acpi_idle_state = 0;
+#ifndef MODULE
+       static int did_version = 0;                     /* Already printed version info. */
        if (speedo_debug > 0  &&  did_version++ == 0)
                printk(version);
+#endif
 
        dev = init_etherdev(dev, sizeof(struct speedo_private));
 
@@ -514,16 +653,31 @@ static void speedo_found1(struct device *dev, long ioaddr, int irq,
        else
                option = 0;
 
+#if defined(HAS_PCI_NETIF)
+       acpi_idle_state = acpi_set_pwr_state(pci_bus, pci_devfn, ACPI_D0);
+#endif
+
        /* Read the station address EEPROM before doing the reset.
-          Perhaps this should even be done before accepting the device,
-          then we wouldn't have a device name with which to report the error. */
+          Nominally his should even be done before accepting the device, but
+          then we wouldn't have a device name with which to report the error.
+          The size test is for 6 bit vs. 8 bit address serial EEPROMs.
+       */
        {
                u16 sum = 0;
                int j;
-               int addr_len = read_eeprom(ioaddr, 0, 6) == 0xffff ? 8 : 6;
+               int read_cmd, ee_size;
+
+               if ((do_eeprom_cmd(ioaddr, EE_READ_CMD << 24, 27) & 0xffe0000)
+                       == 0xffe0000) {
+                       ee_size = 0x100;
+                       read_cmd = EE_READ_CMD << 24;
+               } else {
+                       ee_size = 0x40;
+                       read_cmd = EE_READ_CMD << 22;
+               }
 
-               for (j = 0, i = 0; i < 0x40; i++) {
-                       u16 value = read_eeprom(ioaddr, i, addr_len);
+               for (j = 0, i = 0; i < ee_size; i++) {
+                       u16 value = do_eeprom_cmd(ioaddr, read_cmd | (i << 16), 27);
                        eeprom[i] = value;
                        sum += value;
                        if (i < 3) {
@@ -542,12 +696,12 @@ static void speedo_found1(struct device *dev, long ioaddr, int irq,
        /* Reset the chip: stop Tx and Rx processes and clear counters.
           This takes less than 10usec and will easily finish before the next
           action. */
-       outl(0, ioaddr + SCBPort);
+       outl(PortReset, ioaddr + SCBPort);
 
        if (eeprom[3] & 0x0100)
                product = "OEM i82557/i82558 10/100 Ethernet";
        else
-               product = "Intel EtherExpress Pro 10/100";
+               product = pci_tbl[chip_idx].name;
 
        printk(KERN_INFO "%s: %s at %#3lx, ", dev->name, product, ioaddr);
 
@@ -600,7 +754,7 @@ static void speedo_found1(struct device *dev, long ioaddr, int irq,
                self_test_results = (s32*) ((((long) str) + 15) & ~0xf);
                self_test_results[0] = 0;
                self_test_results[1] = -1;
-               outl(virt_to_bus(self_test_results) | 1, ioaddr + SCBPort);
+               outl(virt_to_bus(self_test_results) | PortSelfTest, ioaddr + SCBPort);
                do {
                        udelay(10);
                } while (self_test_results[1] == -1  &&  --boguscnt >= 0);
@@ -624,19 +778,33 @@ static void speedo_found1(struct device *dev, long ioaddr, int irq,
        }
 #endif  /* kernel_bloat */
 
+       outl(PortReset, ioaddr + SCBPort);
+#if defined(HAS_PCI_NETIF)
+       /* Return the chip to its original power state. */
+       acpi_set_pwr_state(pci_bus, pci_devfn, acpi_idle_state);
+#endif
+
        /* We do a request_region() only to register /proc/ioports info. */
        request_region(ioaddr, SPEEDO3_TOTAL_SIZE, "Intel Speedo3 Ethernet");
 
        dev->base_addr = ioaddr;
        dev->irq = irq;
 
-       if (dev->priv == NULL)
-               dev->priv = kmalloc(sizeof(*sp), GFP_KERNEL);
        sp = dev->priv;
-       memset(sp, 0, sizeof(*sp));
+       if (dev->priv == NULL) {
+               void *mem = kmalloc(sizeof(*sp), GFP_KERNEL);
+               dev->priv = sp = mem;           /* Cache align here if kmalloc does not. */
+               sp->priv_addr = mem;
+       } else
+               memset(sp, 0, sizeof(*sp));
        sp->next_module = root_speedo_dev;
        root_speedo_dev = dev;
 
+       sp->pci_bus = pci_bus;
+       sp->pci_devfn = pci_devfn;
+       sp->chip_id = chip_idx;
+       sp->acpi_pwr = acpi_idle_state;
+
        sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
        if (card_idx >= 0) {
                if (full_duplex[card_idx] >= 0)
@@ -659,7 +827,7 @@ static void speedo_found1(struct device *dev, long ioaddr, int irq,
        dev->set_multicast_list = &set_rx_mode;
        dev->do_ioctl = &speedo_ioctl;
 
-       return;
+       return dev;
 }
 \f
 /* Serial EEPROM section.
@@ -668,47 +836,33 @@ static void speedo_found1(struct device *dev, long ioaddr, int irq,
 #define EE_SHIFT_CLK   0x01    /* EEPROM shift clock. */
 #define EE_CS                  0x02    /* EEPROM chip select. */
 #define EE_DATA_WRITE  0x04    /* EEPROM chip data in. */
-#define EE_WRITE_0             0x01
-#define EE_WRITE_1             0x05
 #define EE_DATA_READ   0x08    /* EEPROM chip data out. */
 #define EE_ENB                 (0x4800 | EE_CS)
+#define EE_WRITE_0             0x4802
+#define EE_WRITE_1             0x4806
+#define EE_OFFSET              SCBeeprom
 
 /* Delay between EEPROM clock transitions.
-   This will actually work with no delay on 33Mhz PCI.  */
-#define eeprom_delay(nanosec)          udelay(1);
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD   (5 << addr_len)
-#define EE_READ_CMD            (6 << addr_len)
-#define EE_ERASE_CMD   (7 << addr_len)
+   The code works with no delay on 33Mhz PCI.  */
+#define eeprom_delay() inw(ee_addr)
 
-static int read_eeprom(long ioaddr, int location, int addr_len)
+static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
 {
-       unsigned short retval = 0;
-       int ee_addr = ioaddr + SCBeeprom;
-       int read_cmd = location | EE_READ_CMD;
-       int i;
+       unsigned retval = 0;
+       long ee_addr = ioaddr + SCBeeprom;
 
-       outw(EE_ENB & ~EE_CS, ee_addr);
-       outw(EE_ENB, ee_addr);
+       outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
 
-       /* Shift the read command bits out. */
-       for (i = 12; i >= 0; i--) {
-               short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-               outw(EE_ENB | dataval, ee_addr);
-               eeprom_delay(100);
-               outw(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-               eeprom_delay(150);
-       }
-       outw(EE_ENB, ee_addr);
-
-       for (i = 15; i >= 0; i--) {
-               outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
-               eeprom_delay(100);
+       /* Shift the command bits out. */
+       do {
+               short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
+               outw(dataval, ee_addr);
+               eeprom_delay();
+               outw(dataval | EE_SHIFT_CLK, ee_addr);
+               eeprom_delay();
                retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
-               outw(EE_ENB, ee_addr);
-               eeprom_delay(100);
-       }
+       } while (--cmd_len >= 0);
+       outw(EE_ENB, ee_addr);
 
        /* Terminate the EEPROM access. */
        outw(EE_ENB & ~EE_CS, ee_addr);
@@ -723,6 +877,7 @@ static int mdio_read(long ioaddr, int phy_id, int location)
                val = inl(ioaddr + SCBCtrlMDI);
                if (--boguscnt < 0) {
                        printk(KERN_ERR " mdio_read() timed out with val = %8.8x.\n", val);
+                       break;
                }
        } while (! (val & 0x10000000));
        return val & 0xffff;
@@ -737,6 +892,7 @@ static int mdio_write(long ioaddr, int phy_id, int location, int value)
                val = inl(ioaddr + SCBCtrlMDI);
                if (--boguscnt < 0) {
                        printk(KERN_ERR" mdio_write() timed out with val = %8.8x.\n", val);
+                       break;
                }
        } while (! (val & 0x10000000));
        return val & 0xffff;
@@ -749,21 +905,31 @@ speedo_open(struct device *dev)
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
        long ioaddr = dev->base_addr;
 
-#ifdef notdef
-       /* We could reset the chip, but should not need to. */
-       /* In fact we MUST NOT, unless we also re-do the init */
-       outl(0, ioaddr + SCBPort);
-       udelay(10);
+#if defined(HAS_PCI_NETIF)
+       acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0);
 #endif
 
-       /* This had better be initialized before we initialize the interrupt! */
-       sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
-
        if (speedo_debug > 1)
                printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
 
-#ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us
-       /* Retrigger negotiation to reset previous errors. */
+       /* Set up the Tx queue early.. */
+       sp->cur_tx = 0;
+       sp->dirty_tx = 0;
+       sp->last_cmd = 0;
+       sp->tx_full = 0;
+       sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+       sp->in_interrupt = 0;
+
+       /* .. we can safely take handler calls during init. */
+       if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) {
+               return -EAGAIN;
+       }
+       MOD_INC_USE_COUNT;
+
+       dev->if_port = sp->default_port;
+#if 0
+       /* With some transceivers we must retrigger negotiation to reset
+          power-up errors. */
        if ((sp->phy[0] & 0x8000) == 0) {
                int phy_addr = sp->phy[0] & 0x1f ;
                /* Use 0x3300 for restarting NWay, other values to force xcvr:
@@ -780,85 +946,30 @@ speedo_open(struct device *dev)
        }
 #endif
 
-       /* Load the statistics block address. */
-       wait_for_cmd_done(ioaddr + SCBCmd);
-       outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer);
-       outw(INT_MASK | CU_STATSADDR, ioaddr + SCBCmd);
-       sp->lstats.done_marker = 0;
-
        speedo_init_rx_ring(dev);
-       wait_for_cmd_done(ioaddr + SCBCmd);
-       outl(0, ioaddr + SCBPointer);
-       outw(INT_MASK | RX_ADDR_LOAD, ioaddr + SCBCmd);
-
-       /* Todo: verify that we must wait for previous command completion. */
-       wait_for_cmd_done(ioaddr + SCBCmd);
-       outl(virt_to_bus(sp->rx_ringp[0]), ioaddr + SCBPointer);
-       outw(INT_MASK | RX_START, ioaddr + SCBCmd);
-
-       /* Fill the first command with our physical address. */
-       {
-               u16 *eaddrs = (u16 *)dev->dev_addr;
-               u16 *setup_frm = (u16 *)&(sp->tx_ring[0].tx_desc_addr);
 
-               /* Avoid a bug(?!) here by marking the command already completed. */
-               sp->tx_ring[0].status = ((CmdSuspend | CmdIASetup) << 16) | 0xa000;
-               sp->tx_ring[0].link = virt_to_bus(&(sp->tx_ring[1]));
-               *setup_frm++ = eaddrs[0];
-               *setup_frm++ = eaddrs[1];
-               *setup_frm++ = eaddrs[2];
-       }
-       sp->last_cmd = (struct descriptor *)&sp->tx_ring[0];
-       sp->cur_tx = 1;
-       sp->dirty_tx = 0;
-       sp->tx_full = 0;
-
-       wait_for_cmd_done(ioaddr + SCBCmd);
-       outl(0, ioaddr + SCBPointer);
-       outw(INT_MASK | CU_CMD_BASE, ioaddr + SCBCmd);
-
-       dev->if_port = sp->default_port;
+       /* Fire up the hardware. */
+       speedo_resume(dev);
 
        dev->tbusy = 0;
        dev->interrupt = 0;
        dev->start = 1;
 
-       /* Start the chip's Tx process and unmask interrupts. */
-       /* Todo: verify that we must wait for previous command completion. */
-       wait_for_cmd_done(ioaddr + SCBCmd);
-       outl(virt_to_bus(&sp->tx_ring[0]), ioaddr + SCBPointer);
-       outw(CU_START, ioaddr + SCBCmd);
-
        /* Setup the chip and configure the multicast list. */
        sp->mc_setup_frm = NULL;
        sp->mc_setup_frm_len = 0;
        sp->mc_setup_busy = 0;
        sp->rx_mode = -1;                       /* Invalid -> always reset the mode. */
+       sp->flow_ctrl = sp->partner = 0;
        set_rx_mode(dev);
+       if ((sp->phy[0] & 0x8000) == 0)
+               sp->advertising = mdio_read(ioaddr, sp->phy[0] & 0x1f, 4);
 
        if (speedo_debug > 2) {
                printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n",
                           dev->name, inw(ioaddr + SCBStatus));
        }
 
-       wait_for_cmd_done(ioaddr + SCBCmd);
-       outw(CU_DUMPSTATS, ioaddr + SCBCmd);
-
-       /*
-        * Request the IRQ last, after we have set up all data structures.
-        * It would be bad to get an interrupt before we're ready.
-        */
-       if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ,
-                                       "Intel EtherExpress Pro 10/100 Ethernet", dev)) {
-               return -EAGAIN;
-       }
-
-       /* No need to wait for the command unit to accept here. */
-       if ((sp->phy[0] & 0x8000) == 0)
-               mdio_read(ioaddr, sp->phy[0] & 0x1f, 0);
-
-       MOD_INC_USE_COUNT;
-
        /* Set the timer.  The timer serves a dual purpose:
           1) to monitor the media interface (e.g. link beat) and perhaps switch
           to an alternate media type
@@ -870,20 +981,104 @@ speedo_open(struct device *dev)
        sp->timer.function = &speedo_timer;                                     /* timer handler */
        add_timer(&sp->timer);
 
+       /* No need to wait for the command unit to accept here. */
+       if ((sp->phy[0] & 0x8000) == 0)
+               mdio_read(ioaddr, sp->phy[0] & 0x1f, 0);
        return 0;
 }
 
+/* Start the chip hardware after a full reset. */
+static void speedo_resume(struct device *dev)
+{
+       struct speedo_private *sp = (struct speedo_private *)dev->priv;
+       long ioaddr = dev->base_addr;
+
+       outw(SCBMaskAll, ioaddr + SCBCmd);
+
+       /* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */
+       sp->tx_threshold = 0x01208000;
+
+       /* Set the segment registers to '0'. */
+       wait_for_cmd_done(ioaddr + SCBCmd);
+       outl(0, ioaddr + SCBPointer);
+       outb(RxAddrLoad, ioaddr + SCBCmd);
+       wait_for_cmd_done(ioaddr + SCBCmd);
+       outb(CUCmdBase, ioaddr + SCBCmd);
+       wait_for_cmd_done(ioaddr + SCBCmd);
+
+       /* Load the statistics block and rx ring addresses. */
+       outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer);
+       outb(CUStatsAddr, ioaddr + SCBCmd);
+       sp->lstats.done_marker = 0;
+       wait_for_cmd_done(ioaddr + SCBCmd);
+
+       outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]),
+                ioaddr + SCBPointer);
+       outb(RxStart, ioaddr + SCBCmd);
+       wait_for_cmd_done(ioaddr + SCBCmd);
+
+       outb(CUDumpStats, ioaddr + SCBCmd);
+
+       /* Fill the first command with our physical address. */
+       {
+               int entry = sp->cur_tx++ % TX_RING_SIZE;
+               struct descriptor *cur_cmd = (struct descriptor *)&sp->tx_ring[entry];
+
+               /* Avoid a bug(?!) here by marking the command already completed. */
+               cur_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000);
+               cur_cmd->link =
+                       virt_to_le32bus(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]);
+               memcpy(cur_cmd->params, dev->dev_addr, 6);
+               if (sp->last_cmd)
+                       clear_suspend(sp->last_cmd);
+               sp->last_cmd = cur_cmd;
+       }
+
+       /* Start the chip's Tx process and unmask interrupts. */
+       wait_for_cmd_done(ioaddr + SCBCmd);
+       outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]),
+                ioaddr + SCBPointer);
+       outw(CUStart, ioaddr + SCBCmd);
+}
+
 /* Media monitoring and control. */
 static void speedo_timer(unsigned long data)
 {
        struct device *dev = (struct device *)data;
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
+       long ioaddr = dev->base_addr;
+       int phy_num = sp->phy[0] & 0x1f;
+
+       /* We have MII and lost link beat. */
+       if ((sp->phy[0] & 0x8000) == 0) {
+               int partner = mdio_read(ioaddr, phy_num, 5);
+               if (partner != sp->partner) {
+                       int flow_ctrl = sp->advertising & partner & 0x0400 ? 1 : 0;
+                       sp->partner = partner;
+                       if (flow_ctrl != sp->flow_ctrl) {
+                               sp->flow_ctrl = flow_ctrl;
+                               sp->rx_mode = -1;       /* Trigger a reload. */
+                       }
+                       /* Clear sticky bit. */
+                       mdio_read(ioaddr, phy_num, 1);
+                       /* If link beat has returned... */
+                       if (mdio_read(ioaddr, phy_num, 1) & 0x0004)
+                               dev->flags |= IFF_RUNNING; 
+                       else
+                               dev->flags &= ~IFF_RUNNING;
+               }
+       }
 
        if (speedo_debug > 3) {
-               long ioaddr = dev->base_addr;
                printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n",
                           dev->name, inw(ioaddr + SCBStatus));
        }
+       /* This has a small false-trigger window. */
+       if (test_bit(0, (void*)&dev->tbusy) &&
+               (jiffies - dev->trans_start) > TX_TIMEOUT) {
+               speedo_tx_timeout(dev);
+               sp->last_reset = jiffies;
+       }
        if (sp->rx_mode < 0  ||
                (sp->rx_bug  && jiffies - sp->last_rx_time > 2*HZ)) {
                /* We haven't received a packet in a Long Time.  We might have been
@@ -896,6 +1091,39 @@ static void speedo_timer(unsigned long data)
        add_timer(&sp->timer);
 }
 
+static void speedo_show_state(struct device *dev)
+{
+       struct speedo_private *sp = (struct speedo_private *)dev->priv;
+       long ioaddr = dev->base_addr;
+       int phy_num = sp->phy[0] & 0x1f;
+       int i;
+
+       /* Print a few items for debugging. */
+       if (speedo_debug > 0) {
+               int i;
+               printk(KERN_DEBUG "%s: Tx ring dump,  Tx queue %d / %d:\n", dev->name,
+                          sp->cur_tx, sp->dirty_tx);
+               for (i = 0; i < TX_RING_SIZE; i++)
+                       printk(KERN_DEBUG "%s: %c%c%d %8.8x.\n", dev->name,
+                                  i == sp->dirty_tx % TX_RING_SIZE ? '*' : ' ',
+                                  i == sp->cur_tx % TX_RING_SIZE ? '=' : ' ',
+                                  i, sp->tx_ring[i].status);
+       }
+       printk(KERN_DEBUG "%s:Printing Rx ring (next to receive into %d).\n",
+                  dev->name, sp->cur_rx);
+
+       for (i = 0; i < RX_RING_SIZE; i++)
+               printk(KERN_DEBUG "  Rx ring entry %d  %8.8x.\n",
+                          i, (int)sp->rx_ringp[i]->status);
+
+       for (i = 0; i < 16; i++) {
+               if (i == 6) i = 21;
+               printk(KERN_DEBUG "  PHY index %d register %d is %4.4x.\n",
+                          phy_num, i, mdio_read(ioaddr, phy_num, i));
+       }
+
+}
+
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void
 speedo_init_rx_ring(struct device *dev)
@@ -917,9 +1145,9 @@ speedo_init_rx_ring(struct device *dev)
                sp->rx_ringp[i] = rxf;
                skb_reserve(skb, sizeof(struct RxFD));
                if (last_rxf)
-                       last_rxf->link = virt_to_bus(rxf);
+                       last_rxf->link = virt_to_le32bus(rxf);
                last_rxf = rxf;
-               rxf->status = 0x00000001;                       /* '1' is flag value only. */
+               rxf->status = cpu_to_le32(0x00000001);  /* '1' is flag value only. */
                rxf->link = 0;                                          /* None yet. */
                /* This field unused by i82557, we use it as a consistency check. */
 #ifdef final_version
@@ -927,12 +1155,11 @@ speedo_init_rx_ring(struct device *dev)
 #else
                rxf->rx_buf_addr = virt_to_bus(skb->tail);
 #endif
-               rxf->count = 0;
-               rxf->size = PKT_BUF_SZ;
+               rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
        }
        sp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
        /* Mark the last entry as end-of-list. */
-       last_rxf->status = 0xC0000002;                  /* '2' is flag value only. */
+       last_rxf->status = cpu_to_le32(0xC0000002);     /* '2' is flag value only. */
        sp->last_rxf = last_rxf;
 }
 
@@ -940,22 +1167,33 @@ static void speedo_tx_timeout(struct device *dev)
 {
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
        long ioaddr = dev->base_addr;
+       int status = inw(ioaddr + SCBStatus);
+
+       /* Trigger a stats dump to give time before the reset. */
+       speedo_get_stats(dev);
 
        printk(KERN_WARNING "%s: Transmit timed out: status %4.4x "
                   " %4.4x at %d/%d command %8.8x.\n",
-                  dev->name, inw(ioaddr + SCBStatus), inw(ioaddr + SCBCmd),
+                  dev->name, status, inw(ioaddr + SCBCmd),
                   sp->dirty_tx, sp->cur_tx,
                   sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status);
-       if ((inw(ioaddr + SCBStatus) & 0x00C0) != 0x0080) {
+       speedo_show_state(dev);
+       if ((status & 0x00C0) != 0x0080
+               &&  (status & 0x003C) == 0x0010) {
+               /* Only the command unit has stopped. */
                printk(KERN_WARNING "%s: Trying to restart the transmitter...\n",
                           dev->name);
                outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]),
                         ioaddr + SCBPointer);
-               outw(CU_START, ioaddr + SCBCmd);
+               outw(CUStart, ioaddr + SCBCmd);
        } else {
-               outw(DRVR_INT, ioaddr + SCBCmd);
+               /* Reset the Tx and Rx units. */
+               outl(PortReset, ioaddr + SCBPort);
+               if (speedo_debug > 0)
+                       speedo_show_state(dev);
+               udelay(10);
+               speedo_resume(dev);
        }
-#ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us
        /* Reset the MII transceiver, suggested by Fred Young @ scalable.com. */
        if ((sp->phy[0] & 0x8000) == 0) {
                int phy_addr = sp->phy[0] & 0x1f;
@@ -967,7 +1205,6 @@ static void speedo_tx_timeout(struct device *dev)
                mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]);
 #endif
        }
-#endif
        sp->stats.tx_errors++;
        dev->trans_start = jiffies;
        return;
@@ -989,7 +1226,7 @@ speedo_start_xmit(struct sk_buff *skb, struct device *dev)
                        return 1;
                if (tickssofar < TX_TIMEOUT) {
                        /* Reap sent packets from the full Tx queue. */
-                       outw(DRVR_INT, ioaddr + SCBCmd);
+                       outw(SCBTriggerIntr, ioaddr + SCBCmd);
                        return 1;
                }
                speedo_tx_timeout(dev);
@@ -1003,43 +1240,39 @@ speedo_start_xmit(struct sk_buff *skb, struct device *dev)
                unsigned long flags;
 
                spin_lock_irqsave(&sp->lock, flags);
-
                /* Calculate the Tx descriptor entry. */
                entry = sp->cur_tx++ % TX_RING_SIZE;
 
                sp->tx_skbuff[entry] = skb;
                /* Todo: be a little more clever about setting the interrupt bit. */
                sp->tx_ring[entry].status =
-                       (CmdSuspend | CmdTx | CmdTxFlex) << 16;
+                       cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex);
                sp->tx_ring[entry].link =
-                 virt_to_bus(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]);
+                       virt_to_le32bus(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]);
                sp->tx_ring[entry].tx_desc_addr =
-                 virt_to_bus(&sp->tx_ring[entry].tx_buf_addr0);
-               /* The data region is always in one buffer descriptor, Tx FIFO
-                  threshold of 256. */
-               sp->tx_ring[entry].count = 0x01208000;
-               sp->tx_ring[entry].tx_buf_addr0 = virt_to_bus(skb->data);
-               sp->tx_ring[entry].tx_buf_size0 = skb->len;
+                       virt_to_le32bus(&sp->tx_ring[entry].tx_buf_addr0);
+               /* The data region is always in one buffer descriptor. */
+               sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold);
+               sp->tx_ring[entry].tx_buf_addr0 = virt_to_le32bus(skb->data);
+               sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len);
                /* Todo: perhaps leave the interrupt bit set if the Tx queue is more
                   than half full.  Argument against: we should be receiving packets
                   and scavenging the queue.  Argument for: if so, it shouldn't
                   matter. */
-               sp->last_cmd->command &= ~(CmdSuspend | CmdIntr);
-               sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-
                /* Trigger the command unit resume. */
-               wait_for_cmd_done(ioaddr + SCBCmd);
-               outw(CU_RESUME, ioaddr + SCBCmd);
-
+               {
+                       struct descriptor *last_cmd = sp->last_cmd;
+                       sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
+                       clear_suspend(last_cmd);
+               }
+               if (sp->cur_tx - sp->dirty_tx >= TX_QUEUE_LIMIT)
+                       sp->tx_full = 1;
+               else
+                       clear_bit(0, (void*)&dev->tbusy);
                spin_unlock_irqrestore(&sp->lock, flags);
        }
-
-       /* Leave room for set_rx_mode() to fill two entries. */
-       if (sp->cur_tx - sp->dirty_tx > TX_RING_SIZE - 3)
-               sp->tx_full = 1;
-       else
-               clear_bit(0, (void*)&dev->tbusy);
-
+       wait_for_cmd_done(ioaddr + SCBCmd);
+       outw(CUResume, ioaddr + SCBCmd);
        dev->trans_start = jiffies;
 
        return 0;
@@ -1063,9 +1296,14 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 
        ioaddr = dev->base_addr;
        sp = (struct speedo_private *)dev->priv;
-       spin_lock(&sp->lock);
-
 #ifndef final_version
+       /* A lock to prevent simultaneous entry on SMP machines. */
+       if (test_and_set_bit(0, (void*)&sp->in_interrupt)) {
+               printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
+                          dev->name);
+               sp->in_interrupt = 0;   /* Avoid halting machine. */
+               return;
+       }
        dev->interrupt = 1;
 #endif
 
@@ -1085,37 +1323,44 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                        speedo_rx(dev);
 
                if (status & 0x1000) {
-                 if ((status & 0x003c) == 0x0028) /* No more Rx buffers. */
-                       outw(RX_RESUMENR, ioaddr + SCBCmd);
-                 else if ((status & 0x003c) == 0x0008) { /* No resources (why?!) */
-                       /* No idea of what went wrong.  Restart the receiver. */
-                       outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]),
-                                ioaddr + SCBPointer);
-                       outw(RX_START, ioaddr + SCBCmd);
-                 }
-                 sp->stats.rx_errors++;
+                       if ((status & 0x003c) == 0x0028) /* No more Rx buffers. */
+                               outw(RxResumeNoResources, ioaddr + SCBCmd);
+                       else if ((status & 0x003c) == 0x0008) { /* No resources (why?!) */
+                               /* No idea of what went wrong.  Restart the receiver. */
+                               outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]),
+                                        ioaddr + SCBPointer);
+                               outw(RxStart, ioaddr + SCBCmd);
+                       }
+                       sp->stats.rx_errors++;
                }
 
                /* User interrupt, Command/Tx unit interrupt or CU not active. */
                if (status & 0xA400) {
-                       unsigned int dirty_tx = sp->dirty_tx;
+                       unsigned int dirty_tx;
+                       spin_lock(&sp->lock);
 
+                       dirty_tx = sp->dirty_tx;
                        while (sp->cur_tx - dirty_tx > 0) {
                                int entry = dirty_tx % TX_RING_SIZE;
-                               int status = sp->tx_ring[entry].status;
+                               int status = le32_to_cpu(sp->tx_ring[entry].status);
 
                                if (speedo_debug > 5)
                                        printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n",
                                                   entry, status);
                                if ((status & StatusComplete) == 0)
                                        break;                  /* It still hasn't been processed. */
+                               if (status & TxUnderrun)
+                                       if (sp->tx_threshold < 0x01e08000)
+                                               sp->tx_threshold += 0x00040000;
                                /* Free the original skb. */
                                if (sp->tx_skbuff[entry]) {
                                        sp->stats.tx_packets++; /* Count only user packets. */
-                                       sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; /* Count transmitted bytes */
+#if LINUX_VERSION_CODE > 0x20127
+                                       sp->stats.tx_bytes += sp->tx_skbuff[entry]->len;
+#endif
                                        dev_free_skb(sp->tx_skbuff[entry]);
                                        sp->tx_skbuff[entry] = 0;
-                               } else if ((sp->tx_ring[entry].status&0x70000) == CmdNOp << 16)
+                               } else if ((status & 0x70000) == CmdNOp)
                                        sp->mc_setup_busy = 0;
                                dirty_tx++;
                        }
@@ -1129,15 +1374,16 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                        }
 #endif
 
-                       if (sp->tx_full && dev->tbusy
-                               && dirty_tx > sp->cur_tx - TX_RING_SIZE + 2) {
+                       sp->dirty_tx = dirty_tx;
+                       if (sp->tx_full
+                               &&  sp->cur_tx - dirty_tx < TX_QUEUE_LIMIT - 1) {
                                /* The ring is no longer full, clear tbusy. */
                                sp->tx_full = 0;
                                clear_bit(0, (void*)&dev->tbusy);
-                               mark_bh(NET_BH);
-                       }
-
-                       sp->dirty_tx = dirty_tx;
+                               spin_unlock(&sp->lock);
+                               netif_wake_queue(dev);
+                       } else
+                               spin_unlock(&sp->lock);
                }
 
                if (--boguscnt < 0) {
@@ -1154,7 +1400,7 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                           dev->name, inw(ioaddr + SCBStatus));
 
        dev->interrupt = 0;
-       spin_unlock(&sp->lock);
+       clear_bit(0, (void*)&sp->in_interrupt);
        return;
 }
 
@@ -1170,26 +1416,25 @@ speedo_rx(struct device *dev)
                printk(KERN_DEBUG " In speedo_rx().\n");
        /* If we own the next entry, it's a new packet. Send it up. */
        while (sp->rx_ringp[entry] != NULL &&
-                  (status = sp->rx_ringp[entry]->status) & RxComplete) {
+                  (status = le32_to_cpu(sp->rx_ringp[entry]->status)) & RxComplete) {
+               int pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff;
 
                if (--rx_work_limit < 0)
                        break;
                if (speedo_debug > 4)
                        printk(KERN_DEBUG "  speedo_rx() status %8.8x len %d.\n", status,
-                                  sp->rx_ringp[entry]->count & 0x3fff);
-               if ((status & (RxErrTooBig|RxOK)) != RxOK) {
+                                  pkt_len);
+               if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) {
                        if (status & RxErrTooBig)
                                printk(KERN_ERR "%s: Ethernet frame overran the Rx buffer, "
                                           "status %8.8x!\n", dev->name, status);
-                       else if ( ! (status & 0x2000)) {
+                       else if ( ! (status & RxOK)) {
                                /* There was a fatal error.  This *should* be impossible. */
                                sp->stats.rx_errors++;
                                printk(KERN_ERR "%s: Anomalous event in speedo_rx(), "
-                                          "status %8.8x.\n",
-                                          dev->name, status);
+                                          "status %8.8x.\n", dev->name, status);
                        }
                } else {
-                       int pkt_len = sp->rx_ringp[entry]->count & 0x3fff;
                        struct sk_buff *skb;
 
                        /* Check if the packet is long enough to just accept without
@@ -1201,13 +1446,11 @@ speedo_rx(struct device *dev)
                                /* 'skb_put()' points to the start of sk_buff data area. */
 #if 1 || USE_IP_CSUM
                                /* Packet is in one chunk -- we can copy + cksum. */
-                               eth_copy_and_sum(skb,
-                                                                bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr),
-                                                                pkt_len, 0);
+                               eth_copy_and_sum(skb, sp->rx_skbuff[entry]->tail, pkt_len, 0);
                                skb_put(skb, pkt_len);
 #else
-                               memcpy(skb_put(skb, pkt_len),
-                                          bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr), pkt_len);
+                               memcpy(skb_put(skb, pkt_len), sp->rx_skbuff[entry]->tail,
+                                          pkt_len);
 #endif
                        } else {
                                void *temp;
@@ -1220,24 +1463,28 @@ speedo_rx(struct device *dev)
                                }
                                sp->rx_skbuff[entry] = NULL;
                                temp = skb_put(skb, pkt_len);
+#if !defined(final_version) && !defined(__powerpc__)
                                if (bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr) != temp)
                                        printk(KERN_ERR "%s: Rx consistency error -- the skbuff "
                                                   "addresses do not match in speedo_rx: %p vs. %p "
                                                   "/ %p.\n", dev->name,
                                                   bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr),
                                                   skb->head, temp);
+#endif
                                sp->rx_ringp[entry] = NULL;
                        }
                        skb->protocol = eth_type_trans(skb, dev);
                        netif_rx(skb);
                        sp->stats.rx_packets++;
-                       sp->stats.rx_bytes += pkt_len; /* Count received bytes */
+#if LINUX_VERSION_CODE > 0x20127
+                       sp->stats.rx_bytes += pkt_len;
+#endif
                }
                entry = (++sp->cur_rx) % RX_RING_SIZE;
        }
 
        /* Refill the Rx ring buffers. */
-       for (; sp->dirty_rx < sp->cur_rx; sp->dirty_rx++) {
+       for (; sp->cur_rx - sp->dirty_rx > 0; sp->dirty_rx++) {
                struct RxFD *rxf;
                entry = sp->dirty_rx % RX_RING_SIZE;
                if (sp->rx_skbuff[entry] == NULL) {
@@ -1252,16 +1499,15 @@ speedo_rx(struct device *dev)
                        rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail;
                        skb->dev = dev;
                        skb_reserve(skb, sizeof(struct RxFD));
-                       rxf->rx_buf_addr = virt_to_bus(skb->tail);
+                       rxf->rx_buf_addr = virt_to_le32bus(skb->tail);
                } else {
                        rxf = sp->rx_ringp[entry];
                }
-               rxf->status = 0xC0000001;       /* '1' for driver use only. */
+               rxf->status = cpu_to_le32(0xC0000001);  /* '1' for driver use only. */
                rxf->link = 0;                  /* None yet. */
-               rxf->count = 0;
-               rxf->size = PKT_BUF_SZ;
-               sp->last_rxf->link = virt_to_bus(rxf);
-               sp->last_rxf->status &= ~0xC0000000;
+               rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
+               sp->last_rxf->link = virt_to_le32bus(rxf);
+               sp->last_rxf->status &= cpu_to_le32(~0xC0000000);
                sp->last_rxf = rxf;
        }
 
@@ -1287,8 +1533,8 @@ speedo_close(struct device *dev)
        del_timer(&sp->timer);
 
        /* Disable interrupts, and stop the chip's Rx process. */
-       outw(INT_MASK, ioaddr + SCBCmd);
-       outw(INT_MASK | RX_ABORT, ioaddr + SCBCmd);
+       outw(SCBMaskAll, ioaddr + SCBCmd);
+       outw(SCBMaskAll | RxAbort, ioaddr + SCBCmd);
 
        free_irq(dev->irq, dev);
 
@@ -1297,8 +1543,12 @@ speedo_close(struct device *dev)
                struct sk_buff *skb = sp->rx_skbuff[i];
                sp->rx_skbuff[i] = 0;
                /* Clear the Rx descriptors. */
-               if (skb)
+               if (skb) {
+#if LINUX_VERSION_CODE < 0x20100
+                       skb->free = 1;
+#endif
                        dev_free_skb(skb);
+               }
        }
 
        for (i = 0; i < TX_RING_SIZE; i++) {
@@ -1314,22 +1564,13 @@ speedo_close(struct device *dev)
        }
 
        /* Print a few items for debugging. */
-       if (speedo_debug > 3) {
-               int phy_num = sp->phy[0] & 0x1f;
-               printk(KERN_DEBUG "%s:Printing Rx ring (next to receive into %d).\n",
-                          dev->name, sp->cur_rx);
-
-               for (i = 0; i < RX_RING_SIZE; i++)
-                       printk(KERN_DEBUG "  Rx ring entry %d  %8.8x.\n",
-                                  i, (int)sp->rx_ringp[i]->status);
-
-               for (i = 0; i < 5; i++)
-                       printk(KERN_DEBUG "  PHY index %d register %d is %4.4x.\n",
-                                  phy_num, i, mdio_read(ioaddr, phy_num, i));
-               for (i = 21; i < 26; i++)
-                       printk(KERN_DEBUG "  PHY index %d register %d is %4.4x.\n",
-                                  phy_num, i, mdio_read(ioaddr, phy_num, i));
-       }
+       if (speedo_debug > 3)
+               speedo_show_state(dev);
+
+#if defined(HAS_PCI_NETIF)
+       /* Alt: acpi_set_pwr_state(pci_bus, pci_devfn, sp->acpi_pwr); */
+       acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D2);
+#endif
        MOD_DEC_USE_COUNT;
 
        return 0;
@@ -1353,22 +1594,23 @@ speedo_get_stats(struct device *dev)
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
        long ioaddr = dev->base_addr;
 
-       if (sp->lstats.done_marker == 0xA007) { /* Previous dump finished */
-               sp->stats.tx_aborted_errors += sp->lstats.tx_coll16_errs;
-               sp->stats.tx_window_errors += sp->lstats.tx_late_colls;
-               sp->stats.tx_fifo_errors += sp->lstats.tx_underruns;
-               sp->stats.tx_fifo_errors += sp->lstats.tx_lost_carrier;
-               /*sp->stats.tx_deferred += sp->lstats.tx_deferred;*/
-               sp->stats.collisions += sp->lstats.tx_total_colls;
-               sp->stats.rx_crc_errors += sp->lstats.rx_crc_errs;
-               sp->stats.rx_frame_errors += sp->lstats.rx_align_errs;
-               sp->stats.rx_over_errors += sp->lstats.rx_resource_errs;
-               sp->stats.rx_fifo_errors += sp->lstats.rx_overrun_errs;
-               sp->stats.rx_length_errors += sp->lstats.rx_runt_errs;
+       /* Update only if the previous dump finished. */
+       if (sp->lstats.done_marker == le32_to_cpu(0xA007)) {
+               sp->stats.tx_aborted_errors += le32_to_cpu(sp->lstats.tx_coll16_errs);
+               sp->stats.tx_window_errors += le32_to_cpu(sp->lstats.tx_late_colls);
+               sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats.tx_underruns);
+               sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats.tx_lost_carrier);
+               /*sp->stats.tx_deferred += le32_to_cpu(sp->lstats.tx_deferred);*/
+               sp->stats.collisions += le32_to_cpu(sp->lstats.tx_total_colls);
+               sp->stats.rx_crc_errors += le32_to_cpu(sp->lstats.rx_crc_errs);
+               sp->stats.rx_frame_errors += le32_to_cpu(sp->lstats.rx_align_errs);
+               sp->stats.rx_over_errors += le32_to_cpu(sp->lstats.rx_resource_errs);
+               sp->stats.rx_fifo_errors += le32_to_cpu(sp->lstats.rx_overrun_errs);
+               sp->stats.rx_length_errors += le32_to_cpu(sp->lstats.rx_runt_errs);
                sp->lstats.done_marker = 0x0000;
                if (dev->start) {
                        wait_for_cmd_done(ioaddr + SCBCmd);
-                       outw(CU_DUMPSTATS, ioaddr + SCBCmd);
+                       outw(CUDumpStats, ioaddr + SCBCmd);
                }
        }
        return &sp->stats;
@@ -1380,17 +1622,32 @@ static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        long ioaddr = dev->base_addr;
        u16 *data = (u16 *)&rq->ifr_data;
        int phy = sp->phy[0] & 0x1f;
+#if defined(HAS_PCI_NETIF)
+       int saved_acpi;
+#endif
 
     switch(cmd) {
        case SIOCDEVPRIVATE:            /* Get the address of the PHY in use. */
                data[0] = phy;
        case SIOCDEVPRIVATE+1:          /* Read the specified MII register. */
+#if defined(HAS_PCI_NETIF)
+               saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0);
                data[3] = mdio_read(ioaddr, data[0], data[1]);
+               acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi);
+#else
+               data[3] = mdio_read(ioaddr, data[0], data[1]);
+#endif
                return 0;
        case SIOCDEVPRIVATE+2:          /* Write the specified MII register */
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
+#if defined(HAS_PCI_NETIF)
+               saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0);
+               mdio_write(ioaddr, data[0], data[1], data[2]);
+               acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi);
+#else
                mdio_write(ioaddr, data[0], data[1], data[2]);
+#endif
                return 0;
        default:
                return -EOPNOTSUPP;
@@ -1406,8 +1663,7 @@ static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd)
    loaded the link -- we convert the current command block, normally a Tx
    command, into a no-op and link it to the new command.
 */
-static void
-set_rx_mode(struct device *dev)
+static void set_rx_mode(struct device *dev)
 {
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
        long ioaddr = dev->base_addr;
@@ -1440,9 +1696,9 @@ set_rx_mode(struct device *dev)
                sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
 
                sp->tx_skbuff[entry] = 0;                       /* Redundant. */
-               sp->tx_ring[entry].status = (CmdSuspend | CmdConfigure) << 16;
+               sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdConfigure);
                sp->tx_ring[entry].link =
-                       virt_to_bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]);
+                       virt_to_le32bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]);
                config_cmd_data = (void *)&sp->tx_ring[entry].tx_desc_addr;
                /* Construct a full CmdConfig frame. */
                memcpy(config_cmd_data, i82558_config_cmd, sizeof(i82558_config_cmd));
@@ -1450,6 +1706,7 @@ set_rx_mode(struct device *dev)
                config_cmd_data[4] = rxdmacount;
                config_cmd_data[5] = txdmacount + 0x80;
                config_cmd_data[15] |= (new_rx_mode & 2) ? 1 : 0;
+               config_cmd_data[19] = sp->flow_ctrl ? 0xBD : 0x80;
                config_cmd_data[19] |= sp->full_duplex ? 0x40 : 0;
                config_cmd_data[21] = (new_rx_mode & 1) ? 0x0D : 0x05;
                if (sp->phy[0] & 0x8000) {                      /* Use the AUI port instead. */
@@ -1457,11 +1714,9 @@ set_rx_mode(struct device *dev)
                        config_cmd_data[8] = 0;
                }
                /* Trigger the command unit resume. */
-               last_cmd->command &= ~CmdSuspend;
-
                wait_for_cmd_done(ioaddr + SCBCmd);
-               outw(CU_RESUME, ioaddr + SCBCmd);
-
+               clear_suspend(last_cmd);
+               outw(CUResume, ioaddr + SCBCmd);
                spin_unlock_irqrestore(&sp->lock, flags);
        }
 
@@ -1477,12 +1732,12 @@ set_rx_mode(struct device *dev)
                sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
 
                sp->tx_skbuff[entry] = 0;
-               sp->tx_ring[entry].status = (CmdSuspend | CmdMulticastList) << 16;
+               sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdMulticastList);
                sp->tx_ring[entry].link =
-                       virt_to_bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]);
+                       virt_to_le32bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]);
                sp->tx_ring[entry].tx_desc_addr = 0; /* Really MC list count. */
                setup_params = (u16 *)&sp->tx_ring[entry].tx_desc_addr;
-               *setup_params++ = dev->mc_count*6;
+               *setup_params++ = cpu_to_le16(dev->mc_count*6);
                /* Fill in the multicast addresses. */
                for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
                         i++, mclist = mclist->next) {
@@ -1492,12 +1747,10 @@ set_rx_mode(struct device *dev)
                        *setup_params++ = *eaddrs++;
                }
 
-               last_cmd->command &= ~CmdSuspend;
-
-               /* Immediately trigger the command unit resume. */
                wait_for_cmd_done(ioaddr + SCBCmd);
-               outw(CU_RESUME, ioaddr + SCBCmd);
-
+               clear_suspend(last_cmd);
+               /* Immediately trigger the command unit resume. */
+               outw(CUResume, ioaddr + SCBCmd);
                spin_unlock_irqrestore(&sp->lock, flags);
        } else if (new_rx_mode == 0) {
                struct dev_mc_list *mclist;
@@ -1521,7 +1774,7 @@ set_rx_mode(struct device *dev)
                        }
                }
                /* If we are busy, someone might be quickly adding to the MC list.
-                  Try again later when the list changes stop. */
+                  Try again later when the list updates stop. */
                if (sp->mc_setup_busy) {
                        sp->rx_mode = -1;
                        return;
@@ -1532,11 +1785,11 @@ set_rx_mode(struct device *dev)
                        printk(KERN_DEBUG "%s: Constructing a setup frame at %p, "
                                   "%d bytes.\n",
                                   dev->name, sp->mc_setup_frm, sp->mc_setup_frm_len);
-               mc_setup_frm->status = 0;
-               mc_setup_frm->command = CmdSuspend | CmdIntr | CmdMulticastList;
+               mc_setup_frm->cmd_status =
+                       cpu_to_le32(CmdSuspend | CmdIntr | CmdMulticastList);
                /* Link set below. */
                setup_params = (u16 *)&mc_setup_frm->params;
-               *setup_params++ = dev->mc_count*6;
+               *setup_params++ = cpu_to_le16(dev->mc_count*6);
                /* Fill in the multicast addresses. */
                for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
                         i++, mclist = mclist->next) {
@@ -1548,7 +1801,6 @@ set_rx_mode(struct device *dev)
 
                /* Disable interrupts while playing with the Tx Cmd list. */
                spin_lock_irqsave(&sp->lock, flags);
-
                entry = sp->cur_tx++ % TX_RING_SIZE;
                last_cmd = sp->last_cmd;
                sp->last_cmd = mc_setup_frm;
@@ -1556,21 +1808,18 @@ set_rx_mode(struct device *dev)
 
                /* Change the command to a NoOp, pointing to the CmdMulti command. */
                sp->tx_skbuff[entry] = 0;
-               sp->tx_ring[entry].status = CmdNOp << 16;
-               sp->tx_ring[entry].link = virt_to_bus(mc_setup_frm);
+               sp->tx_ring[entry].status = cpu_to_le32(CmdNOp);
+               sp->tx_ring[entry].link = virt_to_le32bus(mc_setup_frm);
 
                /* Set the link in the setup frame. */
                mc_setup_frm->link =
-                       virt_to_bus(&(sp->tx_ring[(entry+1) % TX_RING_SIZE]));
-
-               last_cmd->command &= ~CmdSuspend;
+                       virt_to_le32bus(&(sp->tx_ring[(entry+1) % TX_RING_SIZE]));
 
-               /* Immediately trigger the command unit resume. */
                wait_for_cmd_done(ioaddr + SCBCmd);
-               outw(CU_RESUME, ioaddr + SCBCmd);
-
+               clear_suspend(last_cmd);
+               /* Immediately trigger the command unit resume. */
+               outw(CUResume, ioaddr + SCBCmd);
                spin_unlock_irqrestore(&sp->lock, flags);
-
                if (speedo_debug > 5)
                        printk(" CmdMCSetup frame length %d in entry %d.\n",
                                   dev->mc_count, entry);
@@ -1581,42 +1830,64 @@ set_rx_mode(struct device *dev)
 \f
 #ifdef MODULE
 
-int
-init_module(void)
+int init_module(void)
 {
        int cards_found;
 
        if (debug >= 0)
                speedo_debug = debug;
+       /* Always emit the version message. */
        if (speedo_debug)
                printk(KERN_INFO "%s", version);
 
-       root_speedo_dev = NULL;
+#if defined(HAS_PCI_NETIF)
+       cards_found = netif_pci_probe(pci_tbl, NULL);
+       if (cards_found < 0)
+               printk(KERN_INFO "eepro100: No cards found, driver not installed.\n");
+       return cards_found;
+#else
        cards_found = eepro100_init(NULL);
-       return cards_found ? 0 : -ENODEV;
+       if (cards_found <= 0) {
+               printk(KERN_INFO "eepro100: No cards found, driver not installed.\n");
+               return -ENODEV;
+       }
+#endif
+       return 0;
 }
 
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
        struct device *next_dev;
 
        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
        while (root_speedo_dev) {
-               next_dev = ((struct speedo_private *)root_speedo_dev->priv)->next_module;
+               struct speedo_private *sp = (void *)root_speedo_dev->priv;
                unregister_netdev(root_speedo_dev);
+#ifdef USE_IO
                release_region(root_speedo_dev->base_addr, SPEEDO3_TOTAL_SIZE);
+#else
+               iounmap((char *)root_speedo_dev->base_addr);
+#endif
+#if defined(HAS_PCI_NETIF)
+               acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, sp->acpi_pwr);
+#endif
+               next_dev = sp->next_module;
+               if (sp->priv_addr)
+                       kfree(sp->priv_addr);
                kfree(root_speedo_dev);
                root_speedo_dev = next_dev;
        }
 }
+
 #else   /* not MODULE */
+
 int eepro100_probe(struct device *dev)
 {
        int cards_found = 0;
 
        cards_found = eepro100_init(dev);
 
+       /* Only emit the version if the driver is being used. */
        if (speedo_debug > 0  &&  cards_found)
                printk(version);
 
@@ -1626,8 +1897,9 @@ int eepro100_probe(struct device *dev)
 \f
 /*
  * Local variables:
- *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS` `[ -f ./pci-netif.h ] && echo -DHAS_PCI_NETIF`"
+ *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  simple-compile-command: "gcc -DMODULE -D__KERNEL__ -O6 -c eepro100.c"
  *  c-indent-level: 4
  *  c-basic-offset: 4
  *  tab-width: 4
index e2d96d0fae6348252b86fb4ce48a99a53f127b11..7b6d3a05417193e304c29b046eefba39ddec4df1 100644 (file)
@@ -11,6 +11,11 @@ if [ "$CONFIG_PARPORT" != "n" ]; then
   if [ "$CONFIG_PARPORT_PC" != "n" ]; then
     bool '   Use FIFO/DMA if available' CONFIG_PARPORT_PC_FIFO
   fi
+  if [ "$CONFIG_PARPORT_PC" = y ]; then
+    # Don't bother with this if parport_pc is a module; it only affects
+    # the presence or not of some __init's, which are no-ops for modules.
+    bool '   Support for PCMCIA management for PC-style ports' CONFIG_PARPORT_PC_PCMCIA
+  fi
   if [ "$CONFIG_ARM" = "y" ]; then
     dep_tristate '   Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT
   fi
index a65c77501138890ee39737d116868dd6d3b00101..8c155a62cfbb5a4ac6496257dc95f54917b075d9 100644 (file)
@@ -33,7 +33,7 @@ ifeq ($(CONFIG_PARPORT),y)
     LX_OBJS += parport_pc.o
   else
     ifeq ($(CONFIG_PARPORT_PC),m)
-      M_OBJS += parport_pc.o
+      MX_OBJS += parport_pc.o
     endif
   endif
   ifeq ($(CONFIG_PARPORT_AMIGA),y)
@@ -71,10 +71,7 @@ else
     M_OBJS += parport.o
   endif
   ifeq ($(CONFIG_PARPORT_PC),m)
-    M_OBJS += parport_pc.o
-  endif
-  ifeq ($(CONFIG_PARPORT_AX),m)
-    M_OBJS += parport_ax.o
+    MX_OBJS += parport_pc.o
   endif
   ifeq ($(CONFIG_PARPORT_AMIGA),m)
     M_OBJS += parport_amiga.o
index 19cba48cf6648aa61d5594361995f40c2d00536f..30352cfe3cf832250cace13d72f19375c577fd95 100644 (file)
@@ -373,9 +373,10 @@ int ecp_reverse_to_forward (struct parport *port)
 
        /* Event 47: Set nInit high */
        parport_frob_control (port,
-                             PARPORT_CONTROL_INIT,
-                             PARPORT_CONTROL_INIT);
-       parport_data_reverse (port);
+                             PARPORT_CONTROL_INIT
+                             | PARPORT_CONTROL_AUTOFD,
+                             PARPORT_CONTROL_INIT
+                             | PARPORT_CONTROL_AUTOFD);
 
        /* Event 49: PError goes high */
        retval = parport_wait_peripheral (port,
@@ -404,7 +405,6 @@ size_t parport_ieee1284_ecp_write_data (struct parport *port,
 #else
        const unsigned char *buf = buffer;
        size_t written;
-       int ctl = parport_read_control (port) & ~PARPORT_CONTROL_AUTOFD;
        int retry;
 
        port = port->physport;
@@ -416,7 +416,11 @@ size_t parport_ieee1284_ecp_write_data (struct parport *port,
        port->ieee1284.phase = IEEE1284_PH_FWD_DATA;
 
        /* HostAck high (data, not command) */
-       parport_write_control (port, ctl);
+       parport_frob_control (port,
+                             PARPORT_CONTROL_AUTOFD
+                             | PARPORT_CONTROL_STROBE
+                             | PARPORT_CONTROL_INIT,
+                             PARPORT_CONTROL_INIT);
        for (written = 0; written < len; written++, buf++) {
                long expire = jiffies + port->cad->timeout;
                unsigned char byte;
@@ -424,7 +428,8 @@ size_t parport_ieee1284_ecp_write_data (struct parport *port,
                byte = *buf;
        try_again:
                parport_write_data (port, byte);
-               parport_write_control (port, ctl | PARPORT_CONTROL_STROBE);
+               parport_frob_control (port, PARPORT_CONTROL_STROBE,
+                                     PARPORT_CONTROL_STROBE);
                udelay (5);
                for (retry = 0; retry < 100; retry++) {
                        if (!parport_wait_peripheral (port,
@@ -432,7 +437,9 @@ size_t parport_ieee1284_ecp_write_data (struct parport *port,
                                goto success;
 
                        if (signal_pending (current)) {
-                               parport_write_control (port, ctl);
+                               parport_frob_control (port,
+                                                     PARPORT_CONTROL_STROBE,
+                                                     0);
                                break;
                        }
                }
@@ -440,15 +447,16 @@ size_t parport_ieee1284_ecp_write_data (struct parport *port,
                /* Time for Host Transfer Recovery (page 41 of IEEE1284) */
                DPRINTK (KERN_DEBUG "%s: ECP transfer stalled!\n", port->name);
 
-               parport_write_control (port, ctl | PARPORT_CONTROL_INIT);
+               parport_frob_control (port, PARPORT_CONTROL_INIT,
+                                     PARPORT_CONTROL_INIT);
                udelay (50);
                if (parport_read_status (port) & PARPORT_STATUS_PAPEROUT) {
                        /* It's buggered. */
-                       parport_write_control (port, ctl);
+                       parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
                        break;
                }
 
-               parport_write_control (port, ctl);
+               parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
                udelay (50);
                if (!(parport_read_status (port) & PARPORT_STATUS_PAPEROUT))
                        break;
@@ -459,7 +467,7 @@ size_t parport_ieee1284_ecp_write_data (struct parport *port,
                if (time_after_eq (jiffies, expire)) break;
                goto try_again;
        success:
-               parport_write_control (port, ctl);
+               parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
                udelay (5);
                if (parport_wait_peripheral (port,
                                             PARPORT_STATUS_BUSY,
@@ -496,7 +504,10 @@ size_t parport_ieee1284_ecp_read_data (struct parport *port,
        port->ieee1284.phase = IEEE1284_PH_REV_DATA;
 
        /* Set HostAck low to start accepting data. */
-       parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
+       parport_frob_control (port,
+                             PARPORT_CONTROL_AUTOFD
+                             | PARPORT_CONTROL_STROBE
+                             | PARPORT_CONTROL_INIT,
                              PARPORT_CONTROL_AUTOFD);
        while (count < len) {
                long expire = jiffies + dev->timeout;
@@ -505,9 +516,7 @@ size_t parport_ieee1284_ecp_read_data (struct parport *port,
 
                /* Event 43: Peripheral sets nAck low. It can take as
                    long as it wants. */
-               while (parport_wait_peripheral (port,
-                                               PARPORT_STATUS_ACK,
-                                               PARPORT_STATUS_ACK)) {
+               while (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) {
                        /* The peripheral hasn't given us data in
                           35ms.  If we have data to give back to the
                           caller, do it now. */
@@ -578,7 +587,8 @@ size_t parport_ieee1284_ecp_read_data (struct parport *port,
                parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
 
                /* Event 45: The peripheral has 35ms to set nAck high. */
-               if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) {
+               if (parport_wait_peripheral (port, PARPORT_STATUS_ACK,
+                                            PARPORT_STATUS_ACK)) {
                        /* It's gone wrong.  Return what data we have
                            to the caller. */
                        DPRINTK (KERN_DEBUG "ECP read timed out at 45\n");
@@ -630,7 +640,6 @@ size_t parport_ieee1284_ecp_write_addr (struct parport *port,
 #else
        const unsigned char *buf = buffer;
        size_t written;
-       int ctl = parport_read_control (port) | PARPORT_CONTROL_AUTOFD;
        int retry;
 
        port = port->physport;
@@ -642,7 +651,12 @@ size_t parport_ieee1284_ecp_write_addr (struct parport *port,
        port->ieee1284.phase = IEEE1284_PH_FWD_DATA;
 
        /* HostAck low (command, not data) */
-       parport_write_control (port, ctl);
+       parport_frob_control (port,
+                             PARPORT_CONTROL_AUTOFD
+                             | PARPORT_CONTROL_STROBE
+                             | PARPORT_CONTROL_INIT,
+                             PARPORT_CONTROL_AUTOFD
+                             | PARPORT_CONTROL_INIT);
        for (written = 0; written < len; written++, buf++) {
                long expire = jiffies + port->cad->timeout;
                unsigned char byte;
@@ -650,7 +664,8 @@ size_t parport_ieee1284_ecp_write_addr (struct parport *port,
                byte = *buf;
        try_again:
                parport_write_data (port, byte);
-               parport_write_control (port, ctl | PARPORT_CONTROL_STROBE);
+               parport_frob_control (port, PARPORT_CONTROL_STROBE,
+                                     PARPORT_CONTROL_STROBE);
                udelay (5);
                for (retry = 0; retry < 100; retry++) {
                        if (!parport_wait_peripheral (port,
@@ -658,7 +673,9 @@ size_t parport_ieee1284_ecp_write_addr (struct parport *port,
                                goto success;
 
                        if (signal_pending (current)) {
-                               parport_write_control (port, ctl);
+                               parport_frob_control (port,
+                                                     PARPORT_CONTROL_STROBE,
+                                                     0);
                                break;
                        }
                }
@@ -666,15 +683,16 @@ size_t parport_ieee1284_ecp_write_addr (struct parport *port,
                /* Time for Host Transfer Recovery (page 41 of IEEE1284) */
                DPRINTK (KERN_DEBUG "%s: ECP transfer stalled!\n", port->name);
 
-               parport_write_control (port, ctl | PARPORT_CONTROL_INIT);
+               parport_frob_control (port, PARPORT_CONTROL_INIT,
+                                     PARPORT_CONTROL_INIT);
                udelay (50);
                if (parport_read_status (port) & PARPORT_STATUS_PAPEROUT) {
                        /* It's buggered. */
-                       parport_write_control (port, ctl);
+                       parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
                        break;
                }
 
-               parport_write_control (port, ctl);
+               parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
                udelay (50);
                if (!(parport_read_status (port) & PARPORT_STATUS_PAPEROUT))
                        break;
@@ -685,7 +703,7 @@ size_t parport_ieee1284_ecp_write_addr (struct parport *port,
                if (time_after_eq (jiffies, expire)) break;
                goto try_again;
        success:
-               parport_write_control (port, ctl);
+               parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
                udelay (5);
                if (parport_wait_peripheral (port,
                                             PARPORT_STATUS_BUSY,
index 468f54b33a7dd5401a08e327e906bfb585313117..db5255d25b457c8cf530e96fed88e637a943396a 100644 (file)
@@ -966,7 +966,7 @@ struct parport_operations parport_pc_ops =
 /*
  * Checks for port existence, all ports support SPP MODE
  */
-static int __init parport_SPP_supported(struct parport *pb)
+static int __maybe_init parport_SPP_supported(struct parport *pb)
 {
        unsigned char r, w;
 
@@ -1043,7 +1043,7 @@ static int __init parport_SPP_supported(struct parport *pb)
  * two bits of ECR aren't writable, so we check by writing ECR and
  * reading it back to see if it's what we expect.
  */
-static int __init parport_ECR_present(struct parport *pb)
+static int __maybe_init parport_ECR_present(struct parport *pb)
 {
        struct parport_pc_private *priv = pb->private_data;
        unsigned char r = 0xc;
@@ -1096,7 +1096,7 @@ static int __init parport_ECR_present(struct parport *pb)
  * be misdetected here is rather academic. 
  */
 
-static int __init parport_PS2_supported(struct parport *pb)
+static int __maybe_init parport_PS2_supported(struct parport *pb)
 {
        int ok = 0;
   
@@ -1124,7 +1124,7 @@ static int __init parport_PS2_supported(struct parport *pb)
        return ok;
 }
 
-static int __init parport_ECP_supported(struct parport *pb)
+static int __maybe_init parport_ECP_supported(struct parport *pb)
 {
        int i;
        int config;
@@ -1235,7 +1235,7 @@ static int __init parport_ECP_supported(struct parport *pb)
        return 1;
 }
 
-static int __init parport_ECPPS2_supported(struct parport *pb)
+static int __maybe_init parport_ECPPS2_supported(struct parport *pb)
 {
        const struct parport_pc_private *priv = pb->private_data;
        int result;
@@ -1255,7 +1255,7 @@ static int __init parport_ECPPS2_supported(struct parport *pb)
 
 /* EPP mode detection  */
 
-static int __init parport_EPP_supported(struct parport *pb)
+static int __maybe_init parport_EPP_supported(struct parport *pb)
 {
        const struct parport_pc_private *priv = pb->private_data;
 
@@ -1290,15 +1290,15 @@ static int __init parport_EPP_supported(struct parport *pb)
        pb->modes |= PARPORT_MODE_EPP;
 
        /* Set up access functions to use EPP hardware. */
-       parport_pc_ops.epp_read_data = parport_pc_epp_read_data;
-       parport_pc_ops.epp_write_data = parport_pc_epp_write_data;
-       parport_pc_ops.epp_read_addr = parport_pc_epp_read_addr;
-       parport_pc_ops.epp_write_addr = parport_pc_epp_write_addr;
+       pb->ops->epp_read_data = parport_pc_epp_read_data;
+       pb->ops->epp_write_data = parport_pc_epp_write_data;
+       pb->ops->epp_read_addr = parport_pc_epp_read_addr;
+       pb->ops->epp_write_addr = parport_pc_epp_write_addr;
 
        return 1;
 }
 
-static int __init parport_ECPEPP_supported(struct parport *pb)
+static int __maybe_init parport_ECPEPP_supported(struct parport *pb)
 {
        struct parport_pc_private *priv = pb->private_data;
        int result;
@@ -1317,10 +1317,10 @@ static int __init parport_ECPEPP_supported(struct parport *pb)
 
        if (result) {
                /* Set up access functions to use ECP+EPP hardware. */
-               parport_pc_ops.epp_read_data = parport_pc_ecpepp_read_data;
-               parport_pc_ops.epp_write_data = parport_pc_ecpepp_write_data;
-               parport_pc_ops.epp_read_addr = parport_pc_ecpepp_read_addr;
-               parport_pc_ops.epp_write_addr = parport_pc_ecpepp_write_addr;
+               pb->ops->epp_read_data = parport_pc_ecpepp_read_data;
+               pb->ops->epp_write_data = parport_pc_ecpepp_write_data;
+               pb->ops->epp_read_addr = parport_pc_ecpepp_read_addr;
+               pb->ops->epp_write_addr = parport_pc_ecpepp_write_addr;
        }
 
        return result;
@@ -1329,18 +1329,18 @@ static int __init parport_ECPEPP_supported(struct parport *pb)
 #else /* No IEEE 1284 support */
 
 /* Don't bother probing for modes we know we won't use. */
-static int __init parport_PS2_supported(struct parport *pb) { return 0; }
-static int __init parport_ECP_supported(struct parport *pb) { return 0; }
-static int __init parport_EPP_supported(struct parport *pb) { return 0; }
-static int __init parport_ECPEPP_supported(struct parport *pb) { return 0; }
-static int __init parport_ECPPS2_supported(struct parport *pb) { return 0; }
+static int __maybe_init parport_PS2_supported(struct parport *pb) { return 0; }
+static int __maybe_init parport_ECP_supported(struct parport *pb) { return 0; }
+static int __maybe_init parport_EPP_supported(struct parport *pb) { return 0; }
+static int __maybe_init parport_ECPEPP_supported(struct parport *pb){return 0;}
+static int __maybe_init parport_ECPPS2_supported(struct parport *pb){return 0;}
 
 #endif /* No IEEE 1284 support */
 
 /* --- IRQ detection -------------------------------------- */
 
 /* Only if supports ECP mode */
-static int __init programmable_irq_support(struct parport *pb)
+static int __maybe_init programmable_irq_support(struct parport *pb)
 {
        int irq, intrLine;
        unsigned char oecr = inb (ECONTROL (pb));
@@ -1357,7 +1357,7 @@ static int __init programmable_irq_support(struct parport *pb)
        return irq;
 }
 
-static int __init irq_probe_ECP(struct parport *pb)
+static int __maybe_init irq_probe_ECP(struct parport *pb)
 {
        int i;
        unsigned long irqs;
@@ -1386,7 +1386,7 @@ static int __init irq_probe_ECP(struct parport *pb)
  * This detection seems that only works in National Semiconductors
  * This doesn't work in SMC, LGS, and Winbond 
  */
-static int __init irq_probe_EPP(struct parport *pb)
+static int __maybe_init irq_probe_EPP(struct parport *pb)
 {
 #ifndef ADVANCED_DETECT
        return PARPORT_IRQ_NONE;
@@ -1426,7 +1426,7 @@ static int __init irq_probe_EPP(struct parport *pb)
 #endif /* Advanced detection */
 }
 
-static int __init irq_probe_SPP(struct parport *pb)
+static int __maybe_init irq_probe_SPP(struct parport *pb)
 {
        /* Don't even try to do this. */
        return PARPORT_IRQ_NONE;
@@ -1439,7 +1439,7 @@ static int __init irq_probe_SPP(struct parport *pb)
  * When ECP is available we can autoprobe for IRQs.
  * NOTE: If we can autoprobe it, we can register the IRQ.
  */
-static int __init parport_irq_probe(struct parport *pb)
+static int __maybe_init parport_irq_probe(struct parport *pb)
 {
        const struct parport_pc_private *priv = pb->private_data;
 
@@ -1473,7 +1473,7 @@ out:
 /* --- DMA detection -------------------------------------- */
 
 /* Only if supports ECP mode */
-static int __init programmable_dma_support (struct parport *p)
+static int __maybe_init programmable_dma_support (struct parport *p)
 {
        unsigned char oecr = inb (ECONTROL (p));
        int dma;
@@ -1488,7 +1488,7 @@ static int __init programmable_dma_support (struct parport *p)
        return dma;
 }
 
-static int __init parport_dma_probe (struct parport *p)
+static int __maybe_init parport_dma_probe (struct parport *p)
 {
        const struct parport_pc_private *priv = p->private_data;
        if (priv->ecr)
@@ -1499,27 +1499,27 @@ static int __init parport_dma_probe (struct parport *p)
 
 /* --- Initialisation code -------------------------------- */
 
-static int __init probe_one_port(unsigned long int base,
-                                unsigned long int base_hi,
-                                int irq, int dma)
+struct parport *__maybe_init parport_pc_probe_port (unsigned long int base,
+                                                   unsigned long int base_hi,
+                                                   int irq, int dma)
 {
        struct parport_pc_private *priv;
        struct parport_operations *ops;
        struct parport tmp;
        struct parport *p = &tmp;
        int probedirq = PARPORT_IRQ_NONE;
-       if (check_region(base, 3)) return 0;
+       if (check_region(base, 3)) return NULL;
        priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL);
        if (!priv) {
                printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
-               return 0;
+               return NULL;
        }
        ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
        if (!ops) {
                printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n",
                        base);
                kfree (priv);
-               return 0;
+               return NULL;
        }
        memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations));
        priv->ctr = 0xc;
@@ -1550,7 +1550,7 @@ static int __init probe_one_port(unsigned long int base,
        if (!parport_SPP_supported (p)) {
                /* No port. */
                kfree (priv);
-               return 0;
+               return NULL;
        }
 
        parport_PS2_supported (p);
@@ -1559,7 +1559,7 @@ static int __init probe_one_port(unsigned long int base,
                                        PARPORT_DMA_NONE, ops))) {
                kfree (priv);
                kfree (ops);
-               return 0;
+               return NULL;
        }
 
        p->base_hi = base_hi;
@@ -1596,10 +1596,10 @@ static int __init probe_one_port(unsigned long int base,
 
 #ifdef CONFIG_PARPORT_PC_FIFO
        if (priv->fifo_depth > 0 && p->irq != PARPORT_IRQ_NONE) {
-               parport_pc_ops.compat_write_data =
+               p->ops->compat_write_data =
                        parport_pc_compat_write_block_pio;
 #ifdef CONFIG_PARPORT_1284
-               parport_pc_ops.ecp_write_data =
+               p->ops->ecp_write_data =
                        parport_pc_ecp_write_block_pio;
 #endif /* IEEE 1284 support */
                if (p->dma != PARPORT_DMA_NONE)
@@ -1648,7 +1648,7 @@ static int __init probe_one_port(unsigned long int base,
                                        p->name, p->dma);
                                p->dma = PARPORT_DMA_NONE;
                        } else {
-                               priv->dma_buf = (char *) __get_dma_pages(GFP_KERNEL, 1);
+                               priv->dma_buf = (char *) __get_dma_pages(GFP_KERNEL, 0);
                                if (! priv->dma_buf) {
                                        printk (KERN_WARNING "%s: "
                                                "cannot get buffer for DMA, "
@@ -1684,7 +1684,7 @@ static int __init probe_one_port(unsigned long int base,
           know about it. */
        parport_announce_port (p);
 
-       return 1;
+       return p;
 }
 
 /* Look for PCI parallel port cards. */
@@ -1746,6 +1746,7 @@ static int __init parport_pc_init_pci (int irq, int dma)
                { 0, }
        };
 
+       struct pci_dev *pcidev;
        int count = 0;
        int i;
 
@@ -1753,7 +1754,7 @@ static int __init parport_pc_init_pci (int irq, int dma)
                return 0;
 
        for (i = 0; cards[i].vendor; i++) {
-               struct pci_dev *pcidev = NULL;
+               pcidev = NULL;
                while ((pcidev = pci_find_device (cards[i].vendor,
                                                  cards[i].device,
                                                  pcidev)) != NULL) {
@@ -1766,20 +1767,55 @@ static int __init parport_pc_init_pci (int irq, int dma)
                                                pcidev->base_address[hi]);
                                io_lo &= PCI_BASE_ADDRESS_IO_MASK;
                                io_hi &= PCI_BASE_ADDRESS_IO_MASK;
-                               if (irq == PARPORT_IRQ_AUTO)
-                                       count += probe_one_port (io_lo, io_hi,
-                                                                pcidev->irq,
-                                                                dma);
-                               else
-                                       count += probe_one_port (io_lo, io_hi,
-                                                                irq, dma);
+                               if (irq == PARPORT_IRQ_AUTO) {
+                                       if (parport_pc_probe_port (io_lo,
+                                                                  io_hi,
+                                                                  pcidev->irq,
+                                                                  dma))
+                                               count++;
+                               } else if (parport_pc_probe_port (io_lo, io_hi,
+                                                                 irq, dma))
+                                       count++;
                        }
                }
        }
 
+       /* Look for parallel controllers that we don't know about. */
+       for (pcidev = pci_devices; pcidev; pcidev = pcidev->next) {
+               const int class_noprogif = pcidev->class & ~0xff;
+               if (class_noprogif != (PCI_CLASS_COMMUNICATION_PARALLEL << 8))
+                       continue;
+
+               for (i = 0; cards[i].vendor; i++)
+                       if ((cards[i].vendor == pcidev->vendor) &&
+                           (cards[i].device == pcidev->device))
+                               break;
+               if (cards[i].vendor)
+                       /* We know about this one. */
+                       continue;
+
+               printk (KERN_INFO
+                       "Unknown PCI parallel I/O card (%04x/%04x)\n"
+                       "Please send 'lspci' output to "
+                       "tim@cyberelk.demon.co.uk\n",
+                       pcidev->vendor, pcidev->device);
+       }
+
        return count;
 }
 
+/* Exported symbols. */
+#ifdef CONFIG_PARPORT_PC_PCMCIA
+
+/* parport_cs needs this in order to dyncamically get us to find ports. */
+EXPORT_SYMBOL (parport_pc_probe_port);
+
+#else
+
+EXPORT_NO_SYMBOLS;
+
+#endif
+
 #ifdef MODULE
 static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
 static int io_hi[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
index e1166797d9c5d2fa6d7b9bc401c836e640c6c42f..7ad890ee2e4845feebf8eb56ef0778aa8600ad53 100644 (file)
@@ -31,6 +31,10 @@ THANKS file in Inaky's driver):
         The following corporations have helped us in the development
         of Linux USB / UUSBD:
 
+       - 3Com GmbH for donating a ISDN Pro TA and supporting me
+         in technical questions and with test equipment. I'd never 
+         expect such a great help.
+
         - USAR Systems provided us with one of their excellent USB
           Evaluation Kits. It allows us to test the Linux-USB driver
           for compilance with the latest USB specification. USAR
index f47226bbc3096958ad9911b66767e06ad46e968f..a89e5db1575158b9c573c2e5ffbcf82071837b3d 100644 (file)
@@ -28,7 +28,7 @@ if [ ! "$CONFIG_USB" = "n" ]; then
   dep_tristate 'USB mouse support' CONFIG_USB_MOUSE $CONFIG_USB
   dep_tristate 'USB keyboard support' CONFIG_USB_KBD $CONFIG_USB
   dep_tristate 'USB audio parsing support' CONFIG_USB_AUDIO $CONFIG_USB
-  dep_tristate 'USB Abstract Control Model support' CONFIG_USB_ACM $CONFIG_USB
+  dep_tristate 'USB Communications Device Class (ACM) support' CONFIG_USB_ACM $CONFIG_USB
   dep_tristate 'USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
   dep_tristate 'USB SCSI Support' CONFIG_USB_SCSI $CONFIG_USB
   if [ "$CONFIG_USB_SCSI" != "n" ]; then
diff --git a/drivers/usb/README.acm b/drivers/usb/README.acm
new file mode 100644 (file)
index 0000000..c978974
--- /dev/null
@@ -0,0 +1,94 @@
+The ACM driver works with modems and ISDN TAs that use the USB Abstract
+Control Model standard. 
+
+****************************
+Test it:
+Watch out, the driver is not stable and tested. Sync often, make backups,
+most importand: don't blame me...
+
+Create device files:
+mknod /dev/ttyACM0 c 166 0
+mknod /dev/ttyACM1 c 166 1
+mknod /dev/ttyACM2 c 166 2
+mknod /dev/ttyACM3 c 166 3
+Compile a kernel with support for your host controller (uhci only for now!)
+and support for ACM. Boot this kernel. If you connect your device to the
+USB bus you should see messages like the following:
+
+Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1
+Jul 19 20:14:29 office kernel: Found 02:09
+Jul 19 20:14:29 office kernel: Found 04:09
+Jul 19 20:14:29 office kernel: Found 05:07
+Jul 19 20:14:29 office last message repeated 2 times
+Jul 19 20:14:29 office kernel: parsed = 39 len = 67
+Jul 19 20:14:29 office kernel: Expected descriptor 04/09, got 02/09 - skipping
+Jul 19 20:14:29 office kernel:    0 09
+Jul 19 20:14:29 office kernel:    1 02
+Jul 19 20:14:29 office kernel:    2 43
+Jul 19 20:14:29 office kernel:    3 00
+Jul 19 20:14:29 office kernel:    4 02
+Jul 19 20:14:29 office kernel:    5 02
+Jul 19 20:14:29 office kernel:    6 04
+Jul 19 20:14:29 office kernel:    7 60
+Jul 19 20:14:29 office kernel:    8 00
+Jul 19 20:14:29 office kernel: Found 04:09
+Jul 19 20:14:29 office kernel: Found 02:09
+Jul 19 20:14:29 office kernel: Found 04:09
+Jul 19 20:14:29 office kernel: Found 05:07
+Jul 19 20:14:29 office kernel: Found 04:09
+Jul 19 20:14:29 office kernel: Found 05:07
+Jul 19 20:14:29 office kernel: Found 05:07
+Jul 19 20:14:29 office kernel: parsed = 67 len = 0
+Jul 19 20:14:29 office kernel: getstringtable
+Jul 19 20:14:29 office kernel: acm_probe
+Jul 19 20:14:29 office kernel: USB ACM found
+
+Watch out for the line:
+Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1
+and the line:
+Jul 19 20:14:29 office kernel: USB ACM found
+These two lines show that the device was seen by the usb host controller and
+then recognized by the acm driver as a valid device.
+
+If you use a terminal emulation software like minicom with /dev/ttyACM0 you
+should be able to send AT commands to your device and get responses. I've 
+been able to do zmodem downloads to another pc. However downloads from one
+ISDN TA to another ISDN TA connected to the same PC didn't work. Don't
+know why. Flow control is not finised after all and i'd guess there might
+be problems on heavily loades PCs. I also did some tests with ppp but i'm
+not finised with this. There might be a chance to get it working. However
+i'd like to know if your device is recognized as an ACM device. I'm also
+interested if the thing is stable or if it crashes.
+(should i say how it crases?)
+
+You should be able to add and remove devices from the bus. The driver will
+always try to fill up unused ttys. This means if you hotplug devices their
+order may have changed after reboot. This is not the behaviour Linus liked
+to see but it's ok for now. (I hope ;-)
+
+Please report your experiences to me:
+fuerst@in.tum.de
+
+***************************
+I've tested it with:
+3Com ISDN Pro TA.
+
+It should work with (That means i know these devices conform to ACM):
+3Com Office Connect Modem
+3Com Sportster USB (I think that's what it's called)
+
+***************************
+Many thanks to 3Com which did not only support me with hardware but also
+with technical support in USB questions. They also allowed me to do tests in
+their lab. Great!
+
+***************************
+Known bugs:
+Flow control not tested (likely not to work)
+Some tty function calls not implemented (putchar, etc...)
+Huge amounts of debug output (compile in [*] Magic SysRq key and press ALT+PRTSCR+0 )
+Not all mem is freed at close (need terminate irq in hcd)
+
+***************************
+Have fun,
+       Armin Fuerst
index 4521bd701ba1923f2a6d6cfef4e75e5a91a95517..db61c2ea801c5a96f4f4767a4f444b724aa63de8 100644 (file)
@@ -3,6 +3,35 @@
  *
  * Armin Fuerst 5/8/1999
  *
+ * version 0.7: Added usb flow control. Fixed bug in uhci.c (what idiot
+ * wrote this code? ...Oops that was me). Fixed module cleanup. Did some
+ * testing at 3Com => zmodem uload+download works, pppd had trouble but
+ * seems to work now. Changed Menuconfig texts "Communications Device
+ * Class (ACM)" might be a bit more intuitive. Ported to 2.3.13-1 prepatch. 
+ * (2/8/99)
+ *
+ * version 0.6: Modularized driver, added disconnect code, improved
+ * assignment of device to tty minor number.
+ * (21/7/99)
+ *
+ * version 0.5: Driver now generates a tty instead of a simple character
+ * device. Moved async bulk transfer to 2.3.10 kernel version. fixed a bug
+ * in uhci_td_allocate. Commenetd out getstringtable which causes crash.
+ * (13/7/99)
+ *
+ * version 0.4: Small fixes in the FIFO, cleanup. Updated Bulk transfer in 
+ * uhci.c. Should have the correct interface now. 
+ * (6/6/99)
+ *
+ * version 0.5 driver now generates a tty instead of a simple character
+ * device
+ *
+ * version 0.3: Mayor changes. Changed Bulk transfer to interrupt based
+ * transfer. Using FIFO Buffers now. Consistent handling of open/close
+ * file state and detected/nondetected device. File operations behave
+ * according to this. Driver is able to send+receive now! Heureka!
+ * (27/5/99)
+ *
  * version 0.2: Improved Bulk transfer. TX led now flashes every time data is
  * sent. Send Encapsulated Data is not needed, nor does it do anything.
  * Why's that ?!? Thanks to Thomas Sailer for his close look at the bulk code.
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
-#include <linux/miscdevice.h>
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/malloc.h>
+#include <linux/fcntl.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/tty.h>
 #include <linux/module.h>
-
+//#include <sys/ioctl.h>
 #include <asm/spinlock.h>
-
 #include "usb.h"
 
-#define USB_ACM_MINOR 32
+#define NR_PORTS 3
+#define ACM_MAJOR 166
+
+#define info(message); printk(message);
+//#define info(message);
+
+#define CTRL_STAT_DTR  1
+#define CTRL_STAT_RTS  2
+
+static int acm_refcount;
+
+static struct tty_driver acm_tty_driver;
+static struct tty_struct *acm_tty[NR_PORTS];
+static struct termios *acm_termios[NR_PORTS];
+static struct termios *acm_termios_locked[NR_PORTS];
+static struct acm_state acm_state_table[NR_PORTS];
 
 struct acm_state {
-       int present; /* this acm is plugged in */
-       int active; /* someone is has this acm's device open */
-       int serstate; /* Status of the serial port (rate, handshakelines,...) */
-       struct usb_device *dev;
-       unsigned ctrlbuffer;    /*buffer for control messages*/
-       unsigned int readendp,writeendp,ctrlendp;
-       unsigned int readpipe,writepipe,ctrlpipe;
-       char buffer;
+       struct usb_device *dev;                         //the coresponding usb device
+       struct tty_struct *tty;                         //the coresponding tty
+       char present;                                   //a device for this struct was detected => this tty is used
+       char active;                                    //someone has this acm's device open 
+       unsigned int ctrlstate;                         //Status of the serial control lines  (handshake,...)
+       unsigned int linecoding;                        //Status of the line coding (Bits, Stop, Parity)
+       int writesize, readsize;                        //size of the usb buffers
+       char *writebuffer, *readbuffer;                 //the usb buffers
+       void *readtransfer, *writetransfer;
+       void *ctrltransfer;                             //ptr to HC internal transfer struct
+       char writing, reading;                          //flag if transfer is running
+       unsigned int readendp,writeendp,ctrlendp;       //endpoints and
+       unsigned int readpipe,writepipe,ctrlpipe;       //pipes (are one of these obsolete?)
+       unsigned ctrlinterval;                          //interval to poll from device
 };
 
-static struct acm_state static_acm_state;
 
-spinlock_t usb_acm_lock = SPIN_LOCK_UNLOCKED;
+//functions for various ACM requests
 
-static int acm_irq(int state, void *__buffer, int len, void *dev_id)
+void Set_Control_Line_Status (unsigned int status,struct acm_state *acm)
 {
-//     unsigned char *data = __buffer;
-        struct acm_state *acm = &static_acm_state; 
+       devrequest dr;
+
+       info("Set_control_Line_Status\n");
+
+       dr.requesttype = 0x22;
+       dr.request = 0x22;
+       dr.value = status;
+       dr.index = 0;
+       dr.length = 0;
+       acm->dev->bus->op->control_msg(acm->dev, usb_sndctrlpipe(acm->dev,0), &dr, NULL, 0);
+
+       acm->ctrlstate=status;
+}
+
+void Set_Line_Coding (unsigned int coding,struct acm_state *acm)
+{
+       devrequest dr;
+
+       info("Set_Line_Coding\n");
+
+       dr.requesttype = 0x22;
+       dr.request = 0x30;
+       dr.value = coding;
+       dr.index = 0;
+       dr.length = 0;
+       acm->dev->bus->op->control_msg(acm->dev, usb_sndctrlpipe(acm->dev,0), &dr, NULL, 0);
+       
+       acm->linecoding=coding;
+}
+
+//Interrupt handler for various usb events
+static int acm_irq(int state, void *__buffer, int count, void *dev_id)
+{
+
+       unsigned char *data;
+       struct acm_state *acm = (struct acm_state *) dev_id; 
         devrequest *dr;
+               
+       info("ACM_USB_IRQ\n");
 
+       if (!acm->present) {
+               info("NO ACM DEVICE REGISTERED\n");
+               return 0;
+       }
+       if (!acm->active) {
+               info ("ACM DEVICE NOT OPEN\n");
+               return 1;
+       }
+       
         dr=__buffer;
-       printk("ACM_USB_IRQ\n");
+       data=__buffer;
+       data+=sizeof(dr);
+#if 1
         printk("reqtype: %02X\n",dr->requesttype);
         printk("request: %02X\n",dr->request);
        printk("wValue: %02X\n",dr->value);
        printk("wIndex: %02X\n",dr->index);
        printk("wLength: %02X\n",dr->length);
+#endif
        
        switch(dr->request) {
          //Network connection 
          case 0x00:
            printk("Network connection: ");
-           if (dr->request==0) printk("disconnected\n");
-           if (dr->request==1) printk("connected\n");
+           if (dr->request==0) info("disconnected\n");
+           if (dr->request==1) info("connected\n");
            break;
-
+           
          //Response available
          case 0x01:
            printk("Response available\n");
-           acm->buffer=1;
            break;
        
          //Set serial line state
          case 0x20:
+           printk("Set serial control line state\n");
            if ((dr->index==1)&&(dr->length==2)) {
-             acm->serstate=acm->ctrlbuffer;
-             printk("Serstate: %02X\n",acm->ctrlbuffer);
+             acm->ctrlstate=* ((unsigned short int *)data);
+             printk("Serstate: %02X\n",acm->ctrlstate);
            }
            break;
        }
-/*
-       if(!acm->active)
-               return 1;
-*/
+
+       //info("Done\n");
+       //Continue transfer
        return 1;
 }
 
-static int release_acm(struct inode * inode, struct file * file)
+static int acm_read_irq(int state, void *__buffer, int count, void *dev_id)
 {
-       struct acm_state *acm = &static_acm_state;
-       printk("ACM_FILE_RELEASE\n");
+       struct acm_state *acm = (struct acm_state *) dev_id; 
+               struct tty_struct *tty = acm->tty; 
+               unsigned char* data=__buffer;
+       int i;
+
+       info("ACM_READ_IRQ\n");
+       
+       if (!acm->present) {
+               info("NO ACM DEVICE REGISTERED\n");
+               //Stop transfer
+               return 0;
+       }
 
-//     fasync_acm(-1, file, 0);
-       if (--acm->active)
+       if (!acm->active) {
+               info ("ACM DEVICE NOT OPEN\n");
+               //Stop transfer
                return 0;
+       }
+
+//     printk("%d %s\n",count,data);
+       for (i=0;i<count;i++) {
+                tty_insert_flip_char(tty,data[i],0);
+       }
+       tty_flip_buffer_push(tty);
+       
+       //info("Done\n");
+       //Continue transfer
+       return 1;
+}
+
+static int acm_write_irq(int state, void *__buffer, int count, void *dev_id)
+{
+       struct acm_state *acm = (struct acm_state *) dev_id; 
+               struct tty_struct *tty = acm->tty; 
+
+       info("ACM_WRITE_IRQ\n");
+
+       if (!acm->present) {
+               info("NO ACM DEVICE REGISTERED\n");
+               //Stop transfer
+               return 0;
+       }
+       if (!acm->active) {
+               info ("ACM DEVICE NOT OPEN\n");
+               //Stop transfer
+               return 0;
+       }
+
+       usb_terminate_bulk(acm->dev, acm->writetransfer);
+       acm->writing=0;
+       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
+               (tty->ldisc.write_wakeup)(tty);
+       wake_up_interruptible(&tty->write_wait);
+       
+       //info("Done\n");
+       //Stop transfer
        return 0;
 }
 
-static int open_acm(struct inode * inode, struct file * file)
+/*TTY STUFF*/
+static int rs_open(struct tty_struct *tty, struct file * filp) 
 {
-       struct acm_state *acm = &static_acm_state;
-       printk("USB_FILE_OPEN\n");
+       struct acm_state *acm;
 
-       if (!acm->present)
+       
+       info("USB_FILE_OPEN\n");
+
+       tty->driver_data=acm=&acm_state_table[MINOR(tty->device)-tty->driver.minor_start];
+       acm->tty=tty;
+        
+       if (!acm->present) {
+               info("NO ACM DEVICE REGISTERED\n");
                return -EINVAL;
-       if (acm->active++)
-               return 0;
+       }
+
+       if (acm->active) {
+               info ("ACM DEVICE ALREADY OPEN\n");
+               return -EINVAL;
+       }
+       acm->active=1;
+       /*Start reading from the device*/
+       acm->ctrltransfer=usb_request_irq(acm->dev,acm->ctrlpipe, acm_irq, acm->ctrlinterval, acm);
+       
+       acm->reading=1;
+       acm->readtransfer=usb_request_bulk(acm->dev,acm->readpipe, acm_read_irq, acm->readbuffer, acm->readsize, acm );
+       
+       Set_Control_Line_Status (CTRL_STAT_DTR | CTRL_STAT_RTS, acm);
+                                                 
        return 0;
 }
 
-static ssize_t write_acm(struct file * file,
-       const char * buffer, size_t count, loff_t *ppos)
+static void rs_close(struct tty_struct *tty, struct file * filp)
 {
-        devrequest dr;
-       struct acm_state *acm = &static_acm_state;
-       unsigned long retval;           
+       struct acm_state *acm = (struct acm_state *) tty->driver_data; 
+       info("rs_close\n");
+       
+       if (!acm->present) {
+               info("NO ACM DEVICE REGISTERED\n");
+               return;
+       }
 
-       printk("USB_FILE_WRITE\n");
-//Huh, i seem to got that wrong, we don't need this ?!?
-/*
-       dr.requesttype = USB_TYPE_CLASS | USB_RT_ENDPOINT;
-       dr.request = 0;
-       dr.value = 0;
-       dr.index = acm->writeendp;
-       dr.length = count;
-       acm->dev->bus->op->control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), &dr, NULL, 0);
-*/     
-
-       acm->dev->bus->op->bulk_msg(acm->dev,&acm->writepipe,buffer, count, &retval);
-       return -EINVAL;
+       if (!acm->active) {
+               info ("ACM DEVICE NOT OPEN\n");
+               return;
+       }
+
+       Set_Control_Line_Status (0, acm);
+       
+       if (acm->writing){
+               usb_terminate_bulk(acm->dev, acm->writetransfer);
+               acm->writing=0;
+       }
+       if (acm->reading){
+               usb_terminate_bulk(acm->dev, acm->readtransfer);
+               acm->reading=0;
+       }
+//  usb_release_irq(acm->dev,acm->ctrltransfer);
+       
+       acm->active=0;
 }
 
+static int rs_write(struct tty_struct * tty, int from_user,
+                   const unsigned char *buf, int count)
+{
+       struct acm_state *acm = (struct acm_state *) tty->driver_data; 
+       int written;
+       
+       info("rs_write\n");
+
+       if (!acm->present) {
+               info("NO ACM DEVICE REGISTERED\n");
+               return -EINVAL;
+       }
 
-static ssize_t read_acm(struct file * file, const char * buffer, size_t count, loff_t *ppos)
+       if (!acm->active) {
+               info ("ACM DEVICE NOT OPEN\n");
+               return -EINVAL;
+       }
+       
+       if (acm->writing) {
+               info ("already writing\n");
+               return 0;
+       }
+
+       written=(count>acm->writesize) ? acm->writesize : count;
+         
+       if (from_user) {
+               //info("fromuser\n");
+               copy_from_user(acm->writebuffer,buf,written);
+       }
+       else {
+               //info("notfromuser\n");
+               memcpy(acm->writebuffer,buf,written);
+       }  
+
+       //start the transfer
+       acm->writing=1;
+       acm->writetransfer=usb_request_bulk(acm->dev,acm->writepipe, acm_write_irq, acm->writebuffer, written, acm);
+
+       return written;
+} 
+
+static void rs_put_char(struct tty_struct *tty, unsigned char ch)
 {
-       devrequest dr;
-        struct acm_state *acm = &static_acm_state;
-       unsigned long retval;
-       printk("USB_FILE_READ\n");
-//        if (!acm->buffer) return -1;
-       acm->buffer=0;
-//We don't need this
-/*
-       printk("writing control msg\n");
-       dr.requesttype = USB_TYPE_CLASS | USB_RT_ENDPOINT | 0x80;
-       dr.request = 1;
-       dr.value = 0;
-       dr.index = acm->readendp;
-       dr.length = 0;
-       acm->dev->bus->op->control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), &dr, NULL, 0);
-*/
-       printk("reading:>%s<\n",buffer);
-       acm->dev->bus->op->bulk_msg(acm->dev,&acm->readpipe,buffer, 1,&retval);
-       printk("done:>%s<\n",buffer);
-       return 1;
+       struct acm_state *acm = (struct acm_state *) tty->driver_data; 
+       
+       info("rs_put_char\n");
+       
+       if (!acm->present) {
+               info("NO ACM DEVICE REGISTERED\n");
+               return;
+       }
+
+       if (!acm->active) {
+               info ("ACM DEVICE NOT OPEN\n");
+               return;
+       }
+//  printk("%c\n",ch);
+}                   
+
+static int rs_write_room(struct tty_struct *tty) 
+{
+       struct acm_state *acm = (struct acm_state *) tty->driver_data; 
+
+       info("rs_write_room\n");
+       
+       if (!acm->present) {
+               info("NO ACM DEVICE REGISTERED\n");
+               return -EINVAL;
+       }
+
+       if (!acm->active) {
+               info ("ACM DEVICE NOT OPEN\n");
+               return -EINVAL;
+       }
+       
+       if (acm->writing) {
+               return 0;
+       }
+       return acm->writesize;
 }
 
-struct file_operations usb_acm_fops = {
-       NULL,           /* acm_seek */
-       read_acm,
-       write_acm,
-       NULL,           /* acm_readdir */
-       NULL,           /* acm_poll */
-       NULL,           /* acm_ioctl */
-       NULL,           /* acm_mmap */
-       open_acm,
-       NULL,           /* flush */
-       release_acm,
-       NULL,
-       NULL,           /*fasync*/
-};
+static int rs_chars_in_buffer(struct tty_struct *tty) 
+{
+       struct acm_state *acm = (struct acm_state *) tty->driver_data; 
 
-static struct miscdevice usb_acm = {
-       USB_ACM_MINOR, "USB ACM", &usb_acm_fops
-};
+       info("rs_chars_in_buffer\n");
+       
+       if (!acm->present) {
+               info("NO ACM DEVICE REGISTERED\n");
+               return -EINVAL;
+       }
+
+       if (!acm->active) {
+               info ("ACM DEVICE NOT OPEN\n");
+               return -EINVAL;
+       }
+       
+       if (acm->writing) {
+               return acm->writesize;
+       }
+       return 0;
+}
+
+static void rs_throttle(struct tty_struct * tty)
+{
+       struct acm_state *acm = (struct acm_state *) tty->driver_data; 
+       
+       info("rs_throttle\n");
+       
+       if (!acm->present) {
+               info("NO ACM DEVICE REGISTERED\n");
+               return;
+       }
+
+       if (!acm->active) {
+               info ("ACM DEVICE NOT OPEN\n");
+               return;
+       }
+
+/*     
+       if (I_IXOFF(tty))
+               rs_send_xchar(tty, STOP_CHAR(tty));
+*/    
+
+       if (tty->termios->c_cflag & CRTSCTS)
+               Set_Control_Line_Status (acm->ctrlstate & ~CTRL_STAT_RTS, acm);
+}
+
+static void rs_unthrottle(struct tty_struct * tty)
+{
+       struct acm_state *acm = (struct acm_state *) tty->driver_data; 
+       
+       info("rs_unthrottle\n");
+       
+       if (!acm->present) {
+               info("NO ACM DEVICE REGISTERED\n");
+               return;
+       }
+
+       if (!acm->active) {
+               info ("ACM DEVICE NOT OPEN\n");
+               return;
+       }
+
+/*     
+       if (I_IXOFF(tty))
+               rs_send_xchar(tty, STOP_CHAR(tty));
+*/    
+
+       if (tty->termios->c_cflag & CRTSCTS)
+               Set_Control_Line_Status (acm->ctrlstate | CTRL_STAT_RTS, acm);
+}
+
+static int get_free_acm()
+{
+ int i;
+ for (i=0;i<NR_PORTS;i++) {
+        if (!acm_state_table[i].present)
+                return i;
+ }
+ return -1;
+}
 
 static int acm_probe(struct usb_device *dev)
 {
+       struct acm_state *acm;
        struct usb_interface_descriptor *interface;
        struct usb_endpoint_descriptor *endpoint;
-       struct acm_state *acm = &static_acm_state;
-       int cfgnum;
+       int cfgnum,acmno;
+       
+       info("acm_probe\n");
+       
+       if (0>(acmno=get_free_acm())) {
+               info("Too many acm devices connected\n");
+               return -1;
+       }
+       acm = &acm_state_table[acmno];
 
        /* Only use CDC */
        if (dev->descriptor.bDeviceClass != 2 ||
@@ -230,34 +536,74 @@ static int acm_probe(struct usb_device *dev)
                    (endpoint->bmAttributes & 3) != 2)
                        continue;
 
-               printk("USB ACM found\n");
-               if (usb_set_configuration(dev, dev->config[cfgnum].bConfigurationValue)) {
-                       printk (KERN_INFO " Failed usb_set_configuration: ACM\n");
-                       continue;
-               }
+               printk("USB ACM %d found\n",acmno);
+               usb_set_configuration(dev, dev->config[cfgnum].bConfigurationValue);
+
                acm->dev=dev;
+               dev->private=acm;
+
                acm->readendp=dev->config[cfgnum].altsetting[0].interface[1].endpoint[0].bEndpointAddress;
-               acm->writeendp=dev->config[cfgnum].altsetting[0].interface[1].endpoint[1].bEndpointAddress;
-               acm->ctrlendp=dev->config[cfgnum].altsetting[0].interface[0].endpoint[0].bEndpointAddress;
                acm->readpipe=usb_rcvbulkpipe(dev,acm->readendp);
+               acm->readbuffer=kmalloc(acm->readsize=dev->config[cfgnum].altsetting[0].interface[1].endpoint[0].wMaxPacketSize,GFP_KERNEL);
+               acm->reading=0;
+               if (!acm->readbuffer) {
+                       printk("ACM: Couldn't allocate readbuffer\n");
+                       return -1;
+               }
+               
+               acm->writeendp=dev->config[cfgnum].altsetting[0].interface[1].endpoint[1].bEndpointAddress;
                acm->writepipe=usb_sndbulkpipe(dev,acm->writeendp);
-               usb_request_irq(dev,acm->ctrlpipe=usb_rcvctrlpipe(dev,acm->ctrlendp), acm_irq, dev->config[cfgnum].altsetting[0].interface[0].endpoint[0].bInterval, &acm->ctrlbuffer);
-               acm->present = 1;
-               acm->buffer=0;
+               acm->writebuffer=kmalloc(acm->writesize=dev->config[cfgnum].altsetting[0].interface[1].endpoint[1].wMaxPacketSize, GFP_KERNEL);
+               acm->writing=0;
+               if (!acm->writebuffer) {
+                       printk("ACM: Couldn't allocate writebuffer\n");
+                       kfree(acm->readbuffer);
+                       return -1;
+               }
+               
+               acm->ctrlendp=dev->config[cfgnum].altsetting[0].interface[0].endpoint[0].bEndpointAddress;
+               acm->ctrlpipe=usb_rcvctrlpipe(acm->dev,acm->ctrlendp);
+               acm->ctrlinterval=dev->config[cfgnum].altsetting[0].interface[0].endpoint[0].bInterval;
+
+               acm->present=1;                         
+               MOD_INC_USE_COUNT;
                return 0;
        }
-
        return -1;
 }
 
 static void acm_disconnect(struct usb_device *dev)
 {
-       struct acm_state *acm = &static_acm_state;
+       struct acm_state *acm = (struct acm_state *) dev->private;
+
+       info("acm_disconnect\n");
+       
+       if (!acm->present) {
+               printk("device not present\n");
+               return;
+       }
 
-       /* this might need work */
-       acm->present = 0;
+       printk("disconnecting\n");
+       
+       if (acm->writing){
+               usb_terminate_bulk(acm->dev, acm->writetransfer);
+               acm->writing=0;
+       }
+       if (acm->reading){
+               usb_terminate_bulk(acm->dev, acm->readtransfer);
+               acm->reading=0;
+       }
+//  usb_release_irq(acm->dev,acm->ctrltransfer);
+       //BUG: What to do if a device is open?? Notify process or not allow cleanup?
+       acm->active=0;
+       acm->present=0;
+       kfree(acm->writebuffer);
+       kfree(acm->readbuffer);
+
+       MOD_DEC_USE_COUNT;
 }
 
+/*USB DRIVER STUFF*/
 static struct usb_driver acm_driver = {
        "acm",
        acm_probe,
@@ -267,19 +613,83 @@ static struct usb_driver acm_driver = {
 
 int usb_acm_init(void)
 {
-       struct acm_state *acm = &static_acm_state;
-
-       misc_register(&usb_acm);
-
-       acm->present = acm->active = 0;
+       int cnt;
+       
+       info("usb_acm_init\n");
+               
+       //INITIALIZE GLOBAL DATA STRUCTURES
+       for (cnt=0;cnt<NR_PORTS;cnt++) {
+               memset(&acm_state_table[cnt], 0, sizeof(struct acm_state));
+       }
 
+       //REGISTER TTY DRIVER
+       memset(&acm_tty_driver, 0, sizeof(struct tty_driver));
+       acm_tty_driver.magic = TTY_DRIVER_MAGIC;
+       acm_tty_driver.driver_name = "usb";
+       acm_tty_driver.name = "ttyACM";
+       acm_tty_driver.major = ACM_MAJOR;
+       acm_tty_driver.minor_start = 0;
+       acm_tty_driver.num = NR_PORTS;
+       acm_tty_driver.type = TTY_DRIVER_TYPE_SERIAL;
+       acm_tty_driver.subtype = SERIAL_TYPE_NORMAL;
+       acm_tty_driver.init_termios = tty_std_termios;
+       acm_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       acm_tty_driver.flags = TTY_DRIVER_REAL_RAW;
+       acm_tty_driver.refcount = &acm_refcount;
+       acm_tty_driver.table = acm_tty;
+       acm_tty_driver.termios = acm_termios;
+       acm_tty_driver.termios_locked = acm_termios_locked;
+       
+       acm_tty_driver.open = rs_open;
+       acm_tty_driver.close = rs_close;
+       acm_tty_driver.write = rs_write;
+       acm_tty_driver.put_char = rs_put_char; //FUCKIN BUG IN DOKU!!!
+       acm_tty_driver.flush_chars = NULL; //rs_flush_chars;
+       acm_tty_driver.write_room = rs_write_room; //ANBOTHER FUCKIN BUG!!
+       acm_tty_driver.ioctl = NULL; //rs_ioctl;
+       acm_tty_driver.set_termios = NULL; //rs_set_termios;
+       acm_tty_driver.set_ldisc = NULL; 
+       acm_tty_driver.throttle = rs_throttle;
+       acm_tty_driver.unthrottle = rs_unthrottle;
+       acm_tty_driver.stop = NULL; //rs_stop;
+       acm_tty_driver.start = NULL; //rs_start;
+       acm_tty_driver.hangup = NULL; //rs_hangup;
+       acm_tty_driver.break_ctl = NULL; //rs_break;
+       acm_tty_driver.wait_until_sent = NULL; //rs_wait_until_sent;
+       acm_tty_driver.send_xchar = NULL; //rs_send_xchar;
+       acm_tty_driver.read_proc = NULL; //rs_read_proc;
+       acm_tty_driver.chars_in_buffer = rs_chars_in_buffer;
+       acm_tty_driver.flush_buffer = NULL; //rs_flush_buffer;
+       tty_register_driver(&acm_tty_driver);
+       
+       //REGISTER USB DRIVER
        usb_register(&acm_driver);
+
        printk(KERN_INFO "USB ACM registered.\n");
        return 0;
 }
 
-#ifdef MODULE
+void usb_acm_cleanup(void)
+{
+       int i;
+       struct acm_state *acm;
+
+       info("usb_acm_cleanup\n");
+               
+       for (i=0;i<NR_PORTS;i++) {
+               acm=&acm_state_table[i];
+               if (acm->present) {
+                       printk("disconnecting %d\n",i);
+                       acm_disconnect(acm->dev);
+               }  
+       }
+       tty_unregister_driver(&acm_tty_driver);
+       
+       usb_deregister(&acm_driver);
+       
+}
 
+#ifdef MODULE
 int init_module(void)
 {
        return usb_acm_init();
@@ -287,9 +697,6 @@ int init_module(void)
 
 void cleanup_module(void)
 {
-       /* this, too, probably needs work */
-       usb_deregister(&acm_driver);
-       misc_deregister(&usb_acm);
+       usb_acm_cleanup();
 }
-
-#endif
+#endif
\ No newline at end of file
index 84083ce4654bcff9dbb622c128181ee6551c4ea5..8f14e6df1f4ea72e19b976ab88ce8777ad069dee 100644 (file)
@@ -241,7 +241,7 @@ static ssize_t read_printer(struct file * file,
                        return -EIO;
 
                if (this_read) {
-                       if (copy_to_user(buffer, p->obuf, this_read))
+                       if (copy_to_user(buffer, buf, this_read))
                                return -EFAULT;
                        count -= this_read;
                        read_count += this_read;
index 5ddd4c4238ca09765ce30f21a899f85ec1598ad3..cb53710d121ef47f7beefd4f177247fe67cfc2a6 100644 (file)
@@ -87,11 +87,11 @@ static int uhci_map_status(int status, int dir_out)
 static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned long *rval)
 {
        unsigned int status;
-       struct uhci_td *tmp = td->first;
+       struct uhci_td *tmp= td->first;
 
        if(rval)
                *rval = 0;
-
+               
        /* locate the first failing td, if any */
 
        do {
@@ -112,7 +112,6 @@ static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned
                tmp = bus_to_virt(tmp->link & ~0xF);
        } while (1);
 
-
        if (!status)
                return USB_ST_NOERROR;
 
@@ -300,6 +299,7 @@ static struct uhci_td *uhci_td_allocate(struct uhci_device *dev)
 
        if (!inuse) {
                td->inuse = 1;
+                               td->dev=uhci_to_usb(dev);
                return(td);
        }
 
@@ -314,7 +314,6 @@ static struct uhci_td *uhci_td_allocate(struct uhci_device *dev)
 static void uhci_td_deallocate(struct uhci_td *td)
 {
        td->link = 1;
-
        clear_bit(0, &td->inuse);
 }
 
@@ -345,6 +344,39 @@ static void uhci_remove_irq_list(struct uhci_td *td)
 }
 
 
+/*
+ * This function removes and disallcoates all structures set up for an transfer.
+ * It takes the qh out of the skeleton, removes the tq and the td's.
+ * It only removes the associated interrupt handler if removeirq ist set.
+ * The *td argument is any td in the list of td's.
+ */
+static void uhci_remove_transfer(struct uhci_td *td, char removeirq) {
+       int maxcount = 100;
+       struct uhci_td *curtd = td->first;
+       unsigned int nextlink;
+
+/* Remove it from the skeleton */
+       uhci_remove_qh(td->qh->skel, td->qh);
+       uhci_qh_deallocate(td->qh);  
+       do {
+               nextlink = curtd->link;
+               /*IOC? => remove handler*/
+               if (removeirq && (td->status & (1 << 24))) {
+                       uhci_remove_irq_list(td);
+               }
+               uhci_remove_td(curtd);
+               uhci_td_deallocate(curtd);
+               if (nextlink & 1)       /* Tail? */
+               break;
+
+               curtd = bus_to_virt(nextlink & ~0xF);
+               if (!--maxcount) {
+                       printk("runaway td's!?\n");
+                       break;
+               }
+       } while (1);
+}
+
 /*
  * Request a interrupt handler..
  *
@@ -779,6 +811,7 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre
        int ret;
        int maxsze = usb_maxpacket(usb_dev, pipe);
 
+
        if (len > maxsze * 29)
                printk("Warning, too much data for a control packet, crashing\n");
 
@@ -1030,7 +1063,7 @@ static int uhci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
                }
 
                /* Alternate Data0/1 (start with Data0) */
-               usb_dotoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
+               usb_dotoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); 
        }
        td->link = 1;                           /* Terminate */
        td->status |= (1 << 24);                /* IOC */
@@ -1059,10 +1092,94 @@ static int uhci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
                        }
                } while (1);
        }
-
        return ret;
 }
 
+static void * uhci_request_bulk(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, void *data, int len, void *dev_id)
+{
+       struct uhci_device *dev = usb_to_uhci(usb_dev);
+       struct uhci_device *root_hub=usb_to_uhci(dev->uhci->bus->root_hub);
+       struct uhci_td *first, *td, *prevtd;
+       struct uhci_qh *bulk_qh = uhci_qh_allocate(dev);
+       unsigned long destination, status;
+       int maxsze = usb_maxpacket(usb_dev, pipe);
+       
+       if (len > maxsze * 31)
+               printk("Warning, too much data for a bulk packet, crashing\n");
+
+       /* The "pipe" thing contains the destination in bits 8--18, 0x69 is IN */
+       destination = (pipe & 0x0007ff00) | usb_packetid(pipe);
+
+       /* Status:    slow/fast,       Active,    Short Packet Detect     Infinite Errors */
+       status = (pipe & (1 << 26)) | (1 << 23)   |   (1 << 29)       |    (0 << 27);
+
+
+       /*
+        * Build the TDs for the bulk request
+        */
+       first = td = uhci_td_allocate(dev);
+       prevtd=td;
+       while (len > 0) {
+               /* Build the TD for control status */
+               int pktsze = len;
+
+               if (pktsze > maxsze)
+                       pktsze = maxsze;
+
+               td->status = status;                                    /* Status */
+               td->info = destination | ((pktsze-1) << 21) |
+                        (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* pktsze bytes of data */
+               td->buffer = virt_to_bus(data);
+               td->backptr = &prevtd->link;
+               td->first = first;
+               td->qh = bulk_qh;
+               td->dev=usb_dev;
+
+               data += pktsze;
+               len -= pktsze;
+
+               if (len > 0) {
+                       prevtd = td;
+                       td = uhci_td_allocate(dev);
+                       prevtd->link = 4 | virt_to_bus(td);                     /* Update previous TD */
+               }
+
+               /* Alternate Data0/1 */
+               usb_dotoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
+       }
+       
+       first->backptr=NULL;
+       td->link = 1;                           /* Terminate */
+       td->status = status | (1 << 24);        /* IOC */
+       td->first = first;
+               
+       uhci_add_irq_list(dev->uhci, td, handler, dev_id);
+
+       uhci_insert_tds_in_qh(bulk_qh, first, td);
+
+       bulk_qh->skel=&root_hub->skel_bulk0_qh;
+       uhci_insert_qh(&root_hub->skel_bulk0_qh, bulk_qh);
+       
+       //Return last td for removal
+       return td;
+}
+
+/*
+ *Remove a handler from a pipe. This terminates the transfer.
+ *We have some assumptions here:
+ * There is only one queue using this pipe. (the one we remove)
+ * Any data that is in the queue is useless for us, we throw it away.
+ */
+static int uhci_terminate_bulk(struct usb_device *dev, void * first) 
+{
+       //none found? there is nothing to remove!
+       if (!first) return 0;
+
+       uhci_remove_transfer(first,1);
+       return 1;
+
+}
+
 static struct usb_device *uhci_usb_allocate(struct usb_device *parent)
 {
        struct usb_device *usb_dev;
@@ -1088,7 +1205,6 @@ static struct usb_device *uhci_usb_allocate(struct usb_device *parent)
 
        usb_dev->hcpriv = dev;
        dev->usb = usb_dev;
-
        usb_dev->parent = parent;
 
        if (parent) {
@@ -1154,6 +1270,8 @@ struct usb_operations uhci_device_operations = {
        uhci_bulk_msg,
        uhci_request_irq,
        uhci_release_irq,
+       uhci_request_bulk,
+       uhci_terminate_bulk,
        uhci_allocate_isochronous,
        uhci_delete_isochronous,
        uhci_schedule_isochronous,
@@ -1230,9 +1348,7 @@ static void uhci_connect_change(struct uhci *uhci, unsigned int port, unsigned i
                return;
        
        dev = usb_dev->hcpriv;
-
        dev->uhci = uhci;
-
        usb_connect(usb_dev);
 
        root_hub->usb->children[nr] = usb_dev;
@@ -1284,44 +1400,49 @@ static void uhci_interrupt_notify(struct uhci *uhci)
        while (tmp != head) {
                struct uhci_td *td = list_entry(tmp, struct uhci_td, irq_list);
                struct list_head *next;
-
+               
                next = tmp->next;
 
                if (!((status = td->status) & (1 << 23)) ||  /* No longer active? */
-                   (td->qh &&
                    ((td->qh->element & ~15) && 
                      !((status = uhci_link_to_td(td->qh->element)->status) & (1 <<23)) &&
-                     (status & 0x760000) /* is in error state (Stall, db, babble, timeout, bitstuff) */))) {   
-                       /* remove from IRQ list */
-                       __list_del(tmp->prev, next);
-                       INIT_LIST_HEAD(tmp);
-                       if (td->completed(uhci_map_status(status, 0), bus_to_virt(td->buffer), -1, td->dev_id)) {
-                               list_add(&td->irq_list, &uhci->interrupt_list);
-
-                               if (!(td->status & (1 << 25))) {
-                                       struct uhci_qh *interrupt_qh = td->qh;
+                     (status & 0x760000) /* is in error state (Stall, db, babble, timeout, bitstuff) */)) {    
+                               unsigned long rval;
+                               int status;
 
-                                       usb_dotoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info));
-                                       td->info &= ~(1 << 19); /* clear data toggle */
-                                       td->info |= usb_gettoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)) << 19; /* toggle between data0 and data1 */
-                                       td->status = (td->status & 0x2f000000) | (1 << 23) | (1 << 24); /* active */
+                               status=uhci_td_result(usb_to_uhci(td->dev),td,&rval);
+                               /* remove from IRQ list */
+                               __list_del(tmp->prev, next);
+                               INIT_LIST_HEAD(tmp);
 
-                                       /* Remove then readd? Is that necessary */
-                                       uhci_remove_td(td);
-                                       uhci_insert_td_in_qh(interrupt_qh, td);
+                               if (td->completed(status, bus_to_virt(td->buffer), rval, td->dev_id)) {
+                                       list_add(&td->irq_list, &uhci->interrupt_list);
+       
+                                       if (!(td->status & (1 << 25))) {
+                                               struct uhci_qh *interrupt_qh = td->qh;
+
+                                               usb_dotoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info));
+                                               td->info &= ~(1 << 19); /* clear data toggle */
+                                               td->info |= usb_gettoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)) << 19; /* toggle between data0 and data1 */
+                                               td->status = (td->status & 0x2f000000) | (1 << 23) | (1 << 24); /* active */
+       
+                                               /* Remove then readd? Is that necessary */
+                                               uhci_remove_td(td);
+                                               uhci_insert_td_in_qh(interrupt_qh, td);
+                                       }
+                               } else if (td->inuse & 2) {
+                                       struct uhci_qh *interrupt_qh = td->qh;
+                                       /* marked for removal */
+                                       td->inuse &= ~2;
+                                       usb_dotoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info));
+                                       uhci_remove_qh(interrupt_qh->skel, interrupt_qh);
+                                       uhci_qh_deallocate(interrupt_qh);
+                                       uhci_td_deallocate(td);
                                }
-                       } else if (td->inuse & 2) {
-                               struct uhci_qh *interrupt_qh = td->qh;
-                               /* marked for removal */
-                               td->inuse &= ~2;
-                               usb_dotoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info));
-                               uhci_remove_qh(interrupt_qh->skel, interrupt_qh);
-                               uhci_qh_deallocate(interrupt_qh);
-                               uhci_td_deallocate(td);
-                       }
-                       /* If completed wants to not reactivate, then it's */
-                       /* responsible for free'ing the TD's and QH's */
-                       /* or another function (such as run_control) */
+                               /* If completed wants to not reactivate, then it's */
+                               /* responsible for free'ing the TD's and QH's */
+                               /* or another function (such as run_control) */
+
                } 
                tmp = next;
        }
index 5df45936032e473d263dcd23b5d98bb0d6365952..3b5122e32c4e6bbb87b93adf143c40c3a901171e 100644 (file)
@@ -736,21 +736,18 @@ int usb_set_idle(struct usb_device *dev,  int duration, int report_id)
 static void usb_set_maxpacket(struct usb_device *dev)
 {
        int i;
-       struct usb_endpoint_descriptor *ep;
        int act_as = dev->actconfig->act_altsetting;
        struct usb_alternate_setting *as = dev->actconfig->altsetting + act_as;
-       struct usb_interface_descriptor *ip = as->interface;
 
        for (i=0; i<dev->actconfig->bNumInterfaces; i++) {
-               if (as->interface[i].bInterfaceNumber == dev->ifnum) {
-                       ip = &as->interface[i];
-                       break;
+               struct usb_interface_descriptor *ip = &as->interface[i];
+               struct usb_endpoint_descriptor *ep = ip->endpoint;
+               int e;
+               for (e=0; e<ip->bNumEndpoints; e++) {
+                       dev->epmaxpacket[ep[e].bEndpointAddress & 0x0f] =
+                               ep[e].wMaxPacketSize;
                }
        }
-       ep = ip->endpoint;
-       for (i=0; i<ip->bNumEndpoints; i++) {
-               dev->epmaxpacket[ep[i].bEndpointAddress & 0x0f] = ep[i].wMaxPacketSize;
-       }
 }
 
 int usb_clear_halt(struct usb_device *dev, int endp)
@@ -1037,6 +1034,7 @@ void usb_new_device(struct usb_device *dev)
        }
 #endif
 
+
 #if 0
        printk("maxpacketsize: %d\n", dev->descriptor.bMaxPacketSize0);
 #endif
@@ -1106,6 +1104,16 @@ void* usb_request_irq(struct usb_device *dev, unsigned int pipe, usb_device_irq
        return dev->bus->op->request_irq(dev, pipe, handler, period, dev_id);
 }
 
+void* usb_request_bulk(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, void * data, int len, void *dev_id)
+{
+       return dev->bus->op->request_bulk(dev, pipe, handler, data, len, dev_id);
+}
+
+int usb_terminate_bulk(struct usb_device *dev, void* first)
+{
+       return dev->bus->op->terminate_bulk(dev, first);
+}
+
 
 void *usb_allocate_isochronous (struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id)
 {
index 198a209d02b0daecb232aef7ce719b5756cc1df1..3d1b58c03b8ac8095d034a05aac694886575be11 100644 (file)
@@ -290,6 +290,8 @@ struct usb_operations {
        int (*bulk_msg)(struct usb_device *, unsigned int, void *, int,unsigned long *);
        void* (*request_irq)(struct usb_device *, unsigned int, usb_device_irq, int, void *);
        int (*release_irq)(void* handle);
+       void* (*request_bulk)(struct usb_device *, unsigned int, usb_device_irq, void *, int, void *);
+       int (*terminate_bulk)(struct usb_device *, void*);
        void *(*alloc_isoc)(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id);
        void (*delete_isoc)(struct usb_device *dev, void *_isodesc);
        int (*sched_isoc)(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc);
@@ -352,6 +354,9 @@ extern void usb_deregister_bus(struct usb_bus *);
 extern void* usb_request_irq(struct usb_device *, unsigned int, usb_device_irq, int, void *);
 extern int usb_release_irq(struct usb_device *dev, void *handle);
 
+extern void* usb_request_bulk(struct usb_device *, unsigned int, usb_device_irq, void *, int, void *);
+extern int usb_terminate_bulk(struct usb_device *, void*);
+
 extern void usb_init_root_hub(struct usb_device *dev);
 extern void usb_connect(struct usb_device *dev);
 extern void usb_disconnect(struct usb_device **);
index 99ebadf4b9d53e2099f720096c1bf5cf28e89a9c..26ab31f48056dff40ab2b1b71c96aa4ab182c17d 100644 (file)
@@ -1802,7 +1802,7 @@ init_imstt(struct fb_info_imstt *p))
        p->fix.smem_start = (__u8 *)p->frame_buffer_phys;
        p->fix.smem_len = p->total_vram;
        p->fix.mmio_start = (__u8 *)p->dc_regs_phys;
-       p->fix.mmio_len = 0x40000;
+       p->fix.mmio_len = 0x1000;
        p->fix.accel = FB_ACCEL_IMS_TWINTURBO;
        p->fix.type = FB_TYPE_PACKED_PIXELS;
        p->fix.visual = p->disp.var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
index 96407561c9b645149ed4835fbbbc28d4f9f0b974..c5fcdacfb6cbe044464b1b22bdb0515e62bd9466 100644 (file)
@@ -116,7 +116,7 @@ static int         vga_video_font_height;
 static unsigned int    vga_rolled_over = 0;
 
 
-void no_scroll(char *str, int *ints)
+static int __init no_scroll(char *str)
 {
        /*
         * Disabling scrollback is required for the Braillex ib80-piezo
@@ -124,8 +124,11 @@ void no_scroll(char *str, int *ints)
         * Use the "no-scroll" bootflag.
         */
        vga_hardscroll_user_enable = vga_hardscroll_enabled = 0;
+       return 1;
 }
 
+__setup("no-scroll", no_scroll);
+
 /*
  * By replacing the four outb_p with two back to back outw, we can reduce
  * the window of opportunity to see text mislocated to the RHS of the
index 2649d0fa1ae3475fc03e87feafb36db631b47792..658040aeb14a64c8999c0a1bd194dd51e9654690 100644 (file)
@@ -559,11 +559,13 @@ load_aout_library(int fd)
 }
 
 
-int __init init_aout_binfmt(void)
+static int __init init_aout_binfmt(void)
 {
        return register_binfmt(&aout_format);
 }
 
+__initcall(init_aout_binfmt);
+
 #ifdef MODULE
 int init_module(void) {
        return init_aout_binfmt();
index 5b2988201bcbdb2c2916c13f5d299f0c1dd5ff40..e6ab8c58a8214b2a645e2a851405cfe603827783 100644 (file)
@@ -1296,11 +1296,13 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
 }
 #endif         /* USE_ELF_CORE_DUMP */
 
-int __init init_elf_binfmt(void)
+static int __init init_elf_binfmt(void)
 {
        return register_binfmt(&elf_format);
 }
 
+__initcall(init_elf_binfmt);
+
 #ifdef MODULE
 
 int init_module(void)
index 0a499e7d0ea751b22b6d4181805ac796695e9ef3..6e07847321595889e96466c41ae72228f4b50ad8 100644 (file)
@@ -114,11 +114,13 @@ struct linux_binfmt em86_format = {
        load_em86, NULL, NULL, 0
 };
 
-int __init init_em86_binfmt(void)
+static int __init init_em86_binfmt(void)
 {
        return register_binfmt(&em86_format);
 }
 
+__initcall(init_em86_binfmt);
+
 #ifdef MODULE
 int init_module(void)
 {
index 69920f45b151e6345b4f14bd927c99c36322d708..6fc5b570e3996c264601e6145e23c61b96f73f3d 100644 (file)
@@ -495,7 +495,7 @@ static void bm_modcount(struct inode *inode, int fill)
 }
 #endif
 
-int __init init_misc_binfmt(void)
+static int __init init_misc_binfmt(void)
 {
        int error = -ENOENT;
        struct proc_dir_entry *status = NULL, *reg;
@@ -530,6 +530,8 @@ cleanup_bm:
        goto out;
 }
 
+__initcall(init_misc_binfmt);
+
 #ifdef MODULE
 EXPORT_NO_SYMBOLS;
 int init_module(void)
index 1d2e778ec678d219a06b9ed570adb81cd47d1e1d..7a3e1d9fe08ece9b4cef54f723fa2dfd14f9a4ba 100644 (file)
@@ -110,11 +110,13 @@ struct linux_binfmt script_format = {
        load_script, NULL, NULL, 0
 };
 
-int __init init_script_binfmt(void)
+static int __init init_script_binfmt(void)
 {
        return register_binfmt(&script_format);
 }
 
+__initcall(init_script_binfmt);
+
 #ifdef MODULE
 int init_module(void)
 {
index 66f98a70573d035a302c2a28e2dcc806a85279a9..e7aa80f6c7457e7ac4df346a67ba09bb492ded71 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
 
 static struct linux_binfmt *formats = (struct linux_binfmt *) NULL;
 
-void __init binfmt_setup(void)
-{
-#ifdef CONFIG_BINFMT_MISC
-       init_misc_binfmt();
-#endif
-
-#ifdef CONFIG_BINFMT_ELF
-       init_elf_binfmt();
-#endif
-
-#ifdef CONFIG_BINFMT_ELF32
-       init_elf32_binfmt();
-#endif
-
-#ifdef CONFIG_BINFMT_AOUT
-       init_aout_binfmt();
-#endif
-
-#ifdef CONFIG_BINFMT_AOUT32
-       init_aout32_binfmt();
-#endif
-
-#ifdef CONFIG_BINFMT_EM86
-       init_em86_binfmt();
-#endif
-
-       /* This cannot be configured out of the kernel */
-       init_script_binfmt();
-}
-
 int register_binfmt(struct linux_binfmt * fmt)
 {
        struct linux_binfmt ** tmp = &formats;
diff --git a/include/asm-alpha/parport.h b/include/asm-alpha/parport.h
new file mode 100644 (file)
index 0000000..463172f
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * parport.h: platform-specific PC-style parport initialisation
+ *
+ * Copyright (C) 1999  Tim Waugh <tim@cyberelk.demon.co.uk>
+ *
+ * This file should only be included by drivers/parport/parport_pc.c.
+ */
+
+#ifndef _ASM_AXP_PARPORT_H
+#define _ASM_AXP_PARPORT_H 1
+
+/* Maximum number of ports to support.  It is useless to set this greater
+   than PARPORT_MAX (in <linux/parport.h>).  */
+#define PARPORT_PC_MAX_PORTS  8
+
+/* If parport_cs (PCMCIA) is managing ports for us, we'll need the
+ * probing routines forever; otherwise we can lose them at boot time. */
+#ifdef CONFIG_PARPORT_PC_PCMCIA
+#define __maybe_initdata
+#define __maybe_init
+#else
+#define __maybe_initdata __initdata
+#define __maybe_init __init
+#endif
+
+static int __maybe_init parport_pc_init_pci(int irq, int dma);
+
+static int user_specified __maybe_initdata = 0;
+int __init
+parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
+{
+       int count = 0, i = 0;
+
+       if (io && *io) {
+               /* Only probe the ports we were given. */
+               user_specified = 1;
+               do {
+                       if (!*io_hi) *io_hi = 0x400 + *io;
+                       if (parport_pc_probe_port(*(io++), *(io_hi++),
+                                                 *(irq++), *(dma++)))
+                               count++;
+               } while (*io && (++i < PARPORT_PC_MAX_PORTS));
+       } else {
+               /* Probe all the likely ports. */
+               if (parport_pc_probe_port(0x3bc, 0x7bc, irq[0], dma[0]))
+                       count++;
+               if (parport_pc_probe_port(0x378, 0x778, irq[0], dma[0]))
+                       count++;
+               if (parport_pc_probe_port(0x278, 0x678, irq[0], dma[0]))
+                       count++;
+               count += parport_pc_init_pci (irq[0], dma[0]);
+       }
+
+        return count;
+}
+
+#endif /* !(_ASM_AXP_PARPORT_H) */
index 5729b956d18ee598ccf9d1f25fbada5eb93171aa..35c28427fcf50cf025e3a3cb5171854c6f338a89 100644 (file)
@@ -20,7 +20,7 @@
  * This should follow whatever the default interface uses.
  */
 static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
 {
        ide_ioreg_t reg = (ide_ioreg_t) data_port;
        int i;
@@ -30,7 +30,7 @@ ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
                reg += 1;
        }
        hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-       hw->irq = *irq;
+       hw->irq = irq;
 }
 
 /*
@@ -44,8 +44,7 @@ static __inline__ void ide_init_default_hwifs(void)
 
         memset(hw, 0, sizeof(*hw));
 
-       ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
-       hw.irq = IRQ_HARDDISK;
+       ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK);
        ide_register_hw(&hw, NULL);
 #endif
 }
index f6e4c3e330e0dfb5e0908b6b18484e11d7e83f54..2a0045e2dc3c01468664571e193fee405247bef8 100644 (file)
@@ -9,10 +9,24 @@
 #ifndef __ASM_ARM_MMU_CONTEXT_H
 #define __ASM_ARM_MMU_CONTEXT_H
 
-#define get_mmu_context(x) do { } while (0)
+#include <asm/bitops.h>
+#include <asm/pgtable.h>
+#include <asm/arch/memory.h>
 
-#define init_new_context(mm)   do { } while(0)
-#define destroy_context(mm)    do { } while(0)
-#define activate_context(tsk)  do { } while(0)
+#define destroy_context(mm)            do { } while(0)
+#define init_new_context(tsk,mm)       do { } while(0)
+
+/*
+ * This is the actual mm switch as far as the scheduler
+ * is concerned.  No registers are touched.
+ */
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, unsigned int cpu)
+{
+       if (prev != next) {
+               processor.u.armv3v4._set_pgd(__virt_to_phys((unsigned long)next->pgd));
+               clear_bit(cpu, &prev->cpu_vm_mask);
+       }
+       set_bit(cpu, &next->cpu_vm_mask);
+}
 
 #endif
diff --git a/include/asm-arm/parport.h b/include/asm-arm/parport.h
new file mode 100644 (file)
index 0000000..893828e
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * parport.h: ia32-specific parport initialisation
+ *
+ * Copyright (C) 1999  Tim Waugh <tim@cyberelk.demon.co.uk>
+ *
+ * This file should only be included by drivers/parport/parport_pc.c.
+ */
+
+#ifndef _ASM_I386_PARPORT_H
+#define _ASM_I386_PARPORT_H 1
+
+/* Maximum number of ports to support.  It is useless to set this greater
+   than PARPORT_MAX (in <linux/parport.h>).  */
+#define PARPORT_PC_MAX_PORTS  8
+
+static int __init probe_one_port(unsigned long int base,
+                                unsigned long int base_hi,
+                                int irq, int dma);
+static int __init parport_pc_init_pci(int irq, int dma);
+
+static int user_specified __initdata = 0;
+int __init
+parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
+{
+       int count = 0, i = 0;
+
+       if (io && *io) {
+               /* Only probe the ports we were given. */
+               user_specified = 1;
+               do {
+                       if (!*io_hi) *io_hi = 0x400 + *io;
+                       count += probe_one_port(*(io++), *(io_hi++),
+                                               *(irq++), *(dma++));
+               } while (*io && (++i < PARPORT_PC_MAX_PORTS));
+       } else {
+               /* Probe all the likely ports. */
+               count += probe_one_port(0x3bc, 0x7bc, irq[0], dma[0]);
+               count += probe_one_port(0x378, 0x778, irq[0], dma[0]);
+               count += probe_one_port(0x278, 0x678, irq[0], dma[0]);
+               count += parport_pc_init_pci (irq[0], dma[0]);
+       }
+
+        return count;
+}
+
+#endif /* !(_ASM_I386_PARPORT_H) */
index 4cfd77955d04c5ca14a2af73a55e2dd63b0ab8b5..5f5a97521384468aec58e57bc12e95cd9aa5b3f1 100644 (file)
@@ -77,6 +77,8 @@ extern uaccess_t uaccess_user, uaccess_kernel;
 extern unsigned long get_page_8k(int priority);
 extern void free_page_8k(unsigned long page);
 
+#define THREAD_SIZE    (8192)
+
 #define ll_alloc_task_struct() ((struct task_struct *)get_page_8k(GFP_KERNEL))
 #define ll_free_task_struct(p)  free_page_8k((unsigned long)(p))
 
diff --git a/include/asm-arm/proc-armv/domain.h b/include/asm-arm/proc-armv/domain.h
new file mode 100644 (file)
index 0000000..398fdce
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * linux/include/asm-arm/proc-armv/domain.h
+ *
+ * Copyright (C) 1999 Russell King.
+ */
+#ifndef __ASM_PROC_DOMAIN_H
+#define __ASM_PROC_DOMAIN_H
+
+/*
+ * Domain numbers
+ *
+ *  DOMAIN_IO     - domain 2 includes all IO only
+ *  DOMAIN_KERNEL - domain 1 includes all kernel memory only
+ *  DOMAIN_USER   - domain 0 includes all user memory only
+ */
+#define DOMAIN_USER    0
+#define DOMAIN_KERNEL  1
+#define DOMAIN_TABLE   1
+#define DOMAIN_IO      2
+
+/*
+ * Domain types
+ */
+#define DOMAIN_NOACCESS        0
+#define DOMAIN_CLIENT  1
+#define DOMAIN_MANAGER 3
+
+#define domain_val(dom,type)   ((type) << 2*(dom))
+
+#define set_domain(x)                                  \
+       do {                                            \
+       __asm__ __volatile__(                           \
+       "mcr    p15, 0, %0, c3, c0      @ set domain"   \
+         : : "r" (x));                                 \
+       } while (0)
+
+#define modify_domain(dom,type)                                \
+       do {                                            \
+       unsigned int domain = current->thread.domain;   \
+       domain &= ~domain_val(dom, DOMAIN_MANAGER);     \
+       domain |= domain_val(dom, type);                \
+       current->thread.domain = domain;                \
+       set_domain(current->thread.domain);             \
+       } while (0)
+
+#endif
index 8447519c95328009d4154f56de7c0c96f129c829..dfde9e93ae1c96d1ceda469cd1e33b1b2045df31 100644 (file)
@@ -220,25 +220,6 @@ do {                                                               \
 } while (0)
 
 
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-#define pgd_none(pgd)          (0)
-#define pgd_bad(pgd)           (0)
-#define pgd_present(pgd)       (1)
-#define pgd_clear(pgdp)
-
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-
-/* to find an entry in a page-table-directory */
-extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
-{
-       return mm->pgd + (address >> PGDIR_SHIFT);
-}
-
 extern unsigned long get_page_2k(int priority);
 extern void free_page_2k(unsigned long page);
 
@@ -263,55 +244,6 @@ extern struct pgtable_cache_struct {
 #error Pgtable caches have to be per-CPU, so that no locking is needed.
 #endif
 
-extern pgd_t *get_pgd_slow(void);
-
-extern __inline__ pgd_t *get_pgd_fast(void)
-{
-       unsigned long *ret;
-
-       if((ret = pgd_quicklist) != NULL) {
-               pgd_quicklist = (unsigned long *)(*ret);
-               ret[0] = ret[1];
-               clean_cache_area(ret, 4);
-               pgtable_cache_size--;
-       } else
-               ret = (unsigned long *)get_pgd_slow();
-       return (pgd_t *)ret;
-}
-
-extern __inline__ void free_pgd_fast(pgd_t *pgd)
-{
-       *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
-       pgd_quicklist = (unsigned long *) pgd;
-       pgtable_cache_size++;
-}
-
-extern __inline__ void free_pgd_slow(pgd_t *pgd)
-{
-       free_pages((unsigned long) pgd, 2);
-}
-
-#define pgd_free(pgd)          free_pgd_fast(pgd)
-#define pgd_alloc()            get_pgd_fast()
-
-extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
-{
-       struct task_struct * p;
-       pgd_t *pgd;
-
-       read_lock(&tasklist_lock);
-       for_each_task(p) {
-               if (!p->mm)
-                       continue;
-               *pgd_offset(p->mm,address) = entry;
-       }
-       read_unlock(&tasklist_lock);
-       for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
-               pgd[address >> PGDIR_SHIFT] = entry;
-}
-
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
 /****************
 * PMD functions *
 ****************/
@@ -406,7 +338,6 @@ extern __inline__ unsigned long pmd_page(pmd_t pmd)
        return __phys_to_virt(ptr);
 }
 
-
 /****************
 * PTE functions *
 ****************/
@@ -552,8 +483,6 @@ extern __inline__ void free_pte_slow(pte_t *pte)
 #define __S110  PAGE_SHARED
 #define __S111  PAGE_SHARED
 
-
-
 #define pte_present(pte)       (pte_val(pte) & L_PTE_PRESENT)
 
 /*
@@ -569,12 +498,12 @@ extern __inline__ void free_pte_slow(pte_t *pte)
 #define PTE_BIT_FUNC(fn,op)                    \
 extern inline pte_t fn##(pte_t pte) { pte_val(pte) op##; return pte; }
 
-//PTE_BIT_FUNC(pte_rdprotect, &= ~L_PTE_USER);
+/*PTE_BIT_FUNC(pte_rdprotect, &= ~L_PTE_USER);*/
 PTE_BIT_FUNC(pte_wrprotect, &= ~L_PTE_WRITE);
 PTE_BIT_FUNC(pte_exprotect, &= ~L_PTE_EXEC);
 PTE_BIT_FUNC(pte_mkclean,   &= ~L_PTE_DIRTY);
 PTE_BIT_FUNC(pte_mkold,     &= ~L_PTE_YOUNG);
-//PTE_BIT_FUNC(pte_mkread,    |= L_PTE_USER);
+/*PTE_BIT_FUNC(pte_mkread,    |= L_PTE_USER);*/
 PTE_BIT_FUNC(pte_mkwrite,   |= L_PTE_WRITE);
 PTE_BIT_FUNC(pte_mkexec,    |= L_PTE_EXEC);
 PTE_BIT_FUNC(pte_mkdirty,   |= L_PTE_DIRTY);
@@ -630,6 +559,100 @@ extern __inline__ pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
        return (pte_t *) pmd_page(*pmd) + address;
 }
 
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+#define pgd_none(pgd)          (0)
+#define pgd_bad(pgd)           (0)
+#define pgd_present(pgd)       (1)
+#define pgd_clear(pgdp)
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/* used for quicklists */
+#define __pgd_next(pgd) (((unsigned long *)pgd)[1])
+
+/* to find an entry in a page-table-directory */
+extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+{
+       return mm->pgd + (address >> PGDIR_SHIFT);
+}
+
+extern pgd_t *get_pgd_slow(void);
+
+extern __inline__ pgd_t *get_pgd_fast(void)
+{
+       unsigned long *ret;
+
+       if((ret = pgd_quicklist) != NULL) {
+               pgd_quicklist = (unsigned long *)__pgd_next(ret);
+               ret[1] = ret[2];
+               clean_cache_area(ret + 1, 4);
+               pgtable_cache_size--;
+       } else
+               ret = (unsigned long *)get_pgd_slow();
+       return (pgd_t *)ret;
+}
+
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
+{
+       __pgd_next(pgd) = (unsigned long) pgd_quicklist;
+       pgd_quicklist = (unsigned long *) pgd;
+       pgtable_cache_size++;
+}
+
+extern __inline__ void free_pgd_slow(pgd_t *pgd)
+{
+       do {
+               if (pgd) { /* can pgd be NULL? */
+                       pmd_t *pmd;
+                       pte_t *pte;
+
+                       /* pgd is never none and bad - it is
+                        * detected in the pmd macros.
+                        */
+                       pmd = pmd_offset(pgd, 0);
+                       if (pmd_none(*pmd))
+                               break;
+                       if (pmd_bad(*pmd)) {
+                               printk("free_pgd_slow: bad directory entry %08lx\n", pmd_val(*pmd));
+                               pmd_clear(pmd);
+                               break;
+                       }
+
+                       pte = pte_offset(pmd, 0);
+                       pmd_clear(pmd);
+                       pte_free(pte);
+                       pmd_free(pmd);
+               }
+       } while (0);
+       free_pages((unsigned long) pgd, 2);
+}
+
+#define pgd_free(pgd)          free_pgd_fast(pgd)
+#define pgd_alloc()            get_pgd_fast()
+
+extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
+{
+       struct task_struct * p;
+       pgd_t *pgd;
+
+       read_lock(&tasklist_lock);
+       for_each_task(p) {
+               if (!p->mm)
+                       continue;
+               *pgd_offset(p->mm,address) = entry;
+       }
+       read_unlock(&tasklist_lock);
+       for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)__pgd_next(pgd))
+               pgd[address >> PGDIR_SHIFT] = entry;
+}
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
 #define SWP_TYPE(entry) (((entry) >> 2) & 0x7f)
 #define SWP_OFFSET(entry) ((entry) >> 9)
 #define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << 9))
index 7186039f9a69525fed16ab9c8ebca96b7c31e895..60a90f6622e3a4526b4eeca5d36737760664fdb6 100644 (file)
@@ -1,17 +1,20 @@
 /*
  * linux/include/asm-arm/proc-armv/processor.h
  *
- * Copyright (c) 1996 Russell King.
+ * Copyright (c) 1996-1999 Russell King.
  *
  * Changelog:
  *  20-09-1996 RMK     Created
  *  26-09-1996 RMK     Added 'EXTRA_THREAD_STRUCT*'
  *  28-09-1996 RMK     Moved start_thread into the processor dependencies
  *  09-09-1998 PJB     Delete redundant `wp_works_ok'
+ *  31-07-1999 RMK     Added 'domain' stuff
  */
 #ifndef __ASM_PROC_PROCESSOR_H
 #define __ASM_PROC_PROCESSOR_H
 
+#include <asm/proc/domain.h>
+
 #define KERNEL_STACK_SIZE      PAGE_SIZE
 
 struct context_save_struct {
@@ -28,8 +31,14 @@ struct context_save_struct {
 
 #define INIT_CSS (struct context_save_struct){ SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0 }
 
-#define EXTRA_THREAD_STRUCT
-#define EXTRA_THREAD_STRUCT_INIT
+#define EXTRA_THREAD_STRUCT                                            \
+       unsigned int    domain;
+
+#define EXTRA_THREAD_STRUCT_INIT                                       \
+       , domain_val(DOMAIN_USER, DOMAIN_CLIENT) |                      \
+         domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |                   \
+         domain_val(DOMAIN_IO, DOMAIN_CLIENT)
+
 #define SWAPPER_PG_DIR (((unsigned long)swapper_pg_dir) - PAGE_OFFSET)
 
 #define start_thread(regs,pc,sp)                                       \
@@ -52,6 +61,7 @@ struct context_save_struct {
 /*
  * NOTE! The task struct and the stack go together
  */
+#define THREAD_SIZE    (PAGE_SIZE * 2)
 #define ll_alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
 #define ll_free_task_struct(p) free_pages((unsigned long)(p),1)
 
index a015a07380f13695c238bf4217756f415f3cc457..7bef26d3873a66c1af42a714fed935858faac133 100644 (file)
@@ -2,36 +2,8 @@
  * linux/include/asm-arm/proc-armv/uaccess.h
  */
 
-/*
- * The fs functions are implemented on the ARMV3 and V4 architectures
- * using the domain register.
- *
- *  DOMAIN_IO     - domain 2 includes all IO only
- *  DOMAIN_KERNEL - domain 1 includes all kernel memory only
- *  DOMAIN_USER   - domain 0 includes all user memory only
- */
-
 #include <asm/hardware.h>
-
-#define DOMAIN_CLIENT  1
-#define DOMAIN_MANAGER 3
-#define DOMAIN_USER_CLIENT     ((DOMAIN_CLIENT) << 0)
-#define DOMAIN_USER_MANAGER    ((DOMAIN_MANAGER) << 0)
-
-#define DOMAIN_KERNEL_CLIENT   ((DOMAIN_CLIENT) << 2)
-#define DOMAIN_KERNEL_MANAGER  ((DOMAIN_MANAGER) << 2)
-
-#define DOMAIN_IO_CLIENT       ((DOMAIN_CLIENT) << 4)
-#define DOMAIN_IO_MANAGER      ((DOMAIN_MANAGER) << 4)
-
-/*
- * When we want to access kernel memory in the *_user functions,
- * we change the domain register to KERNEL_DS, thus allowing
- * unrestricted access
- */
-#define KERNEL_DOMAIN  (DOMAIN_USER_CLIENT | DOMAIN_KERNEL_MANAGER | DOMAIN_IO_CLIENT)
-#define USER_DOMAIN    (DOMAIN_USER_CLIENT | DOMAIN_KERNEL_CLIENT  | DOMAIN_IO_CLIENT)
+#include <asm/proc/domain.h>
 
 /*
  * Note that this is actually 0x1,0000,0000
@@ -48,8 +20,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
 {
        current->addr_limit = fs;
 
-       __asm__ __volatile__("mcr       p15, 0, %0, c3, c0" :
-               : "r" (fs ? USER_DOMAIN : KERNEL_DOMAIN));
+       modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
 }
 
 /* We use 33-bit arithmetic here... */
index 75e97624434f9ebacccf995e6dab7f3cf9b9b1fd..b607bbfc3cecac929c37f7147ee323f4fe8acf1d 100644 (file)
@@ -19,11 +19,6 @@ struct task_struct;
 extern struct processor {
        const char *name;
        /* MISC
-        *
-        * flush caches for task switch
-        */
-       struct task_struct *(*_switch_to)(struct task_struct *prev, struct task_struct *next);
-       /*
         * get data abort address/flags
         */
        void (*_data_abort)(unsigned long pc);
@@ -75,6 +70,10 @@ extern struct processor {
                         * flush a specific TLB
                         */
                        void (*_flush_tlb_area)(unsigned long address, unsigned long end, int flags);
+                       /*
+                        * Set the page table
+                        */
+                       void (*_set_pgd)(unsigned long pgd_phys);
                        /*
                         * Set a PMD (handling IMP bit 4)
                         */
index 1282c7469c4e4a7e7fbaf5b151549f7cfc1593a2..c0a20c7edf61055bf23808f5c4923676ce6b6f5e 100644 (file)
@@ -49,27 +49,29 @@ struct debug_info {
 };
 
 struct thread_struct {
-       unsigned long                   address;          /* Address of fault   */
-       unsigned long                   trap_no;          /* Trap number        */
-       unsigned long                   error_code;       /* Error code of trap */
-       union fp_state                  fpstate;          /* FPE save state     */
-       struct debug_info               debug;            /* Debug/ptrace       */
-       struct context_save_struct      *save;            /* context save       */
-       unsigned long                   memmap;           /* page tables        */
+                                                       /* fault info     */
+       unsigned long                   address;
+       unsigned long                   trap_no;
+       unsigned long                   error_code;
+                                                       /* floating point */
+       union fp_state                  fpstate;
+                                                       /* debugging      */
+       struct debug_info               debug;
+                                                       /* context info   */
+       struct context_save_struct      *save;
        EXTRA_THREAD_STRUCT
 };
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
 
-#define INIT_TSS  {                            \
+#define INIT_THREAD  {                         \
        0,                                      \
        0,                                      \
        0,                                      \
        { { { 0, }, }, },                       \
        { 0, },                                 \
-       (struct context_save_struct *)0,        \
-       SWAPPER_PG_DIR                          \
+       (struct context_save_struct *)0 \
        EXTRA_THREAD_STRUCT_INIT                \
 }
 
@@ -102,7 +104,7 @@ struct mm_struct;
 extern void release_thread(struct task_struct *);
 
 /* Copy and release all segment info associated with a VM */
-#define copy_segments(nr, tsk, mm)     do { } while (0)
+#define copy_segments(tsk, mm)         do { } while (0)
 #define release_segments(mm)           do { } while (0)
 #define forget_segments()              do { } while (0)
 
index c8b5e88f0aff98ffe7eda83b3f7605d289738756..b5c6ccc6fbf7d2c0d17ac70f68215db67a9e6512 100644 (file)
@@ -28,7 +28,7 @@
        { _STK_LIM, _STK_LIM },                         \
        {        0, LONG_MAX },                         \
        { LONG_MAX, LONG_MAX },                         \
-       { MAX_TASKS_PER_USER, MAX_TASKS_PER_USER },     \
+       {        0,        0 },                         \
        { INR_OPEN, INR_OPEN },                         \
        { LONG_MAX, LONG_MAX },                         \
        { LONG_MAX, LONG_MAX },                         \
index cfb62a24f338c67d4cf1a3919edb105001a4a625..cbe04acc871f4ccf145493595e0d182e63696c03 100644 (file)
@@ -146,10 +146,12 @@ extern asmlinkage void __backtrace(void);
  * `prev' will never be the same as `next'.
  * The `mb' is to tell GCC not to cache `current' across this call.
  */
-#define switch_to(prev,next,last)                      \
-       do {                                            \
-               last = processor._switch_to(prev,next); \
-               mb();                                   \
+extern struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next);
+
+#define switch_to(prev,next,last)              \
+       do {                                    \
+               last = __switch_to(prev,next);  \
+               mb();                           \
        } while (0)
 
 #endif
index 046fd52784f6a770dd5a6cf44d7bfdca2d55a310..64b25eaddbe714857fbf79830d343a04209e0bf5 100644 (file)
 
 #define CONFIG_BUGi386
 
-__initfunc(static void no_halt(char *s, int *ints))
+static int __init no_halt(char *s)
 {
        boot_cpu_data.hlt_works_ok = 0;
+       return 1;
 }
 
-__initfunc(static void mca_pentium(char *s, int *ints))
+__setup("no-hlt", no_halt);
+
+static int __init mca_pentium(char *s)
 {
        mca_pentium_flag = 1;
+       return 1;
 }
 
-__initfunc(static void no_387(char *s, int *ints))
+__setup("mca-pentium", mca_pentium);
+
+static int __init no_387(char *s)
 {
        boot_cpu_data.hard_math = 0;
        write_cr0(0xE | read_cr0());
+       return 1;
 }
 
+__setup("no387", no_387);
+
 static char __initdata fpu_error = 0;
 
 __initfunc(static void copro_timeout(void))
index 7618c005426a662c68578ed13a1316210ee3bae0..593661ca2e337618db3d4173b6b09a6d70166759 100644 (file)
@@ -1,6 +1,26 @@
 #ifndef _I386_INIT_H
 #define _I386_INIT_H
 
+typedef int (*initcall_t)(void);
+
+extern initcall_t __initcall_start, __initcall_end;
+
+struct kernel_param {
+       const char *str;
+       int (*setup_func)(char *);
+};
+
+extern struct kernel_param __setup_start, __setup_end;
+
+/* Used for initialization calls.. */
+#define __initcall(fn) \
+       static __attribute__ ((unused,__section__ (".initcall.init"))) initcall_t __initcall_##fn = fn
+
+/* Used for kernel command line parameter setup */
+#define __setup(str, fn) \
+       static __attribute__ ((unused,__section__ (".setup.init"))) struct kernel_param __setup_##fn = { str, fn }
+
+
 #define __init __attribute__ ((__section__ (".text.init")))
 #define __initdata __attribute__ ((__section__ (".data.init")))
 #define __initfunc(__arginit) \
index 893828e37bafda6a9c3c507874a9527bbacce451..a7e59b4462e03570eacbe623d6b0ebf3335b8155 100644 (file)
    than PARPORT_MAX (in <linux/parport.h>).  */
 #define PARPORT_PC_MAX_PORTS  8
 
-static int __init probe_one_port(unsigned long int base,
-                                unsigned long int base_hi,
-                                int irq, int dma);
-static int __init parport_pc_init_pci(int irq, int dma);
+/* If parport_cs (PCMCIA) is managing ports for us, we'll need the
+ * probing routines forever; otherwise we can lose them at boot time. */
+#ifdef CONFIG_PARPORT_PC_PCMCIA
+#define __maybe_initdata
+#define __maybe_init
+#else
+#define __maybe_initdata __initdata
+#define __maybe_init __init
+#endif
 
-static int user_specified __initdata = 0;
+static int __maybe_init parport_pc_init_pci(int irq, int dma);
+
+static int user_specified __maybe_initdata = 0;
 int __init
 parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
 {
@@ -29,14 +36,18 @@ parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
                user_specified = 1;
                do {
                        if (!*io_hi) *io_hi = 0x400 + *io;
-                       count += probe_one_port(*(io++), *(io_hi++),
-                                               *(irq++), *(dma++));
+                       if (parport_pc_probe_port(*(io++), *(io_hi++),
+                                                 *(irq++), *(dma++)))
+                               count++;
                } while (*io && (++i < PARPORT_PC_MAX_PORTS));
        } else {
                /* Probe all the likely ports. */
-               count += probe_one_port(0x3bc, 0x7bc, irq[0], dma[0]);
-               count += probe_one_port(0x378, 0x778, irq[0], dma[0]);
-               count += probe_one_port(0x278, 0x678, irq[0], dma[0]);
+               if (parport_pc_probe_port(0x3bc, 0x7bc, irq[0], dma[0]))
+                       count++;
+               if (parport_pc_probe_port(0x378, 0x778, irq[0], dma[0]))
+                       count++;
+               if (parport_pc_probe_port(0x278, 0x678, irq[0], dma[0]))
+                       count++;
                count += parport_pc_init_pci (irq[0], dma[0]);
        }
 
index c961fdd2e801f2c3cbb9c5f0798f86d4e38e3101..ee60551ae2aaea9e4279f4ee69d7873a7c7285d3 100644 (file)
@@ -287,7 +287,6 @@ __syscall_return(type,__res); \
  * some others too.
  */
 #define __NR__exit __NR_exit
-static inline _syscall0(int,idle)
 static inline _syscall0(int,pause)
 static inline _syscall0(int,sync)
 static inline _syscall0(pid_t,setsid)
index 2bb409a62b597ef5b8dc8ae61054d6fe69adfca0..f2fc8eff58b1a59299242b43f0d2d0d353a56ce1 100644 (file)
 #include <asm/ebus.h>
 #include <asm/ns87303.h>
 
+#ifdef CONFIG_PARPORT_PC_PCMCIA
+#define __maybe_init
+#define __maybe_initdata
+#else
+#define __maybe_init __init
+#define __maybe_initdata __initdata
+#endif
+
+#undef HAVE_SLOW_DEVICES
+
 static struct linux_ebus_dma *sparc_ebus_dmas[PARPORT_MAX];
 
 static __inline__ void
@@ -17,11 +27,10 @@ reset_dma(unsigned int dmanr)
 {
        unsigned int dcsr;
 
-       dcsr = readl(&sparc_ebus_dmas[dmanr]->dcsr) & EBUS_DCSR_INT_EN;
        writel(EBUS_DCSR_RESET, &sparc_ebus_dmas[dmanr]->dcsr);
-
-       dcsr |= EBUS_DCSR_BURST_SZ_16 | EBUS_DCSR_TCI_DIS |
-               EBUS_DCSR_EN_CNT;
+       udelay(1);
+       dcsr = EBUS_DCSR_BURST_SZ_16 | EBUS_DCSR_TCI_DIS |
+              EBUS_DCSR_EN_CNT;
        writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
 }
 
@@ -41,14 +50,21 @@ disable_dma(unsigned int dmanr)
        unsigned int dcsr;
 
        dcsr = readl(&sparc_ebus_dmas[dmanr]->dcsr);
-       while (dcsr & EBUS_DCSR_DRAIN)
+       if (dcsr & EBUS_DCSR_EN_DMA) {
+               while (dcsr & EBUS_DCSR_DRAIN) {
+                       udelay(1);
+                       dcsr = readl(&sparc_ebus_dmas[dmanr]->dcsr);
+               }
+               dcsr &= ~(EBUS_DCSR_EN_DMA);
+               writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
+
                dcsr = readl(&sparc_ebus_dmas[dmanr]->dcsr);
-       dcsr &= ~(EBUS_DCSR_EN_DMA);
-       if (dcsr & EBUS_DCSR_ERR_PEND) {
-               reset_dma(dmanr);
-               dcsr &= ~(EBUS_DCSR_ERR_PEND);
+               if (dcsr & EBUS_DCSR_ERR_PEND) {
+                       reset_dma(dmanr);
+                       dcsr &= ~(EBUS_DCSR_ERR_PEND);
+               }
+               writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
        }
-       writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
 }
 
 static __inline__ void
@@ -86,13 +102,19 @@ set_dma_count(unsigned int dmanr, unsigned int count)
 static __inline__ int
 get_dma_residue(unsigned int dmanr)
 {
-       return readl(&sparc_ebus_dmas[dmanr]->dbcr);
+       unsigned int dcsr;
+       int res;
+
+       res = readl(&sparc_ebus_dmas[dmanr]->dbcr);
+       if (res != 0) {
+               dcsr = readl(&sparc_ebus_dmas[dmanr]->dcsr);
+               reset_dma(dmanr);
+               writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
+       }
+       return res;
 }
 
-static int __init probe_one_port(unsigned long int base,
-                                unsigned long int base_hi,
-                                int irq, int dma);
-static int __init parport_pc_init_pci(int irq, int dma);
+static int __maybe_init parport_pc_init_pci(int irq, int dma);
 
 int __init
 parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
@@ -114,6 +136,7 @@ parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
                                sparc_ebus_dmas[count] =
                                                (struct linux_ebus_dma *)
                                                        edev->base_address[2];
+                               reset_dma(count);
 
                                /* Enable ECP, set bit 2 of the CTR first */
                                outb(0x04, base + 0x02);
@@ -139,8 +162,10 @@ parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
                                ns87303_writeb(config, FCR, cfg);
 #endif
 
-                               count += probe_one_port(base, base + 0x400,
-                                                       edev->irqs[0], count);
+                               if (parport_pc_probe_port(base, base + 0x400,
+                                                         edev->irqs[0],
+                                                         count))
+                                       count++;
                        }
                }
        }
index 89024e2ab511eeae27219727fe473df917bf5a4d..4f7fe13f775ea167435f130802b6c1065b217541 100644 (file)
@@ -50,15 +50,6 @@ extern int read_exec(struct dentry *, unsigned long offset,
 
 extern int open_dentry(struct dentry *, int mode);
 
-extern int init_elf_binfmt(void);
-extern int init_elf32_binfmt(void);
-extern int init_irix_binfmt(void);
-extern int init_aout_binfmt(void);
-extern int init_aout32_binfmt(void);
-extern int init_script_binfmt(void);
-extern int init_em86_binfmt(void);
-extern int init_misc_binfmt(void);
-
 extern int prepare_binprm(struct linux_binprm *);
 extern void remove_arg_zero(struct linux_binprm *);
 extern int search_binary_handler(struct linux_binprm *,struct pt_regs *);
index fa4272075543dac07e273788f0096e9525d18ad2..7b960299ae0cd5927408d4c0b749c9bdd10b7e16 100644 (file)
@@ -333,24 +333,6 @@ static void floppy_off(unsigned int nr);
 #define DEVICE_ON(device)
 #define DEVICE_OFF(device)
 
-#elif (MAJOR_NR == MFM_ACORN_MAJOR)
-
-#define DEVICE_NAME "mfm disk"
-#define DEVICE_INTR do_mfm
-#define DEVICE_REQUEST do_mfm_request
-#define DEVICE_NR(device) (MINOR(device) >> 6)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
-
-#elif (MAJOR_NR == MFM_ACORN_MAJOR)
-
-#define DEVICE_NAME "mfm disk"
-#define DEVICE_INTR do_mfm
-#define DEVICE_REQUEST do_mfm_request
-#define DEVICE_NR(device) (MINOR(device) >> 6)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
-
 #elif (MAJOR_NR == NBD_MAJOR)
 
 #define DEVICE_NAME "nbd"
diff --git a/include/linux/busmouse.h b/include/linux/busmouse.h
deleted file mode 100644 (file)
index ccbf0f8..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-#ifndef _LINUX_BUSMOUSE_H
-#define _LINUX_BUSMOUSE_H
-
-/*
- * linux/include/linux/busmouse.h: header file for Logitech Bus Mouse driver
- * by James Banks
- *
- * based on information gleamed from various mouse drivers on the net
- *
- * Heavily modified by David giller (rafetmad@oxy.edu)
- *
- * Minor modifications for Linux 0.96c-pl1 by Nathan Laredo
- * gt7080a@prism.gatech.edu (13JUL92)
- *
- * Microsoft BusMouse support by Teemu Rantanen (tvr@cs.hut.fi) (02AUG92)
- *
- * Microsoft Bus Mouse support modified by Derrick Cole (cole@concert.net)
- *    8/28/92
- *
- * Microsoft Bus Mouse support folded into 0.97pl4 code
- *    by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92)
- * Changes:  Logitech and Microsoft support in the same kernel.
- *           Defined new constants in busmouse.h for MS mice.
- *           Added int mse_busmouse_type to distinguish busmouse types
- *           Added a couple of new functions to handle differences in using
- *             MS vs. Logitech (where the int variable wasn't appropriate).
- *
- */
-
-#define MOUSE_IRQ              5
-#define LOGITECH_BUSMOUSE       0   /* Minor device # for Logitech  */
-#define MICROSOFT_BUSMOUSE      2   /* Minor device # for Microsoft */
-
-/*--------- LOGITECH BUSMOUSE ITEMS -------------*/
-
-#define        LOGIBM_BASE             0x23c
-#define        MSE_DATA_PORT           0x23c
-#define        MSE_SIGNATURE_PORT      0x23d
-#define        MSE_CONTROL_PORT        0x23e
-#define        MSE_INTERRUPT_PORT      0x23e
-#define        MSE_CONFIG_PORT         0x23f
-#define        LOGIBM_EXTENT           0x4
-
-#define        MSE_ENABLE_INTERRUPTS   0x00
-#define        MSE_DISABLE_INTERRUPTS  0x10
-
-#define        MSE_READ_X_LOW          0x80
-#define        MSE_READ_X_HIGH         0xa0
-#define        MSE_READ_Y_LOW          0xc0
-#define        MSE_READ_Y_HIGH         0xe0
-
-/* Magic number used to check if the mouse exists */
-#define MSE_CONFIG_BYTE                0x91
-#define MSE_DEFAULT_MODE       0x90
-#define MSE_SIGNATURE_BYTE     0xa5
-
-/* useful Logitech Mouse macros */
-
-#define MSE_INT_OFF()  outb(MSE_DISABLE_INTERRUPTS, MSE_CONTROL_PORT)
-#define MSE_INT_ON()   outb(MSE_ENABLE_INTERRUPTS, MSE_CONTROL_PORT)
-
-/*--------- MICROSOFT BUSMOUSE ITEMS -------------*/
-
-#define        MSBM_BASE                       0x23d
-#define        MS_MSE_DATA_PORT                0x23d
-#define        MS_MSE_SIGNATURE_PORT           0x23e
-#define        MS_MSE_CONTROL_PORT             0x23c
-#define        MS_MSE_CONFIG_PORT              0x23f
-#define        MSBM_EXTENT                     0x3
-
-#define        MS_MSE_ENABLE_INTERRUPTS        0x11
-#define        MS_MSE_DISABLE_INTERRUPTS       0x10
-
-#define        MS_MSE_READ_BUTTONS             0x00
-#define        MS_MSE_READ_X                   0x01
-#define        MS_MSE_READ_Y                   0x02
-
-#define MS_MSE_START                    0x80
-#define MS_MSE_COMMAND_MODE             0x07
-
-/* useful microsoft busmouse macros */
-
-#define MS_MSE_INT_OFF() {outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT); \
-                           outb(MS_MSE_DISABLE_INTERRUPTS, MS_MSE_DATA_PORT);}
-#define MS_MSE_INT_ON()  {outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT); \
-                           outb(MS_MSE_ENABLE_INTERRUPTS, MS_MSE_DATA_PORT);}
-
-struct mouse_status {
-       unsigned char   buttons;
-       unsigned char   latch_buttons;
-       int             dx;
-       int             dy;     
-       int             present;
-       int             ready;
-       int             active;
-       wait_queue_head_t wait;
-       struct fasync_struct *fasyncptr;
-};
-
-/* Function Prototypes */
-
-#endif
-
index e4672ec82ee0551b6294b68d891c2b2fa84fd151..03e19e1ec83f989aadc1352a4b2368a93a45ae90 100644 (file)
@@ -23,7 +23,6 @@ struct resource {
 extern struct resource ioport_resource;
 extern struct resource iomem_resource;
 
-extern void reserve_setup(char *str, int *ints);
 extern int get_resource_list(struct resource *, char *buf, int size);
 
 extern int request_resource(struct resource *root, struct resource *new);
index 2b3b44ff93bc45e091a6e34d54418dcb229b18ba..d4275c5fab8142c5c773fa46ed1145df1837da70 100644 (file)
@@ -49,6 +49,7 @@ extern unsigned long simple_strtoul(const char *,char **,unsigned int);
 extern long simple_strtol(const char *,char **,unsigned int);
 extern int sprintf(char * buf, const char * fmt, ...);
 extern int vsprintf(char *buf, const char *, va_list);
+extern char *get_options(char *str, int *ints);
 
 extern int session_of_pgrp(int pgrp);
 
diff --git a/include/linux/logibusmouse.h b/include/linux/logibusmouse.h
new file mode 100644 (file)
index 0000000..ccbf0f8
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef _LINUX_BUSMOUSE_H
+#define _LINUX_BUSMOUSE_H
+
+/*
+ * linux/include/linux/busmouse.h: header file for Logitech Bus Mouse driver
+ * by James Banks
+ *
+ * based on information gleamed from various mouse drivers on the net
+ *
+ * Heavily modified by David giller (rafetmad@oxy.edu)
+ *
+ * Minor modifications for Linux 0.96c-pl1 by Nathan Laredo
+ * gt7080a@prism.gatech.edu (13JUL92)
+ *
+ * Microsoft BusMouse support by Teemu Rantanen (tvr@cs.hut.fi) (02AUG92)
+ *
+ * Microsoft Bus Mouse support modified by Derrick Cole (cole@concert.net)
+ *    8/28/92
+ *
+ * Microsoft Bus Mouse support folded into 0.97pl4 code
+ *    by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92)
+ * Changes:  Logitech and Microsoft support in the same kernel.
+ *           Defined new constants in busmouse.h for MS mice.
+ *           Added int mse_busmouse_type to distinguish busmouse types
+ *           Added a couple of new functions to handle differences in using
+ *             MS vs. Logitech (where the int variable wasn't appropriate).
+ *
+ */
+
+#define MOUSE_IRQ              5
+#define LOGITECH_BUSMOUSE       0   /* Minor device # for Logitech  */
+#define MICROSOFT_BUSMOUSE      2   /* Minor device # for Microsoft */
+
+/*--------- LOGITECH BUSMOUSE ITEMS -------------*/
+
+#define        LOGIBM_BASE             0x23c
+#define        MSE_DATA_PORT           0x23c
+#define        MSE_SIGNATURE_PORT      0x23d
+#define        MSE_CONTROL_PORT        0x23e
+#define        MSE_INTERRUPT_PORT      0x23e
+#define        MSE_CONFIG_PORT         0x23f
+#define        LOGIBM_EXTENT           0x4
+
+#define        MSE_ENABLE_INTERRUPTS   0x00
+#define        MSE_DISABLE_INTERRUPTS  0x10
+
+#define        MSE_READ_X_LOW          0x80
+#define        MSE_READ_X_HIGH         0xa0
+#define        MSE_READ_Y_LOW          0xc0
+#define        MSE_READ_Y_HIGH         0xe0
+
+/* Magic number used to check if the mouse exists */
+#define MSE_CONFIG_BYTE                0x91
+#define MSE_DEFAULT_MODE       0x90
+#define MSE_SIGNATURE_BYTE     0xa5
+
+/* useful Logitech Mouse macros */
+
+#define MSE_INT_OFF()  outb(MSE_DISABLE_INTERRUPTS, MSE_CONTROL_PORT)
+#define MSE_INT_ON()   outb(MSE_ENABLE_INTERRUPTS, MSE_CONTROL_PORT)
+
+/*--------- MICROSOFT BUSMOUSE ITEMS -------------*/
+
+#define        MSBM_BASE                       0x23d
+#define        MS_MSE_DATA_PORT                0x23d
+#define        MS_MSE_SIGNATURE_PORT           0x23e
+#define        MS_MSE_CONTROL_PORT             0x23c
+#define        MS_MSE_CONFIG_PORT              0x23f
+#define        MSBM_EXTENT                     0x3
+
+#define        MS_MSE_ENABLE_INTERRUPTS        0x11
+#define        MS_MSE_DISABLE_INTERRUPTS       0x10
+
+#define        MS_MSE_READ_BUTTONS             0x00
+#define        MS_MSE_READ_X                   0x01
+#define        MS_MSE_READ_Y                   0x02
+
+#define MS_MSE_START                    0x80
+#define MS_MSE_COMMAND_MODE             0x07
+
+/* useful microsoft busmouse macros */
+
+#define MS_MSE_INT_OFF() {outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT); \
+                           outb(MS_MSE_DISABLE_INTERRUPTS, MS_MSE_DATA_PORT);}
+#define MS_MSE_INT_ON()  {outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT); \
+                           outb(MS_MSE_ENABLE_INTERRUPTS, MS_MSE_DATA_PORT);}
+
+struct mouse_status {
+       unsigned char   buttons;
+       unsigned char   latch_buttons;
+       int             dx;
+       int             dy;     
+       int             present;
+       int             ready;
+       int             active;
+       wait_queue_head_t wait;
+       struct fasync_struct *fasyncptr;
+};
+
+/* Function Prototypes */
+
+#endif
+
index 955e685ad9de1883ed60e017302cec44bfe88f15..5c08f7f940c3c5f5ba6fee8044f60e7cda4a052b 100644 (file)
@@ -147,4 +147,9 @@ extern void parport_pc_inc_use_count(void);
 
 extern void parport_pc_dec_use_count(void);
 
+/* PCMCIA code will want to get us to look at a port.  Provide a mechanism. */
+extern struct parport *parport_pc_probe_port (unsigned long base,
+                                             unsigned long base_hi,
+                                             int irq, int dma);
+
 #endif
index a927b9e7112636c9d08cacd152cdb19fe12c0bf4..af008bd9ae69974f8524553786abcc5e551453c0 100644 (file)
@@ -27,6 +27,7 @@
 #define PER_IRIX32              (0x0009 | STICKY_TIMEOUTS) /* IRIX5 32-bit     */
 #define PER_IRIXN32             (0x000a | STICKY_TIMEOUTS) /* IRIX6 new 32-bit */
 #define PER_IRIX64              (0x000b | STICKY_TIMEOUTS) /* IRIX6 64-bit     */
+#define PER_RISCOS             (0x000c)
 
 /* Prototype for an lcall7 syscall handler. */
 typedef void (*lcall7_func)(struct pt_regs *);
index bbe90c2293c80aca96a10ea2cf4922a8a1c583a7..a32b1ea7243d06d713ca0cee2e4290d88aabf320 100644 (file)
@@ -231,6 +231,7 @@ enum bus_directory_inos {
        PROC_BUS_PCI_DEVICES,
        PROC_BUS_ZORRO,
        PROC_BUS_ZORRO_DEVICES,
+       PROC_BUS_ECARD_DEVICES,
        PROC_BUS_LAST
 };
 
index 41113ea3c4d0e90512c2a9b6cb847dde8f1b1744..62e055f1c01dbeb1171efe2902fa303210361a6f 100644 (file)
@@ -84,8 +84,6 @@ extern void sysctl_init(void);
 extern void filescache_init(void);
 extern void signals_init(void);
 
-extern void device_setup(void);
-extern void binfmt_setup(void);
 extern void free_initmem(void);
 extern void filesystem_setup(void);
 
@@ -93,250 +91,6 @@ extern void filesystem_setup(void);
 extern void ecard_init(void);
 #endif
 
-extern void smp_setup(char *str, int *ints);
-#ifdef __i386__
-extern void ioapic_pirq_setup(char *str, int *ints);
-extern void ioapic_setup(char *str, int *ints);
-#endif
-extern void no_scroll(char *str, int *ints);
-extern void kbd_reset_setup(char *str, int *ints);
-extern void panic_setup(char *str, int *ints);
-extern void bmouse_setup(char *str, int *ints);
-extern void msmouse_setup(char *str, int *ints);
-extern void console_setup(char *str, int *ints);
-#ifdef CONFIG_PRINTER
-extern void lp_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_JOY_AMIGA
-extern void js_am_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_JOY_ANALOG
-extern void js_an_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_JOY_ASSASIN
-extern void js_as_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_JOY_CONSOLE
-extern void js_console_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_JOY_DB9
-extern void js_db9_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_JOY_TURBOGRAFX
-extern void js_tg_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_JOY_LIGHTNING
-extern void js_l4_setup(char *str, int *ints);
-#endif
-extern void eth_setup(char *str, int *ints);
-#ifdef CONFIG_ARCNET_COM20020
-extern void com20020_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_ARCNET_RIM_I
-extern void arcrimi_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_ARCNET_COM90xxIO
-extern void com90io_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_ARCNET_COM90xx
-extern void com90xx_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_DECNET
-extern void decnet_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_BLK_DEV_XD
-extern void xd_setup(char *str, int *ints);
-extern void xd_manual_geo_init(char *str, int *ints);
-#endif
-#ifdef CONFIG_BLK_DEV_IDE
-extern void ide_setup(char *);
-#endif
-#ifdef CONFIG_PARIDE_PD
-extern void pd_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_PARIDE_PF
-extern void pf_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_PARIDE_PT
-extern void pt_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_PARIDE_PG
-extern void pg_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_PARIDE_PCD
-extern void pcd_setup(char *str, int *ints);
-#endif
-extern void floppy_setup(char *str, int *ints);
-extern void st_setup(char *str, int *ints);
-extern void st0x_setup(char *str, int *ints);
-extern void advansys_setup(char *str, int *ints);
-extern void tmc8xx_setup(char *str, int *ints);
-extern void t128_setup(char *str, int *ints);
-extern void pas16_setup(char *str, int *ints);
-extern void generic_NCR5380_setup(char *str, int *intr);
-extern void generic_NCR53C400_setup(char *str, int *intr);
-extern void generic_NCR53C400A_setup(char *str, int *intr);
-extern void generic_DTC3181E_setup(char *str, int *intr);
-extern void aha152x_setup(char *str, int *ints);
-extern void aha1542_setup(char *str, int *ints);
-extern void gdth_setup(char *str, int *ints);
-extern void aic7xxx_setup(char *str, int *ints);
-extern void AM53C974_setup(char *str, int *ints);
-extern void BusLogic_Setup(char *str, int *ints);
-extern void ncr53c8xx_setup(char *str, int *ints);
-extern void sym53c8xx_setup(char *str, int *ints);
-extern void eata2x_setup(char *str, int *ints);
-extern void u14_34f_setup(char *str, int *ints);
-extern void fdomain_setup(char *str, int *ints);
-extern void ibmmca_scsi_setup(char *str, int *ints);
-extern void fd_mcs_setup(char *str, int *ints);
-extern void in2000_setup(char *str, int *ints);
-extern void NCR53c406a_setup(char *str, int *ints);
-extern void sym53c416_setup(char *str, int *ints);
-extern void wd7000_setup(char *str, int *ints);
-extern void dc390_setup(char* str, int *ints);
-extern void scsi_luns_setup(char *str, int *ints);
-extern void scsi_logging_setup(char *str, int *ints);
-extern void sound_setup(char *str, int *ints);
-extern void reboot_setup(char *str, int *ints);
-extern void video_setup(char *str, int *ints);
-#ifdef CONFIG_CDU31A
-extern void cdu31a_setup(char *str, int *ints);
-#endif CONFIG_CDU31A
-#ifdef CONFIG_BLK_DEV_PS2
-extern void ed_setup(char *str, int *ints);
-extern void tp720_setup(char *str, int *ints);
-#endif CONFIG_BLK_DEV_PS2
-#ifdef CONFIG_MCD
-extern void mcd_setup(char *str, int *ints);
-#endif CONFIG_MCD
-#ifdef CONFIG_MCDX
-extern void mcdx_setup(char *str, int *ints);
-#endif CONFIG_MCDX
-#ifdef CONFIG_SBPCD
-extern void sbpcd_setup(char *str, int *ints);
-#endif CONFIG_SBPCD
-#ifdef CONFIG_AZTCD
-extern void aztcd_setup(char *str, int *ints);
-#endif CONFIG_AZTCD
-#ifdef CONFIG_CDU535
-extern void sonycd535_setup(char *str, int *ints);
-#endif CONFIG_CDU535
-#ifdef CONFIG_GSCD
-extern void gscd_setup(char *str, int *ints);
-#endif CONFIG_GSCD
-#ifdef CONFIG_CM206
-extern void cm206_setup(char *str, int *ints);
-#endif CONFIG_CM206
-#ifdef CONFIG_OPTCD
-extern void optcd_setup(char *str, int *ints);
-#endif CONFIG_OPTCD
-#ifdef CONFIG_SJCD
-extern void sjcd_setup(char *str, int *ints);
-#endif CONFIG_SJCD
-#ifdef CONFIG_ISP16_CDI
-extern void isp16_setup(char *str, int *ints);
-#endif CONFIG_ISP16_CDI
-#ifdef CONFIG_BLK_DEV_RAM
-static void ramdisk_start_setup(char *str, int *ints);
-static void load_ramdisk(char *str, int *ints);
-static void prompt_ramdisk(char *str, int *ints);
-static void ramdisk_size(char *str, int *ints);
-#ifdef CONFIG_BLK_DEV_INITRD
-static void no_initrd(char *s,int *ints);
-#endif
-#endif CONFIG_BLK_DEV_RAM
-#ifdef CONFIG_ISDN_DRV_ICN
-extern void icn_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_ISDN_DRV_HISAX
-extern void HiSax_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_DIGIEPCA
-extern void epca_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_ISDN_DRV_PCBIT
-extern void pcbit_setup(char *str, int *ints);
-#endif
-
-#ifdef CONFIG_ATARIMOUSE
-extern void atari_mouse_setup (char *str, int *ints);
-#endif
-#ifdef CONFIG_DMASOUND
-extern void dmasound_setup (char *str, int *ints);
-#endif
-#ifdef CONFIG_ATARI_SCSI
-extern void atari_scsi_setup (char *str, int *ints);
-#endif
-extern void stram_swap_setup (char *str, int *ints);
-extern void wd33c93_setup (char *str, int *ints);
-extern void gvp11_setup (char *str, int *ints);
-extern void ncr53c7xx_setup (char *str, int *ints);
-#ifdef CONFIG_MAC_SCSI
-extern void mac_scsi_setup (char *str, int *ints);
-#endif
-
-#ifdef CONFIG_CYCLADES
-extern void cy_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_DIGI
-extern void pcxx_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_RISCOM8
-extern void riscom8_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_SPECIALIX
-extern void specialix_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_DMASCC
-extern void dmascc_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_BAYCOM_PAR
-extern void baycom_par_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_BAYCOM_SER_FDX
-extern void baycom_ser_fdx_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_BAYCOM_SER_HDX
-extern void baycom_ser_hdx_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_SOUNDMODEM
-extern void sm_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_ADBMOUSE
-extern void adb_mouse_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_WDT
-extern void wdt_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_PARPORT
-extern void parport_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_PLIP
-extern void plip_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_HFMODEM
-extern void hfmodem_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_IP_PNP
-extern void ip_auto_config_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_ROOT_NFS
-extern void nfs_root_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_FTAPE
-extern void ftape_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_MDA_CONSOLE
-extern void mdacon_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_LTPC
-extern void ltpc_setup(char *str, int *ints);
-#endif
-#ifdef CONFIG_BLK_CPQ_DA
-extern void cpqarray_setup(char *str, int *ints);
-#endif
-
 #if defined(CONFIG_SYSVIPC)
 extern void ipc_init(void);
 #endif
@@ -344,10 +98,6 @@ extern void ipc_init(void);
 extern void dquot_init_hash(void);
 #endif
 
-#ifdef CONFIG_MD_BOOT
-extern void md_setup(char *str,int *ints) __init;
-#endif
-
 /*
  * Boot command-line arguments
  */
@@ -361,16 +111,6 @@ static unsigned long memory_end = 0;
 
 int rows, cols;
 
-#ifdef CONFIG_BLK_DEV_RAM
-extern int rd_doload;          /* 1 = load ramdisk, 0 = don't load 2 = dual disk */
-extern int rd_prompt;          /* 1 = prompt for ramdisk, 0 = don't prompt */
-extern int rd_size;            /* Size of the ramdisk(s) */
-extern int rd_image_start;     /* starting block # of image */
-#ifdef CONFIG_BLK_DEV_INITRD
-kdev_t real_root_dev;
-#endif
-#endif
-
 int root_mountflags = MS_RDONLY;
 char *execute_command = NULL;
 
@@ -391,23 +131,20 @@ char *get_options(char *str, int *ints)
        return(cur);
 }
 
-static void __init profile_setup(char *str, int *ints)
+static int __init profile_setup(char *str)
 {
-       if (ints[0] > 0)
-               prof_shift = (unsigned long) ints[1];
-       else
-               prof_shift = 2;
+       prof_shift = simple_strtol(str,NULL,0);
+       return 1;
 }
 
+__setup("profile=", profile_setup);
+
 
 static struct dev_name_struct {
        const char *name;
        const int num;
 } root_dev_names[] __initdata = {
-#ifdef CONFIG_ROOT_NFS
        { "nfs",     0x00ff },
-#endif
-#ifdef CONFIG_BLK_DEV_IDE
        { "hda",     0x0300 },
        { "hdb",     0x0340 },
        { "hdc",     0x1600 },
@@ -424,8 +161,6 @@ static struct dev_name_struct {
        { "hdn",     0x5840 },
        { "hdo",     0x5900 },
        { "hdp",     0x5940 },
-#endif
-#ifdef CONFIG_BLK_DEV_SD
        { "sda",     0x0800 },
        { "sdb",     0x0810 },
        { "sdc",     0x0820 },
@@ -442,71 +177,34 @@ static struct dev_name_struct {
        { "sdn",     0x08d0 },
        { "sdo",     0x08e0 },
        { "sdp",     0x08f0 },
-#endif
-#ifdef CONFIG_ATARI_ACSI
        { "ada",     0x1c00 },
        { "adb",     0x1c10 },
        { "adc",     0x1c20 },
        { "add",     0x1c30 },
        { "ade",     0x1c40 },
-#endif
-#ifdef CONFIG_BLK_DEV_FD
        { "fd",      0x0200 },
-#endif
-#ifdef CONFIG_MD_BOOT
        { "md",      0x0900 },       
-#endif     
-#ifdef CONFIG_BLK_DEV_XD
        { "xda",     0x0d00 },
        { "xdb",     0x0d40 },
-#endif
-#ifdef CONFIG_BLK_DEV_RAM
        { "ram",     0x0100 },
-#endif
-#ifdef CONFIG_BLK_DEV_SR
        { "scd",     0x0b00 },
-#endif
-#ifdef CONFIG_MCD
        { "mcd",     0x1700 },
-#endif
-#ifdef CONFIG_CDU535
        { "cdu535",  0x1800 },
        { "sonycd",  0x1800 },
-#endif
-#ifdef CONFIG_AZTCD
        { "aztcd",   0x1d00 },
-#endif
-#ifdef CONFIG_CM206
        { "cm206cd", 0x2000 },
-#endif
-#ifdef CONFIG_GSCD
        { "gscd",    0x1000 },
-#endif
-#ifdef CONFIG_SBPCD
        { "sbpcd",   0x1900 },
-#endif
-#ifdef CONFIG_BLK_DEV_PS2
        { "eda",     0x2400 },
        { "edb",     0x2440 },
-#endif
-#ifdef CONFIG_PARIDE_PD
        { "pda",        0x2d00 },
        { "pdb",        0x2d10 },
        { "pdc",        0x2d20 },
        { "pdd",        0x2d30 },
-#endif
-#ifdef CONFIG_PARIDE_PCD
        { "pcd",        0x2e00 },
-#endif
-#ifdef CONFIG_PARIDE_PF
        { "pf",         0x2f00 },
-#endif
-#if CONFIG_APBLOCK
        { "apblock", APBLOCK_MAJOR << 8},
-#endif
-#if CONFIG_DDV
        { "ddv", DDV_MAJOR << 8},
-#endif
        { NULL, 0 }
 };
 
@@ -529,440 +227,27 @@ kdev_t __init name_to_kdev_t(char *line)
        return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
 }
 
-static void __init root_dev_setup(char *line, int *num)
+static int __init root_dev_setup(char *line)
 {
        ROOT_DEV = name_to_kdev_t(line);
+       return 1;
 }
 
-/*
- * List of kernel command line parameters. The first table lists parameters
- * which are subject to values parsing (leading numbers are converted to
- * an array of ints and chopped off the string), the second table contains
- * the few exceptions which obey their own syntax rules.
- */
-
-struct kernel_param {
-       const char *str;
-       void (*setup_func)(char *, int *);
-};
-
-static struct kernel_param cooked_params[] __initdata = {
-/* FIXME: make PNP just become reserve_setup */
-#ifndef CONFIG_KERNEL_PNP_RESOURCE
-       { "reserve=", reserve_setup },
-#else
-       { "reserve=", pnp_reserve_setup },
-#endif
-       { "profile=", profile_setup },
-#ifdef __SMP__
-       { "nosmp", smp_setup },
-       { "maxcpus=", smp_setup },
-#ifdef CONFIG_X86_IO_APIC
-       { "noapic", ioapic_setup },
-       { "pirq=", ioapic_pirq_setup },
-#endif
-#endif
-#ifdef CONFIG_BLK_DEV_RAM
-       { "ramdisk_start=", ramdisk_start_setup },
-       { "load_ramdisk=", load_ramdisk },
-       { "prompt_ramdisk=", prompt_ramdisk },
-       { "ramdisk=", ramdisk_size },
-       { "ramdisk_size=", ramdisk_size },
-#ifdef CONFIG_BLK_DEV_INITRD
-       { "noinitrd", no_initrd },
-#endif
-#endif
-#ifdef CONFIG_FB
-       { "video=", video_setup },
-#endif
-       { "panic=", panic_setup },
-       { "console=", console_setup },
-#ifdef CONFIG_VGA_CONSOLE
-       { "no-scroll", no_scroll },
-#endif
-#ifdef CONFIG_MDA_CONSOLE
-       { "mdacon=", mdacon_setup },
-#endif
-#ifdef CONFIG_VT
-       { "kbd-reset", kbd_reset_setup },
-#endif
-#ifdef CONFIG_BUGi386
-       { "no-hlt", no_halt },
-       { "no387", no_387 },
-       { "reboot=", reboot_setup },
-       { "mca-pentium", mca_pentium },
-#endif
-#ifdef CONFIG_INET
-       { "ether=", eth_setup },
-#endif
-#ifdef CONFIG_ARCNET_COM20020
-       { "com20020=", com20020_setup },
-#endif
-#ifdef CONFIG_ARCNET_RIM_I
-       { "arcrimi=", arcrimi_setup },
-#endif
-#ifdef CONFIG_ARCNET_COM90xxIO
-       { "com90io=", com90io_setup },
-#endif
-#ifdef CONFIG_ARCNET_COM90xx
-       { "com90xx=", com90xx_setup },
-#endif
-#ifdef CONFIG_DECNET
-       { "decnet=", decnet_setup },
-#endif
-#ifdef CONFIG_PRINTER
-        { "lp=", lp_setup },
-#endif
-#ifdef CONFIG_JOY_AMIGA
-       { "js_am=", js_am_setup },
-#endif
-#ifdef CONFIG_JOY_ANALOG
-       { "js_an=", js_an_setup },
-#endif
-#ifdef CONFIG_JOY_ASSASIN
-       { "js_as=", js_as_setup },
-#endif
-#ifdef CONFIG_JOY_CONSOLE
-       { "js_console=", js_console_setup },
-       { "js_console2=", js_console_setup },
-       { "js_console3=", js_console_setup },
-#endif
-#ifdef CONFIG_JOY_DB9
-       { "js_db9=", js_db9_setup },
-       { "js_db9_2=", js_db9_setup },
-       { "js_db9_3=", js_db9_setup },
-#endif
-#ifdef CONFIG_JOY_TURBOGRAFX
-       { "js_tg=", js_tg_setup },
-       { "js_tg_2=", js_tg_setup },
-       { "js_tg_3=", js_tg_setup },
-#endif
-#ifdef CONFIG_SCSI
-       { "max_scsi_luns=", scsi_luns_setup },
-       { "scsi_logging=", scsi_logging_setup },
-#endif
-#ifdef CONFIG_JOY_LIGHTNING
-       { "js_l4=", js_l4_setup },
-#endif
-#ifdef CONFIG_SCSI_ADVANSYS
-       { "advansys=", advansys_setup },
-#endif
-#if defined(CONFIG_BLK_DEV_HD)
-       { "hd=", hd_setup },
-#endif
-#ifdef CONFIG_CHR_DEV_ST
-       { "st=", st_setup },
-#endif
-#ifdef CONFIG_BUSMOUSE
-       { "bmouse=", bmouse_setup },
-#endif
-#ifdef CONFIG_MS_BUSMOUSE
-       { "msmouse=", msmouse_setup },
-#endif
-#ifdef CONFIG_SCSI_SEAGATE
-       { "st0x=", st0x_setup },
-       { "tmc8xx=", tmc8xx_setup },
-#endif
-#ifdef CONFIG_SCSI_T128
-       { "t128=", t128_setup },
-#endif
-#ifdef CONFIG_SCSI_PAS16
-       { "pas16=", pas16_setup },
-#endif
-#ifdef CONFIG_SCSI_GENERIC_NCR5380
-       { "ncr5380=", generic_NCR5380_setup },
-       { "ncr53c400=", generic_NCR53C400_setup },
-       { "ncr53c400a=", generic_NCR53C400A_setup },
-       { "dtc3181e=", generic_DTC3181E_setup },
-#endif
-#ifdef CONFIG_SCSI_AHA152X
-       { "aha152x=", aha152x_setup},
-#endif
-#ifdef CONFIG_SCSI_AHA1542
-       { "aha1542=", aha1542_setup},
-#endif
-#ifdef CONFIG_SCSI_GDTH
-       { "gdth=", gdth_setup},
-#endif
-#ifdef CONFIG_SCSI_AIC7XXX
-       { "aic7xxx=", aic7xxx_setup},
-#endif
-#ifdef CONFIG_SCSI_BUSLOGIC
-       { "BusLogic=", BusLogic_Setup},
-#endif
-#ifdef CONFIG_SCSI_NCR53C8XX
-       { "ncr53c8xx=", ncr53c8xx_setup},
-#endif
-#ifdef CONFIG_SCSI_SYM53C8XX
-       { "sym53c8xx=", sym53c8xx_setup},
-#endif
-#ifdef CONFIG_SCSI_EATA
-       { "eata=", eata2x_setup},
-#endif
-#ifdef CONFIG_SCSI_U14_34F
-       { "u14-34f=", u14_34f_setup},
-#endif
-#ifdef CONFIG_SCSI_AM53C974
-        { "AM53C974=", AM53C974_setup},
-#endif
-#ifdef CONFIG_SCSI_NCR53C406A
-       { "ncr53c406a=", NCR53c406a_setup},
-#endif
-#ifdef CONFIG_SCSI_SYM53C416
-       { "sym53c416=", sym53c416_setup},
-#endif
-#ifdef CONFIG_SCSI_FUTURE_DOMAIN
-       { "fdomain=", fdomain_setup},
-#endif
-#ifdef CONFIG_SCSI_IN2000
-       { "in2000=", in2000_setup},
-#endif
-#ifdef CONFIG_SCSI_7000FASST
-       { "wd7000=", wd7000_setup},
-#endif
-#ifdef CONFIG_SCSI_IBMMCA
-        { "ibmmcascsi=", ibmmca_scsi_setup },
-#endif
-#ifdef CONFIG_SCSI_FD_MCS
-       { "fd_mcs=", fd_mcs_setup },
-#endif
-#if defined(CONFIG_SCSI_DC390T) && ! defined(CONFIG_SCSI_DC390T_NOGENSUPP)
-        { "tmscsim=", dc390_setup },
-#endif
-#ifdef CONFIG_BLK_DEV_XD
-       { "xd=", xd_setup },
-       { "xd_geo=", xd_manual_geo_init },
-#endif
-#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
-       { "floppy=", floppy_setup },
-#endif
-#ifdef CONFIG_BLK_DEV_PS2
-       { "eda=", ed_setup },
-       { "edb=", ed_setup },
-       { "tp720=", tp720_setup },
-#endif
-#ifdef CONFIG_CDU31A
-       { "cdu31a=", cdu31a_setup },
-#endif CONFIG_CDU31A
-#ifdef CONFIG_MCD
-       { "mcd=", mcd_setup },
-#endif CONFIG_MCD
-#ifdef CONFIG_MCDX
-       { "mcdx=", mcdx_setup },
-#endif CONFIG_MCDX
-#ifdef CONFIG_SBPCD
-       { "sbpcd=", sbpcd_setup },
-#endif CONFIG_SBPCD
-#ifdef CONFIG_AZTCD
-       { "aztcd=", aztcd_setup },
-#endif CONFIG_AZTCD
-#ifdef CONFIG_CDU535
-       { "sonycd535=", sonycd535_setup },
-#endif CONFIG_CDU535
-#ifdef CONFIG_GSCD
-       { "gscd=", gscd_setup },
-#endif CONFIG_GSCD
-#ifdef CONFIG_CM206
-       { "cm206=", cm206_setup },
-#endif CONFIG_CM206
-#ifdef CONFIG_OPTCD
-       { "optcd=", optcd_setup },
-#endif CONFIG_OPTCD
-#ifdef CONFIG_SJCD
-       { "sjcd=", sjcd_setup },
-#endif CONFIG_SJCD
-#ifdef CONFIG_ISP16_CDI
-       { "isp16=", isp16_setup },
-#endif CONFIG_ISP16_CDI
-#ifdef CONFIG_SOUND_OSS
-       { "sound=", sound_setup },
-#endif
-#ifdef CONFIG_ISDN_DRV_ICN
-       { "icn=", icn_setup },
-#endif
-#ifdef CONFIG_ISDN_DRV_HISAX
-       { "hisax=", HiSax_setup },
-       { "HiSax=", HiSax_setup },
-#endif
-#ifdef CONFIG_ISDN_DRV_PCBIT
-       { "pcbit=", pcbit_setup },
-#endif
-#ifdef CONFIG_ATARIMOUSE
-       { "atamouse=", atari_mouse_setup },
-#endif
-#ifdef CONFIG_DMASOUND
-       { "dmasound=", dmasound_setup },
-#endif
-#ifdef CONFIG_ATARI_SCSI
-       { "atascsi=", atari_scsi_setup },
-#endif
-#ifdef CONFIG_STRAM_SWAP
-       { "stram_swap=", stram_swap_setup },
-#endif
-#if defined(CONFIG_A4000T_SCSI) || defined(CONFIG_WARPENGINE_SCSI) \
-           || defined(CONFIG_A4091_SCSI) || defined(CONFIG_MVME16x_SCSI) \
-           || defined(CONFIG_BVME6000_SCSI) \
-           || defined(CONFIG_BLZ603EPLUS_SCSI)
-        { "53c7xx=", ncr53c7xx_setup },
-#endif
-#if defined(CONFIG_A3000_SCSI) || defined(CONFIG_A2091_SCSI) \
-           || defined(CONFIG_GVP11_SCSI)
-       { "wd33c93=", wd33c93_setup },
-#endif
-#if defined(CONFIG_GVP11_SCSI)
-       { "gvp11=", gvp11_setup },
-#endif
-#ifdef CONFIG_MAC_SCSI
-       { "mac5380=", mac_scsi_setup },
-#endif
-#ifdef CONFIG_CYCLADES
-       { "cyclades=", cy_setup },
-#endif
-#ifdef CONFIG_DIGI
-       { "digi=", pcxx_setup },
-#endif
-#ifdef CONFIG_DIGIEPCA
-       { "digiepca=", epca_setup },
-#endif
-#ifdef CONFIG_RISCOM8
-       { "riscom8=", riscom8_setup },
-#endif
-#ifdef CONFIG_DMASCC
-       { "dmascc=", dmascc_setup },
-#endif
-#ifdef CONFIG_SPECIALIX
-       { "specialix=", specialix_setup },
-#endif
-#ifdef CONFIG_BAYCOM_PAR
-       { "baycom_par=", baycom_par_setup },
-#endif
-#ifdef CONFIG_BAYCOM_SER_FDX
-       { "baycom_ser_fdx=", baycom_ser_fdx_setup },
-#endif
-#ifdef CONFIG_BAYCOM_SER_HDX
-       { "baycom_ser_hdx=", baycom_ser_hdx_setup },
-#endif
-#ifdef CONFIG_SOUNDMODEM
-       { "soundmodem=", sm_setup },
-#endif
-#ifdef CONFIG_WDT
-       { "wdt=", wdt_setup },
-#endif
-#ifdef CONFIG_PARPORT
-       { "parport=", parport_setup },
-#endif
-#ifdef CONFIG_PLIP
-       { "plip=", plip_setup },
-#endif
-#ifdef CONFIG_HFMODEM
-       { "hfmodem=", hfmodem_setup },
-#endif
-#ifdef CONFIG_FTAPE
-       { "ftape=", ftape_setup},
-#endif
-#ifdef CONFIG_MD_BOOT
-       { "md=", md_setup},
-#endif
-#ifdef CONFIG_ADBMOUSE
-       { "adb_buttons=", adb_mouse_setup },
-#endif
-#ifdef CONFIG_LTPC
-       { "ltpc=", ltpc_setup },
-#endif
-#ifdef CONFIG_BLK_CPQ_DA
-       { "smart2=", cpqarray_setup },
-#endif
-       { 0, 0 }
-};
-
-static struct kernel_param raw_params[] __initdata = {
-       { "root=", root_dev_setup },
-#ifdef CONFIG_ROOT_NFS
-       { "nfsroot=", nfs_root_setup },
-       { "nfsaddrs=", ip_auto_config_setup },
-#endif
-#ifdef CONFIG_IP_PNP
-       { "ip=", ip_auto_config_setup },
-#endif
-#ifdef CONFIG_PCI
-       { "pci=", pci_setup },
-#endif
-#ifdef CONFIG_PARIDE_PD
-       { "pd.", pd_setup },
-#endif
-#ifdef CONFIG_PARIDE_PCD
-       { "pcd.", pcd_setup },
-#endif
-#ifdef CONFIG_PARIDE_PF
-       { "pf.", pf_setup },
-#endif
-#ifdef CONFIG_PARIDE_PT
-        { "pt.", pt_setup },
-#endif
-#ifdef CONFIG_PARIDE_PG
-        { "pg.", pg_setup },
-#endif
-#ifdef CONFIG_APM
-       { "apm=", apm_setup },
-#endif
-       { 0, 0 }
-};
-
-#ifdef CONFIG_BLK_DEV_RAM
-static void __init ramdisk_start_setup(char *str, int *ints)
-{
-   if (ints[0] > 0 && ints[1] >= 0)
-      rd_image_start = ints[1];
-}
-
-static void __init load_ramdisk(char *str, int *ints)
-{
-   if (ints[0] > 0 && ints[1] >= 0)
-      rd_doload = ints[1] & 3;
-}
-
-static void __init prompt_ramdisk(char *str, int *ints)
-{
-   if (ints[0] > 0 && ints[1] >= 0)
-      rd_prompt = ints[1] & 1;
-}
-
-static void __init ramdisk_size(char *str, int *ints)
-{
-       if (ints[0] > 0 && ints[1] >= 0)
-               rd_size = ints[1];
-}
-#endif
+__setup("root=", root_dev_setup);
 
 static int __init checksetup(char *line)
 {
-       int i, ints[11];
-
-#ifdef CONFIG_BLK_DEV_IDE
-       /* ide driver needs the basic string, rather than pre-processed values */
-       if (!strncmp(line,"ide",3) ||
-#ifdef CONFIG_BLK_DEV_VIA82C586
-           !strncmp(line,"splitfifo",9) ||
-#endif /* CONFIG_BLK_DEV_VIA82C586 */
-           (!strncmp(line,"hd",2) && line[2] != '=')) {
-               ide_setup(line);
-               return 1;
-       }
-#endif
-       for (i=0; raw_params[i].str; i++) {
-               int n = strlen(raw_params[i].str);
-               if (!strncmp(line,raw_params[i].str,n)) {
-                       raw_params[i].setup_func(line+n, NULL);
-                       return 1;
-               }
-       }
-       for (i=0; cooked_params[i].str; i++) {
-               int n = strlen(cooked_params[i].str);
-               if (!strncmp(line,cooked_params[i].str,n)) {
-                       cooked_params[i].setup_func(get_options(line+n, ints), ints);
-                       return 1;
+       struct kernel_param *p;
+
+       p = &__setup_start;
+       do {
+               int n = strlen(p->str);
+               if (!strncmp(line,p->str,n)) {
+                       if (p->setup_func(line+n))
+                               return 1;
                }
-       }
+               p++;
+       } while (p < &__setup_end);
        return 0;
 }
 
@@ -1018,6 +303,34 @@ void __init calibrate_delay(void)
                ((loops_per_sec+2500)/5000) % 100);
 }
 
+static int __init readonly(char *str)
+{
+       if (*str)
+               return 0;
+       root_mountflags |= MS_RDONLY;
+       return 1;
+}
+
+static int __init readwrite(char *str)
+{
+       if (*str)
+               return 0;
+       root_mountflags &= ~MS_RDONLY;
+       return 1;
+}
+
+static int __init debug_kernel(char *str)
+{
+       if (*str)
+               return 0;
+       console_loglevel = 10;
+       return 1;
+}
+
+__setup("ro", readonly);
+__setup("rw", readwrite);
+__setup("debug", debug_kernel);
+
 /*
  * This is a simple kernel command line parsing function: it parses
  * the command line, and fills in the arguments/environment to init
@@ -1040,21 +353,6 @@ static void __init parse_options(char *line)
        while ((line = next) != NULL) {
                if ((next = strchr(line,' ')) != NULL)
                        *next++ = 0;
-               /*
-                * check for kernel options first..
-                */
-               if (!strcmp(line,"ro")) {
-                       root_mountflags |= MS_RDONLY;
-                       continue;
-               }
-               if (!strcmp(line,"rw")) {
-                       root_mountflags &= ~MS_RDONLY;
-                       continue;
-               }
-               if (!strcmp(line,"debug")) {
-                       console_loglevel = 10;
-                       continue;
-               }
                if (!strncmp(line,"init=",5)) {
                        line += 5;
                        execute_command = line;
@@ -1089,7 +387,7 @@ static void __init parse_options(char *line)
 
 
 extern void setup_arch(char **, unsigned long *, unsigned long *);
-extern int cpu_idle(void * unused);
+extern int cpu_idle(void);
 
 #ifndef __SMP__
 
@@ -1201,7 +499,7 @@ asmlinkage void __init start_kernel(void)
        kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
        unlock_kernel();
        current->need_resched = 1;
-       cpu_idle(NULL);
+       cpu_idle();
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -1225,6 +523,17 @@ static void __init no_initrd(char *s,int *ints)
 
 struct task_struct *child_reaper = &init_task;
 
+static void __init do_initcalls(void)
+{
+       initcall_t *call;
+
+       call = &__initcall_start;
+       do {
+               (*call)();
+               call++;
+       } while (call < &__initcall_end);
+}
+
 /*
  * Ok, the machine is now initialized. None of the devices
  * have been touched yet, but the CPU subsystem is up and
@@ -1296,6 +605,8 @@ static void __init do_basic_setup(void)
        /* Networking initialization needs a process context */ 
        sock_init();
 
+       do_initcalls();
+
        /* Launch bdflush from here, instead of the old syscall way. */
        kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
        /* Start the background pageout daemon. */
@@ -1318,12 +629,6 @@ static void __init do_basic_setup(void)
        else mount_initrd =0;
 #endif
 
-       /* Set up devices .. */
-       device_setup();
-
-       /* .. executable formats .. */
-       binfmt_setup();
-
        /* .. filesystems .. */
        filesystem_setup();
 
index df365209e28cad1e9dcf63cd6062021eb335449e..dc46ad564e85783b8f4e3eb85ca97afbadd5662e 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -687,9 +687,9 @@ static unsigned long shm_nopage(struct vm_area_struct * shmd, unsigned long addr
                --current->maj_flt;  /* was incremented in do_no_page */
 
 done:  /* pte_val(pte) == shp->shm_pages[idx] */
+       get_page(mem_map + MAP_NR(pte_page(pte)));
        unlock_kernel();
        current->min_flt++;
-       get_page(mem_map + MAP_NR(pte_page(pte)));
        return pte_page(pte);
 
 changed:
index ee654c47231df820a90891410747146fdb72b2e4..beee85a06a6916741e36e09fd06a65dc0ef8c4ad 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/kmod.h>
 #endif
 
-extern char *get_options(char *str, int *ints);
 extern void set_device_ro(kdev_t dev,int flag);
 extern struct file_operations * get_blkfops(unsigned int);
 extern int blkdev_release(struct inode * inode);
index f64ccfb3745beeedf0611f85f7248b396579036f..b26439eeadffe38dadbc424a9c24412fe8b8e0ad 100644 (file)
@@ -25,12 +25,14 @@ extern int C_A_D;
 
 int panic_timeout = 0;
 
-void __init panic_setup(char *str, int *ints)
+static int __init panic_setup(char *str)
 {
-       if (ints[0] == 1)
-               panic_timeout = ints[1];
+       panic_timeout = simple_strtoul(str, NULL, 0);
+       return 1;
 }
 
+__setup("panic=", panic_setup);
+
 NORET_TYPE void panic(const char * fmt, ...)
 {
        static char buf[1024];
index c2cbd4a7882edd991237826cb9b2693450bb03a2..5e3de0a3db3c138cd5cad3c089136b7221a79cda 100644 (file)
@@ -50,16 +50,18 @@ static int preferred_console = -1;
 /*
  *     Setup a list of consoles. Called from init/main.c
  */
-void __init console_setup(char *str, int *ints)
+static int __init console_setup(char *str)
 {
        struct console_cmdline *c;
        char name[sizeof(c->name)];
        char *s, *options;
        int i, idx;
+       int ints[11];
 
        /*
         *      Decode str into name, index, options.
         */
+       str = get_options(str, ints);
        if (str[0] >= '0' && str[0] <= '9') {
                strcpy(name, "ttyS");
                strncpy(name + 4, str, sizeof(name) - 5);
@@ -88,17 +90,19 @@ void __init console_setup(char *str, int *ints)
                if (strcmp(console_cmdline[i].name, name) == 0 &&
                          console_cmdline[i].index == idx) {
                                preferred_console = i;
-                               return;
+                               return 1;
                }
        if (i == MAX_CMDLINECONSOLES)
-               return;
+               return 1;
        preferred_console = i;
        c = &console_cmdline[i];
        memcpy(c->name, name, sizeof(c->name));
        c->options = options;
        c->index = idx;
+       return 1;
 }
 
+__setup("console=", console_setup);
 
 /*
  * Commands to do_syslog:
index 19b056682ad51d85d14ebec4f35ff24f51aca241..928e9f048e39a1825fb0cb692f29da5ad88a083d 100644 (file)
@@ -165,11 +165,14 @@ void __release_region(struct resource *parent, unsigned long start, unsigned lon
  * Called from init/main.c to reserve IO ports.
  */
 #define MAXRESERVE 4
-void __init reserve_setup(char *str, int *ints)
+static int __init reserve_setup(char *str)
 {
        int i;
        static int reserved = 0;
        static struct resource reserve[MAXRESERVE];
+       int ints[11];
+
+       get_options(str, ints);
 
        for (i = 1; i < ints[0]; i += 2) {
                int x = reserved;
@@ -183,4 +186,7 @@ void __init reserve_setup(char *str, int *ints)
                                reserved = x+1;
                }
        }
+       return 1;
 }
+
+__setup("reserve=", reserve_setup);
index b78d4e2deafe44ca8664739a3c18fd07eb5de364..992ed781af0b2fd0f0415c6ed5505fb0f150fd99 100644 (file)
@@ -986,7 +986,9 @@ static int do_swap_page(struct task_struct * tsk,
 
        vma->vm_mm->rss++;
        tsk->min_flt++;
+       lock_kernel();
        swap_free(entry);
+       unlock_kernel();
 
        pte = mk_pte(page_address(page), vma->vm_page_prot);
 
index 59fc0d5f9954c715c759c53a53fc8d8bfe9409db..73a4c912a029985cc65186e39e4be7b68a071229 100644 (file)
@@ -31,8 +31,7 @@
  * using a process that no longer actually exists (it might
  * have died while we slept).
  */
-static int try_to_swap_out(struct task_struct * tsk, struct vm_area_struct* vma,
-       unsigned long address, pte_t * page_table, int gfp_mask)
+static int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pte_t * page_table, int gfp_mask)
 {
        pte_t pte;
        unsigned long entry;
@@ -47,7 +46,7 @@ static int try_to_swap_out(struct task_struct * tsk, struct vm_area_struct* vma,
                goto out_failed;
 
        page = mem_map + MAP_NR(page_addr);
-       spin_lock(&tsk->mm->page_table_lock);
+       spin_lock(&vma->vm_mm->page_table_lock);
        if (pte_val(pte) != pte_val(*page_table))
                goto out_failed_unlock;
 
@@ -136,15 +135,16 @@ drop_pte:
         */
        flush_cache_page(vma, address);
        if (vma->vm_ops && vma->vm_ops->swapout) {
-               pid_t pid = tsk->pid;
+               int error;
                pte_clear(page_table);
-               spin_unlock(&tsk->mm->page_table_lock);
+               spin_unlock(&vma->vm_mm->page_table_lock);
                flush_tlb_page(vma, address);
                vma->vm_mm->rss--;
-               
-               if (vma->vm_ops->swapout(vma, page))
-                       kill_proc(pid, SIGBUS, 1);
-               goto out_free_success;
+               error = vma->vm_ops->swapout(vma, page);
+               if (!error)
+                       goto out_free_success;
+               __free_page(page);
+               return error;
        }
 
        /*
@@ -158,9 +158,8 @@ drop_pte:
                goto out_failed_unlock; /* No swap space left */
                
        vma->vm_mm->rss--;
-       tsk->nswap++;
        set_pte(page_table, __pte(entry));
-       spin_unlock(&tsk->mm->page_table_lock);
+       spin_unlock(&vma->vm_mm->page_table_lock);
 
        flush_tlb_page(vma, address);
        swap_duplicate(entry);  /* One for the process, one for the swap cache */
@@ -175,7 +174,7 @@ out_free_success:
        __free_page(page);
        return 1;
 out_failed_unlock:
-       spin_unlock(&tsk->mm->page_table_lock);
+       spin_unlock(&vma->vm_mm->page_table_lock);
 out_failed:
        return 0;
 }
@@ -194,8 +193,7 @@ out_failed:
  * (C) 1993 Kai Petzke, wpp@marie.physik.tu-berlin.de
  */
 
-static inline int swap_out_pmd(struct task_struct * tsk, struct vm_area_struct * vma,
-       pmd_t *dir, unsigned long address, unsigned long end, int gfp_mask)
+static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long end, int gfp_mask)
 {
        pte_t * pte;
        unsigned long pmd_end;
@@ -216,8 +214,8 @@ static inline int swap_out_pmd(struct task_struct * tsk, struct vm_area_struct *
 
        do {
                int result;
-               tsk->mm->swap_address = address + PAGE_SIZE;
-               result = try_to_swap_out(tsk, vma, address, pte, gfp_mask);
+               vma->vm_mm->swap_address = address + PAGE_SIZE;
+               result = try_to_swap_out(vma, address, pte, gfp_mask);
                if (result)
                        return result;
                address += PAGE_SIZE;
@@ -226,8 +224,7 @@ static inline int swap_out_pmd(struct task_struct * tsk, struct vm_area_struct *
        return 0;
 }
 
-static inline int swap_out_pgd(struct task_struct * tsk, struct vm_area_struct * vma,
-       pgd_t *dir, unsigned long address, unsigned long end, int gfp_mask)
+static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir, unsigned long address, unsigned long end, int gfp_mask)
 {
        pmd_t * pmd;
        unsigned long pgd_end;
@@ -247,7 +244,7 @@ static inline int swap_out_pgd(struct task_struct * tsk, struct vm_area_struct *
                end = pgd_end;
        
        do {
-               int result = swap_out_pmd(tsk, vma, pmd, address, end, gfp_mask);
+               int result = swap_out_pmd(vma, pmd, address, end, gfp_mask);
                if (result)
                        return result;
                address = (address + PMD_SIZE) & PMD_MASK;
@@ -256,8 +253,7 @@ static inline int swap_out_pgd(struct task_struct * tsk, struct vm_area_struct *
        return 0;
 }
 
-static int swap_out_vma(struct task_struct * tsk, struct vm_area_struct * vma,
-       unsigned long address, int gfp_mask)
+static int swap_out_vma(struct vm_area_struct * vma, unsigned long address, int gfp_mask)
 {
        pgd_t *pgdir;
        unsigned long end;
@@ -266,11 +262,11 @@ static int swap_out_vma(struct task_struct * tsk, struct vm_area_struct * vma,
        if (vma->vm_flags & VM_LOCKED)
                return 0;
 
-       pgdir = pgd_offset(tsk->mm, address);
+       pgdir = pgd_offset(vma->vm_mm, address);
 
        end = vma->vm_end;
        while (address < end) {
-               int result = swap_out_pgd(tsk, vma, pgdir, address, end, gfp_mask);
+               int result = swap_out_pgd(vma, pgdir, address, end, gfp_mask);
                if (result)
                        return result;
                address = (address + PGDIR_SIZE) & PGDIR_MASK;
@@ -279,7 +275,7 @@ static int swap_out_vma(struct task_struct * tsk, struct vm_area_struct * vma,
        return 0;
 }
 
-static int swap_out_process(struct task_struct * p, int gfp_mask)
+static int swap_out_mm(struct mm_struct * mm, int gfp_mask)
 {
        unsigned long address;
        struct vm_area_struct* vma;
@@ -287,18 +283,18 @@ static int swap_out_process(struct task_struct * p, int gfp_mask)
        /*
         * Go through process' page directory.
         */
-       address = p->mm->swap_address;
+       address = mm->swap_address;
 
        /*
         * Find the proper vm-area
         */
-       vma = find_vma(p->mm, address);
+       vma = find_vma(mm, address);
        if (vma) {
                if (address < vma->vm_start)
                        address = vma->vm_start;
 
                for (;;) {
-                       int result = swap_out_vma(p, vma, address, gfp_mask);
+                       int result = swap_out_vma(vma, address, gfp_mask);
                        if (result)
                                return result;
                        vma = vma->vm_next;
@@ -309,8 +305,8 @@ static int swap_out_process(struct task_struct * p, int gfp_mask)
        }
 
        /* We didn't find anything for the process */
-       p->mm->swap_cnt = 0;
-       p->mm->swap_address = 0;
+       mm->swap_cnt = 0;
+       mm->swap_address = 0;
        return 0;
 }
 
@@ -321,8 +317,8 @@ static int swap_out_process(struct task_struct * p, int gfp_mask)
  */
 static int swap_out(unsigned int priority, int gfp_mask)
 {
-       struct task_struct * p, * pbest;
-       int counter, assign, max_cnt;
+       struct task_struct * p;
+       int counter;
 
        /* 
         * We make one or two passes through the task list, indexed by 
@@ -345,36 +341,49 @@ static int swap_out(unsigned int priority, int gfp_mask)
                counter = nr_threads;
 
        for (; counter >= 0; counter--) {
-               assign = 0;
-               max_cnt = 0;
-               pbest = NULL;
+               int assign = 0;
+               int max_cnt = 0;
+               struct mm_struct *best = NULL;
+               int pid = 0;
        select:
                read_lock(&tasklist_lock);
                p = init_task.next_task;
                for (; p != &init_task; p = p->next_task) {
-                       if (!p->swappable || !p->mm)
+                       struct mm_struct *mm = p->mm;
+                       if (!p->swappable || !mm)
                                continue;
-                       if (p->mm->rss <= 0)
+                       if (mm->rss <= 0)
                                continue;
                        /* Refresh swap_cnt? */
                        if (assign)
-                               p->mm->swap_cnt = p->mm->rss;
-                       if (p->mm->swap_cnt > max_cnt) {
-                               max_cnt = p->mm->swap_cnt;
-                               pbest = p;
+                               mm->swap_cnt = mm->rss;
+                       if (mm->swap_cnt > max_cnt) {
+                               max_cnt = mm->swap_cnt;
+                               best = mm;
+                               pid = p->pid;
                        }
                }
                read_unlock(&tasklist_lock);
-               if (!pbest) {
+               if (!best) {
                        if (!assign) {
                                assign = 1;
                                goto select;
                        }
                        goto out;
-               }
+               } else {
+                       int ret;
+
+                       atomic_inc(&best->mm_count);
+                       ret = swap_out_mm(best, gfp_mask);
+                       mmdrop(best);
 
-               if (swap_out_process(pbest, gfp_mask))
+                       if (!ret)
+                               continue;
+
+                       if (ret < 0)
+                               kill_proc(pid, SIGBUS, 1);
                        return 1;
+               }
        }
 out:
        return 0;
index 128c2a5e959bb0d97867a08b55a49d788467b575..ce43e74791889f66ec9302ed6e1a350df944c07c 100644 (file)
 #include <asm/checksum.h>
 
 
-__initfunc(void eth_setup(char *str, int *ints))
+static int __init eth_setup(char *str)
 {
+       int ints[11];
        struct device *d;
 
+       str = get_options(str, ints);
+
        if (!str || !*str)
-               return;
+               return 0;
 
        d = dev_base;
        while (d) 
@@ -85,8 +88,10 @@ __initfunc(void eth_setup(char *str, int *ints))
                }
                d=d->next;
        }
+       return 1;
 }
 
+__setup("ether=", eth_setup);
 
 /*
  *      Create the Ethernet MAC header for an arbitrary protocol layer 
index 9d889ca5165606d194d074ce3700fa60539daa9a..ca01de257278190d1120e47947b3d8adf2cdb7f4 100644 (file)
@@ -66,7 +66,7 @@ void grow_config(int len)
        while (len_config + len > size_config) {
                str_config = realloc(str_config, size_config *= 2);
                if (str_config == NULL)
-                       { perror("malloc"); exit(1); }
+                       { perror("malloc config"); exit(1); }
        }
 }
 
@@ -126,6 +126,55 @@ void clear_config(void)
 
 
 
+/*
+ * This records all the precious .h filenames.  No need for a hash,
+ * it's a long string of values enclosed in tab and newline.
+ */
+char * str_precious  = NULL;
+int    size_precious = 0;
+int    len_precious  = 0;
+
+
+
+/*
+ * Grow the precious string to a desired length.
+ * Usually the first growth is plenty.
+ */
+void grow_precious(int len)
+{
+       if (str_precious == NULL) {
+               len_precious  = 0;
+               size_precious = 4096;
+               str_precious  = malloc(4096);
+               if (str_precious == NULL)
+                       { perror("malloc precious"); exit(1); }
+       }
+
+       while (len_precious + len > size_precious) {
+               str_precious = realloc(str_precious, size_precious *= 2);
+               if (str_precious == NULL)
+                       { perror("malloc"); exit(1); }
+       }
+}
+
+
+
+/*
+ * Add a new value to the precious string.
+ */
+void define_precious(const char * filename)
+{
+       int len = strlen(filename);
+       grow_precious(len + 4);
+       *(str_precious+len_precious++) = '\t';
+       memcpy(str_precious+len_precious, filename, len);
+       len_precious += len;
+       memcpy(str_precious+len_precious, " \\\n", 3);
+       len_precious += 3;
+}
+
+
+
 /*
  * Handle an #include line.
  */
@@ -458,8 +507,11 @@ void do_depend(const char * filename, const char * command)
        hasdep = 0;
        clear_config();
        state_machine(map, map+st.st_size);
-       if (hasdep)
+       if (hasdep) {
                puts(command);
+               if (*command)
+                       define_precious(filename);
+       }
 
        munmap(map, mapsize);
        close(fd);
@@ -501,5 +553,9 @@ int main(int argc, char **argv)
                }
                do_depend(filename, command);
        }
+       if (len_precious) {
+               *(str_precious+len_precious) = '\0';
+               printf(".PRECIOUS:%s\n", str_precious);
+       }
        return 0;
 }