(2006-08-06) rescue-bootcd
This commit is contained in:
1
extra/linux-2.6.10/drivers/input/serio/.built-in.o.cmd
Normal file
1
extra/linux-2.6.10/drivers/input/serio/.built-in.o.cmd
Normal file
@@ -0,0 +1 @@
|
||||
cmd_drivers/input/serio/built-in.o := ld -m elf_i386 -r -o drivers/input/serio/built-in.o drivers/input/serio/serio.o drivers/input/serio/i8042.o
|
||||
243
extra/linux-2.6.10/drivers/input/serio/.i8042.o.cmd
Normal file
243
extra/linux-2.6.10/drivers/input/serio/.i8042.o.cmd
Normal file
@@ -0,0 +1,243 @@
|
||||
cmd_drivers/input/serio/i8042.o := gcc -Wp,-MD,drivers/input/serio/.i8042.o.d -nostdinc -iwithprefix include -D__KERNEL__ -Iinclude -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2 -fomit-frame-pointer -pipe -msoft-float -mpreferred-stack-boundary=2 -fno-unit-at-a-time -march=pentium-mmx -Iinclude/asm-i386/mach-default -Wdeclaration-after-statement -DKBUILD_BASENAME=i8042 -DKBUILD_MODNAME=i8042 -c -o drivers/input/serio/i8042.o drivers/input/serio/i8042.c
|
||||
|
||||
deps_drivers/input/serio/i8042.o := \
|
||||
drivers/input/serio/i8042.c \
|
||||
include/linux/delay.h \
|
||||
include/asm/delay.h \
|
||||
include/linux/module.h \
|
||||
$(wildcard include/config/modules.h) \
|
||||
$(wildcard include/config/modversions.h) \
|
||||
$(wildcard include/config/module/unload.h) \
|
||||
$(wildcard include/config/kallsyms.h) \
|
||||
include/linux/config.h \
|
||||
$(wildcard include/config/h.h) \
|
||||
include/linux/sched.h \
|
||||
$(wildcard include/config/keys.h) \
|
||||
$(wildcard include/config/schedstats.h) \
|
||||
$(wildcard include/config/smp.h) \
|
||||
$(wildcard include/config/numa.h) \
|
||||
$(wildcard include/config/security.h) \
|
||||
$(wildcard include/config/preempt.h) \
|
||||
$(wildcard include/config/magic/sysrq.h) \
|
||||
include/asm/param.h \
|
||||
include/linux/capability.h \
|
||||
include/linux/types.h \
|
||||
$(wildcard include/config/uid16.h) \
|
||||
include/linux/posix_types.h \
|
||||
include/linux/stddef.h \
|
||||
include/linux/compiler.h \
|
||||
include/linux/compiler-gcc3.h \
|
||||
include/linux/compiler-gcc.h \
|
||||
include/asm/posix_types.h \
|
||||
include/asm/types.h \
|
||||
$(wildcard include/config/highmem64g.h) \
|
||||
$(wildcard include/config/lbd.h) \
|
||||
include/linux/spinlock.h \
|
||||
$(wildcard include/config/debug/spinlock.h) \
|
||||
$(wildcard include/config/lockmeter.h) \
|
||||
include/linux/preempt.h \
|
||||
include/linux/linkage.h \
|
||||
include/asm/linkage.h \
|
||||
$(wildcard include/config/regparm.h) \
|
||||
$(wildcard include/config/x86/alignment/16.h) \
|
||||
include/linux/thread_info.h \
|
||||
include/linux/bitops.h \
|
||||
include/asm/bitops.h \
|
||||
include/asm/thread_info.h \
|
||||
$(wildcard include/config/4kstacks.h) \
|
||||
$(wildcard include/config/debug/stack/usage.h) \
|
||||
include/asm/page.h \
|
||||
$(wildcard include/config/x86/use/3dnow.h) \
|
||||
$(wildcard include/config/x86/pae.h) \
|
||||
$(wildcard include/config/hugetlb/page.h) \
|
||||
$(wildcard include/config/highmem4g.h) \
|
||||
$(wildcard include/config/discontigmem.h) \
|
||||
include/asm/processor.h \
|
||||
$(wildcard include/config/mk8.h) \
|
||||
$(wildcard include/config/mk7.h) \
|
||||
include/asm/vm86.h \
|
||||
include/asm/math_emu.h \
|
||||
include/asm/sigcontext.h \
|
||||
include/asm/segment.h \
|
||||
include/asm/cpufeature.h \
|
||||
include/asm/msr.h \
|
||||
include/asm/system.h \
|
||||
$(wildcard include/config/x86/cmpxchg.h) \
|
||||
$(wildcard include/config/x86/oostore.h) \
|
||||
include/linux/kernel.h \
|
||||
$(wildcard include/config/debug/spinlock/sleep.h) \
|
||||
/usr/lib/gcc/i686-pc-linux-gnu/3.4.1/include/stdarg.h \
|
||||
include/asm/byteorder.h \
|
||||
$(wildcard include/config/x86/bswap.h) \
|
||||
include/linux/byteorder/little_endian.h \
|
||||
include/linux/byteorder/swab.h \
|
||||
include/linux/byteorder/generic.h \
|
||||
include/asm/bug.h \
|
||||
include/asm-generic/bug.h \
|
||||
include/linux/cache.h \
|
||||
include/asm/cache.h \
|
||||
$(wildcard include/config/x86/l1/cache/shift.h) \
|
||||
include/linux/threads.h \
|
||||
$(wildcard include/config/nr/cpus.h) \
|
||||
include/asm/percpu.h \
|
||||
include/asm-generic/percpu.h \
|
||||
include/linux/stringify.h \
|
||||
include/linux/timex.h \
|
||||
$(wildcard include/config/time/interpolation.h) \
|
||||
include/linux/time.h \
|
||||
include/linux/seqlock.h \
|
||||
include/asm/timex.h \
|
||||
$(wildcard include/config/x86/elan.h) \
|
||||
$(wildcard include/config/x86/tsc.h) \
|
||||
$(wildcard include/config/x86/generic.h) \
|
||||
include/linux/jiffies.h \
|
||||
include/asm/div64.h \
|
||||
include/linux/rbtree.h \
|
||||
include/linux/cpumask.h \
|
||||
$(wildcard include/config/hotplug/cpu.h) \
|
||||
include/linux/bitmap.h \
|
||||
include/linux/string.h \
|
||||
include/asm/string.h \
|
||||
include/asm/semaphore.h \
|
||||
include/asm/atomic.h \
|
||||
$(wildcard include/config/m386.h) \
|
||||
include/linux/wait.h \
|
||||
include/linux/list.h \
|
||||
include/linux/prefetch.h \
|
||||
include/asm/current.h \
|
||||
include/linux/rwsem.h \
|
||||
$(wildcard include/config/rwsem/generic/spinlock.h) \
|
||||
include/asm/rwsem.h \
|
||||
include/asm/ptrace.h \
|
||||
$(wildcard include/config/frame/pointer.h) \
|
||||
include/asm/mmu.h \
|
||||
include/linux/smp.h \
|
||||
include/linux/sem.h \
|
||||
$(wildcard include/config/sysvipc.h) \
|
||||
include/linux/ipc.h \
|
||||
include/asm/ipcbuf.h \
|
||||
include/asm/sembuf.h \
|
||||
include/linux/signal.h \
|
||||
include/asm/signal.h \
|
||||
include/asm/siginfo.h \
|
||||
include/asm-generic/siginfo.h \
|
||||
include/linux/resource.h \
|
||||
include/asm/resource.h \
|
||||
include/linux/securebits.h \
|
||||
include/linux/fs_struct.h \
|
||||
include/linux/completion.h \
|
||||
include/linux/pid.h \
|
||||
include/linux/percpu.h \
|
||||
include/linux/slab.h \
|
||||
$(wildcard include/config/.h) \
|
||||
include/linux/gfp.h \
|
||||
include/linux/mmzone.h \
|
||||
$(wildcard include/config/force/max/zoneorder.h) \
|
||||
include/linux/numa.h \
|
||||
include/linux/topology.h \
|
||||
$(wildcard include/config/sched/smt.h) \
|
||||
include/asm/topology.h \
|
||||
include/asm-generic/topology.h \
|
||||
include/linux/init.h \
|
||||
$(wildcard include/config/hotplug.h) \
|
||||
include/linux/kmalloc_sizes.h \
|
||||
$(wildcard include/config/mmu.h) \
|
||||
$(wildcard include/config/large/allocs.h) \
|
||||
include/linux/param.h \
|
||||
include/linux/timer.h \
|
||||
include/linux/aio.h \
|
||||
include/linux/workqueue.h \
|
||||
include/linux/aio_abi.h \
|
||||
include/linux/stat.h \
|
||||
include/asm/stat.h \
|
||||
include/linux/kmod.h \
|
||||
$(wildcard include/config/kmod.h) \
|
||||
include/linux/errno.h \
|
||||
include/asm/errno.h \
|
||||
include/asm-generic/errno.h \
|
||||
include/asm-generic/errno-base.h \
|
||||
include/linux/elf.h \
|
||||
include/asm/elf.h \
|
||||
include/asm/user.h \
|
||||
include/linux/utsname.h \
|
||||
include/linux/kobject.h \
|
||||
include/linux/sysfs.h \
|
||||
$(wildcard include/config/sysfs.h) \
|
||||
include/linux/kref.h \
|
||||
include/linux/kobject_uevent.h \
|
||||
$(wildcard include/config/kobject/uevent.h) \
|
||||
include/linux/moduleparam.h \
|
||||
include/asm/local.h \
|
||||
include/asm/module.h \
|
||||
$(wildcard include/config/m486.h) \
|
||||
$(wildcard include/config/m586.h) \
|
||||
$(wildcard include/config/m586tsc.h) \
|
||||
$(wildcard include/config/m586mmx.h) \
|
||||
$(wildcard include/config/m686.h) \
|
||||
$(wildcard include/config/mpentiumii.h) \
|
||||
$(wildcard include/config/mpentiumiii.h) \
|
||||
$(wildcard include/config/mpentiumm.h) \
|
||||
$(wildcard include/config/mpentium4.h) \
|
||||
$(wildcard include/config/mk6.h) \
|
||||
$(wildcard include/config/mcrusoe.h) \
|
||||
$(wildcard include/config/mefficeon.h) \
|
||||
$(wildcard include/config/mwinchipc6.h) \
|
||||
$(wildcard include/config/mwinchip2.h) \
|
||||
$(wildcard include/config/mwinchip3d.h) \
|
||||
$(wildcard include/config/mcyrixiii.h) \
|
||||
$(wildcard include/config/mviac3/2.h) \
|
||||
include/linux/interrupt.h \
|
||||
$(wildcard include/config/generic/hardirqs.h) \
|
||||
$(wildcard include/config/generic/irq/probe.h) \
|
||||
include/linux/hardirq.h \
|
||||
include/linux/smp_lock.h \
|
||||
$(wildcard include/config/lock/kernel.h) \
|
||||
include/asm/hardirq.h \
|
||||
include/linux/irq.h \
|
||||
$(wildcard include/config/arch/s390.h) \
|
||||
include/asm/irq.h \
|
||||
$(wildcard include/config/x86/local/apic.h) \
|
||||
$(wildcard include/config/irqbalance.h) \
|
||||
include/asm-i386/mach-default/irq_vectors.h \
|
||||
include/asm-i386/mach-default/irq_vectors_limits.h \
|
||||
$(wildcard include/config/pci/msi.h) \
|
||||
$(wildcard include/config/x86/io/apic.h) \
|
||||
include/asm/hw_irq.h \
|
||||
include/linux/profile.h \
|
||||
$(wildcard include/config/proc/fs.h) \
|
||||
$(wildcard include/config/profiling.h) \
|
||||
include/asm/sections.h \
|
||||
include/asm-generic/sections.h \
|
||||
include/linux/irq_cpustat.h \
|
||||
include/linux/ioport.h \
|
||||
include/linux/reboot.h \
|
||||
include/linux/notifier.h \
|
||||
include/linux/sysdev.h \
|
||||
include/linux/pm.h \
|
||||
$(wildcard include/config/pm.h) \
|
||||
include/linux/serio.h \
|
||||
include/linux/ioctl.h \
|
||||
include/asm/ioctl.h \
|
||||
include/linux/device.h \
|
||||
include/linux/err.h \
|
||||
include/asm/io.h \
|
||||
$(wildcard include/config/x86/ppro/fence.h) \
|
||||
$(wildcard include/config/x86/numaq.h) \
|
||||
include/asm-generic/iomap.h \
|
||||
include/linux/vmalloc.h \
|
||||
drivers/input/serio/i8042.h \
|
||||
$(wildcard include/config/mips/jazz.h) \
|
||||
$(wildcard include/config/sgi/ip22.h) \
|
||||
$(wildcard include/config/ppc.h) \
|
||||
$(wildcard include/config/sparc32.h) \
|
||||
$(wildcard include/config/sparc64.h) \
|
||||
drivers/input/serio/i8042-io.h \
|
||||
$(wildcard include/config/superh64.h) \
|
||||
$(wildcard include/config/ppc64.h) \
|
||||
include/linux/dmi.h \
|
||||
$(wildcard include/config/x86.h) \
|
||||
$(wildcard include/config/x86/64.h) \
|
||||
|
||||
drivers/input/serio/i8042.o: $(deps_drivers/input/serio/i8042.o)
|
||||
|
||||
$(deps_drivers/input/serio/i8042.o):
|
||||
231
extra/linux-2.6.10/drivers/input/serio/.serio.o.cmd
Normal file
231
extra/linux-2.6.10/drivers/input/serio/.serio.o.cmd
Normal file
@@ -0,0 +1,231 @@
|
||||
cmd_drivers/input/serio/serio.o := gcc -Wp,-MD,drivers/input/serio/.serio.o.d -nostdinc -iwithprefix include -D__KERNEL__ -Iinclude -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2 -fomit-frame-pointer -pipe -msoft-float -mpreferred-stack-boundary=2 -fno-unit-at-a-time -march=pentium-mmx -Iinclude/asm-i386/mach-default -Wdeclaration-after-statement -DKBUILD_BASENAME=serio -DKBUILD_MODNAME=serio -c -o drivers/input/serio/serio.o drivers/input/serio/serio.c
|
||||
|
||||
deps_drivers/input/serio/serio.o := \
|
||||
drivers/input/serio/serio.c \
|
||||
include/linux/stddef.h \
|
||||
include/linux/compiler.h \
|
||||
include/linux/compiler-gcc3.h \
|
||||
include/linux/compiler-gcc.h \
|
||||
include/linux/module.h \
|
||||
$(wildcard include/config/modules.h) \
|
||||
$(wildcard include/config/modversions.h) \
|
||||
$(wildcard include/config/module/unload.h) \
|
||||
$(wildcard include/config/kallsyms.h) \
|
||||
include/linux/config.h \
|
||||
$(wildcard include/config/h.h) \
|
||||
include/linux/sched.h \
|
||||
$(wildcard include/config/keys.h) \
|
||||
$(wildcard include/config/schedstats.h) \
|
||||
$(wildcard include/config/smp.h) \
|
||||
$(wildcard include/config/numa.h) \
|
||||
$(wildcard include/config/security.h) \
|
||||
$(wildcard include/config/preempt.h) \
|
||||
$(wildcard include/config/magic/sysrq.h) \
|
||||
include/asm/param.h \
|
||||
include/linux/capability.h \
|
||||
include/linux/types.h \
|
||||
$(wildcard include/config/uid16.h) \
|
||||
include/linux/posix_types.h \
|
||||
include/asm/posix_types.h \
|
||||
include/asm/types.h \
|
||||
$(wildcard include/config/highmem64g.h) \
|
||||
$(wildcard include/config/lbd.h) \
|
||||
include/linux/spinlock.h \
|
||||
$(wildcard include/config/debug/spinlock.h) \
|
||||
$(wildcard include/config/lockmeter.h) \
|
||||
include/linux/preempt.h \
|
||||
include/linux/linkage.h \
|
||||
include/asm/linkage.h \
|
||||
$(wildcard include/config/regparm.h) \
|
||||
$(wildcard include/config/x86/alignment/16.h) \
|
||||
include/linux/thread_info.h \
|
||||
include/linux/bitops.h \
|
||||
include/asm/bitops.h \
|
||||
include/asm/thread_info.h \
|
||||
$(wildcard include/config/4kstacks.h) \
|
||||
$(wildcard include/config/debug/stack/usage.h) \
|
||||
include/asm/page.h \
|
||||
$(wildcard include/config/x86/use/3dnow.h) \
|
||||
$(wildcard include/config/x86/pae.h) \
|
||||
$(wildcard include/config/hugetlb/page.h) \
|
||||
$(wildcard include/config/highmem4g.h) \
|
||||
$(wildcard include/config/discontigmem.h) \
|
||||
include/asm/processor.h \
|
||||
$(wildcard include/config/mk8.h) \
|
||||
$(wildcard include/config/mk7.h) \
|
||||
include/asm/vm86.h \
|
||||
include/asm/math_emu.h \
|
||||
include/asm/sigcontext.h \
|
||||
include/asm/segment.h \
|
||||
include/asm/cpufeature.h \
|
||||
include/asm/msr.h \
|
||||
include/asm/system.h \
|
||||
$(wildcard include/config/x86/cmpxchg.h) \
|
||||
$(wildcard include/config/x86/oostore.h) \
|
||||
include/linux/kernel.h \
|
||||
$(wildcard include/config/debug/spinlock/sleep.h) \
|
||||
/usr/lib/gcc/i686-pc-linux-gnu/3.4.1/include/stdarg.h \
|
||||
include/asm/byteorder.h \
|
||||
$(wildcard include/config/x86/bswap.h) \
|
||||
include/linux/byteorder/little_endian.h \
|
||||
include/linux/byteorder/swab.h \
|
||||
include/linux/byteorder/generic.h \
|
||||
include/asm/bug.h \
|
||||
include/asm-generic/bug.h \
|
||||
include/linux/cache.h \
|
||||
include/asm/cache.h \
|
||||
$(wildcard include/config/x86/l1/cache/shift.h) \
|
||||
include/linux/threads.h \
|
||||
$(wildcard include/config/nr/cpus.h) \
|
||||
include/asm/percpu.h \
|
||||
include/asm-generic/percpu.h \
|
||||
include/linux/stringify.h \
|
||||
include/linux/timex.h \
|
||||
$(wildcard include/config/time/interpolation.h) \
|
||||
include/linux/time.h \
|
||||
include/linux/seqlock.h \
|
||||
include/asm/timex.h \
|
||||
$(wildcard include/config/x86/elan.h) \
|
||||
$(wildcard include/config/x86/tsc.h) \
|
||||
$(wildcard include/config/x86/generic.h) \
|
||||
include/linux/jiffies.h \
|
||||
include/asm/div64.h \
|
||||
include/linux/rbtree.h \
|
||||
include/linux/cpumask.h \
|
||||
$(wildcard include/config/hotplug/cpu.h) \
|
||||
include/linux/bitmap.h \
|
||||
include/linux/string.h \
|
||||
include/asm/string.h \
|
||||
include/asm/semaphore.h \
|
||||
include/asm/atomic.h \
|
||||
$(wildcard include/config/m386.h) \
|
||||
include/linux/wait.h \
|
||||
include/linux/list.h \
|
||||
include/linux/prefetch.h \
|
||||
include/asm/current.h \
|
||||
include/linux/rwsem.h \
|
||||
$(wildcard include/config/rwsem/generic/spinlock.h) \
|
||||
include/asm/rwsem.h \
|
||||
include/asm/ptrace.h \
|
||||
$(wildcard include/config/frame/pointer.h) \
|
||||
include/asm/mmu.h \
|
||||
include/linux/smp.h \
|
||||
include/linux/sem.h \
|
||||
$(wildcard include/config/sysvipc.h) \
|
||||
include/linux/ipc.h \
|
||||
include/asm/ipcbuf.h \
|
||||
include/asm/sembuf.h \
|
||||
include/linux/signal.h \
|
||||
include/asm/signal.h \
|
||||
include/asm/siginfo.h \
|
||||
include/asm-generic/siginfo.h \
|
||||
include/linux/resource.h \
|
||||
include/asm/resource.h \
|
||||
include/linux/securebits.h \
|
||||
include/linux/fs_struct.h \
|
||||
include/linux/completion.h \
|
||||
include/linux/pid.h \
|
||||
include/linux/percpu.h \
|
||||
include/linux/slab.h \
|
||||
$(wildcard include/config/.h) \
|
||||
include/linux/gfp.h \
|
||||
include/linux/mmzone.h \
|
||||
$(wildcard include/config/force/max/zoneorder.h) \
|
||||
include/linux/numa.h \
|
||||
include/linux/topology.h \
|
||||
$(wildcard include/config/sched/smt.h) \
|
||||
include/asm/topology.h \
|
||||
include/asm-generic/topology.h \
|
||||
include/linux/init.h \
|
||||
$(wildcard include/config/hotplug.h) \
|
||||
include/linux/kmalloc_sizes.h \
|
||||
$(wildcard include/config/mmu.h) \
|
||||
$(wildcard include/config/large/allocs.h) \
|
||||
include/linux/param.h \
|
||||
include/linux/timer.h \
|
||||
include/linux/aio.h \
|
||||
include/linux/workqueue.h \
|
||||
include/linux/aio_abi.h \
|
||||
include/linux/stat.h \
|
||||
include/asm/stat.h \
|
||||
include/linux/kmod.h \
|
||||
$(wildcard include/config/kmod.h) \
|
||||
include/linux/errno.h \
|
||||
include/asm/errno.h \
|
||||
include/asm-generic/errno.h \
|
||||
include/asm-generic/errno-base.h \
|
||||
include/linux/elf.h \
|
||||
include/asm/elf.h \
|
||||
include/asm/user.h \
|
||||
include/linux/utsname.h \
|
||||
include/linux/kobject.h \
|
||||
include/linux/sysfs.h \
|
||||
$(wildcard include/config/sysfs.h) \
|
||||
include/linux/kref.h \
|
||||
include/linux/kobject_uevent.h \
|
||||
$(wildcard include/config/kobject/uevent.h) \
|
||||
include/linux/moduleparam.h \
|
||||
include/asm/local.h \
|
||||
include/asm/module.h \
|
||||
$(wildcard include/config/m486.h) \
|
||||
$(wildcard include/config/m586.h) \
|
||||
$(wildcard include/config/m586tsc.h) \
|
||||
$(wildcard include/config/m586mmx.h) \
|
||||
$(wildcard include/config/m686.h) \
|
||||
$(wildcard include/config/mpentiumii.h) \
|
||||
$(wildcard include/config/mpentiumiii.h) \
|
||||
$(wildcard include/config/mpentiumm.h) \
|
||||
$(wildcard include/config/mpentium4.h) \
|
||||
$(wildcard include/config/mk6.h) \
|
||||
$(wildcard include/config/mcrusoe.h) \
|
||||
$(wildcard include/config/mefficeon.h) \
|
||||
$(wildcard include/config/mwinchipc6.h) \
|
||||
$(wildcard include/config/mwinchip2.h) \
|
||||
$(wildcard include/config/mwinchip3d.h) \
|
||||
$(wildcard include/config/mcyrixiii.h) \
|
||||
$(wildcard include/config/mviac3/2.h) \
|
||||
include/linux/serio.h \
|
||||
include/linux/ioctl.h \
|
||||
include/asm/ioctl.h \
|
||||
include/linux/interrupt.h \
|
||||
$(wildcard include/config/generic/hardirqs.h) \
|
||||
$(wildcard include/config/generic/irq/probe.h) \
|
||||
include/linux/hardirq.h \
|
||||
include/linux/smp_lock.h \
|
||||
$(wildcard include/config/lock/kernel.h) \
|
||||
include/asm/hardirq.h \
|
||||
include/linux/irq.h \
|
||||
$(wildcard include/config/arch/s390.h) \
|
||||
include/asm/irq.h \
|
||||
$(wildcard include/config/x86/local/apic.h) \
|
||||
$(wildcard include/config/irqbalance.h) \
|
||||
include/asm-i386/mach-default/irq_vectors.h \
|
||||
include/asm-i386/mach-default/irq_vectors_limits.h \
|
||||
$(wildcard include/config/pci/msi.h) \
|
||||
$(wildcard include/config/x86/io/apic.h) \
|
||||
include/asm/hw_irq.h \
|
||||
include/linux/profile.h \
|
||||
$(wildcard include/config/proc/fs.h) \
|
||||
$(wildcard include/config/profiling.h) \
|
||||
include/asm/sections.h \
|
||||
include/asm-generic/sections.h \
|
||||
include/linux/irq_cpustat.h \
|
||||
include/linux/device.h \
|
||||
include/linux/ioport.h \
|
||||
include/linux/pm.h \
|
||||
$(wildcard include/config/pm.h) \
|
||||
include/linux/suspend.h \
|
||||
$(wildcard include/config/x86.h) \
|
||||
$(wildcard include/config/software/suspend.h) \
|
||||
include/asm/suspend.h \
|
||||
$(wildcard include/config/acpi/sleep.h) \
|
||||
include/asm/desc.h \
|
||||
include/asm/ldt.h \
|
||||
include/asm/i387.h \
|
||||
include/linux/swap.h \
|
||||
$(wildcard include/config/swap.h) \
|
||||
include/linux/notifier.h \
|
||||
|
||||
drivers/input/serio/serio.o: $(deps_drivers/input/serio/serio.o)
|
||||
|
||||
$(deps_drivers/input/serio/serio.o):
|
||||
148
extra/linux-2.6.10/drivers/input/serio/Kconfig
Normal file
148
extra/linux-2.6.10/drivers/input/serio/Kconfig
Normal file
@@ -0,0 +1,148 @@
|
||||
#
|
||||
# Input core configuration
|
||||
#
|
||||
config SERIO
|
||||
tristate "Serial i/o support" if EMBEDDED || !X86
|
||||
default y
|
||||
---help---
|
||||
Say Yes here if you have any input device that uses serial I/O to
|
||||
communicate with the system. This includes the
|
||||
* standard AT keyboard and PS/2 mouse *
|
||||
as well as serial mice, Sun keyboards, some joysticks and 6dof
|
||||
devices and more.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called serio.
|
||||
|
||||
config SERIO_I8042
|
||||
tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
|
||||
default y
|
||||
select SERIO
|
||||
depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K
|
||||
---help---
|
||||
i8042 is the chip over which the standard AT keyboard and PS/2
|
||||
mouse are connected to the computer. If you use these devices,
|
||||
you'll need to say Y here.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called i8042.
|
||||
|
||||
config SERIO_SERPORT
|
||||
tristate "Serial port line discipline"
|
||||
default y
|
||||
depends on SERIO
|
||||
---help---
|
||||
Say Y here if you plan to use an input device (mouse, joystick,
|
||||
tablet, 6dof) that communicates over the RS232 serial (COM) port.
|
||||
|
||||
More information is available: <file:Documentation/input/input.txt>
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called serport.
|
||||
|
||||
config SERIO_CT82C710
|
||||
tristate "ct82c710 Aux port controller"
|
||||
depends on SERIO
|
||||
depends on !PARISC
|
||||
---help---
|
||||
Say Y here if you have a Texas Instruments TravelMate notebook
|
||||
equipped with the ct82c710 chip and want to use a mouse connected
|
||||
to the "QuickPort".
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ct82c710.
|
||||
|
||||
config SERIO_Q40KBD
|
||||
tristate "Q40 keyboard controller"
|
||||
depends on Q40 && SERIO
|
||||
|
||||
config SERIO_PARKBD
|
||||
tristate "Parallel port keyboard adapter"
|
||||
depends on SERIO && PARPORT
|
||||
---help---
|
||||
Say Y here if you built a simple parallel port adapter to attach
|
||||
an additional AT keyboard, XT keyboard or PS/2 mouse.
|
||||
|
||||
More information is available: <file:Documentation/input/input.txt>
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called parkbd.
|
||||
|
||||
config SERIO_RPCKBD
|
||||
tristate "Acorn RiscPC keyboard controller"
|
||||
depends on (ARCH_ACORN || ARCH_CLPS7500) && SERIO
|
||||
default y
|
||||
help
|
||||
Say Y here if you have the Acorn RiscPC and want to use an AT
|
||||
keyboard connected to its keyboard controller.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called rpckbd.
|
||||
|
||||
config SERIO_AMBAKMI
|
||||
tristate "AMBA KMI keyboard controller"
|
||||
depends on ARM_AMBA && SERIO
|
||||
|
||||
config SERIO_SA1111
|
||||
tristate "Intel SA1111 keyboard controller"
|
||||
depends on SA1111 && SERIO
|
||||
|
||||
config SERIO_GSCPS2
|
||||
tristate "HP GSC PS/2 keyboard and PS/2 mouse controller"
|
||||
depends on GSC && SERIO
|
||||
default y
|
||||
help
|
||||
This driver provides support for the PS/2 ports on PA-RISC machines
|
||||
over which HP PS/2 keyboards and PS/2 mice may be connected.
|
||||
If you use these devices, you'll need to say Y here.
|
||||
|
||||
It's safe to enable this driver, so if unsure, say Y.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called gscps2.
|
||||
|
||||
config SERIO_PCIPS2
|
||||
tristate "PCI PS/2 keyboard and PS/2 mouse controller"
|
||||
depends on PCI && SERIO
|
||||
help
|
||||
Say Y here if you have a Mobility Docking station with PS/2
|
||||
keyboard and mice ports.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called pcips2.
|
||||
|
||||
config SERIO_MACEPS2
|
||||
tristate "SGI O2 MACE PS/2 controller"
|
||||
depends on SGI_IP32 && SERIO
|
||||
help
|
||||
Say Y here if you have SGI O2 workstation and want to use its
|
||||
PS/2 ports.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called maceps2.
|
||||
|
||||
config SERIO_RAW
|
||||
tristate "Raw access to serio ports"
|
||||
depends on SERIO
|
||||
help
|
||||
Say Y here if you want to have raw access to serio ports, such as
|
||||
AUX ports on i8042 keyboard controller. Each serio port that is
|
||||
bound to this driver will be accessible via a char device with
|
||||
major 10 and dynamically allocated minor. The driver will try
|
||||
allocating minor 1 (that historically corresponds to /dev/psaux)
|
||||
first. To bind this driver to a serio port use sysfs interface:
|
||||
|
||||
echo -n "serio_raw" > /sys/bus/serio/devices/serioX/driver
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called serio_raw.
|
||||
20
extra/linux-2.6.10/drivers/input/serio/Makefile
Normal file
20
extra/linux-2.6.10/drivers/input/serio/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Makefile for the input core drivers.
|
||||
#
|
||||
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-$(CONFIG_SERIO) += serio.o
|
||||
obj-$(CONFIG_SERIO_I8042) += i8042.o
|
||||
obj-$(CONFIG_SERIO_PARKBD) += parkbd.o
|
||||
obj-$(CONFIG_SERIO_SERPORT) += serport.o
|
||||
obj-$(CONFIG_SERIO_CT82C710) += ct82c710.o
|
||||
obj-$(CONFIG_SERIO_RPCKBD) += rpckbd.o
|
||||
obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o
|
||||
obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o
|
||||
obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o
|
||||
obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o
|
||||
obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o
|
||||
obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o
|
||||
obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o
|
||||
obj-$(CONFIG_SERIO_RAW) += serio_raw.o
|
||||
231
extra/linux-2.6.10/drivers/input/serio/ambakmi.c
Normal file
231
extra/linux-2.6.10/drivers/input/serio/ambakmi.c
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* linux/drivers/input/serio/ambakmi.c
|
||||
*
|
||||
* Copyright (C) 2000-2003 Deep Blue Solutions Ltd.
|
||||
* Copyright (C) 2002 Russell King.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/hardware/amba.h>
|
||||
#include <asm/hardware/amba_kmi.h>
|
||||
#include <asm/hardware/clock.h>
|
||||
|
||||
#define KMI_BASE (kmi->base)
|
||||
|
||||
struct amba_kmi_port {
|
||||
struct serio *io;
|
||||
struct clk *clk;
|
||||
unsigned char *base;
|
||||
unsigned int irq;
|
||||
unsigned int divisor;
|
||||
unsigned int open;
|
||||
};
|
||||
|
||||
static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct amba_kmi_port *kmi = dev_id;
|
||||
unsigned int status = readb(KMIIR);
|
||||
int handled = IRQ_NONE;
|
||||
|
||||
while (status & KMIIR_RXINTR) {
|
||||
serio_interrupt(kmi->io, readb(KMIDATA), 0, regs);
|
||||
status = readb(KMIIR);
|
||||
handled = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
static int amba_kmi_write(struct serio *io, unsigned char val)
|
||||
{
|
||||
struct amba_kmi_port *kmi = io->port_data;
|
||||
unsigned int timeleft = 10000; /* timeout in 100ms */
|
||||
|
||||
while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--)
|
||||
udelay(10);
|
||||
|
||||
if (timeleft)
|
||||
writeb(val, KMIDATA);
|
||||
|
||||
return timeleft ? 0 : SERIO_TIMEOUT;
|
||||
}
|
||||
|
||||
static int amba_kmi_open(struct serio *io)
|
||||
{
|
||||
struct amba_kmi_port *kmi = io->port_data;
|
||||
unsigned int divisor;
|
||||
int ret;
|
||||
|
||||
ret = clk_use(kmi->clk);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = clk_enable(kmi->clk);
|
||||
if (ret)
|
||||
goto clk_unuse;
|
||||
|
||||
divisor = clk_get_rate(kmi->clk) / 8000000 - 1;
|
||||
writeb(divisor, KMICLKDIV);
|
||||
writeb(KMICR_EN, KMICR);
|
||||
|
||||
ret = request_irq(kmi->irq, amba_kmi_int, 0, "kmi-pl050", kmi);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq);
|
||||
writeb(0, KMICR);
|
||||
goto clk_disable;
|
||||
}
|
||||
|
||||
writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
|
||||
|
||||
return 0;
|
||||
|
||||
clk_disable:
|
||||
clk_disable(kmi->clk);
|
||||
clk_unuse:
|
||||
clk_unuse(kmi->clk);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void amba_kmi_close(struct serio *io)
|
||||
{
|
||||
struct amba_kmi_port *kmi = io->port_data;
|
||||
|
||||
writeb(0, KMICR);
|
||||
|
||||
free_irq(kmi->irq, kmi);
|
||||
clk_disable(kmi->clk);
|
||||
clk_unuse(kmi->clk);
|
||||
}
|
||||
|
||||
static int amba_kmi_probe(struct amba_device *dev, void *id)
|
||||
{
|
||||
struct amba_kmi_port *kmi;
|
||||
struct serio *io;
|
||||
int ret;
|
||||
|
||||
ret = amba_request_regions(dev, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
kmi = kmalloc(sizeof(struct amba_kmi_port), GFP_KERNEL);
|
||||
io = kmalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (!kmi || !io) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(kmi, 0, sizeof(struct amba_kmi_port));
|
||||
memset(io, 0, sizeof(struct serio));
|
||||
|
||||
io->type = SERIO_8042;
|
||||
io->write = amba_kmi_write;
|
||||
io->open = amba_kmi_open;
|
||||
io->close = amba_kmi_close;
|
||||
strlcpy(io->name, dev->dev.bus_id, sizeof(io->name));
|
||||
strlcpy(io->phys, dev->dev.bus_id, sizeof(io->phys));
|
||||
io->port_data = kmi;
|
||||
io->dev.parent = &dev->dev;
|
||||
|
||||
kmi->io = io;
|
||||
kmi->base = ioremap(dev->res.start, KMI_SIZE);
|
||||
if (!kmi->base) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
kmi->clk = clk_get(&dev->dev, "KMIREFCLK");
|
||||
if (IS_ERR(kmi->clk)) {
|
||||
ret = PTR_ERR(kmi->clk);
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
kmi->irq = dev->irq[0];
|
||||
amba_set_drvdata(dev, kmi);
|
||||
|
||||
serio_register_port(kmi->io);
|
||||
return 0;
|
||||
|
||||
unmap:
|
||||
iounmap(kmi->base);
|
||||
out:
|
||||
kfree(kmi);
|
||||
kfree(io);
|
||||
amba_release_regions(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int amba_kmi_remove(struct amba_device *dev)
|
||||
{
|
||||
struct amba_kmi_port *kmi = amba_get_drvdata(dev);
|
||||
|
||||
amba_set_drvdata(dev, NULL);
|
||||
|
||||
serio_unregister_port(kmi->io);
|
||||
clk_put(kmi->clk);
|
||||
iounmap(kmi->base);
|
||||
kfree(kmi);
|
||||
amba_release_regions(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amba_kmi_resume(struct amba_device *dev)
|
||||
{
|
||||
struct amba_kmi_port *kmi = amba_get_drvdata(dev);
|
||||
|
||||
/* kick the serio layer to rescan this port */
|
||||
serio_reconnect(kmi->io);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct amba_id amba_kmi_idtable[] = {
|
||||
{
|
||||
.id = 0x00041050,
|
||||
.mask = 0x000fffff,
|
||||
},
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static struct amba_driver ambakmi_driver = {
|
||||
.drv = {
|
||||
.name = "kmi-pl050",
|
||||
},
|
||||
.id_table = amba_kmi_idtable,
|
||||
.probe = amba_kmi_probe,
|
||||
.remove = amba_kmi_remove,
|
||||
.resume = amba_kmi_resume,
|
||||
};
|
||||
|
||||
static int __init amba_kmi_init(void)
|
||||
{
|
||||
return amba_driver_register(&ambakmi_driver);
|
||||
}
|
||||
|
||||
static void __exit amba_kmi_exit(void)
|
||||
{
|
||||
amba_driver_unregister(&ambakmi_driver);
|
||||
}
|
||||
|
||||
module_init(amba_kmi_init);
|
||||
module_exit(amba_kmi_exit);
|
||||
|
||||
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
|
||||
MODULE_DESCRIPTION("AMBA KMI controller driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
BIN
extra/linux-2.6.10/drivers/input/serio/built-in.o
Normal file
BIN
extra/linux-2.6.10/drivers/input/serio/built-in.o
Normal file
Binary file not shown.
225
extra/linux-2.6.10/drivers/input/serio/ct82c710.c
Normal file
225
extra/linux-2.6.10/drivers/input/serio/ct82c710.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* $Id: ct82c710.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
|
||||
*
|
||||
* Copyright (c) 1999-2001 Vojtech Pavlik
|
||||
*/
|
||||
|
||||
/*
|
||||
* 82C710 C&T mouse port chip driver for Linux
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
||||
MODULE_DESCRIPTION("82C710 C&T mouse port chip driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
* ct82c710 interface
|
||||
*/
|
||||
|
||||
#define CT82C710_DEV_IDLE 0x01 /* Device Idle */
|
||||
#define CT82C710_RX_FULL 0x02 /* Device Char received */
|
||||
#define CT82C710_TX_IDLE 0x04 /* Device XMIT Idle */
|
||||
#define CT82C710_RESET 0x08 /* Device Reset */
|
||||
#define CT82C710_INTS_ON 0x10 /* Device Interrupt On */
|
||||
#define CT82C710_ERROR_FLAG 0x20 /* Device Error */
|
||||
#define CT82C710_CLEAR 0x40 /* Device Clear */
|
||||
#define CT82C710_ENABLE 0x80 /* Device Enable */
|
||||
|
||||
#define CT82C710_IRQ 12
|
||||
|
||||
#define CT82C710_DATA ct82c710_iores.start
|
||||
#define CT82C710_STATUS (ct82c710_iores.start + 1)
|
||||
|
||||
static struct serio *ct82c710_port;
|
||||
static struct platform_device *ct82c710_device;
|
||||
static struct resource ct82c710_iores;
|
||||
|
||||
/*
|
||||
* Interrupt handler for the 82C710 mouse port. A character
|
||||
* is waiting in the 82C710.
|
||||
*/
|
||||
|
||||
static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
|
||||
{
|
||||
return serio_interrupt(ct82c710_port, inb(CT82C710_DATA), 0, regs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for device to send output char and flush any input char.
|
||||
*/
|
||||
|
||||
static int ct82c170_wait(void)
|
||||
{
|
||||
int timeout = 60000;
|
||||
|
||||
while ((inb(CT82C710_STATUS) & (CT82C710_RX_FULL | CT82C710_TX_IDLE | CT82C710_DEV_IDLE))
|
||||
!= (CT82C710_DEV_IDLE | CT82C710_TX_IDLE) && timeout) {
|
||||
|
||||
if (inb_p(CT82C710_STATUS) & CT82C710_RX_FULL) inb_p(CT82C710_DATA);
|
||||
|
||||
udelay(1);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
return !timeout;
|
||||
}
|
||||
|
||||
static void ct82c710_close(struct serio *serio)
|
||||
{
|
||||
if (ct82c170_wait())
|
||||
printk(KERN_WARNING "ct82c710.c: Device busy in close()\n");
|
||||
|
||||
outb_p(inb_p(CT82C710_STATUS) & ~(CT82C710_ENABLE | CT82C710_INTS_ON), CT82C710_STATUS);
|
||||
|
||||
if (ct82c170_wait())
|
||||
printk(KERN_WARNING "ct82c710.c: Device busy in close()\n");
|
||||
|
||||
free_irq(CT82C710_IRQ, NULL);
|
||||
}
|
||||
|
||||
static int ct82c710_open(struct serio *serio)
|
||||
{
|
||||
unsigned char status;
|
||||
|
||||
if (request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL))
|
||||
return -1;
|
||||
|
||||
status = inb_p(CT82C710_STATUS);
|
||||
|
||||
status |= (CT82C710_ENABLE | CT82C710_RESET);
|
||||
outb_p(status, CT82C710_STATUS);
|
||||
|
||||
status &= ~(CT82C710_RESET);
|
||||
outb_p(status, CT82C710_STATUS);
|
||||
|
||||
status |= CT82C710_INTS_ON;
|
||||
outb_p(status, CT82C710_STATUS); /* Enable interrupts */
|
||||
|
||||
while (ct82c170_wait()) {
|
||||
printk(KERN_ERR "ct82c710: Device busy in open()\n");
|
||||
status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON);
|
||||
outb_p(status, CT82C710_STATUS);
|
||||
free_irq(CT82C710_IRQ, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to the 82C710 mouse device.
|
||||
*/
|
||||
|
||||
static int ct82c710_write(struct serio *port, unsigned char c)
|
||||
{
|
||||
if (ct82c170_wait()) return -1;
|
||||
outb_p(c, CT82C710_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we can find a 82C710 device. Read mouse address.
|
||||
*/
|
||||
|
||||
static int __init ct82c710_probe(void)
|
||||
{
|
||||
outb_p(0x55, 0x2fa); /* Any value except 9, ff or 36 */
|
||||
outb_p(0xaa, 0x3fa); /* Inverse of 55 */
|
||||
outb_p(0x36, 0x3fa); /* Address the chip */
|
||||
outb_p(0xe4, 0x3fa); /* 390/4; 390 = config address */
|
||||
outb_p(0x1b, 0x2fa); /* Inverse of e4 */
|
||||
outb_p(0x0f, 0x390); /* Write index */
|
||||
if (inb_p(0x391) != 0xe4) /* Config address found? */
|
||||
return -1; /* No: no 82C710 here */
|
||||
|
||||
outb_p(0x0d, 0x390); /* Write index */
|
||||
ct82c710_iores.start = inb_p(0x391) << 2; /* Get mouse I/O address */
|
||||
ct82c710_iores.end = ct82c710_iores.start + 1;
|
||||
ct82c710_iores.flags = IORESOURCE_IO;
|
||||
outb_p(0x0f, 0x390);
|
||||
outb_p(0x0f, 0x391); /* Close config mode */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct serio * __init ct82c710_allocate_port(void)
|
||||
{
|
||||
struct serio *serio;
|
||||
|
||||
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (serio) {
|
||||
memset(serio, 0, sizeof(struct serio));
|
||||
serio->type = SERIO_8042;
|
||||
serio->open = ct82c710_open;
|
||||
serio->close = ct82c710_close;
|
||||
serio->write = ct82c710_write;
|
||||
serio->dev.parent = &ct82c710_device->dev;
|
||||
strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name));
|
||||
snprintf(serio->phys, sizeof(serio->phys), "isa%04lx/serio0", CT82C710_DATA);
|
||||
}
|
||||
|
||||
return serio;
|
||||
}
|
||||
|
||||
int __init ct82c710_init(void)
|
||||
{
|
||||
if (ct82c710_probe())
|
||||
return -ENODEV;
|
||||
|
||||
ct82c710_device = platform_device_register_simple("ct82c710", -1, &ct82c710_iores, 1);
|
||||
if (IS_ERR(ct82c710_device))
|
||||
return PTR_ERR(ct82c710_device);
|
||||
|
||||
if (!(ct82c710_port = ct82c710_allocate_port())) {
|
||||
platform_device_unregister(ct82c710_device);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
serio_register_port(ct82c710_port);
|
||||
|
||||
printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n",
|
||||
CT82C710_DATA, CT82C710_IRQ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit ct82c710_exit(void)
|
||||
{
|
||||
serio_unregister_port(ct82c710_port);
|
||||
platform_device_unregister(ct82c710_device);
|
||||
}
|
||||
|
||||
module_init(ct82c710_init);
|
||||
module_exit(ct82c710_exit);
|
||||
484
extra/linux-2.6.10/drivers/input/serio/gscps2.c
Normal file
484
extra/linux-2.6.10/drivers/input/serio/gscps2.c
Normal file
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* drivers/input/serio/gscps2.c
|
||||
*
|
||||
* Copyright (c) 2004 Helge Deller <deller@gmx.de>
|
||||
* Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
|
||||
* Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
|
||||
*
|
||||
* Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
|
||||
* Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca>
|
||||
* Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
|
||||
* Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
|
||||
* Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
|
||||
*
|
||||
* HP GSC PS/2 port driver, found in PA/RISC Workstations
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* TODO:
|
||||
* - Dino testing (did HP ever shipped a machine on which this port
|
||||
* was usable/enabled ?)
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci_ids.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/parisc-device.h>
|
||||
|
||||
MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>, Thibaut Varene <varenet@esiee.fr>, Helge Deller <deller@gmx.de>");
|
||||
MODULE_DESCRIPTION("HP GSC PS/2 port driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl);
|
||||
|
||||
#define PFX "gscps2.c: "
|
||||
|
||||
/*
|
||||
* Driver constants
|
||||
*/
|
||||
|
||||
/* various constants */
|
||||
#define ENABLE 1
|
||||
#define DISABLE 0
|
||||
|
||||
#define GSC_DINO_OFFSET 0x0800 /* offset for DINO controller versus LASI one */
|
||||
|
||||
/* PS/2 IO port offsets */
|
||||
#define GSC_ID 0x00 /* device ID offset (see: GSC_ID_XXX) */
|
||||
#define GSC_RESET 0x00 /* reset port offset */
|
||||
#define GSC_RCVDATA 0x04 /* receive port offset */
|
||||
#define GSC_XMTDATA 0x04 /* transmit port offset */
|
||||
#define GSC_CONTROL 0x08 /* see: Control register bits */
|
||||
#define GSC_STATUS 0x0C /* see: Status register bits */
|
||||
|
||||
/* Control register bits */
|
||||
#define GSC_CTRL_ENBL 0x01 /* enable interface */
|
||||
#define GSC_CTRL_LPBXR 0x02 /* loopback operation */
|
||||
#define GSC_CTRL_DIAG 0x20 /* directly control clock/data line */
|
||||
#define GSC_CTRL_DATDIR 0x40 /* data line direct control */
|
||||
#define GSC_CTRL_CLKDIR 0x80 /* clock line direct control */
|
||||
|
||||
/* Status register bits */
|
||||
#define GSC_STAT_RBNE 0x01 /* Receive Buffer Not Empty */
|
||||
#define GSC_STAT_TBNE 0x02 /* Transmit Buffer Not Empty */
|
||||
#define GSC_STAT_TERR 0x04 /* Timeout Error */
|
||||
#define GSC_STAT_PERR 0x08 /* Parity Error */
|
||||
#define GSC_STAT_CMPINTR 0x10 /* Composite Interrupt = irq on any port */
|
||||
#define GSC_STAT_DATSHD 0x40 /* Data Line Shadow */
|
||||
#define GSC_STAT_CLKSHD 0x80 /* Clock Line Shadow */
|
||||
|
||||
/* IDs returned by GSC_ID port register */
|
||||
#define GSC_ID_KEYBOARD 0 /* device ID values */
|
||||
#define GSC_ID_MOUSE 1
|
||||
|
||||
|
||||
static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs);
|
||||
|
||||
#define BUFFER_SIZE 0x0f
|
||||
|
||||
/* GSC PS/2 port device struct */
|
||||
struct gscps2port {
|
||||
struct list_head node;
|
||||
struct parisc_device *padev;
|
||||
struct serio *port;
|
||||
spinlock_t lock;
|
||||
char *addr;
|
||||
u8 act, append; /* position in buffer[] */
|
||||
struct {
|
||||
u8 data;
|
||||
u8 str;
|
||||
} buffer[BUFFER_SIZE+1];
|
||||
int id;
|
||||
};
|
||||
|
||||
/*
|
||||
* Various HW level routines
|
||||
*/
|
||||
|
||||
#define gscps2_readb_input(x) readb((x)+GSC_RCVDATA)
|
||||
#define gscps2_readb_control(x) readb((x)+GSC_CONTROL)
|
||||
#define gscps2_readb_status(x) readb((x)+GSC_STATUS)
|
||||
#define gscps2_writeb_control(x, y) writeb((x), (y)+GSC_CONTROL)
|
||||
|
||||
|
||||
/*
|
||||
* wait_TBE() - wait for Transmit Buffer Empty
|
||||
*/
|
||||
|
||||
static int wait_TBE(char *addr)
|
||||
{
|
||||
int timeout = 25000; /* device is expected to react within 250 msec */
|
||||
while (gscps2_readb_status(addr) & GSC_STAT_TBNE) {
|
||||
if (!--timeout)
|
||||
return 0; /* This should not happen */
|
||||
udelay(10);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* gscps2_flush() - flush the receive buffer
|
||||
*/
|
||||
|
||||
static void gscps2_flush(struct gscps2port *ps2port)
|
||||
{
|
||||
while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE)
|
||||
gscps2_readb_input(ps2port->addr);
|
||||
ps2port->act = ps2port->append = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* gscps2_writeb_output() - write a byte to the port
|
||||
*
|
||||
* returns 1 on sucess, 0 on error
|
||||
*/
|
||||
|
||||
static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data)
|
||||
{
|
||||
unsigned long flags;
|
||||
char *addr = ps2port->addr;
|
||||
|
||||
if (!wait_TBE(addr)) {
|
||||
printk(KERN_DEBUG PFX "timeout - could not write byte %#x\n", data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE)
|
||||
/* wait */;
|
||||
|
||||
spin_lock_irqsave(&ps2port->lock, flags);
|
||||
writeb(data, addr+GSC_XMTDATA);
|
||||
spin_unlock_irqrestore(&ps2port->lock, flags);
|
||||
|
||||
/* this is ugly, but due to timing of the port it seems to be necessary. */
|
||||
mdelay(6);
|
||||
|
||||
/* make sure any received data is returned as fast as possible */
|
||||
/* this is important e.g. when we set the LEDs on the keyboard */
|
||||
gscps2_interrupt(0, NULL, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* gscps2_enable() - enables or disables the port
|
||||
*/
|
||||
|
||||
static void gscps2_enable(struct gscps2port *ps2port, int enable)
|
||||
{
|
||||
unsigned long flags;
|
||||
u8 data;
|
||||
|
||||
/* now enable/disable the port */
|
||||
spin_lock_irqsave(&ps2port->lock, flags);
|
||||
gscps2_flush(ps2port);
|
||||
data = gscps2_readb_control(ps2port->addr);
|
||||
if (enable)
|
||||
data |= GSC_CTRL_ENBL;
|
||||
else
|
||||
data &= ~GSC_CTRL_ENBL;
|
||||
gscps2_writeb_control(data, ps2port->addr);
|
||||
spin_unlock_irqrestore(&ps2port->lock, flags);
|
||||
wait_TBE(ps2port->addr);
|
||||
gscps2_flush(ps2port);
|
||||
}
|
||||
|
||||
/*
|
||||
* gscps2_reset() - resets the PS/2 port
|
||||
*/
|
||||
|
||||
static void gscps2_reset(struct gscps2port *ps2port)
|
||||
{
|
||||
char *addr = ps2port->addr;
|
||||
unsigned long flags;
|
||||
|
||||
/* reset the interface */
|
||||
spin_lock_irqsave(&ps2port->lock, flags);
|
||||
gscps2_flush(ps2port);
|
||||
writeb(0xff, addr+GSC_RESET);
|
||||
gscps2_flush(ps2port);
|
||||
spin_unlock_irqrestore(&ps2port->lock, flags);
|
||||
|
||||
/* enable it */
|
||||
gscps2_enable(ps2port, ENABLE);
|
||||
}
|
||||
|
||||
static LIST_HEAD(ps2port_list);
|
||||
|
||||
/**
|
||||
* gscps2_interrupt() - Interruption service routine
|
||||
*
|
||||
* This function reads received PS/2 bytes and processes them on
|
||||
* all interfaces.
|
||||
* The problematic part here is, that the keyboard and mouse PS/2 port
|
||||
* share the same interrupt and it's not possible to send data if any
|
||||
* one of them holds input data. To solve this problem we try to receive
|
||||
* the data as fast as possible and handle the reporting to the upper layer
|
||||
* later.
|
||||
*/
|
||||
|
||||
static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
|
||||
{
|
||||
struct gscps2port *ps2port;
|
||||
|
||||
list_for_each_entry(ps2port, &ps2port_list, node) {
|
||||
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&ps2port->lock, flags);
|
||||
|
||||
while ( (ps2port->buffer[ps2port->append].str =
|
||||
gscps2_readb_status(ps2port->addr)) & GSC_STAT_RBNE ) {
|
||||
ps2port->buffer[ps2port->append].data =
|
||||
gscps2_readb_input(ps2port->addr);
|
||||
ps2port->append = ((ps2port->append+1) & BUFFER_SIZE);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ps2port->lock, flags);
|
||||
|
||||
} /* list_for_each_entry */
|
||||
|
||||
/* all data was read from the ports - now report the data to upper layer */
|
||||
|
||||
list_for_each_entry(ps2port, &ps2port_list, node) {
|
||||
|
||||
while (ps2port->act != ps2port->append) {
|
||||
|
||||
unsigned int rxflags;
|
||||
u8 data, status;
|
||||
|
||||
/* Did new data arrived while we read existing data ?
|
||||
If yes, exit now and let the new irq handler start over again */
|
||||
if (gscps2_readb_status(ps2port->addr) & GSC_STAT_CMPINTR)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
status = ps2port->buffer[ps2port->act].str;
|
||||
data = ps2port->buffer[ps2port->act].data;
|
||||
|
||||
ps2port->act = ((ps2port->act+1) & BUFFER_SIZE);
|
||||
rxflags = ((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) |
|
||||
((status & GSC_STAT_PERR) ? SERIO_PARITY : 0 );
|
||||
|
||||
serio_interrupt(ps2port->port, data, rxflags, regs);
|
||||
|
||||
} /* while() */
|
||||
|
||||
} /* list_for_each_entry */
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* gscps2_write() - send a byte out through the aux interface.
|
||||
*/
|
||||
|
||||
static int gscps2_write(struct serio *port, unsigned char data)
|
||||
{
|
||||
struct gscps2port *ps2port = port->port_data;
|
||||
|
||||
if (!gscps2_writeb_output(ps2port, data)) {
|
||||
printk(KERN_DEBUG PFX "sending byte %#x failed.\n", data);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* gscps2_open() is called when a port is opened by the higher layer.
|
||||
* It resets and enables the port.
|
||||
*/
|
||||
|
||||
static int gscps2_open(struct serio *port)
|
||||
{
|
||||
struct gscps2port *ps2port = port->port_data;
|
||||
|
||||
gscps2_reset(ps2port);
|
||||
|
||||
gscps2_interrupt(0, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* gscps2_close() disables the port
|
||||
*/
|
||||
|
||||
static void gscps2_close(struct serio *port)
|
||||
{
|
||||
struct gscps2port *ps2port = port->port_data;
|
||||
gscps2_enable(ps2port, DISABLE);
|
||||
}
|
||||
|
||||
static struct serio gscps2_serio_port =
|
||||
{
|
||||
.name = "GSC PS/2",
|
||||
.idbus = BUS_GSC,
|
||||
.idvendor = PCI_VENDOR_ID_HP,
|
||||
.idproduct = 0x0001,
|
||||
.idversion = 0x0010,
|
||||
.type = SERIO_8042,
|
||||
.write = gscps2_write,
|
||||
.open = gscps2_open,
|
||||
.close = gscps2_close,
|
||||
};
|
||||
|
||||
/**
|
||||
* gscps2_probe() - Probes PS2 devices
|
||||
* @return: success/error report
|
||||
*/
|
||||
|
||||
static int __init gscps2_probe(struct parisc_device *dev)
|
||||
{
|
||||
struct gscps2port *ps2port;
|
||||
struct serio *serio;
|
||||
unsigned long hpa = dev->hpa;
|
||||
int ret;
|
||||
|
||||
if (!dev->irq)
|
||||
return -ENODEV;
|
||||
|
||||
/* Offset for DINO PS/2. Works with LASI even */
|
||||
if (dev->id.sversion == 0x96)
|
||||
hpa += GSC_DINO_OFFSET;
|
||||
|
||||
ps2port = kmalloc(sizeof(struct gscps2port), GFP_KERNEL);
|
||||
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (!ps2port || !serio) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_nomem;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&dev->dev, ps2port);
|
||||
|
||||
memset(ps2port, 0, sizeof(struct gscps2port));
|
||||
memset(serio, 0, sizeof(struct serio));
|
||||
ps2port->port = serio;
|
||||
ps2port->padev = dev;
|
||||
ps2port->addr = ioremap(hpa, GSC_STATUS + 4);
|
||||
spin_lock_init(&ps2port->lock);
|
||||
|
||||
gscps2_reset(ps2port);
|
||||
ps2port->id = readb(ps2port->addr + GSC_ID) & 0x0f;
|
||||
|
||||
snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s",
|
||||
(ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse");
|
||||
strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
|
||||
serio->idbus = BUS_GSC;
|
||||
serio->idvendor = PCI_VENDOR_ID_HP;
|
||||
serio->idproduct = 0x0001;
|
||||
serio->idversion = 0x0010;
|
||||
serio->type = SERIO_8042;
|
||||
serio->write = gscps2_write;
|
||||
serio->open = gscps2_open;
|
||||
serio->close = gscps2_close;
|
||||
serio->port_data = ps2port;
|
||||
serio->dev.parent = &dev->dev;
|
||||
|
||||
list_add_tail(&ps2port->node, &ps2port_list);
|
||||
|
||||
ret = -EBUSY;
|
||||
if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->port->name, ps2port))
|
||||
goto fail_miserably;
|
||||
|
||||
if (ps2port->id != GSC_ID_KEYBOARD && ps2port->id != GSC_ID_MOUSE) {
|
||||
printk(KERN_WARNING PFX "Unsupported PS/2 port at 0x%08lx (id=%d) ignored\n",
|
||||
hpa, ps2port->id);
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (!request_mem_region(hpa, GSC_STATUS + 4, ps2port->port.name))
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
printk(KERN_INFO "serio: %s port at 0x%p irq %d @ %s\n",
|
||||
ps2port->port->name,
|
||||
ps2port->addr,
|
||||
ps2port->padev->irq,
|
||||
ps2port->port->phys);
|
||||
|
||||
serio_register_port(ps2port->port);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
free_irq(dev->irq, ps2port);
|
||||
|
||||
fail_miserably:
|
||||
list_del(&ps2port->node);
|
||||
iounmap(ps2port->addr);
|
||||
release_mem_region(dev->hpa, GSC_STATUS + 4);
|
||||
|
||||
fail_nomem:
|
||||
kfree(ps2port);
|
||||
kfree(serio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gscps2_remove() - Removes PS2 devices
|
||||
* @return: success/error report
|
||||
*/
|
||||
|
||||
static int __devexit gscps2_remove(struct parisc_device *dev)
|
||||
{
|
||||
struct gscps2port *ps2port = dev_get_drvdata(&dev->dev);
|
||||
|
||||
serio_unregister_port(ps2port->port);
|
||||
free_irq(dev->irq, ps2port);
|
||||
gscps2_flush(ps2port);
|
||||
list_del(&ps2port->node);
|
||||
iounmap(ps2port->addr);
|
||||
#if 0
|
||||
release_mem_region(dev->hpa, GSC_STATUS + 4);
|
||||
#endif
|
||||
dev_set_drvdata(&dev->dev, NULL);
|
||||
kfree(ps2port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct parisc_device_id gscps2_device_tbl[] = {
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, /* LASI PS/2 */
|
||||
#ifdef DINO_TESTED
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 }, /* DINO PS/2 */
|
||||
#endif
|
||||
{ 0, } /* 0 terminated list */
|
||||
};
|
||||
|
||||
static struct parisc_driver parisc_ps2_driver = {
|
||||
.name = "GSC PS/2",
|
||||
.id_table = gscps2_device_tbl,
|
||||
.probe = gscps2_probe,
|
||||
.remove = gscps2_remove,
|
||||
};
|
||||
|
||||
static int __init gscps2_init(void)
|
||||
{
|
||||
register_parisc_driver(&parisc_ps2_driver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit gscps2_exit(void)
|
||||
{
|
||||
unregister_parisc_driver(&parisc_ps2_driver);
|
||||
}
|
||||
|
||||
|
||||
module_init(gscps2_init);
|
||||
module_exit(gscps2_exit);
|
||||
|
||||
130
extra/linux-2.6.10/drivers/input/serio/i8042-io.h
Normal file
130
extra/linux-2.6.10/drivers/input/serio/i8042-io.h
Normal file
@@ -0,0 +1,130 @@
|
||||
#ifndef _I8042_IO_H
|
||||
#define _I8042_IO_H
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Names.
|
||||
*/
|
||||
|
||||
#define I8042_KBD_PHYS_DESC "isa0060/serio0"
|
||||
#define I8042_AUX_PHYS_DESC "isa0060/serio1"
|
||||
#define I8042_MUX_PHYS_DESC "isa0060/serio%d"
|
||||
|
||||
/*
|
||||
* IRQs.
|
||||
*/
|
||||
|
||||
#ifdef __alpha__
|
||||
# define I8042_KBD_IRQ 1
|
||||
# define I8042_AUX_IRQ (RTC_PORT(0) == 0x170 ? 9 : 12) /* Jensen is special */
|
||||
#elif defined(__ia64__)
|
||||
# define I8042_KBD_IRQ isa_irq_to_vector(1)
|
||||
# define I8042_AUX_IRQ isa_irq_to_vector(12)
|
||||
#elif defined(__arm__)
|
||||
/* defined in include/asm-arm/arch-xxx/irqs.h */
|
||||
#include <asm/irq.h>
|
||||
#elif defined(CONFIG_SUPERH64)
|
||||
#include <asm/irq.h>
|
||||
#else
|
||||
# define I8042_KBD_IRQ 1
|
||||
# define I8042_AUX_IRQ 12
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Register numbers.
|
||||
*/
|
||||
|
||||
#define I8042_COMMAND_REG 0x64
|
||||
#define I8042_STATUS_REG 0x64
|
||||
#define I8042_DATA_REG 0x60
|
||||
|
||||
static inline int i8042_read_data(void)
|
||||
{
|
||||
return inb(I8042_DATA_REG);
|
||||
}
|
||||
|
||||
static inline int i8042_read_status(void)
|
||||
{
|
||||
return inb(I8042_STATUS_REG);
|
||||
}
|
||||
|
||||
static inline void i8042_write_data(int val)
|
||||
{
|
||||
outb(val, I8042_DATA_REG);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void i8042_write_command(int val)
|
||||
{
|
||||
outb(val, I8042_COMMAND_REG);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(__i386__)
|
||||
|
||||
#include <linux/dmi.h>
|
||||
|
||||
static struct dmi_system_id __initdata i8042_dmi_table[] = {
|
||||
{
|
||||
.ident = "Compaq Proliant 8500",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "8500"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Compaq Proliant DL760",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
#endif
|
||||
|
||||
static inline int i8042_platform_init(void)
|
||||
{
|
||||
/*
|
||||
* On ix86 platforms touching the i8042 data register region can do really
|
||||
* bad things. Because of this the region is always reserved on ix86 boxes.
|
||||
*/
|
||||
#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(__mips__) && !defined (CONFIG_PPC64)
|
||||
if (!request_region(I8042_DATA_REG, 16, "i8042"))
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#if !defined(__i386__) && !defined(__x86_64__)
|
||||
i8042_reset = 1;
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
if (dmi_check_system(i8042_dmi_table))
|
||||
i8042_noloop = 1;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PPC64)
|
||||
if (check_legacy_ioport(I8042_DATA_REG))
|
||||
return -1;
|
||||
if (!request_region(I8042_DATA_REG, 16, "i8042"))
|
||||
return -1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void i8042_platform_exit(void)
|
||||
{
|
||||
#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(CONFIG_PPC64)
|
||||
release_region(I8042_DATA_REG, 16);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _I8042_IO_H */
|
||||
76
extra/linux-2.6.10/drivers/input/serio/i8042-ip22io.h
Normal file
76
extra/linux-2.6.10/drivers/input/serio/i8042-ip22io.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef _I8042_IP22_H
|
||||
#define _I8042_IP22_H
|
||||
|
||||
#include <asm/sgi/ioc.h>
|
||||
#include <asm/sgi/ip22.h>
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Names.
|
||||
*/
|
||||
|
||||
#define I8042_KBD_PHYS_DESC "hpc3ps2/serio0"
|
||||
#define I8042_AUX_PHYS_DESC "hpc3ps2/serio1"
|
||||
#define I8042_MUX_PHYS_DESC "hpc3ps2/serio%d"
|
||||
|
||||
/*
|
||||
* IRQs.
|
||||
*/
|
||||
|
||||
#define I8042_KBD_IRQ SGI_KEYBD_IRQ
|
||||
#define I8042_AUX_IRQ SGI_KEYBD_IRQ
|
||||
|
||||
/*
|
||||
* Register numbers.
|
||||
*/
|
||||
|
||||
#define I8042_COMMAND_REG ((unsigned long)&sgioc->kbdmouse.command)
|
||||
#define I8042_STATUS_REG ((unsigned long)&sgioc->kbdmouse.command)
|
||||
#define I8042_DATA_REG ((unsigned long)&sgioc->kbdmouse.data)
|
||||
|
||||
static inline int i8042_read_data(void)
|
||||
{
|
||||
return sgioc->kbdmouse.data;
|
||||
}
|
||||
|
||||
static inline int i8042_read_status(void)
|
||||
{
|
||||
return sgioc->kbdmouse.command;
|
||||
}
|
||||
|
||||
static inline void i8042_write_data(int val)
|
||||
{
|
||||
sgioc->kbdmouse.data = val;
|
||||
}
|
||||
|
||||
static inline void i8042_write_command(int val)
|
||||
{
|
||||
sgioc->kbdmouse.command = val;
|
||||
}
|
||||
|
||||
static inline int i8042_platform_init(void)
|
||||
{
|
||||
#if 0
|
||||
/* XXX sgi_kh is a virtual address */
|
||||
if (!request_mem_region(sgi_kh, sizeof(struct hpc_keyb), "i8042"))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
i8042_reset = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void i8042_platform_exit(void)
|
||||
{
|
||||
#if 0
|
||||
release_mem_region(JAZZ_KEYBOARD_ADDRESS, sizeof(struct hpc_keyb));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _I8042_IP22_H */
|
||||
69
extra/linux-2.6.10/drivers/input/serio/i8042-jazzio.h
Normal file
69
extra/linux-2.6.10/drivers/input/serio/i8042-jazzio.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef _I8042_JAZZ_H
|
||||
#define _I8042_JAZZ_H
|
||||
|
||||
#include <asm/jazz.h>
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Names.
|
||||
*/
|
||||
|
||||
#define I8042_KBD_PHYS_DESC "R4030/serio0"
|
||||
#define I8042_AUX_PHYS_DESC "R4030/serio1"
|
||||
#define I8042_MUX_PHYS_DESC "R4030/serio%d"
|
||||
|
||||
/*
|
||||
* IRQs.
|
||||
*/
|
||||
|
||||
#define I8042_KBD_IRQ JAZZ_KEYBOARD_IRQ
|
||||
#define I8042_AUX_IRQ JAZZ_MOUSE_IRQ
|
||||
|
||||
#define I8042_COMMAND_REG ((unsigned long)&jazz_kh->command)
|
||||
#define I8042_STATUS_REG ((unsigned long)&jazz_kh->command)
|
||||
#define I8042_DATA_REG ((unsigned long)&jazz_kh->data)
|
||||
|
||||
static inline int i8042_read_data(void)
|
||||
{
|
||||
return jazz_kh->data;
|
||||
}
|
||||
|
||||
static inline int i8042_read_status(void)
|
||||
{
|
||||
return jazz_kh->command;
|
||||
}
|
||||
|
||||
static inline void i8042_write_data(int val)
|
||||
{
|
||||
jazz_kh->data = val;
|
||||
}
|
||||
|
||||
static inline void i8042_write_command(int val)
|
||||
{
|
||||
jazz_kh->command = val;
|
||||
}
|
||||
|
||||
static inline int i8042_platform_init(void)
|
||||
{
|
||||
#if 0
|
||||
/* XXX JAZZ_KEYBOARD_ADDRESS is a virtual address */
|
||||
if (!request_mem_region(JAZZ_KEYBOARD_ADDRESS, 2, "i8042"))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void i8042_platform_exit(void)
|
||||
{
|
||||
#if 0
|
||||
release_mem_region(JAZZ_KEYBOARD_ADDRESS, 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _I8042_JAZZ_H */
|
||||
136
extra/linux-2.6.10/drivers/input/serio/i8042-ppcio.h
Normal file
136
extra/linux-2.6.10/drivers/input/serio/i8042-ppcio.h
Normal file
@@ -0,0 +1,136 @@
|
||||
#ifndef _I8042_PPCIO_H
|
||||
#define _I8042_PPCIO_H
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_WALNUT)
|
||||
|
||||
#define I8042_KBD_IRQ 25
|
||||
#define I8042_AUX_IRQ 26
|
||||
|
||||
#define I8042_KBD_PHYS_DESC "walnutps2/serio0"
|
||||
#define I8042_AUX_PHYS_DESC "walnutps2/serio1"
|
||||
#define I8042_MUX_PHYS_DESC "walnutps2/serio%d"
|
||||
|
||||
extern void *kb_cs;
|
||||
extern void *kb_data;
|
||||
|
||||
#define I8042_COMMAND_REG (*(int *)kb_cs)
|
||||
#define I8042_DATA_REG (*(int *)kb_data)
|
||||
|
||||
static inline int i8042_read_data(void)
|
||||
{
|
||||
return readb(kb_data);
|
||||
}
|
||||
|
||||
static inline int i8042_read_status(void)
|
||||
{
|
||||
return readb(kb_cs);
|
||||
}
|
||||
|
||||
static inline void i8042_write_data(int val)
|
||||
{
|
||||
writeb(val, kb_data);
|
||||
}
|
||||
|
||||
static inline void i8042_write_command(int val)
|
||||
{
|
||||
writeb(val, kb_cs);
|
||||
}
|
||||
|
||||
static inline int i8042_platform_init(void)
|
||||
{
|
||||
i8042_reset = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void i8042_platform_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_SPRUCE)
|
||||
|
||||
#define I8042_KBD_IRQ 22
|
||||
#define I8042_AUX_IRQ 21
|
||||
|
||||
#define I8042_KBD_PHYS_DESC "spruceps2/serio0"
|
||||
#define I8042_AUX_PHYS_DESC "spruceps2/serio1"
|
||||
#define I8042_MUX_PHYS_DESC "spruceps2/serio%d"
|
||||
|
||||
#define I8042_COMMAND_REG 0xff810000
|
||||
#define I8042_DATA_REG 0xff810001
|
||||
|
||||
static inline int i8042_read_data(void)
|
||||
{
|
||||
unsigned long kbd_data;
|
||||
|
||||
__raw_writel(0x00000088, 0xff500008);
|
||||
eieio();
|
||||
|
||||
__raw_writel(0x03000000, 0xff50000c);
|
||||
eieio();
|
||||
|
||||
asm volatile("lis 7,0xff88 \n\
|
||||
lswi 6,7,0x8 \n\
|
||||
mr %0,6"
|
||||
: "=r" (kbd_data) :: "6", "7");
|
||||
|
||||
__raw_writel(0x00000000, 0xff50000c);
|
||||
eieio();
|
||||
|
||||
return (unsigned char)(kbd_data >> 24);
|
||||
}
|
||||
|
||||
static inline int i8042_read_status(void)
|
||||
{
|
||||
unsigned long kbd_status;
|
||||
|
||||
__raw_writel(0x00000088, 0xff500008);
|
||||
eieio();
|
||||
|
||||
__raw_writel(0x03000000, 0xff50000c);
|
||||
eieio();
|
||||
|
||||
asm volatile("lis 7,0xff88 \n\
|
||||
ori 7,7,0x8 \n\
|
||||
lswi 6,7,0x8 \n\
|
||||
mr %0,6"
|
||||
: "=r" (kbd_status) :: "6", "7");
|
||||
|
||||
__raw_writel(0x00000000, 0xff50000c);
|
||||
eieio();
|
||||
|
||||
return (unsigned char)(kbd_status >> 24);
|
||||
}
|
||||
|
||||
static inline void i8042_write_data(int val)
|
||||
{
|
||||
*((unsigned char *)0xff810000) = (char)val;
|
||||
}
|
||||
|
||||
static inline void i8042_write_command(int val)
|
||||
{
|
||||
*((unsigned char *)0xff810001) = (char)val;
|
||||
}
|
||||
|
||||
static inline int i8042_platform_init(void)
|
||||
{
|
||||
i8042_reset = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void i8042_platform_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "i8042-io.h"
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _I8042_PPCIO_H */
|
||||
116
extra/linux-2.6.10/drivers/input/serio/i8042-sparcio.h
Normal file
116
extra/linux-2.6.10/drivers/input/serio/i8042-sparcio.h
Normal file
@@ -0,0 +1,116 @@
|
||||
#ifndef _I8042_SPARCIO_H
|
||||
#define _I8042_SPARCIO_H
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
#include <asm/oplib.h>
|
||||
#include <asm/ebus.h>
|
||||
#endif
|
||||
|
||||
static int i8042_kbd_irq = -1;
|
||||
static int i8042_aux_irq = -1;
|
||||
#define I8042_KBD_IRQ i8042_kbd_irq
|
||||
#define I8042_AUX_IRQ i8042_aux_irq
|
||||
|
||||
#define I8042_KBD_PHYS_DESC "sparcps2/serio0"
|
||||
#define I8042_AUX_PHYS_DESC "sparcps2/serio1"
|
||||
#define I8042_MUX_PHYS_DESC "sparcps2/serio%d"
|
||||
|
||||
static void __iomem *kbd_iobase;
|
||||
|
||||
#define I8042_COMMAND_REG (kbd_iobase + 0x64UL)
|
||||
#define I8042_DATA_REG (kbd_iobase + 0x60UL)
|
||||
|
||||
static inline int i8042_read_data(void)
|
||||
{
|
||||
return readb(kbd_iobase + 0x60UL);
|
||||
}
|
||||
|
||||
static inline int i8042_read_status(void)
|
||||
{
|
||||
return readb(kbd_iobase + 0x64UL);
|
||||
}
|
||||
|
||||
static inline void i8042_write_data(int val)
|
||||
{
|
||||
writeb(val, kbd_iobase + 0x60UL);
|
||||
}
|
||||
|
||||
static inline void i8042_write_command(int val)
|
||||
{
|
||||
writeb(val, kbd_iobase + 0x64UL);
|
||||
}
|
||||
|
||||
#define OBP_PS2KBD_NAME1 "kb_ps2"
|
||||
#define OBP_PS2KBD_NAME2 "keyboard"
|
||||
#define OBP_PS2MS_NAME1 "kdmouse"
|
||||
#define OBP_PS2MS_NAME2 "mouse"
|
||||
|
||||
static int i8042_platform_init(void)
|
||||
{
|
||||
#ifndef CONFIG_PCI
|
||||
return -1;
|
||||
#else
|
||||
char prop[128];
|
||||
int len;
|
||||
|
||||
len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
|
||||
if (len < 0) {
|
||||
printk("i8042: Cannot get name property of root OBP node.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
|
||||
/* Hardcoded values for MrCoffee. */
|
||||
i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
|
||||
kbd_iobase = ioremap(0x71300060, 8);
|
||||
if (!kbd_iobase)
|
||||
return -1;
|
||||
} else {
|
||||
struct linux_ebus *ebus;
|
||||
struct linux_ebus_device *edev;
|
||||
struct linux_ebus_child *child;
|
||||
|
||||
for_each_ebus(ebus) {
|
||||
for_each_ebusdev(edev, ebus) {
|
||||
if (!strcmp(edev->prom_name, "8042"))
|
||||
goto edev_found;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
edev_found:
|
||||
for_each_edevchild(edev, child) {
|
||||
if (!strcmp(child->prom_name, OBP_PS2KBD_NAME1) ||
|
||||
!strcmp(child->prom_name, OBP_PS2KBD_NAME2)) {
|
||||
i8042_kbd_irq = child->irqs[0];
|
||||
kbd_iobase =
|
||||
ioremap(child->resource[0].start, 8);
|
||||
}
|
||||
if (!strcmp(child->prom_name, OBP_PS2MS_NAME1) ||
|
||||
!strcmp(child->prom_name, OBP_PS2MS_NAME2))
|
||||
i8042_aux_irq = child->irqs[0];
|
||||
}
|
||||
if (i8042_kbd_irq == -1 ||
|
||||
i8042_aux_irq == -1) {
|
||||
printk("i8042: Error, 8042 device lacks both kbd and "
|
||||
"mouse nodes.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
i8042_reset = 1;
|
||||
|
||||
return 0;
|
||||
#endif /* CONFIG_PCI */
|
||||
}
|
||||
|
||||
static inline void i8042_platform_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
iounmap(kbd_iobase);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _I8042_SPARCIO_H */
|
||||
1122
extra/linux-2.6.10/drivers/input/serio/i8042.c
Normal file
1122
extra/linux-2.6.10/drivers/input/serio/i8042.c
Normal file
File diff suppressed because it is too large
Load Diff
127
extra/linux-2.6.10/drivers/input/serio/i8042.h
Normal file
127
extra/linux-2.6.10/drivers/input/serio/i8042.h
Normal file
@@ -0,0 +1,127 @@
|
||||
#ifndef _I8042_H
|
||||
#define _I8042_H
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999-2002 Vojtech Pavlik
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Arch-dependent inline functions and defines.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_MIPS_JAZZ)
|
||||
#include "i8042-jazzio.h"
|
||||
#elif defined(CONFIG_SGI_IP22)
|
||||
#include "i8042-ip22io.h"
|
||||
#elif defined(CONFIG_PPC)
|
||||
#include "i8042-ppcio.h"
|
||||
#elif defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64)
|
||||
#include "i8042-sparcio.h"
|
||||
#else
|
||||
#include "i8042-io.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is in 50us units, the time we wait for the i8042 to react. This
|
||||
* has to be long enough for the i8042 itself to timeout on sending a byte
|
||||
* to a non-existent mouse.
|
||||
*/
|
||||
|
||||
#define I8042_CTL_TIMEOUT 10000
|
||||
|
||||
/*
|
||||
* When the device isn't opened and it's interrupts aren't used, we poll it at
|
||||
* regular intervals to see if any characters arrived. If yes, we can start
|
||||
* probing for any mouse / keyboard connected. This is the period of the
|
||||
* polling.
|
||||
*/
|
||||
|
||||
#define I8042_POLL_PERIOD HZ/20
|
||||
|
||||
/*
|
||||
* Status register bits.
|
||||
*/
|
||||
|
||||
#define I8042_STR_PARITY 0x80
|
||||
#define I8042_STR_TIMEOUT 0x40
|
||||
#define I8042_STR_AUXDATA 0x20
|
||||
#define I8042_STR_KEYLOCK 0x10
|
||||
#define I8042_STR_CMDDAT 0x08
|
||||
#define I8042_STR_MUXERR 0x04
|
||||
#define I8042_STR_IBF 0x02
|
||||
#define I8042_STR_OBF 0x01
|
||||
|
||||
/*
|
||||
* Control register bits.
|
||||
*/
|
||||
|
||||
#define I8042_CTR_KBDINT 0x01
|
||||
#define I8042_CTR_AUXINT 0x02
|
||||
#define I8042_CTR_IGNKEYLOCK 0x08
|
||||
#define I8042_CTR_KBDDIS 0x10
|
||||
#define I8042_CTR_AUXDIS 0x20
|
||||
#define I8042_CTR_XLATE 0x40
|
||||
|
||||
/*
|
||||
* Commands.
|
||||
*/
|
||||
|
||||
#define I8042_CMD_CTL_RCTR 0x0120
|
||||
#define I8042_CMD_CTL_WCTR 0x1060
|
||||
#define I8042_CMD_CTL_TEST 0x01aa
|
||||
|
||||
#define I8042_CMD_KBD_DISABLE 0x00ad
|
||||
#define I8042_CMD_KBD_ENABLE 0x00ae
|
||||
#define I8042_CMD_KBD_TEST 0x01ab
|
||||
#define I8042_CMD_KBD_LOOP 0x11d2
|
||||
|
||||
#define I8042_CMD_AUX_DISABLE 0x00a7
|
||||
#define I8042_CMD_AUX_ENABLE 0x00a8
|
||||
#define I8042_CMD_AUX_TEST 0x01a9
|
||||
#define I8042_CMD_AUX_SEND 0x10d4
|
||||
#define I8042_CMD_AUX_LOOP 0x11d3
|
||||
|
||||
#define I8042_CMD_MUX_PFX 0x0090
|
||||
#define I8042_CMD_MUX_SEND 0x1090
|
||||
|
||||
/*
|
||||
* Return codes.
|
||||
*/
|
||||
|
||||
#define I8042_RET_CTL_TEST 0x55
|
||||
|
||||
/*
|
||||
* Expected maximum internal i8042 buffer size. This is used for flushing
|
||||
* the i8042 buffers. 32 should be more than enough.
|
||||
*/
|
||||
|
||||
#define I8042_BUFFER_SIZE 32
|
||||
|
||||
/*
|
||||
* Number of AUX ports on controllers supporting active multiplexing
|
||||
* specification
|
||||
*/
|
||||
|
||||
#define I8042_NUM_MUX_PORTS 4
|
||||
|
||||
/*
|
||||
* Debug.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
static unsigned long i8042_start;
|
||||
#define dbg_init() do { i8042_start = jiffies; } while (0)
|
||||
#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format " [%d]\n" ,\
|
||||
## arg, (int) (jiffies - i8042_start))
|
||||
#else
|
||||
#define dbg_init() do { } while (0)
|
||||
#define dbg(format, arg...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* _I8042_H */
|
||||
BIN
extra/linux-2.6.10/drivers/input/serio/i8042.o
Normal file
BIN
extra/linux-2.6.10/drivers/input/serio/i8042.o
Normal file
Binary file not shown.
176
extra/linux-2.6.10/drivers/input/serio/maceps2.c
Normal file
176
extra/linux-2.6.10/drivers/input/serio/maceps2.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* SGI O2 MACE PS2 controller driver for linux
|
||||
*
|
||||
* Copyright (C) 2002 Vivien Chappelier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/ip32/mace.h>
|
||||
#include <asm/ip32/ip32_ints.h>
|
||||
|
||||
MODULE_AUTHOR("Vivien Chappelier <vivien.chappelier@linux-mips.org");
|
||||
MODULE_DESCRIPTION("SGI O2 MACE PS2 controller driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#define MACE_PS2_TIMEOUT 10000 /* in 50us unit */
|
||||
|
||||
#define PS2_STATUS_CLOCK_SIGNAL BIT(0) /* external clock signal */
|
||||
#define PS2_STATUS_CLOCK_INHIBIT BIT(1) /* clken output signal */
|
||||
#define PS2_STATUS_TX_INPROGRESS BIT(2) /* transmission in progress */
|
||||
#define PS2_STATUS_TX_EMPTY BIT(3) /* empty transmit buffer */
|
||||
#define PS2_STATUS_RX_FULL BIT(4) /* full receive buffer */
|
||||
#define PS2_STATUS_RX_INPROGRESS BIT(5) /* reception in progress */
|
||||
#define PS2_STATUS_ERROR_PARITY BIT(6) /* parity error */
|
||||
#define PS2_STATUS_ERROR_FRAMING BIT(7) /* framing error */
|
||||
|
||||
#define PS2_CONTROL_TX_CLOCK_DISABLE BIT(0) /* inhibit clock signal after TX */
|
||||
#define PS2_CONTROL_TX_ENABLE BIT(1) /* transmit enable */
|
||||
#define PS2_CONTROL_TX_INT_ENABLE BIT(2) /* enable transmit interrupt */
|
||||
#define PS2_CONTROL_RX_INT_ENABLE BIT(3) /* enable receive interrupt */
|
||||
#define PS2_CONTROL_RX_CLOCK_ENABLE BIT(4) /* pause reception if set to 0 */
|
||||
#define PS2_CONTROL_RESET BIT(5) /* reset */
|
||||
|
||||
struct maceps2_data {
|
||||
struct mace_ps2port *port;
|
||||
int irq;
|
||||
};
|
||||
|
||||
static struct maceps2_data port_data[2];
|
||||
static struct serio *maceps2_port[2];
|
||||
static struct platform_device *maceps2_device;
|
||||
|
||||
static int maceps2_write(struct serio *dev, unsigned char val)
|
||||
{
|
||||
struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
|
||||
unsigned int timeout = MACE_PS2_TIMEOUT;
|
||||
|
||||
do {
|
||||
if (mace_read(port->status) & PS2_STATUS_TX_EMPTY) {
|
||||
mace_write(val, port->tx);
|
||||
return 0;
|
||||
}
|
||||
udelay(50);
|
||||
} while (timeout--);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static irqreturn_t maceps2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct serio *dev = dev_id;
|
||||
struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
|
||||
unsigned int byte;
|
||||
|
||||
if (mace_read(port->status) & PS2_STATUS_RX_FULL) {
|
||||
byte = mace_read(port->rx);
|
||||
serio_interrupt(dev, byte & 0xff, 0, regs);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int maceps2_open(struct serio *dev)
|
||||
{
|
||||
struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
|
||||
|
||||
if (request_irq(data->irq, maceps2_interrupt, 0, "PS/2 port", dev)) {
|
||||
printk(KERN_ERR "Could not allocate PS/2 IRQ\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Reset port */
|
||||
mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET,
|
||||
data->port->control);
|
||||
udelay(100);
|
||||
|
||||
/* Enable interrupts */
|
||||
mace_write(PS2_CONTROL_RX_CLOCK_ENABLE | PS2_CONTROL_TX_ENABLE |
|
||||
PS2_CONTROL_RX_INT_ENABLE, data->port->control);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void maceps2_close(struct serio *dev)
|
||||
{
|
||||
struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
|
||||
|
||||
mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET,
|
||||
data->port->control);
|
||||
udelay(100);
|
||||
free_irq(data->irq, dev);
|
||||
}
|
||||
|
||||
|
||||
static struct serio * __init maceps2_allocate_port(int idx)
|
||||
{
|
||||
struct serio *serio;
|
||||
|
||||
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (serio) {
|
||||
memset(serio, 0, sizeof(struct serio));
|
||||
serio->type = SERIO_8042;
|
||||
serio->write = maceps2_write;
|
||||
serio->open = maceps2_open;
|
||||
serio->close = maceps2_close;
|
||||
snprintf(serio->name, sizeof(serio->name), "MACE PS/2 port%d", idx);
|
||||
snprintf(serio->phys, sizeof(serio->phys), "mace/serio%d", idx);
|
||||
serio->port_data = &port_data[idx];
|
||||
serio->dev.parent = &maceps2_device->dev;
|
||||
}
|
||||
|
||||
return serio;
|
||||
}
|
||||
|
||||
|
||||
static int __init maceps2_init(void)
|
||||
{
|
||||
maceps2_device = platform_device_register_simple("maceps2", -1, NULL, 0);
|
||||
if (IS_ERR(maceps2_device))
|
||||
return PTR_ERR(maceps2_device);
|
||||
|
||||
port_data[0].port = &mace->perif.ps2.keyb;
|
||||
port_data[0].irq = MACEISA_KEYB_IRQ;
|
||||
port_data[1].port = &mace->perif.ps2.mouse;
|
||||
port_data[1].irq = MACEISA_MOUSE_IRQ;
|
||||
|
||||
maceps2_port[0] = maceps2_allocate_port(0);
|
||||
maceps2_port[1] = maceps2_allocate_port(1);
|
||||
if (!maceps2_port[0] || !maceps2_port[1]) {
|
||||
kfree(maceps2_port[0]);
|
||||
kfree(maceps2_port[1]);
|
||||
platform_device_unregister(maceps2_device);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
serio_register_port(maceps2_port[0]);
|
||||
serio_register_port(maceps2_port[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit maceps2_exit(void)
|
||||
{
|
||||
serio_unregister_port(maceps2_port[0]);
|
||||
serio_unregister_port(maceps2_port[1]);
|
||||
platform_device_unregister(maceps2_device);
|
||||
}
|
||||
|
||||
module_init(maceps2_init);
|
||||
module_exit(maceps2_exit);
|
||||
205
extra/linux-2.6.10/drivers/input/serio/parkbd.c
Normal file
205
extra/linux-2.6.10/drivers/input/serio/parkbd.c
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* $Id: parkbd.c,v 1.10 2002/03/13 10:09:20 vojtech Exp $
|
||||
*
|
||||
* Copyright (c) 1999-2001 Vojtech Pavlik
|
||||
*/
|
||||
|
||||
/*
|
||||
* Parallel port to Keyboard port adapter driver for Linux
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/parport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serio.h>
|
||||
|
||||
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
||||
MODULE_DESCRIPTION("Parallel port to Keyboard port adapter driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
MODULE_PARM(parkbd, "1i");
|
||||
MODULE_PARM(parkbd_mode, "1i");
|
||||
|
||||
#define PARKBD_CLOCK 0x01 /* Strobe & Ack */
|
||||
#define PARKBD_DATA 0x02 /* AutoFd & Busy */
|
||||
|
||||
static int parkbd;
|
||||
static int parkbd_mode = SERIO_8042;
|
||||
|
||||
static int parkbd_buffer;
|
||||
static int parkbd_counter;
|
||||
static unsigned long parkbd_last;
|
||||
static int parkbd_writing;
|
||||
static unsigned long parkbd_start;
|
||||
|
||||
static struct pardevice *parkbd_dev;
|
||||
static struct serio *parkbd_port;
|
||||
|
||||
static int parkbd_readlines(void)
|
||||
{
|
||||
return (parport_read_status(parkbd_dev->port) >> 6) ^ 2;
|
||||
}
|
||||
|
||||
static void parkbd_writelines(int data)
|
||||
{
|
||||
parport_write_control(parkbd_dev->port, (~data & 3) | 0x10);
|
||||
}
|
||||
|
||||
static int parkbd_write(struct serio *port, unsigned char c)
|
||||
{
|
||||
unsigned char p;
|
||||
|
||||
if (!parkbd_mode) return -1;
|
||||
|
||||
p = c ^ (c >> 4);
|
||||
p = p ^ (p >> 2);
|
||||
p = p ^ (p >> 1);
|
||||
|
||||
parkbd_counter = 0;
|
||||
parkbd_writing = 1;
|
||||
parkbd_buffer = c | (((int) (~p & 1)) << 8) | 0x600;
|
||||
|
||||
parkbd_writelines(2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
|
||||
if (parkbd_writing) {
|
||||
|
||||
if (parkbd_counter && ((parkbd_counter == 11) || time_after(jiffies, parkbd_last + HZ/100))) {
|
||||
parkbd_counter = 0;
|
||||
parkbd_buffer = 0;
|
||||
parkbd_writing = 0;
|
||||
parkbd_writelines(3);
|
||||
return;
|
||||
}
|
||||
|
||||
parkbd_writelines(((parkbd_buffer >> parkbd_counter++) & 1) | 2);
|
||||
|
||||
if (parkbd_counter == 11) {
|
||||
parkbd_counter = 0;
|
||||
parkbd_buffer = 0;
|
||||
parkbd_writing = 0;
|
||||
parkbd_writelines(3);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ((parkbd_counter == parkbd_mode + 10) || time_after(jiffies, parkbd_last + HZ/100)) {
|
||||
parkbd_counter = 0;
|
||||
parkbd_buffer = 0;
|
||||
}
|
||||
|
||||
parkbd_buffer |= (parkbd_readlines() >> 1) << parkbd_counter++;
|
||||
|
||||
if (parkbd_counter == parkbd_mode + 10)
|
||||
serio_interrupt(parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs);
|
||||
}
|
||||
|
||||
parkbd_last = jiffies;
|
||||
}
|
||||
|
||||
static int parkbd_getport(void)
|
||||
{
|
||||
struct parport *pp;
|
||||
|
||||
if (parkbd < 0) {
|
||||
printk(KERN_ERR "parkbd: no port specified\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pp = parport_find_number(parkbd);
|
||||
|
||||
if (pp == NULL) {
|
||||
printk(KERN_ERR "parkbd: no such parport\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
parkbd_dev = parport_register_device(pp, "parkbd", NULL, NULL, parkbd_interrupt, PARPORT_DEV_EXCL, NULL);
|
||||
parport_put_port(pp);
|
||||
|
||||
if (!parkbd_dev)
|
||||
return -ENODEV;
|
||||
|
||||
if (parport_claim(parkbd_dev)) {
|
||||
parport_unregister_device(parkbd_dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
parkbd_start = jiffies;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct serio * __init parkbd_allocate_serio(void)
|
||||
{
|
||||
struct serio *serio;
|
||||
|
||||
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (serio) {
|
||||
memset(serio, 0, sizeof(struct serio));
|
||||
serio->type = parkbd_mode;
|
||||
serio->write = parkbd_write,
|
||||
strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
|
||||
snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
|
||||
}
|
||||
|
||||
return serio;
|
||||
}
|
||||
|
||||
int __init parkbd_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = parkbd_getport();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
parkbd_port = parkbd_allocate_serio();
|
||||
if (!parkbd_port) {
|
||||
parport_release(parkbd_dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
parkbd_writelines(3);
|
||||
|
||||
serio_register_port(parkbd_port);
|
||||
|
||||
printk(KERN_INFO "serio: PARKBD %s adapter on %s\n",
|
||||
parkbd_mode ? "AT" : "XT", parkbd_dev->port->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit parkbd_exit(void)
|
||||
{
|
||||
parport_release(parkbd_dev);
|
||||
serio_unregister_port(parkbd_port);
|
||||
parport_unregister_device(parkbd_dev);
|
||||
}
|
||||
|
||||
module_init(parkbd_init);
|
||||
module_exit(parkbd_exit);
|
||||
234
extra/linux-2.6.10/drivers/input/serio/pcips2.c
Normal file
234
extra/linux-2.6.10/drivers/input/serio/pcips2.c
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* linux/drivers/input/serio/pcips2.c
|
||||
*
|
||||
* Copyright (C) 2003 Russell King, All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License.
|
||||
*
|
||||
* I'm not sure if this is a generic PS/2 PCI interface or specific to
|
||||
* the Mobility Electronics docking station.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define PS2_CTRL (0)
|
||||
#define PS2_STATUS (1)
|
||||
#define PS2_DATA (2)
|
||||
|
||||
#define PS2_CTRL_CLK (1<<0)
|
||||
#define PS2_CTRL_DAT (1<<1)
|
||||
#define PS2_CTRL_TXIRQ (1<<2)
|
||||
#define PS2_CTRL_ENABLE (1<<3)
|
||||
#define PS2_CTRL_RXIRQ (1<<4)
|
||||
|
||||
#define PS2_STAT_CLK (1<<0)
|
||||
#define PS2_STAT_DAT (1<<1)
|
||||
#define PS2_STAT_PARITY (1<<2)
|
||||
#define PS2_STAT_RXFULL (1<<5)
|
||||
#define PS2_STAT_TXBUSY (1<<6)
|
||||
#define PS2_STAT_TXEMPTY (1<<7)
|
||||
|
||||
struct pcips2_data {
|
||||
struct serio *io;
|
||||
unsigned int base;
|
||||
struct pci_dev *dev;
|
||||
};
|
||||
|
||||
static int pcips2_write(struct serio *io, unsigned char val)
|
||||
{
|
||||
struct pcips2_data *ps2if = io->port_data;
|
||||
unsigned int stat;
|
||||
|
||||
do {
|
||||
stat = inb(ps2if->base + PS2_STATUS);
|
||||
cpu_relax();
|
||||
} while (!(stat & PS2_STAT_TXEMPTY));
|
||||
|
||||
outb(val, ps2if->base + PS2_DATA);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t pcips2_interrupt(int irq, void *devid, struct pt_regs *regs)
|
||||
{
|
||||
struct pcips2_data *ps2if = devid;
|
||||
unsigned char status, scancode;
|
||||
int handled = 0;
|
||||
|
||||
do {
|
||||
unsigned int flag;
|
||||
|
||||
status = inb(ps2if->base + PS2_STATUS);
|
||||
if (!(status & PS2_STAT_RXFULL))
|
||||
break;
|
||||
handled = 1;
|
||||
scancode = inb(ps2if->base + PS2_DATA);
|
||||
if (status == 0xff && scancode == 0xff)
|
||||
break;
|
||||
|
||||
flag = (status & PS2_STAT_PARITY) ? 0 : SERIO_PARITY;
|
||||
|
||||
if (hweight8(scancode) & 1)
|
||||
flag ^= SERIO_PARITY;
|
||||
|
||||
serio_interrupt(ps2if->io, scancode, flag, regs);
|
||||
} while (1);
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
static void pcips2_flush_input(struct pcips2_data *ps2if)
|
||||
{
|
||||
unsigned char status, scancode;
|
||||
|
||||
do {
|
||||
status = inb(ps2if->base + PS2_STATUS);
|
||||
if (!(status & PS2_STAT_RXFULL))
|
||||
break;
|
||||
scancode = inb(ps2if->base + PS2_DATA);
|
||||
if (status == 0xff && scancode == 0xff)
|
||||
break;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
static int pcips2_open(struct serio *io)
|
||||
{
|
||||
struct pcips2_data *ps2if = io->port_data;
|
||||
int ret, val = 0;
|
||||
|
||||
outb(PS2_CTRL_ENABLE, ps2if->base);
|
||||
pcips2_flush_input(ps2if);
|
||||
|
||||
ret = request_irq(ps2if->dev->irq, pcips2_interrupt, SA_SHIRQ,
|
||||
"pcips2", ps2if);
|
||||
if (ret == 0)
|
||||
val = PS2_CTRL_ENABLE | PS2_CTRL_RXIRQ;
|
||||
|
||||
outb(val, ps2if->base);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pcips2_close(struct serio *io)
|
||||
{
|
||||
struct pcips2_data *ps2if = io->port_data;
|
||||
|
||||
outb(0, ps2if->base);
|
||||
|
||||
free_irq(ps2if->dev->irq, ps2if);
|
||||
}
|
||||
|
||||
static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
struct pcips2_data *ps2if;
|
||||
struct serio *serio;
|
||||
int ret;
|
||||
|
||||
ret = pci_enable_device(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = pci_request_regions(dev, "pcips2");
|
||||
if (ret)
|
||||
goto disable;
|
||||
|
||||
ps2if = kmalloc(sizeof(struct pcips2_data), GFP_KERNEL);
|
||||
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (!ps2if || !serio) {
|
||||
ret = -ENOMEM;
|
||||
goto release;
|
||||
}
|
||||
|
||||
memset(ps2if, 0, sizeof(struct pcips2_data));
|
||||
memset(serio, 0, sizeof(struct serio));
|
||||
|
||||
serio->type = SERIO_8042;
|
||||
serio->write = pcips2_write;
|
||||
serio->open = pcips2_open;
|
||||
serio->close = pcips2_close;
|
||||
strlcpy(serio->name, pci_name(dev), sizeof(serio->name));
|
||||
strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
|
||||
serio->port_data = ps2if;
|
||||
serio->dev.parent = &dev->dev;
|
||||
ps2if->io = serio;
|
||||
ps2if->dev = dev;
|
||||
ps2if->base = pci_resource_start(dev, 0);
|
||||
|
||||
pci_set_drvdata(dev, ps2if);
|
||||
|
||||
serio_register_port(ps2if->io);
|
||||
return 0;
|
||||
|
||||
release:
|
||||
kfree(ps2if);
|
||||
kfree(serio);
|
||||
pci_release_regions(dev);
|
||||
disable:
|
||||
pci_disable_device(dev);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit pcips2_remove(struct pci_dev *dev)
|
||||
{
|
||||
struct pcips2_data *ps2if = pci_get_drvdata(dev);
|
||||
|
||||
serio_unregister_port(ps2if->io);
|
||||
pci_set_drvdata(dev, NULL);
|
||||
kfree(ps2if);
|
||||
pci_release_regions(dev);
|
||||
pci_disable_device(dev);
|
||||
}
|
||||
|
||||
static struct pci_device_id pcips2_ids[] = {
|
||||
{
|
||||
.vendor = 0x14f2, /* MOBILITY */
|
||||
.device = 0x0123, /* Keyboard */
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.class = PCI_CLASS_INPUT_KEYBOARD << 8,
|
||||
.class_mask = 0xffff00,
|
||||
},
|
||||
{
|
||||
.vendor = 0x14f2, /* MOBILITY */
|
||||
.device = 0x0124, /* Mouse */
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.class = PCI_CLASS_INPUT_MOUSE << 8,
|
||||
.class_mask = 0xffff00,
|
||||
},
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
static struct pci_driver pcips2_driver = {
|
||||
.name = "pcips2",
|
||||
.id_table = pcips2_ids,
|
||||
.probe = pcips2_probe,
|
||||
.remove = __devexit_p(pcips2_remove),
|
||||
};
|
||||
|
||||
static int __init pcips2_init(void)
|
||||
{
|
||||
return pci_module_init(&pcips2_driver);
|
||||
}
|
||||
|
||||
static void __exit pcips2_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&pcips2_driver);
|
||||
}
|
||||
|
||||
module_init(pcips2_init);
|
||||
module_exit(pcips2_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
|
||||
MODULE_DESCRIPTION("PCI PS/2 keyboard/mouse driver");
|
||||
MODULE_DEVICE_TABLE(pci, pcips2_ids);
|
||||
163
extra/linux-2.6.10/drivers/input/serio/q40kbd.c
Normal file
163
extra/linux-2.6.10/drivers/input/serio/q40kbd.c
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* $Id: q40kbd.c,v 1.12 2002/02/02 22:26:44 vojtech Exp $
|
||||
*
|
||||
* Copyright (c) 2000-2001 Vojtech Pavlik
|
||||
*
|
||||
* Based on the work of:
|
||||
* Richard Zidlicky <Richard.Zidlicky@stud.informatik.uni-erlangen.de>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Q40 PS/2 keyboard controller driver for Linux/m68k
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/q40_master.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/q40ints.h>
|
||||
|
||||
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
||||
MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
spinlock_t q40kbd_lock = SPIN_LOCK_UNLOCKED;
|
||||
static struct serio *q40kbd_port;
|
||||
static struct platform_device *q40kbd_device;
|
||||
|
||||
static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&q40kbd_lock, flags);
|
||||
|
||||
if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))
|
||||
serio_interrupt(q40kbd_port, master_inb(KEYCODE_REG), 0, regs);
|
||||
|
||||
master_outb(-1, KEYBOARD_UNLOCK_REG);
|
||||
|
||||
spin_unlock_irqrestore(&q40kbd_lock, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* q40kbd_flush() flushes all data that may be in the keyboard buffers
|
||||
*/
|
||||
|
||||
static void q40kbd_flush(void)
|
||||
{
|
||||
int maxread = 100;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&q40kbd_lock, flags);
|
||||
|
||||
while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
|
||||
master_inb(KEYCODE_REG);
|
||||
|
||||
spin_unlock_irqrestore(&q40kbd_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* q40kbd_open() is called when a port is open by the higher layer.
|
||||
* It allocates the interrupt and enables in in the chip.
|
||||
*/
|
||||
|
||||
static int q40kbd_open(struct serio *port)
|
||||
{
|
||||
q40kbd_flush();
|
||||
|
||||
if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) {
|
||||
printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* off we go */
|
||||
master_outb(-1, KEYBOARD_UNLOCK_REG);
|
||||
master_outb(1, KEY_IRQ_ENABLE_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void q40kbd_close(struct serio *port)
|
||||
{
|
||||
master_outb(0, KEY_IRQ_ENABLE_REG);
|
||||
master_outb(-1, KEYBOARD_UNLOCK_REG);
|
||||
free_irq(Q40_IRQ_KEYBOARD, NULL);
|
||||
|
||||
q40kbd_flush();
|
||||
}
|
||||
|
||||
static struct serio * __init q40kbd_allocate_port(void)
|
||||
{
|
||||
struct serio *serio;
|
||||
|
||||
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (serio) {
|
||||
memset(serio, 0, sizeof(struct serio));
|
||||
serio->type = SERIO_8042;
|
||||
serio->open = q40kbd_open;
|
||||
serio->close = q40kbd_close;
|
||||
serio->dev.parent = &q40kbd_device->dev;
|
||||
strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name));
|
||||
strlcpy(serio->phys, "Q40", sizeof(serio->phys));
|
||||
}
|
||||
|
||||
return serio;
|
||||
}
|
||||
|
||||
static int __init q40kbd_init(void)
|
||||
{
|
||||
if (!MACH_IS_Q40)
|
||||
return -EIO;
|
||||
|
||||
q40kbd_device = platform_device_register_simple("q40kbd", -1, NULL, 0);
|
||||
if (IS_ERR(q40kbd_device))
|
||||
return PTR_ERR(q40kbd_device);
|
||||
|
||||
if (!(q40kbd_port = q40kbd_allocate_port())) {
|
||||
platform_device_unregister(q40kbd_device);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
serio_register_port(q40kbd_port);
|
||||
printk(KERN_INFO "serio: Q40 kbd registered\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit q40kbd_exit(void)
|
||||
{
|
||||
serio_unregister_port(q40kbd_port);
|
||||
platform_device_unregister(q40kbd_device);
|
||||
}
|
||||
|
||||
module_init(q40kbd_init);
|
||||
module_exit(q40kbd_exit);
|
||||
156
extra/linux-2.6.10/drivers/input/serio/rpckbd.c
Normal file
156
extra/linux-2.6.10/drivers/input/serio/rpckbd.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* $Id: rpckbd.c,v 1.7 2001/09/25 10:12:07 vojtech Exp $
|
||||
*
|
||||
* Copyright (c) 2000-2001 Vojtech Pavlik
|
||||
* Copyright (c) 2002 Russell King
|
||||
*/
|
||||
|
||||
/*
|
||||
* Acorn RiscPC PS/2 keyboard controller driver for Linux/ARM
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/hardware/iomd.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
MODULE_AUTHOR("Vojtech Pavlik, Russell King");
|
||||
MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int rpckbd_write(struct serio *port, unsigned char val)
|
||||
{
|
||||
while (!(iomd_readb(IOMD_KCTRL) & (1 << 7)))
|
||||
cpu_relax();
|
||||
|
||||
iomd_writeb(val, IOMD_KARTTX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t rpckbd_rx(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct serio *port = dev_id;
|
||||
unsigned int byte;
|
||||
int handled = IRQ_NONE;
|
||||
|
||||
while (iomd_readb(IOMD_KCTRL) & (1 << 5)) {
|
||||
byte = iomd_readb(IOMD_KARTRX);
|
||||
|
||||
serio_interrupt(port, byte, 0, regs);
|
||||
handled = IRQ_HANDLED;
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
static irqreturn_t rpckbd_tx(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rpckbd_open(struct serio *port)
|
||||
{
|
||||
/* Reset the keyboard state machine. */
|
||||
iomd_writeb(0, IOMD_KCTRL);
|
||||
iomd_writeb(8, IOMD_KCTRL);
|
||||
iomd_readb(IOMD_KARTRX);
|
||||
|
||||
if (request_irq(IRQ_KEYBOARDRX, rpckbd_rx, 0, "rpckbd", port) != 0) {
|
||||
printk(KERN_ERR "rpckbd.c: Could not allocate keyboard receive IRQ\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (request_irq(IRQ_KEYBOARDTX, rpckbd_tx, 0, "rpckbd", port) != 0) {
|
||||
printk(KERN_ERR "rpckbd.c: Could not allocate keyboard transmit IRQ\n");
|
||||
free_irq(IRQ_KEYBOARDRX, NULL);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rpckbd_close(struct serio *port)
|
||||
{
|
||||
free_irq(IRQ_KEYBOARDRX, port);
|
||||
free_irq(IRQ_KEYBOARDTX, port);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and initialize serio structure for subsequent registration
|
||||
* with serio core.
|
||||
*/
|
||||
static int __devinit rpckbd_probe(struct device *dev)
|
||||
{
|
||||
struct serio *serio;
|
||||
|
||||
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (!serio)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(serio, 0, sizeof(struct serio));
|
||||
serio->type = SERIO_8042;
|
||||
serio->write = rpckbd_write;
|
||||
serio->open = rpckbd_open;
|
||||
serio->close = rpckbd_close;
|
||||
serio->dev.parent = dev;
|
||||
strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name));
|
||||
strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys));
|
||||
|
||||
dev_set_drvdata(dev, serio);
|
||||
serio_register_port(serio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit rpckbd_remove(struct device *dev)
|
||||
{
|
||||
struct serio *serio = dev_get_drvdata(dev);
|
||||
serio_unregister_port(serio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_driver rpckbd_driver = {
|
||||
.name = "kart",
|
||||
.bus = &platform_bus_type,
|
||||
.probe = rpckbd_probe,
|
||||
.remove = __devexit_p(rpckbd_remove),
|
||||
};
|
||||
|
||||
static int __init rpckbd_init(void)
|
||||
{
|
||||
return driver_register(&rpckbd_driver);
|
||||
}
|
||||
|
||||
static void __exit rpckbd_exit(void)
|
||||
{
|
||||
driver_unregister(&rpckbd_driver);
|
||||
}
|
||||
|
||||
module_init(rpckbd_init);
|
||||
module_exit(rpckbd_exit);
|
||||
359
extra/linux-2.6.10/drivers/input/serio/sa1111ps2.c
Normal file
359
extra/linux-2.6.10/drivers/input/serio/sa1111ps2.c
Normal file
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* linux/drivers/input/serio/sa1111ps2.c
|
||||
*
|
||||
* Copyright (C) 2002 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#include <asm/hardware/sa1111.h>
|
||||
|
||||
struct ps2if {
|
||||
struct serio *io;
|
||||
struct sa1111_dev *dev;
|
||||
unsigned long base;
|
||||
unsigned int open;
|
||||
spinlock_t lock;
|
||||
unsigned int head;
|
||||
unsigned int tail;
|
||||
unsigned char buf[4];
|
||||
};
|
||||
|
||||
/*
|
||||
* Read all bytes waiting in the PS2 port. There should be
|
||||
* at the most one, but we loop for safety. If there was a
|
||||
* framing error, we have to manually clear the status.
|
||||
*/
|
||||
static irqreturn_t ps2_rxint(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct ps2if *ps2if = dev_id;
|
||||
unsigned int scancode, flag, status;
|
||||
|
||||
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
||||
while (status & PS2STAT_RXF) {
|
||||
if (status & PS2STAT_STP)
|
||||
sa1111_writel(PS2STAT_STP, ps2if->base + SA1111_PS2STAT);
|
||||
|
||||
flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) |
|
||||
(status & PS2STAT_RXP ? 0 : SERIO_PARITY);
|
||||
|
||||
scancode = sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff;
|
||||
|
||||
if (hweight8(scancode) & 1)
|
||||
flag ^= SERIO_PARITY;
|
||||
|
||||
serio_interrupt(ps2if->io, scancode, flag, regs);
|
||||
|
||||
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Completion of ps2 write
|
||||
*/
|
||||
static irqreturn_t ps2_txint(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct ps2if *ps2if = dev_id;
|
||||
unsigned int status;
|
||||
|
||||
spin_lock(&ps2if->lock);
|
||||
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
||||
if (ps2if->head == ps2if->tail) {
|
||||
disable_irq(irq);
|
||||
/* done */
|
||||
} else if (status & PS2STAT_TXE) {
|
||||
sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA);
|
||||
ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
|
||||
}
|
||||
spin_unlock(&ps2if->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a byte to the PS2 port. We have to wait for the
|
||||
* port to indicate that the transmitter is empty.
|
||||
*/
|
||||
static int ps2_write(struct serio *io, unsigned char val)
|
||||
{
|
||||
struct ps2if *ps2if = io->port_data;
|
||||
unsigned long flags;
|
||||
unsigned int head;
|
||||
|
||||
spin_lock_irqsave(&ps2if->lock, flags);
|
||||
|
||||
/*
|
||||
* If the TX register is empty, we can go straight out.
|
||||
*/
|
||||
if (sa1111_readl(ps2if->base + SA1111_PS2STAT) & PS2STAT_TXE) {
|
||||
sa1111_writel(val, ps2if->base + SA1111_PS2DATA);
|
||||
} else {
|
||||
if (ps2if->head == ps2if->tail)
|
||||
enable_irq(ps2if->dev->irq[1]);
|
||||
head = (ps2if->head + 1) & (sizeof(ps2if->buf) - 1);
|
||||
if (head != ps2if->tail) {
|
||||
ps2if->buf[ps2if->head] = val;
|
||||
ps2if->head = head;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ps2if->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ps2_open(struct serio *io)
|
||||
{
|
||||
struct ps2if *ps2if = io->port_data;
|
||||
int ret;
|
||||
|
||||
sa1111_enable_device(ps2if->dev);
|
||||
|
||||
ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0,
|
||||
SA1111_DRIVER_NAME(ps2if->dev), ps2if);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
|
||||
ps2if->dev->irq[0], ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = request_irq(ps2if->dev->irq[1], ps2_txint, 0,
|
||||
SA1111_DRIVER_NAME(ps2if->dev), ps2if);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
|
||||
ps2if->dev->irq[1], ret);
|
||||
free_irq(ps2if->dev->irq[0], ps2if);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ps2if->open = 1;
|
||||
|
||||
enable_irq_wake(ps2if->dev->irq[0]);
|
||||
|
||||
sa1111_writel(PS2CR_ENA, ps2if->base + SA1111_PS2CR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ps2_close(struct serio *io)
|
||||
{
|
||||
struct ps2if *ps2if = io->port_data;
|
||||
|
||||
sa1111_writel(0, ps2if->base + SA1111_PS2CR);
|
||||
|
||||
disable_irq_wake(ps2if->dev->irq[0]);
|
||||
|
||||
ps2if->open = 0;
|
||||
|
||||
free_irq(ps2if->dev->irq[1], ps2if);
|
||||
free_irq(ps2if->dev->irq[0], ps2if);
|
||||
|
||||
sa1111_disable_device(ps2if->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the input buffer.
|
||||
*/
|
||||
static void __init ps2_clear_input(struct ps2if *ps2if)
|
||||
{
|
||||
int maxread = 100;
|
||||
|
||||
while (maxread--) {
|
||||
if ((sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff) == 0xff)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
ps2_test_one(struct ps2if *ps2if, unsigned int mask)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
sa1111_writel(PS2CR_ENA | mask, ps2if->base + SA1111_PS2CR);
|
||||
|
||||
udelay(2);
|
||||
|
||||
val = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
||||
return val & (PS2STAT_KBC | PS2STAT_KBD);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test the keyboard interface. We basically check to make sure that
|
||||
* we can drive each line to the keyboard independently of each other.
|
||||
*/
|
||||
static int __init ps2_test(struct ps2if *ps2if)
|
||||
{
|
||||
unsigned int stat;
|
||||
int ret = 0;
|
||||
|
||||
stat = ps2_test_one(ps2if, PS2CR_FKC);
|
||||
if (stat != PS2STAT_KBD) {
|
||||
printk("PS/2 interface test failed[1]: %02x\n", stat);
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
stat = ps2_test_one(ps2if, 0);
|
||||
if (stat != (PS2STAT_KBC | PS2STAT_KBD)) {
|
||||
printk("PS/2 interface test failed[2]: %02x\n", stat);
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
stat = ps2_test_one(ps2if, PS2CR_FKD);
|
||||
if (stat != PS2STAT_KBC) {
|
||||
printk("PS/2 interface test failed[3]: %02x\n", stat);
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
sa1111_writel(0, ps2if->base + SA1111_PS2CR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add one device to this driver.
|
||||
*/
|
||||
static int ps2_probe(struct sa1111_dev *dev)
|
||||
{
|
||||
struct ps2if *ps2if;
|
||||
struct serio *serio;
|
||||
int ret;
|
||||
|
||||
ps2if = kmalloc(sizeof(struct ps2if), GFP_KERNEL);
|
||||
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (!ps2if || !serio) {
|
||||
ret = -ENOMEM;
|
||||
goto free;
|
||||
}
|
||||
|
||||
memset(ps2if, 0, sizeof(struct ps2if));
|
||||
memset(serio, 0, sizeof(struct serio));
|
||||
|
||||
serio->type = SERIO_8042;
|
||||
serio->write = ps2_write;
|
||||
serio->open = ps2_open;
|
||||
serio->close = ps2_close;
|
||||
strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name));
|
||||
strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
|
||||
serio->port_data = ps2if;
|
||||
serio->dev.parent = &dev->dev;
|
||||
ps2if->io = serio;
|
||||
ps2if->dev = dev;
|
||||
sa1111_set_drvdata(dev, ps2if);
|
||||
|
||||
spin_lock_init(&ps2if->lock);
|
||||
|
||||
/*
|
||||
* Request the physical region for this PS2 port.
|
||||
*/
|
||||
if (!request_mem_region(dev->res.start,
|
||||
dev->res.end - dev->res.start + 1,
|
||||
SA1111_DRIVER_NAME(dev))) {
|
||||
ret = -EBUSY;
|
||||
goto free;
|
||||
}
|
||||
|
||||
/*
|
||||
* Our parent device has already mapped the region.
|
||||
*/
|
||||
ps2if->base = (unsigned long)dev->mapbase;
|
||||
|
||||
sa1111_enable_device(ps2if->dev);
|
||||
|
||||
/* Incoming clock is 8MHz */
|
||||
sa1111_writel(0, ps2if->base + SA1111_PS2CLKDIV);
|
||||
sa1111_writel(127, ps2if->base + SA1111_PS2PRECNT);
|
||||
|
||||
/*
|
||||
* Flush any pending input.
|
||||
*/
|
||||
ps2_clear_input(ps2if);
|
||||
|
||||
/*
|
||||
* Test the keyboard interface.
|
||||
*/
|
||||
ret = ps2_test(ps2if);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Flush any pending input.
|
||||
*/
|
||||
ps2_clear_input(ps2if);
|
||||
|
||||
sa1111_disable_device(ps2if->dev);
|
||||
serio_register_port(ps2if->io);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
sa1111_disable_device(ps2if->dev);
|
||||
release_mem_region(dev->res.start,
|
||||
dev->res.end - dev->res.start + 1);
|
||||
free:
|
||||
sa1111_set_drvdata(dev, NULL);
|
||||
kfree(ps2if);
|
||||
kfree(serio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove one device from this driver.
|
||||
*/
|
||||
static int ps2_remove(struct sa1111_dev *dev)
|
||||
{
|
||||
struct ps2if *ps2if = sa1111_get_drvdata(dev);
|
||||
|
||||
serio_unregister_port(ps2if->io);
|
||||
release_mem_region(dev->res.start,
|
||||
dev->res.end - dev->res.start + 1);
|
||||
sa1111_set_drvdata(dev, NULL);
|
||||
|
||||
kfree(ps2if);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Our device driver structure
|
||||
*/
|
||||
static struct sa1111_driver ps2_driver = {
|
||||
.drv = {
|
||||
.name = "sa1111-ps2",
|
||||
},
|
||||
.devid = SA1111_DEVID_PS2,
|
||||
.probe = ps2_probe,
|
||||
.remove = ps2_remove,
|
||||
};
|
||||
|
||||
static int __init ps2_init(void)
|
||||
{
|
||||
return sa1111_driver_register(&ps2_driver);
|
||||
}
|
||||
|
||||
static void __exit ps2_exit(void)
|
||||
{
|
||||
sa1111_driver_unregister(&ps2_driver);
|
||||
}
|
||||
|
||||
module_init(ps2_init);
|
||||
module_exit(ps2_exit);
|
||||
|
||||
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
|
||||
MODULE_DESCRIPTION("SA1111 PS2 controller driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
667
extra/linux-2.6.10/drivers/input/serio/serio.c
Normal file
667
extra/linux-2.6.10/drivers/input/serio/serio.c
Normal file
@@ -0,0 +1,667 @@
|
||||
/*
|
||||
* The Serio abstraction module
|
||||
*
|
||||
* Copyright (c) 1999-2004 Vojtech Pavlik
|
||||
* Copyright (c) 2004 Dmitry Torokhov
|
||||
* Copyright (c) 2003 Daniele Bellucci
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
||||
MODULE_DESCRIPTION("Serio abstraction core");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
EXPORT_SYMBOL(serio_interrupt);
|
||||
EXPORT_SYMBOL(serio_register_port);
|
||||
EXPORT_SYMBOL(serio_register_port_delayed);
|
||||
EXPORT_SYMBOL(serio_unregister_port);
|
||||
EXPORT_SYMBOL(serio_unregister_port_delayed);
|
||||
EXPORT_SYMBOL(serio_register_driver);
|
||||
EXPORT_SYMBOL(serio_unregister_driver);
|
||||
EXPORT_SYMBOL(serio_open);
|
||||
EXPORT_SYMBOL(serio_close);
|
||||
EXPORT_SYMBOL(serio_rescan);
|
||||
EXPORT_SYMBOL(serio_reconnect);
|
||||
|
||||
static DECLARE_MUTEX(serio_sem); /* protects serio_list and serio_diriver_list */
|
||||
static LIST_HEAD(serio_list);
|
||||
static LIST_HEAD(serio_driver_list);
|
||||
static unsigned int serio_no;
|
||||
|
||||
struct bus_type serio_bus = {
|
||||
.name = "serio",
|
||||
};
|
||||
|
||||
static void serio_find_driver(struct serio *serio);
|
||||
static void serio_create_port(struct serio *serio);
|
||||
static void serio_destroy_port(struct serio *serio);
|
||||
static void serio_connect_port(struct serio *serio, struct serio_driver *drv);
|
||||
static void serio_reconnect_port(struct serio *serio);
|
||||
static void serio_disconnect_port(struct serio *serio);
|
||||
|
||||
static int serio_bind_driver(struct serio *serio, struct serio_driver *drv)
|
||||
{
|
||||
get_driver(&drv->driver);
|
||||
|
||||
drv->connect(serio, drv);
|
||||
if (serio->drv) {
|
||||
down_write(&serio_bus.subsys.rwsem);
|
||||
serio->dev.driver = &drv->driver;
|
||||
device_bind_driver(&serio->dev);
|
||||
up_write(&serio_bus.subsys.rwsem);
|
||||
return 1;
|
||||
}
|
||||
|
||||
put_driver(&drv->driver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* serio_find_driver() must be called with serio_sem down. */
|
||||
static void serio_find_driver(struct serio *serio)
|
||||
{
|
||||
struct serio_driver *drv;
|
||||
|
||||
list_for_each_entry(drv, &serio_driver_list, node)
|
||||
if (!drv->manual_bind)
|
||||
if (serio_bind_driver(serio, drv))
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Serio event processing.
|
||||
*/
|
||||
|
||||
struct serio_event {
|
||||
int type;
|
||||
struct serio *serio;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
enum serio_event_type {
|
||||
SERIO_RESCAN,
|
||||
SERIO_RECONNECT,
|
||||
SERIO_REGISTER_PORT,
|
||||
SERIO_UNREGISTER_PORT,
|
||||
};
|
||||
|
||||
static spinlock_t serio_event_lock = SPIN_LOCK_UNLOCKED; /* protects serio_event_list */
|
||||
static LIST_HEAD(serio_event_list);
|
||||
static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
|
||||
static DECLARE_COMPLETION(serio_exited);
|
||||
static int serio_pid;
|
||||
|
||||
static void serio_queue_event(struct serio *serio, int event_type)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct serio_event *event;
|
||||
|
||||
spin_lock_irqsave(&serio_event_lock, flags);
|
||||
|
||||
if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
|
||||
event->type = event_type;
|
||||
event->serio = serio;
|
||||
|
||||
list_add_tail(&event->node, &serio_event_list);
|
||||
wake_up(&serio_wait);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&serio_event_lock, flags);
|
||||
}
|
||||
|
||||
static struct serio_event *serio_get_event(void)
|
||||
{
|
||||
struct serio_event *event;
|
||||
struct list_head *node;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&serio_event_lock, flags);
|
||||
|
||||
if (list_empty(&serio_event_list)) {
|
||||
spin_unlock_irqrestore(&serio_event_lock, flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node = serio_event_list.next;
|
||||
event = container_of(node, struct serio_event, node);
|
||||
list_del_init(node);
|
||||
|
||||
spin_unlock_irqrestore(&serio_event_lock, flags);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
static void serio_handle_events(void)
|
||||
{
|
||||
struct serio_event *event;
|
||||
|
||||
while ((event = serio_get_event())) {
|
||||
|
||||
down(&serio_sem);
|
||||
|
||||
switch (event->type) {
|
||||
case SERIO_REGISTER_PORT :
|
||||
serio_create_port(event->serio);
|
||||
serio_connect_port(event->serio, NULL);
|
||||
break;
|
||||
|
||||
case SERIO_UNREGISTER_PORT :
|
||||
serio_disconnect_port(event->serio);
|
||||
serio_destroy_port(event->serio);
|
||||
break;
|
||||
|
||||
case SERIO_RECONNECT :
|
||||
serio_reconnect_port(event->serio);
|
||||
break;
|
||||
|
||||
case SERIO_RESCAN :
|
||||
serio_disconnect_port(event->serio);
|
||||
serio_connect_port(event->serio, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
up(&serio_sem);
|
||||
kfree(event);
|
||||
}
|
||||
}
|
||||
|
||||
static void serio_remove_pending_events(struct serio *serio)
|
||||
{
|
||||
struct list_head *node, *next;
|
||||
struct serio_event *event;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&serio_event_lock, flags);
|
||||
|
||||
list_for_each_safe(node, next, &serio_event_list) {
|
||||
event = container_of(node, struct serio_event, node);
|
||||
if (event->serio == serio) {
|
||||
list_del_init(node);
|
||||
kfree(event);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&serio_event_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
static int serio_thread(void *nothing)
|
||||
{
|
||||
lock_kernel();
|
||||
daemonize("kseriod");
|
||||
allow_signal(SIGTERM);
|
||||
|
||||
do {
|
||||
serio_handle_events();
|
||||
wait_event_interruptible(serio_wait, !list_empty(&serio_event_list));
|
||||
if (current->flags & PF_FREEZE)
|
||||
refrigerator(PF_FREEZE);
|
||||
} while (!signal_pending(current));
|
||||
|
||||
printk(KERN_DEBUG "serio: kseriod exiting\n");
|
||||
|
||||
unlock_kernel();
|
||||
complete_and_exit(&serio_exited, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Serio port operations
|
||||
*/
|
||||
|
||||
static ssize_t serio_show_description(struct device *dev, char *buf)
|
||||
{
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
return sprintf(buf, "%s\n", serio->name);
|
||||
}
|
||||
|
||||
static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
|
||||
{
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
struct device_driver *drv;
|
||||
int retval;
|
||||
|
||||
retval = down_interruptible(&serio_sem);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = count;
|
||||
if (!strncmp(buf, "none", count)) {
|
||||
serio_disconnect_port(serio);
|
||||
} else if (!strncmp(buf, "reconnect", count)) {
|
||||
serio_reconnect_port(serio);
|
||||
} else if (!strncmp(buf, "rescan", count)) {
|
||||
serio_disconnect_port(serio);
|
||||
serio_connect_port(serio, NULL);
|
||||
} else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
|
||||
serio_disconnect_port(serio);
|
||||
serio_connect_port(serio, to_serio_driver(drv));
|
||||
put_driver(drv);
|
||||
} else {
|
||||
retval = -EINVAL;
|
||||
}
|
||||
|
||||
up(&serio_sem);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t serio_show_bind_mode(struct device *dev, char *buf)
|
||||
{
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
return sprintf(buf, "%s\n", serio->manual_bind ? "manual" : "auto");
|
||||
}
|
||||
|
||||
static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t count)
|
||||
{
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
int retval;
|
||||
|
||||
retval = count;
|
||||
if (!strncmp(buf, "manual", count)) {
|
||||
serio->manual_bind = 1;
|
||||
} else if (!strncmp(buf, "auto", count)) {
|
||||
serio->manual_bind = 0;
|
||||
} else {
|
||||
retval = -EINVAL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static struct device_attribute serio_device_attrs[] = {
|
||||
__ATTR(description, S_IRUGO, serio_show_description, NULL),
|
||||
__ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver),
|
||||
__ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
|
||||
static void serio_release_port(struct device *dev)
|
||||
{
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
|
||||
kfree(serio);
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
static void serio_create_port(struct serio *serio)
|
||||
{
|
||||
try_module_get(THIS_MODULE);
|
||||
|
||||
spin_lock_init(&serio->lock);
|
||||
list_add_tail(&serio->node, &serio_list);
|
||||
snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), "serio%d", serio_no++);
|
||||
serio->dev.bus = &serio_bus;
|
||||
serio->dev.release = serio_release_port;
|
||||
if (serio->parent)
|
||||
serio->dev.parent = &serio->parent->dev;
|
||||
device_register(&serio->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* serio_destroy_port() completes deregistration process and removes
|
||||
* port from the system
|
||||
*/
|
||||
static void serio_destroy_port(struct serio *serio)
|
||||
{
|
||||
struct serio_driver *drv = serio->drv;
|
||||
unsigned long flags;
|
||||
|
||||
serio_remove_pending_events(serio);
|
||||
list_del_init(&serio->node);
|
||||
|
||||
if (drv) {
|
||||
drv->disconnect(serio);
|
||||
down_write(&serio_bus.subsys.rwsem);
|
||||
device_release_driver(&serio->dev);
|
||||
up_write(&serio_bus.subsys.rwsem);
|
||||
put_driver(&drv->driver);
|
||||
}
|
||||
|
||||
if (serio->parent) {
|
||||
spin_lock_irqsave(&serio->parent->lock, flags);
|
||||
serio->parent->child = NULL;
|
||||
spin_unlock_irqrestore(&serio->parent->lock, flags);
|
||||
}
|
||||
|
||||
device_unregister(&serio->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* serio_connect_port() tries to bind the port and possible all its
|
||||
* children to appropriate drivers. If driver passed in the function will not
|
||||
* try otehr drivers when binding parent port.
|
||||
*/
|
||||
static void serio_connect_port(struct serio *serio, struct serio_driver *drv)
|
||||
{
|
||||
WARN_ON(serio->drv);
|
||||
WARN_ON(serio->child);
|
||||
|
||||
if (drv)
|
||||
serio_bind_driver(serio, drv);
|
||||
else if (!serio->manual_bind)
|
||||
serio_find_driver(serio);
|
||||
|
||||
/* Ok, now bind children, if any */
|
||||
while (serio->child) {
|
||||
serio = serio->child;
|
||||
|
||||
WARN_ON(serio->drv);
|
||||
WARN_ON(serio->child);
|
||||
|
||||
serio_create_port(serio);
|
||||
|
||||
if (!serio->manual_bind) {
|
||||
/*
|
||||
* With children we just _prefer_ passed in driver,
|
||||
* but we will try other options in case preferred
|
||||
* is not the one
|
||||
*/
|
||||
if (!drv || !serio_bind_driver(serio, drv))
|
||||
serio_find_driver(serio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void serio_reconnect_port(struct serio *serio)
|
||||
{
|
||||
do {
|
||||
if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
|
||||
serio_disconnect_port(serio);
|
||||
serio_connect_port(serio, NULL);
|
||||
/* Ok, old children are now gone, we are done */
|
||||
break;
|
||||
}
|
||||
serio = serio->child;
|
||||
} while (serio);
|
||||
}
|
||||
|
||||
/*
|
||||
* serio_disconnect_port() unbinds a port from its driver. As a side effect
|
||||
* all child ports are unbound and destroyed.
|
||||
*/
|
||||
static void serio_disconnect_port(struct serio *serio)
|
||||
{
|
||||
struct serio_driver *drv = serio->drv;
|
||||
struct serio *s;
|
||||
|
||||
if (serio->child) {
|
||||
/*
|
||||
* Children ports should be disconnected and destroyed
|
||||
* first, staring with the leaf one, since we don't want
|
||||
* to do recursion
|
||||
*/
|
||||
do {
|
||||
s = serio->child;
|
||||
} while (s->child);
|
||||
|
||||
while (s != serio) {
|
||||
s = s->parent;
|
||||
serio_destroy_port(s->child);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ok, no children left, now disconnect this port
|
||||
*/
|
||||
if (drv) {
|
||||
drv->disconnect(serio);
|
||||
down_write(&serio_bus.subsys.rwsem);
|
||||
device_release_driver(&serio->dev);
|
||||
up_write(&serio_bus.subsys.rwsem);
|
||||
put_driver(&drv->driver);
|
||||
}
|
||||
}
|
||||
|
||||
void serio_rescan(struct serio *serio)
|
||||
{
|
||||
serio_queue_event(serio, SERIO_RESCAN);
|
||||
}
|
||||
|
||||
void serio_reconnect(struct serio *serio)
|
||||
{
|
||||
serio_queue_event(serio, SERIO_RECONNECT);
|
||||
}
|
||||
|
||||
void serio_register_port(struct serio *serio)
|
||||
{
|
||||
down(&serio_sem);
|
||||
serio_create_port(serio);
|
||||
serio_connect_port(serio, NULL);
|
||||
up(&serio_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Submits register request to kseriod for subsequent execution.
|
||||
* Can be used when it is not obvious whether the serio_sem is
|
||||
* taken or not and when delayed execution is feasible.
|
||||
*/
|
||||
void serio_register_port_delayed(struct serio *serio)
|
||||
{
|
||||
serio_queue_event(serio, SERIO_REGISTER_PORT);
|
||||
}
|
||||
|
||||
void serio_unregister_port(struct serio *serio)
|
||||
{
|
||||
down(&serio_sem);
|
||||
serio_disconnect_port(serio);
|
||||
serio_destroy_port(serio);
|
||||
up(&serio_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Submits unregister request to kseriod for subsequent execution.
|
||||
* Can be used when it is not obvious whether the serio_sem is
|
||||
* taken or not and when delayed execution is feasible.
|
||||
*/
|
||||
void serio_unregister_port_delayed(struct serio *serio)
|
||||
{
|
||||
serio_queue_event(serio, SERIO_UNREGISTER_PORT);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Serio driver operations
|
||||
*/
|
||||
|
||||
static ssize_t serio_driver_show_description(struct device_driver *drv, char *buf)
|
||||
{
|
||||
struct serio_driver *driver = to_serio_driver(drv);
|
||||
return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
|
||||
}
|
||||
|
||||
static ssize_t serio_driver_show_bind_mode(struct device_driver *drv, char *buf)
|
||||
{
|
||||
struct serio_driver *serio_drv = to_serio_driver(drv);
|
||||
return sprintf(buf, "%s\n", serio_drv->manual_bind ? "manual" : "auto");
|
||||
}
|
||||
|
||||
static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char *buf, size_t count)
|
||||
{
|
||||
struct serio_driver *serio_drv = to_serio_driver(drv);
|
||||
int retval;
|
||||
|
||||
retval = count;
|
||||
if (!strncmp(buf, "manual", count)) {
|
||||
serio_drv->manual_bind = 1;
|
||||
} else if (!strncmp(buf, "auto", count)) {
|
||||
serio_drv->manual_bind = 0;
|
||||
} else {
|
||||
retval = -EINVAL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static struct driver_attribute serio_driver_attrs[] = {
|
||||
__ATTR(description, S_IRUGO, serio_driver_show_description, NULL),
|
||||
__ATTR(bind_mode, S_IWUSR | S_IRUGO,
|
||||
serio_driver_show_bind_mode, serio_driver_set_bind_mode),
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
void serio_register_driver(struct serio_driver *drv)
|
||||
{
|
||||
struct serio *serio;
|
||||
|
||||
down(&serio_sem);
|
||||
|
||||
list_add_tail(&drv->node, &serio_driver_list);
|
||||
|
||||
drv->driver.bus = &serio_bus;
|
||||
driver_register(&drv->driver);
|
||||
|
||||
if (drv->manual_bind)
|
||||
goto out;
|
||||
|
||||
start_over:
|
||||
list_for_each_entry(serio, &serio_list, node) {
|
||||
if (!serio->drv) {
|
||||
serio_connect_port(serio, drv);
|
||||
/*
|
||||
* if new child appeared then the list is changed,
|
||||
* we need to start over
|
||||
*/
|
||||
if (serio->child)
|
||||
goto start_over;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
up(&serio_sem);
|
||||
}
|
||||
|
||||
void serio_unregister_driver(struct serio_driver *drv)
|
||||
{
|
||||
struct serio *serio;
|
||||
|
||||
down(&serio_sem);
|
||||
|
||||
list_del_init(&drv->node);
|
||||
|
||||
start_over:
|
||||
list_for_each_entry(serio, &serio_list, node) {
|
||||
if (serio->drv == drv) {
|
||||
serio_disconnect_port(serio);
|
||||
serio_connect_port(serio, NULL);
|
||||
/* we could've deleted some ports, restart */
|
||||
goto start_over;
|
||||
}
|
||||
}
|
||||
|
||||
driver_unregister(&drv->driver);
|
||||
|
||||
up(&serio_sem);
|
||||
}
|
||||
|
||||
/* called from serio_driver->connect/disconnect methods under serio_sem */
|
||||
int serio_open(struct serio *serio, struct serio_driver *drv)
|
||||
{
|
||||
serio_pause_rx(serio);
|
||||
serio->drv = drv;
|
||||
serio_continue_rx(serio);
|
||||
|
||||
if (serio->open && serio->open(serio)) {
|
||||
serio_pause_rx(serio);
|
||||
serio->drv = NULL;
|
||||
serio_continue_rx(serio);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* called from serio_driver->connect/disconnect methods under serio_sem */
|
||||
void serio_close(struct serio *serio)
|
||||
{
|
||||
if (serio->close)
|
||||
serio->close(serio);
|
||||
|
||||
serio_pause_rx(serio);
|
||||
serio->drv = NULL;
|
||||
serio_continue_rx(serio);
|
||||
}
|
||||
|
||||
irqreturn_t serio_interrupt(struct serio *serio,
|
||||
unsigned char data, unsigned int dfl, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
spin_lock_irqsave(&serio->lock, flags);
|
||||
|
||||
if (likely(serio->drv)) {
|
||||
ret = serio->drv->interrupt(serio, data, dfl, regs);
|
||||
} else {
|
||||
if (!dfl) {
|
||||
if ((serio->type != SERIO_8042 &&
|
||||
serio->type != SERIO_8042_XL) || (data == 0xaa)) {
|
||||
serio_rescan(serio);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&serio->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init serio_init(void)
|
||||
{
|
||||
if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) {
|
||||
printk(KERN_WARNING "serio: Failed to start kseriod\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
serio_bus.dev_attrs = serio_device_attrs;
|
||||
serio_bus.drv_attrs = serio_driver_attrs;
|
||||
bus_register(&serio_bus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit serio_exit(void)
|
||||
{
|
||||
bus_unregister(&serio_bus);
|
||||
kill_proc(serio_pid, SIGTERM, 1);
|
||||
wait_for_completion(&serio_exited);
|
||||
}
|
||||
|
||||
module_init(serio_init);
|
||||
module_exit(serio_exit);
|
||||
BIN
extra/linux-2.6.10/drivers/input/serio/serio.o
Normal file
BIN
extra/linux-2.6.10/drivers/input/serio/serio.o
Normal file
Binary file not shown.
390
extra/linux-2.6.10/drivers/input/serio/serio_raw.c
Normal file
390
extra/linux-2.6.10/drivers/input/serio/serio_raw.c
Normal file
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* Raw serio device providing access to a raw byte stream from underlying
|
||||
* serio port. Closely emulates behavior of pre-2.6 /dev/psaux device
|
||||
*
|
||||
* Copyright (c) 2004 Dmitry Torokhov
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/devfs_fs_kernel.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#define DRIVER_DESC "Raw serio driver"
|
||||
|
||||
MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#define SERIO_RAW_QUEUE_LEN 64
|
||||
struct serio_raw {
|
||||
unsigned char queue[SERIO_RAW_QUEUE_LEN];
|
||||
unsigned int tail, head;
|
||||
|
||||
char name[16];
|
||||
unsigned int refcnt;
|
||||
struct serio *serio;
|
||||
struct miscdevice dev;
|
||||
wait_queue_head_t wait;
|
||||
struct list_head list;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct serio_raw_list {
|
||||
struct fasync_struct *fasync;
|
||||
struct serio_raw *serio_raw;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
static DECLARE_MUTEX(serio_raw_sem);
|
||||
static LIST_HEAD(serio_raw_list);
|
||||
static unsigned int serio_raw_no;
|
||||
|
||||
/*********************************************************************
|
||||
* Interface with userspace (file operations) *
|
||||
*********************************************************************/
|
||||
|
||||
static int serio_raw_fasync(int fd, struct file *file, int on)
|
||||
{
|
||||
struct serio_raw_list *list = file->private_data;
|
||||
int retval;
|
||||
|
||||
retval = fasync_helper(fd, file, on, &list->fasync);
|
||||
return retval < 0 ? retval : 0;
|
||||
}
|
||||
|
||||
static struct serio_raw *serio_raw_locate(int minor)
|
||||
{
|
||||
struct serio_raw *serio_raw;
|
||||
|
||||
list_for_each_entry(serio_raw, &serio_raw_list, node) {
|
||||
if (serio_raw->dev.minor == minor)
|
||||
return serio_raw;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int serio_raw_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct serio_raw *serio_raw;
|
||||
struct serio_raw_list *list;
|
||||
int retval = 0;
|
||||
|
||||
retval = down_interruptible(&serio_raw_sem);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (!(serio_raw = serio_raw_locate(iminor(inode)))) {
|
||||
retval = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!serio_raw->serio) {
|
||||
retval = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(list = kmalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) {
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(list, 0, sizeof(struct serio_raw_list));
|
||||
list->serio_raw = serio_raw;
|
||||
file->private_data = list;
|
||||
|
||||
serio_raw->refcnt++;
|
||||
list_add_tail(&list->node, &serio_raw->list);
|
||||
|
||||
out:
|
||||
up(&serio_raw_sem);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int serio_raw_cleanup(struct serio_raw *serio_raw)
|
||||
{
|
||||
if (--serio_raw->refcnt == 0) {
|
||||
misc_deregister(&serio_raw->dev);
|
||||
list_del_init(&serio_raw->node);
|
||||
kfree(serio_raw);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serio_raw_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct serio_raw_list *list = file->private_data;
|
||||
struct serio_raw *serio_raw = list->serio_raw;
|
||||
|
||||
down(&serio_raw_sem);
|
||||
|
||||
serio_raw_fasync(-1, file, 0);
|
||||
serio_raw_cleanup(serio_raw);
|
||||
|
||||
up(&serio_raw_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
|
||||
{
|
||||
unsigned long flags;
|
||||
int empty;
|
||||
|
||||
spin_lock_irqsave(&serio_raw->serio->lock, flags);
|
||||
|
||||
empty = serio_raw->head == serio_raw->tail;
|
||||
if (!empty) {
|
||||
*c = serio_raw->queue[serio_raw->tail];
|
||||
serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&serio_raw->serio->lock, flags);
|
||||
|
||||
return !empty;
|
||||
}
|
||||
|
||||
static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct serio_raw_list *list = file->private_data;
|
||||
struct serio_raw *serio_raw = list->serio_raw;
|
||||
char c;
|
||||
ssize_t retval = 0;
|
||||
|
||||
if (!serio_raw->serio)
|
||||
return -ENODEV;
|
||||
|
||||
if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
|
||||
return -EAGAIN;
|
||||
|
||||
retval = wait_event_interruptible(list->serio_raw->wait,
|
||||
serio_raw->head != serio_raw->tail || !serio_raw->serio);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (!serio_raw->serio)
|
||||
return -ENODEV;
|
||||
|
||||
while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
|
||||
if (put_user(c, buffer++))
|
||||
return -EFAULT;
|
||||
retval++;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t serio_raw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct serio_raw_list *list = file->private_data;
|
||||
ssize_t written = 0;
|
||||
int retval;
|
||||
unsigned char c;
|
||||
|
||||
retval = down_interruptible(&serio_raw_sem);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (!list->serio_raw->serio) {
|
||||
retval = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (count > 32)
|
||||
count = 32;
|
||||
|
||||
while (count--) {
|
||||
if (get_user(c, buffer++)) {
|
||||
retval = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
if (serio_write(list->serio_raw->serio, c)) {
|
||||
retval = -EIO;
|
||||
goto out;
|
||||
}
|
||||
written++;
|
||||
};
|
||||
|
||||
out:
|
||||
up(&serio_raw_sem);
|
||||
return written;
|
||||
}
|
||||
|
||||
static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
struct serio_raw_list *list = file->private_data;
|
||||
|
||||
poll_wait(file, &list->serio_raw->wait, wait);
|
||||
|
||||
if (list->serio_raw->head != list->serio_raw->tail)
|
||||
return POLLIN | POLLRDNORM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct file_operations serio_raw_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = serio_raw_open,
|
||||
.release = serio_raw_release,
|
||||
.read = serio_raw_read,
|
||||
.write = serio_raw_write,
|
||||
.poll = serio_raw_poll,
|
||||
.fasync = serio_raw_fasync,
|
||||
};
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* Interface with serio port *
|
||||
*********************************************************************/
|
||||
|
||||
static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
|
||||
unsigned int dfl, struct pt_regs *regs)
|
||||
{
|
||||
struct serio_raw *serio_raw = serio->private;
|
||||
struct serio_raw_list *list;
|
||||
unsigned int head = serio_raw->head;
|
||||
|
||||
/* we are holding serio->lock here so we are prootected */
|
||||
serio_raw->queue[head] = data;
|
||||
head = (head + 1) % SERIO_RAW_QUEUE_LEN;
|
||||
if (likely(head != serio_raw->tail)) {
|
||||
serio_raw->head = head;
|
||||
list_for_each_entry(list, &serio_raw->list, node)
|
||||
kill_fasync(&list->fasync, SIGIO, POLL_IN);
|
||||
wake_up_interruptible(&serio_raw->wait);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void serio_raw_connect(struct serio *serio, struct serio_driver *drv)
|
||||
{
|
||||
struct serio_raw *serio_raw;
|
||||
int err;
|
||||
|
||||
if ((serio->type & SERIO_TYPE) != SERIO_8042)
|
||||
return;
|
||||
|
||||
if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
|
||||
printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
|
||||
return;
|
||||
}
|
||||
|
||||
down(&serio_raw_sem);
|
||||
|
||||
memset(serio_raw, 0, sizeof(struct serio_raw));
|
||||
snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
|
||||
serio_raw->refcnt = 1;
|
||||
serio_raw->serio = serio;
|
||||
INIT_LIST_HEAD(&serio_raw->list);
|
||||
init_waitqueue_head(&serio_raw->wait);
|
||||
|
||||
serio->private = serio_raw;
|
||||
if (serio_open(serio, drv))
|
||||
goto out_free;
|
||||
|
||||
list_add_tail(&serio_raw->node, &serio_raw_list);
|
||||
|
||||
serio_raw->dev.minor = PSMOUSE_MINOR;
|
||||
serio_raw->dev.name = serio_raw->name;
|
||||
serio_raw->dev.fops = &serio_raw_fops;
|
||||
|
||||
err = misc_register(&serio_raw->dev);
|
||||
if (err) {
|
||||
serio_raw->dev.minor = MISC_DYNAMIC_MINOR;
|
||||
err = misc_register(&serio_raw->dev);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
printk(KERN_INFO "serio_raw: failed to register raw access device for %s\n",
|
||||
serio->phys);
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "serio_raw: raw access enabled on %s (%s, minor %d)\n",
|
||||
serio->phys, serio_raw->name, serio_raw->dev.minor);
|
||||
goto out;
|
||||
|
||||
out_close:
|
||||
serio_close(serio);
|
||||
list_del_init(&serio_raw->node);
|
||||
out_free:
|
||||
serio->private = NULL;
|
||||
kfree(serio_raw);
|
||||
out:
|
||||
up(&serio_raw_sem);
|
||||
}
|
||||
|
||||
static int serio_raw_reconnect(struct serio *serio)
|
||||
{
|
||||
struct serio_raw *serio_raw = serio->private;
|
||||
struct serio_driver *drv = serio->drv;
|
||||
|
||||
if (!drv || !serio_raw) {
|
||||
printk(KERN_DEBUG "serio_raw: reconnect request, but serio is disconnected, ignoring...\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Nothing needs to be done here, we just need this method to
|
||||
* keep the same device.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void serio_raw_disconnect(struct serio *serio)
|
||||
{
|
||||
struct serio_raw *serio_raw;
|
||||
|
||||
down(&serio_raw_sem);
|
||||
|
||||
serio_raw = serio->private;
|
||||
|
||||
serio_close(serio);
|
||||
serio->private = NULL;
|
||||
|
||||
serio_raw->serio = NULL;
|
||||
if (!serio_raw_cleanup(serio_raw))
|
||||
wake_up_interruptible(&serio_raw->wait);
|
||||
|
||||
up(&serio_raw_sem);
|
||||
}
|
||||
|
||||
static struct serio_driver serio_raw_drv = {
|
||||
.driver = {
|
||||
.name = "serio_raw",
|
||||
},
|
||||
.description = DRIVER_DESC,
|
||||
.interrupt = serio_raw_interrupt,
|
||||
.connect = serio_raw_connect,
|
||||
.reconnect = serio_raw_reconnect,
|
||||
.disconnect = serio_raw_disconnect,
|
||||
.manual_bind = 1,
|
||||
};
|
||||
|
||||
int __init serio_raw_init(void)
|
||||
{
|
||||
serio_register_driver(&serio_raw_drv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit serio_raw_exit(void)
|
||||
{
|
||||
serio_unregister_driver(&serio_raw_drv);
|
||||
}
|
||||
|
||||
module_init(serio_raw_init);
|
||||
module_exit(serio_raw_exit);
|
||||
213
extra/linux-2.6.10/drivers/input/serio/serport.c
Normal file
213
extra/linux-2.6.10/drivers/input/serio/serport.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Input device TTY line discipline
|
||||
*
|
||||
* Copyright (c) 1999-2002 Vojtech Pavlik
|
||||
*
|
||||
* This is a module that converts a tty line into a much simpler
|
||||
* 'serial io port' abstraction that the input device drivers use.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/tty.h>
|
||||
|
||||
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
||||
MODULE_DESCRIPTION("Input device TTY line discipline");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_LDISC(N_MOUSE);
|
||||
|
||||
#define SERPORT_BUSY 1
|
||||
|
||||
struct serport {
|
||||
struct tty_struct *tty;
|
||||
wait_queue_head_t wait;
|
||||
struct serio *serio;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* Callback functions from the serio code.
|
||||
*/
|
||||
|
||||
static int serport_serio_write(struct serio *serio, unsigned char data)
|
||||
{
|
||||
struct serport *serport = serio->port_data;
|
||||
return -(serport->tty->driver->write(serport->tty, &data, 1) != 1);
|
||||
}
|
||||
|
||||
static void serport_serio_close(struct serio *serio)
|
||||
{
|
||||
struct serport *serport = serio->port_data;
|
||||
|
||||
serport->serio->type = 0;
|
||||
wake_up_interruptible(&serport->wait);
|
||||
}
|
||||
|
||||
/*
|
||||
* serport_ldisc_open() is the routine that is called upon setting our line
|
||||
* discipline on a tty. It prepares the serio struct.
|
||||
*/
|
||||
|
||||
static int serport_ldisc_open(struct tty_struct *tty)
|
||||
{
|
||||
struct serport *serport;
|
||||
struct serio *serio;
|
||||
char name[64];
|
||||
|
||||
serport = kmalloc(sizeof(struct serport), GFP_KERNEL);
|
||||
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (unlikely(!serport || !serio)) {
|
||||
kfree(serport);
|
||||
kfree(serio);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(serport, 0, sizeof(struct serport));
|
||||
serport->serio = serio;
|
||||
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
||||
serport->tty = tty;
|
||||
tty->disc_data = serport;
|
||||
|
||||
memset(serio, 0, sizeof(struct serio));
|
||||
strlcpy(serio->name, "Serial port", sizeof(serio->name));
|
||||
snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
|
||||
serio->type = SERIO_RS232;
|
||||
serio->write = serport_serio_write;
|
||||
serio->close = serport_serio_close;
|
||||
serio->port_data = serport;
|
||||
|
||||
init_waitqueue_head(&serport->wait);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* serport_ldisc_close() is the opposite of serport_ldisc_open()
|
||||
*/
|
||||
|
||||
static void serport_ldisc_close(struct tty_struct *tty)
|
||||
{
|
||||
struct serport *serport = (struct serport*) tty->disc_data;
|
||||
kfree(serport);
|
||||
}
|
||||
|
||||
/*
|
||||
* serport_ldisc_receive() is called by the low level tty driver when characters
|
||||
* are ready for us. We forward the characters, one by one to the 'interrupt'
|
||||
* routine.
|
||||
*
|
||||
* FIXME: We should get pt_regs from the tty layer and forward them to
|
||||
* serio_interrupt here.
|
||||
*/
|
||||
|
||||
static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
|
||||
{
|
||||
struct serport *serport = (struct serport*) tty->disc_data;
|
||||
int i;
|
||||
for (i = 0; i < count; i++)
|
||||
serio_interrupt(serport->serio, cp[i], 0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* serport_ldisc_room() reports how much room we do have for receiving data.
|
||||
* Although we in fact have infinite room, we need to specify some value
|
||||
* here, and 256 seems to be reasonable.
|
||||
*/
|
||||
|
||||
static int serport_ldisc_room(struct tty_struct *tty)
|
||||
{
|
||||
return 256;
|
||||
}
|
||||
|
||||
/*
|
||||
* serport_ldisc_read() just waits indefinitely if everything goes well.
|
||||
* However, when the serio driver closes the serio port, it finishes,
|
||||
* returning 0 characters.
|
||||
*/
|
||||
|
||||
static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char __user * buf, size_t nr)
|
||||
{
|
||||
struct serport *serport = (struct serport*) tty->disc_data;
|
||||
char name[64];
|
||||
|
||||
if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
|
||||
return -EBUSY;
|
||||
|
||||
serio_register_port(serport->serio);
|
||||
printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
|
||||
wait_event_interruptible(serport->wait, !serport->serio->type);
|
||||
serio_unregister_port(serport->serio);
|
||||
|
||||
clear_bit(SERPORT_BUSY, &serport->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* serport_ldisc_ioctl() allows to set the port protocol, and device ID
|
||||
*/
|
||||
|
||||
static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct serport *serport = (struct serport*) tty->disc_data;
|
||||
|
||||
if (cmd == SPIOCSTYPE)
|
||||
return get_user(serport->serio->type, (unsigned long __user *) arg);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void serport_ldisc_write_wakeup(struct tty_struct * tty)
|
||||
{
|
||||
struct serport *sp = (struct serport *) tty->disc_data;
|
||||
|
||||
serio_drv_write_wakeup(sp->serio);
|
||||
}
|
||||
|
||||
/*
|
||||
* The line discipline structure.
|
||||
*/
|
||||
|
||||
static struct tty_ldisc serport_ldisc = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "input",
|
||||
.open = serport_ldisc_open,
|
||||
.close = serport_ldisc_close,
|
||||
.read = serport_ldisc_read,
|
||||
.ioctl = serport_ldisc_ioctl,
|
||||
.receive_buf = serport_ldisc_receive,
|
||||
.receive_room = serport_ldisc_room,
|
||||
.write_wakeup = serport_ldisc_write_wakeup
|
||||
};
|
||||
|
||||
/*
|
||||
* The functions for insering/removing us as a module.
|
||||
*/
|
||||
|
||||
static int __init serport_init(void)
|
||||
{
|
||||
int retval;
|
||||
retval = tty_register_ldisc(N_MOUSE, &serport_ldisc);
|
||||
if (retval)
|
||||
printk(KERN_ERR "serport.c: Error registering line discipline.\n");
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __exit serport_exit(void)
|
||||
{
|
||||
tty_register_ldisc(N_MOUSE, NULL);
|
||||
}
|
||||
|
||||
module_init(serport_init);
|
||||
module_exit(serport_exit);
|
||||
Reference in New Issue
Block a user