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
#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
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]
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)
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,
#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
void flush_thread(void)
{
- int i;
-
- memset(¤t->tss.debug, 0, sizeof(current->tss.debug));
+ memset(¤t->thread.debug, 0, sizeof(current->thread.debug));
current->used_math = 0;
current->flags &= ~PF_USEDFPU;
}
save = ((struct context_save_struct *)(childregs)) - 1;
init_thread_css(save);
- p->tss.save = save;
+ p->thread.save = save;
return 0;
}
int fpvalid = 0;
if (current->used_math)
- memcpy (fp, ¤t->tss.fpstate.soft, sizeof (fp));
+ memcpy (fp, ¤t->thread.fpstate.soft, sizeof (fp));
return fpvalid;
}
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;
/*
* 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.
*/
/*
* 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.
*/
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;
*/
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;
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;
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;
{
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);*/
}
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);
}
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);
}
{
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)) {
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
#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);
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)
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);
/* 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);
* 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 */
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 \
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 ()
*
_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 ()
*
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
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
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
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
/*
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
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)
{
/*
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.
*/
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
* 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();
}
/*
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) {
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
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 */
int cpucount = 0;
-extern int cpu_idle(void * unused);
+extern int cpu_idle(void);
/*
* Activate a secondary processor.
smp_callin();
while (!atomic_read(&smp_commenced))
/* nothing */ ;
- return cpu_idle(NULL);
+ return cpu_idle();
}
/*
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) {
__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 : {
__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 : {
* 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
};
-int floppy_init(void)
+int fd1772_init(void)
{
int i;
#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;
* 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; })
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
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)),
{
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) {
#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)
*/
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;
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
break;
case RESTORE_POINTERS:
+ if (msglen != 1)
+ goto unrecognised;
+
/*
* Restore current data pointer from SAVED data pointer
*/
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);
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);
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)
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)
}
/* 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
* structure as *SCpntp2.
*/
static void fas216_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2,
- int result)
+ int result, int no_report)
{
Scsi_Cmnd *SCpnt = *SCpntp1;
*SCpntp1 = NULL;
SCpnt->result = result;
- SCpnt->scsi_done(SCpnt);
+ if (!no_report || SCpnt != *SCpntp2)
+ SCpnt->scsi_done(SCpnt);
}
if (SCpnt == *SCpntp2)
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");
/*
* 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) {
/*
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;
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 */
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)
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);
#ifdef CONFIG_MD_BOOT
md_setup_drive();
#endif
+ return 0;
}
+__initcall(device_setup);
+
#ifdef CONFIG_PROC_FS
int get_partition_list(char * page)
{
* 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
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)
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;
(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);
}
}
#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;
}
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 = {
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 */
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
/*
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
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
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
* 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>
#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.
int init_module(void)
{
- return adb_mouse_init();
+ return adb_mouse_init();
}
void cleanup_module(void)
{
- misc_deregister(&adb_mouse);
+ unregister_busmouse(msedev);
}
+
#endif
* 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>
#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)
{
unsigned short joy0dat, potgor;
+#if 0
if(!mouseint_allowed)
return;
AMI_MSE_INT_OFF();
+#endif
/*
* This routine assumes, just like Kickstart, that the mouse
(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
}
/*
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;
}
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)
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
void cleanup_module(void)
{
- misc_deregister(&amiga_mouse);
+ unregsiter_busmouse(msedev);
}
#endif
* 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;
| (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;
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]);
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;
}
void cleanup_module(void)
{
- misc_deregister(&atari_mouse);
+ unregister_busmouse(msedev);
}
#endif
* 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
*/
#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)
{
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;
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;
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
void cleanup_module(void)
{
- misc_deregister(&atixl_mouse);
+ unregister_busmouse(msedev);
}
#endif
/*
- * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
* 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>
#include <linux/selection.h>
#include <linux/kmod.h>
+#include "busmouse.h"
+
/*
* Head entry for the doubly linked miscdevice 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
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)
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
#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",
*
* 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
*/
#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>
#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
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;
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;
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
void cleanup_module(void)
{
- misc_deregister(&ms_bus_mouse);
+ unregister_busmouse(msedev);
release_region(MS_MSE_CONTROL_PORT, 0x04);
}
#endif
#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 */
-/* 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 */
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>
#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");
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
*/
-/* 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. */
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 {
};
/* 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];
};
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. */
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. */
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, };
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);
\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. */
/* 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;
for (; pci_index < 8; pci_index++) {
unsigned char pci_bus, pci_device_fn, pci_latency;
+ u32 pciaddr;
long ioaddr;
int irq;
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);
} 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));
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) {
/* 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);
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);
}
#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)
dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = &speedo_ioctl;
- return;
+ return dev;
}
\f
/* Serial EEPROM section.
#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);
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;
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;
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:
}
#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
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
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)
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
#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;
}
{
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;
mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]);
#endif
}
-#endif
sp->stats.tx_errors++;
dev->trans_start = jiffies;
return;
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);
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;
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
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++;
}
}
#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) {
dev->name, inw(ioaddr + SCBStatus));
dev->interrupt = 0;
- spin_unlock(&sp->lock);
+ clear_bit(0, (void*)&sp->in_interrupt);
return;
}
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
/* '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;
}
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) {
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;
}
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);
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++) {
}
/* 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;
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;
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;
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;
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));
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. */
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);
}
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) {
*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;
}
}
/* 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;
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) {
/* 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;
/* 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);
\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);
\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
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
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)
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
/* 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,
#else
const unsigned char *buf = buffer;
size_t written;
- int ctl = parport_read_control (port) & ~PARPORT_CONTROL_AUTOFD;
int retry;
port = port->physport;
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;
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,
goto success;
if (signal_pending (current)) {
- parport_write_control (port, ctl);
+ parport_frob_control (port,
+ PARPORT_CONTROL_STROBE,
+ 0);
break;
}
}
/* 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;
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,
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;
/* 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. */
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");
#else
const unsigned char *buf = buffer;
size_t written;
- int ctl = parport_read_control (port) | PARPORT_CONTROL_AUTOFD;
int retry;
port = port->physport;
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;
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,
goto success;
if (signal_pending (current)) {
- parport_write_control (port, ctl);
+ parport_frob_control (port,
+ PARPORT_CONTROL_STROBE,
+ 0);
break;
}
}
/* 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;
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,
/*
* 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;
* 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;
* 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;
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;
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;
/* 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;
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;
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;
#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));
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;
* 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;
#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;
* 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;
/* --- 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;
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)
/* --- 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;
if (!parport_SPP_supported (p)) {
/* No port. */
kfree (priv);
- return 0;
+ return NULL;
}
parport_PS2_supported (p);
PARPORT_DMA_NONE, ops))) {
kfree (priv);
kfree (ops);
- return 0;
+ return NULL;
}
p->base_hi = base_hi;
#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)
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, "
know about it. */
parport_announce_port (p);
- return 1;
+ return p;
}
/* Look for PCI parallel port cards. */
{ 0, }
};
+ struct pci_dev *pcidev;
int count = 0;
int i;
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) {
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 };
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
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
--- /dev/null
+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
*
* 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 ||
(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,
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();
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
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;
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 {
tmp = bus_to_virt(tmp->link & ~0xF);
} while (1);
-
if (!status)
return USB_ST_NOERROR;
if (!inuse) {
td->inuse = 1;
+ td->dev=uhci_to_usb(dev);
return(td);
}
static void uhci_td_deallocate(struct uhci_td *td)
{
td->link = 1;
-
clear_bit(0, &td->inuse);
}
}
+/*
+ * 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..
*
int ret;
int maxsze = usb_maxpacket(usb_dev, pipe);
+
if (len > maxsze * 29)
printk("Warning, too much data for a control packet, crashing\n");
}
/* 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 */
}
} 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;
usb_dev->hcpriv = dev;
dev->usb = usb_dev;
-
usb_dev->parent = parent;
if (parent) {
uhci_bulk_msg,
uhci_request_irq,
uhci_release_irq,
+ uhci_request_bulk,
+ uhci_terminate_bulk,
uhci_allocate_isochronous,
uhci_delete_isochronous,
uhci_schedule_isochronous,
return;
dev = usb_dev->hcpriv;
-
dev->uhci = uhci;
-
usb_connect(usb_dev);
root_hub->usb->children[nr] = usb_dev;
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;
}
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)
}
#endif
+
#if 0
printk("maxpacketsize: %d\n", dev->descriptor.bMaxPacketSize0);
#endif
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)
{
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);
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 **);
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
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
* 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
}
-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();
}
#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)
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)
{
}
#endif
-int __init init_misc_binfmt(void)
+static int __init init_misc_binfmt(void)
{
int error = -ENOENT;
struct proc_dir_entry *status = NULL, *reg;
goto out;
}
+__initcall(init_misc_binfmt);
+
#ifdef MODULE
EXPORT_NO_SYMBOLS;
int init_module(void)
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)
{
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;
--- /dev/null
+/*
+ * 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) */
* 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;
reg += 1;
}
hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
- hw->irq = *irq;
+ hw->irq = irq;
}
/*
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
}
#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
--- /dev/null
+/*
+ * 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) */
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))
--- /dev/null
+/*
+ * 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
} 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);
#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 *
****************/
return __phys_to_virt(ptr);
}
-
/****************
* PTE functions *
****************/
#define __S110 PAGE_SHARED
#define __S111 PAGE_SHARED
-
-
#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT)
/*
#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);
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))
/*
* 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 {
#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) \
/*
* 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)
* 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
{
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... */
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);
* 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)
*/
};
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 \
}
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)
{ _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 }, \
* `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
#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))
#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) \
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)
{
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]);
}
* 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)
#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
{
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);
}
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
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)
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);
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++;
}
}
}
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 *);
#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"
+++ /dev/null
-#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
-
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);
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);
--- /dev/null
+#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
+
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
#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 *);
PROC_BUS_PCI_DEVICES,
PROC_BUS_ZORRO,
PROC_BUS_ZORRO_DEVICES,
+ PROC_BUS_ECARD_DEVICES,
PROC_BUS_LAST
};
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);
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
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
*/
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;
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 },
{ "hdn", 0x5840 },
{ "hdo", 0x5900 },
{ "hdp", 0x5940 },
-#endif
-#ifdef CONFIG_BLK_DEV_SD
{ "sda", 0x0800 },
{ "sdb", 0x0810 },
{ "sdc", 0x0820 },
{ "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 }
};
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;
}
((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
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;
extern void setup_arch(char **, unsigned long *, unsigned long *);
-extern int cpu_idle(void * unused);
+extern int cpu_idle(void);
#ifndef __SMP__
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
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
/* 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. */
else mount_initrd =0;
#endif
- /* Set up devices .. */
- device_setup();
-
- /* .. executable formats .. */
- binfmt_setup();
-
/* .. filesystems .. */
filesystem_setup();
--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:
#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);
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];
/*
* 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);
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:
* 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;
reserved = x+1;
}
}
+ return 1;
}
+
+__setup("reserve=", reserve_setup);
vma->vm_mm->rss++;
tsk->min_flt++;
+ lock_kernel();
swap_free(entry);
+ unlock_kernel();
pte = mk_pte(page_address(page), vma->vm_page_prot);
* 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;
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;
*/
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;
}
/*
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 */
__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;
}
* (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;
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;
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;
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;
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;
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;
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;
/*
* 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;
}
/* 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;
}
*/
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
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;
#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)
}
d=d->next;
}
+ return 1;
}
+__setup("ether=", eth_setup);
/*
* Create the Ethernet MAC header for an arbitrary protocol layer
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); }
}
}
+/*
+ * 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.
*/
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);
}
do_depend(filename, command);
}
+ if (len_precious) {
+ *(str_precious+len_precious) = '\0';
+ printf(".PRECIOUS:%s\n", str_precious);
+ }
return 0;
}